From 66404f34d255eb7304a6ecf8350589684e62951d Mon Sep 17 00:00:00 2001 From: Stefan Schindler Date: Tue, 10 May 2016 11:06:30 +0200 Subject: [PATCH 01/16] Simplify text --- src/libcore/sync/atomic.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index cf3e45cf3de79..e141a92c3ee3d 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -142,13 +142,13 @@ pub enum Ordering { #[stable(feature = "rust1", since = "1.0.0")] Relaxed, /// When coupled with a store, all previous writes become visible - /// to another thread that performs a load with `Acquire` ordering + /// to the other threads that perform a load with `Acquire` ordering /// on the same value. #[stable(feature = "rust1", since = "1.0.0")] Release, /// When coupled with a load, all subsequent loads will see data /// written before a store with `Release` ordering on the same value - /// in another thread. + /// in other threads. #[stable(feature = "rust1", since = "1.0.0")] Acquire, /// When coupled with a load, uses `Acquire` ordering, and with a store From 85e02429b2ef07e11a40ebf6df28b37bcba528b2 Mon Sep 17 00:00:00 2001 From: Cristian Oliveira Date: Wed, 4 May 2016 00:40:53 -0300 Subject: [PATCH 02/16] Add error description for E0455 - Adding name attribute to the sample code - Fix description sentences --- src/librustc_metadata/diagnostics.rs | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/librustc_metadata/diagnostics.rs b/src/librustc_metadata/diagnostics.rs index 8fa23de9a2d16..ae9f500c5de59 100644 --- a/src/librustc_metadata/diagnostics.rs +++ b/src/librustc_metadata/diagnostics.rs @@ -26,6 +26,27 @@ name. Example: ``` "##, +E0455: r##" +Linking with `kind=framework` is only supported when targeting OS X, +as frameworks are specific to that operating system. + +Erroneous code example: + +```compile_fail" +#[link(name = "FooCoreServices", kind = "framework")] extern {} +// OS used to compile is Linux for example +``` + +To solve this error you can use conditional compilation: + +``` +#[cfg_attr(target="macos", link(name = "FooCoreServices", kind = "framework"))] +extern {} +``` + +See more: https://doc.rust-lang.org/book/conditional-compilation.html +"##, + E0458: r##" An unknown "kind" was specified for a link attribute. Erroneous code example: @@ -73,7 +94,6 @@ well, and you link to them the same way. } register_diagnostics! { - E0455, // native frameworks are only available on OSX targets E0456, // plugin `..` is not available for triple `..` E0457, // plugin `..` only found in rlib format, but must be available... E0514, // metadata version mismatch From 7a9f4c22ff974ec68300f68c46df49d3f83329de Mon Sep 17 00:00:00 2001 From: ggomez Date: Tue, 10 May 2016 10:54:29 +0200 Subject: [PATCH 03/16] Add E0500 error explanation --- src/librustc_borrowck/diagnostics.rs | 48 +++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/src/librustc_borrowck/diagnostics.rs b/src/librustc_borrowck/diagnostics.rs index 8d9b88e899be2..2c38bc36dc3d4 100644 --- a/src/librustc_borrowck/diagnostics.rs +++ b/src/librustc_borrowck/diagnostics.rs @@ -378,6 +378,53 @@ let c = &i; // still ok! ``` "##, +E0500: r##" +A borrowed variable was used in another closure. Example of erroneous code: + +```compile_fail +fn you_know_nothing(jon_snow: &mut i32) { + let nights_watch = || { + *jon_snow = 2; + }; + let starks = || { + *jon_snow = 3; // error: closure requires unique access to `jon_snow` + // but it is already borrowed + }; +} + +In here, `jon_snow` is already borrowed by the `nights_watch` closure, so it +cannot be borrowed by the `starks` closure at the same time. To fix this issue, +you can put the closure in its own scope: + +``` +fn you_know_nothing(jon_snow: &mut i32) { + { + let nights_watch = || { + *jon_snow = 2; + }; + } // At this point, `jon_snow` is free. + let starks = || { + *jon_snow = 3; + }; +} +``` + +Or, if the type implements the `Clone` trait, you can clone it between +closures: + +``` +fn you_know_nothing(jon_snow: &mut i32) { + let mut jon_copy = jon_snow.clone(); + let nights_watch = || { + jon_copy = 2; + }; + let starks = || { + *jon_snow = 3; + }; +} +``` +"##, + E0501: r##" This error indicates that a mutable variable is being used while it is still captured by a closure. Because the closure has borrowed the variable, it is not @@ -753,7 +800,6 @@ fn main() { register_diagnostics! { E0385, // {} in an aliasable location E0388, // {} in a static location - E0500, // closure requires unique access to `..` but .. is already borrowed E0502, // cannot borrow `..`.. as .. because .. is also borrowed as ... E0503, // cannot use `..` because it was mutably borrowed E0504, // cannot move `..` into closure because it is borrowed From 5cbfa1285d7f3e6f93a5cd204ef9efbaefe222ed Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Wed, 11 May 2016 20:42:26 +0100 Subject: [PATCH 04/16] Fix typo in std::sync::Once documentation --- src/libstd/sync/once.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index e228d236a3ca7..d8a4a69c73cd3 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -218,7 +218,6 @@ impl Once { /// The closure `f` is yielded a structure which can be used to query the /// state of this `Once` (whether initialization has previously panicked or /// not). - /// poisoned or not. #[unstable(feature = "once_poison", issue = "31688")] pub fn call_once_force(&'static self, f: F) where F: FnOnce(&OnceState) { // same as above, just with a different parameter to `call_inner`. From bf09a9eda02c3930c0beee011a6f06138260cdf4 Mon Sep 17 00:00:00 2001 From: billyevans Date: Sat, 7 May 2016 00:27:32 +0100 Subject: [PATCH 05/16] Add detailed error explanation for E0505 Part of #32777 --- src/librustc_borrowck/diagnostics.rs | 80 +++++++++++++++++++++++++++- 1 file changed, 79 insertions(+), 1 deletion(-) diff --git a/src/librustc_borrowck/diagnostics.rs b/src/librustc_borrowck/diagnostics.rs index 0687faa112f5e..b5d54567191c8 100644 --- a/src/librustc_borrowck/diagnostics.rs +++ b/src/librustc_borrowck/diagnostics.rs @@ -642,6 +642,85 @@ fn print_fancy_ref(fancy_ref: &FancyNum){ ``` "##, +E0505: r##" +A value was moved out while it was still borrowed. +Erroneous code example: + +```compile_fail +struct Value {} + +fn eat(val: Value) {} + +fn main() { + let x = Value{}; + { + let _ref_to_val: &Value = &x; + eat(x); + } +} +``` + +Here, the function `eat` takes the ownership of `x`. However, +`x` cannot be moved because it was borrowed to `_ref_to_val`. +To fix that you can do few different things: + +* Try to avoid moving the variable. +* Release borrow before move. +* Implement the `Copy` trait on the type. + +Examples: + +``` +struct Value {} + +fn eat(val: &Value) {} + +fn main() { + let x = Value{}; + { + let _ref_to_val: &Value = &x; + eat(&x); // pass by reference, if it's possible + } +} +``` + +Or: + +``` +struct Value {} + +fn eat(val: Value) {} + +fn main() { + let x = Value{}; + { + let _ref_to_val: &Value = &x; + } + eat(x); // release borrow and then move it. +} +``` + +Or: + +``` +#[derive(Clone, Copy)] // implement Copy trait +struct Value {} + +fn eat(val: Value) {} + +fn main() { + let x = Value{}; + { + let _ref_to_val: &Value = &x; + eat(x); // it will be copied here. + } +} +``` + +You can find more information about borrowing in the rust-book: +http://doc.rust-lang.org/stable/book/references-and-borrowing.html +"##, + E0507: r##" You tried to move out of a value which was borrowed. Erroneous code example: @@ -860,7 +939,6 @@ register_diagnostics! { E0500, // closure requires unique access to `..` but .. is already borrowed E0502, // cannot borrow `..`.. as .. because .. is also borrowed as ... E0503, // cannot use `..` because it was mutably borrowed - E0505, // cannot move out of `..` because it is borrowed E0508, // cannot move out of type `..`, a non-copy fixed-size array E0524, // two closures require unique access to `..` at the same time } From 6458b0454f66f9cf16a4b50b8e0874b950326ef3 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Thu, 12 May 2016 00:05:25 -0400 Subject: [PATCH 06/16] Cleanup formatting and wording for `std::env::temp_dir` docs. --- src/libstd/env.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/libstd/env.rs b/src/libstd/env.rs index 9dc6a26cdeed3..6956dc0d901a4 100644 --- a/src/libstd/env.rs +++ b/src/libstd/env.rs @@ -452,16 +452,16 @@ pub fn home_dir() -> Option { /// Returns the path of a temporary directory. /// -/// On Unix, returns the value of the 'TMPDIR' environment variable if it is -/// set, otherwise for non-Android it returns '/tmp'. If Android, since there -/// is no global temporary folder (it is usually allocated per-app), we return -/// '/data/local/tmp'. -/// -/// On Windows, returns the value of, in order, the 'TMP', 'TEMP', -/// 'USERPROFILE' environment variable if any are set and not the empty -/// string. Otherwise, tmpdir returns the path of the Windows directory. This -/// behavior is identical to that of [GetTempPath][msdn], which this function -/// uses internally. +/// On Unix, returns the value of the `TMPDIR` environment variable if it is +/// set, otherwise for non-Android it returns `/tmp`. If Android, since there +/// is no global temporary folder (it is usually allocated per-app), it returns +/// `/data/local/tmp`. +/// +/// On Windows, returns the value of, in order, the `TMP`, `TEMP`, +/// `USERPROFILE` environment variable if any are set and not the empty +/// string. Otherwise, `temp_dir` returns the path of the Windows directory. +/// This behavior is identical to that of [`GetTempPath`][msdn], which this +/// function uses internally. /// /// [msdn]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa364992(v=vs.85).aspx /// From a7902b12e8045c1781c71e171f715344c38b6c01 Mon Sep 17 00:00:00 2001 From: Seo Sanghyeon Date: Thu, 12 May 2016 13:42:57 +0900 Subject: [PATCH 07/16] Tighten span for E0063 --- src/librustc_typeck/check/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index f428023da9b82..1afc6e1e33edf 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3299,7 +3299,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let expr_ty = self.instantiate_type(def.def_id(), path); self.write_ty(expr.id, expr_ty); - self.check_expr_struct_fields(expr_ty, expr.span, variant, fields, + self.check_expr_struct_fields(expr_ty, path.span, variant, fields, base_expr.is_none()); if let &Some(ref base_expr) = base_expr { self.check_expr_has_type(base_expr, expr_ty); From 843b174e93b253824a62fba3ac4be2753e30c9c2 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Mon, 2 May 2016 14:52:48 +0200 Subject: [PATCH 08/16] typeck: if a private field exists, also check for a public method For example, `Vec::len` is both a field and a method, and usually encountering `vec.len` just means that the parens were forgotten. Fixes: #26472 --- src/librustc_typeck/check/method/mod.rs | 5 +++-- src/librustc_typeck/check/mod.rs | 12 +++++++++--- src/test/compile-fail/issue-26472.rs | 24 ++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 5 deletions(-) create mode 100644 src/test/compile-fail/issue-26472.rs diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index f27ae181f77e3..00eeefa0449ce 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -84,7 +84,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { span: Span, method_name: ast::Name, self_ty: ty::Ty<'tcx>, - call_expr_id: ast::NodeId) + call_expr_id: ast::NodeId, + allow_private: bool) -> bool { let mode = probe::Mode::MethodCall; @@ -93,7 +94,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { Err(NoMatch(..)) => false, Err(Ambiguity(..)) => true, Err(ClosureAmbiguity(..)) => true, - Err(PrivateMatch(..)) => true, + Err(PrivateMatch(..)) => allow_private, } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index f428023da9b82..060075e6f0d90 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3045,12 +3045,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let Some((did, field_ty)) = private_candidate { let struct_path = self.tcx().item_path_str(did); - let msg = format!("field `{}` of struct `{}` is private", field.node, struct_path); - self.tcx().sess.span_err(expr.span, &msg); self.write_ty(expr.id, field_ty); + let msg = format!("field `{}` of struct `{}` is private", field.node, struct_path); + let mut err = self.tcx().sess.struct_span_err(expr.span, &msg); + // Also check if an accessible method exists, which is often what is meant. + if self.method_exists(field.span, field.node, expr_t, expr.id, false) { + err.note(&format!("a method `{}` also exists, perhaps you wish to call it", + field.node)); + } + err.emit(); } else if field.node == keywords::Invalid.name() { self.write_error(expr.id); - } else if self.method_exists(field.span, field.node, expr_t, expr.id) { + } else if self.method_exists(field.span, field.node, expr_t, expr.id, true) { self.type_error_struct(field.span, |actual| { format!("attempted to take value of method `{}` on type \ `{}`", field.node, actual) diff --git a/src/test/compile-fail/issue-26472.rs b/src/test/compile-fail/issue-26472.rs new file mode 100644 index 0000000000000..0d59a897ef1af --- /dev/null +++ b/src/test/compile-fail/issue-26472.rs @@ -0,0 +1,24 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +mod sub { + pub struct S { len: usize } + impl S { + pub fn new() -> S { S { len: 0 } } + pub fn len(&self) -> usize { self.len } + } +} + +fn main() { + let s = sub::S::new(); + let v = s.len; + //~^ ERROR field `len` of struct `sub::S` is private + //~| NOTE a method `len` also exists, perhaps you wish to call it +} From df4fe5fbd44d8b4d698397dc8a05db56fbd9ab42 Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Thu, 12 May 2016 10:40:10 -0400 Subject: [PATCH 09/16] update "reason" for fnbox feature gate It isn't "newly introduced" anymore. --- src/liballoc/boxed.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 7bdf9eaccc323..20645dc90a810 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -525,14 +525,14 @@ impl ExactSizeIterator for Box {} /// } /// ``` #[rustc_paren_sugar] -#[unstable(feature = "fnbox", reason = "Newly introduced", issue = "28796")] +#[unstable(feature = "fnbox", reason = "will be deprecated if and when Box becomes usable", issue = "28796")] pub trait FnBox { type Output; fn call_box(self: Box, args: A) -> Self::Output; } -#[unstable(feature = "fnbox", reason = "Newly introduced", issue = "28796")] +#[unstable(feature = "fnbox", reason = "will be deprecated if and when Box becomes usable", issue = "28796")] impl FnBox for F where F: FnOnce { type Output = F::Output; @@ -542,7 +542,7 @@ impl FnBox for F where F: FnOnce } } -#[unstable(feature = "fnbox", reason = "Newly introduced", issue = "28796")] +#[unstable(feature = "fnbox", reason = "will be deprecated if and when Box becomes usable", issue = "28796")] impl<'a, A, R> FnOnce for Box + 'a> { type Output = R; @@ -551,7 +551,7 @@ impl<'a, A, R> FnOnce for Box + 'a> { } } -#[unstable(feature = "fnbox", reason = "Newly introduced", issue = "28796")] +#[unstable(feature = "fnbox", reason = "will be deprecated if and when Box becomes usable", issue = "28796")] impl<'a, A, R> FnOnce for Box + Send + 'a> { type Output = R; From b9fce76f470ca95e6801c19a82ebac874d34e92f Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Thu, 12 May 2016 10:59:37 -0400 Subject: [PATCH 10/16] fix tidy --- src/liballoc/boxed.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 20645dc90a810..10e4ea1c3f055 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -525,14 +525,16 @@ impl ExactSizeIterator for Box {} /// } /// ``` #[rustc_paren_sugar] -#[unstable(feature = "fnbox", reason = "will be deprecated if and when Box becomes usable", issue = "28796")] +#[unstable(feature = "fnbox", + reason = "will be deprecated if and when Box becomes usable", issue = "28796")] pub trait FnBox { type Output; fn call_box(self: Box, args: A) -> Self::Output; } -#[unstable(feature = "fnbox", reason = "will be deprecated if and when Box becomes usable", issue = "28796")] +#[unstable(feature = "fnbox", + reason = "will be deprecated if and when Box becomes usable", issue = "28796")] impl FnBox for F where F: FnOnce { type Output = F::Output; @@ -542,7 +544,8 @@ impl FnBox for F where F: FnOnce } } -#[unstable(feature = "fnbox", reason = "will be deprecated if and when Box becomes usable", issue = "28796")] +#[unstable(feature = "fnbox", + reason = "will be deprecated if and when Box becomes usable", issue = "28796")] impl<'a, A, R> FnOnce for Box + 'a> { type Output = R; @@ -551,7 +554,8 @@ impl<'a, A, R> FnOnce for Box + 'a> { } } -#[unstable(feature = "fnbox", reason = "will be deprecated if and when Box becomes usable", issue = "28796")] +#[unstable(feature = "fnbox", + reason = "will be deprecated if and when Box becomes usable", issue = "28796")] impl<'a, A, R> FnOnce for Box + Send + 'a> { type Output = R; From 91e43acf1fe68c02af0284e550c5418fad082d66 Mon Sep 17 00:00:00 2001 From: Stefan Schindler Date: Thu, 12 May 2016 17:38:20 +0200 Subject: [PATCH 11/16] Use the correct word in the explanation --- src/libstd/time/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/time/mod.rs b/src/libstd/time/mod.rs index bc50b0d3a7066..80963a9b735a5 100644 --- a/src/libstd/time/mod.rs +++ b/src/libstd/time/mod.rs @@ -76,7 +76,7 @@ pub struct Instant(time::Instant); /// Distinct from the `Instant` type, this time measurement **is not /// monotonic**. This means that you can save a file to the file system, then /// save another file to the file system, **and the second file has a -/// `SystemTime` measurement earlier than the second**. In other words, an +/// `SystemTime` measurement earlier than the first**. In other words, an /// operation that happens after another operation in real time may have an /// earlier `SystemTime`! /// From d4bff0cddaeedcac954c10930b71f5f2ceba286c Mon Sep 17 00:00:00 2001 From: Haiko Schol Date: Thu, 12 May 2016 21:49:14 +0200 Subject: [PATCH 12/16] doc: Fix comment in std::string::String example code --- src/libcollections/string.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index 306fad2328b62..eedf4c2c11f34 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -184,7 +184,7 @@ use boxed::Box; /// let len = story.len(); /// let capacity = story.capacity(); /// -/// // story has thirteen bytes +/// // story has nineteen bytes /// assert_eq!(19, len); /// /// // Now that we have our parts, we throw the story away. From 1e901de9e878519b962dbca0c6e39f0bdf39af8f Mon Sep 17 00:00:00 2001 From: Dan Fockler Date: Wed, 4 May 2016 15:42:56 -0700 Subject: [PATCH 13/16] Add error explanations for E0374, E0375, E0376 on issue #33383 --- src/librustc_typeck/diagnostics.rs | 165 +++++++++++++++++++++++++++-- 1 file changed, 158 insertions(+), 7 deletions(-) diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 05e4c79a7e8d5..629a715d6bf6b 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 { + a: i32, +} + +// error: Struct `Foo` has no unsized fields that need `CoerceUnsized`. +impl CoerceUnsized> for Foo + where T: CoerceUnsized {} +``` + +`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 { + a: i32, + b: T, +} + +// The struct has an unsized field so we can implement +// `CoerceUnsized` for it. +impl CoerceUnsized> for Bar + where T: CoerceUnsized {} +``` + +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 { + a: i32, + b: T, + c: U, +} + +// error: Struct `Foo` has more than one unsized field. +impl CoerceUnsized> for Foo {} +``` + +`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 { + a: i32, + b: T, +} + +impl CoerceUnsized> for Foo + where T: CoerceUnsized {} + +fn coerce_foo, U>(t: T) -> Foo { + Foo { a: 12i32, b: t } // we use coercion to get the `Foo` 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 { + a: T, +} + +// error: The type `U` is not a struct +impl CoerceUnsized for Foo {} +``` + +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 { + a: T, +} + +// The `Foo` is a struct so `CoerceUnsized` can be implemented +impl CoerceUnsized> for Foo where T: CoerceUnsized {} +``` + +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 From a181d2fad466b716006e0ad8b68c022a84e27494 Mon Sep 17 00:00:00 2001 From: Tshepang Lekhonkhobe Date: Thu, 12 May 2016 23:25:33 +0200 Subject: [PATCH 14/16] doc: line these comments up Looks more nice, and same is done with prior examples --- src/libcollections/fmt.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcollections/fmt.rs b/src/libcollections/fmt.rs index ce1d6ec5a6478..ca8cb25e1a441 100644 --- a/src/libcollections/fmt.rs +++ b/src/libcollections/fmt.rs @@ -81,7 +81,7 @@ //! //! ``` //! format!("{argument}", argument = "test"); // => "test" -//! format!("{name} {}", 1, name = 2); // => "2 1" +//! format!("{name} {}", 1, name = 2); // => "2 1" //! format!("{a} {c} {b}", a="a", b='b', c=3); // => "a 3 b" //! ``` //! From 10c984a155eda8bada42f4b74528eb5c1a2bc826 Mon Sep 17 00:00:00 2001 From: Tshepang Lekhonkhobe Date: Thu, 12 May 2016 23:37:17 +0200 Subject: [PATCH 15/16] doc: use less awkward and less confusing language --- src/libcollections/fmt.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcollections/fmt.rs b/src/libcollections/fmt.rs index ce1d6ec5a6478..3f88183d27aad 100644 --- a/src/libcollections/fmt.rs +++ b/src/libcollections/fmt.rs @@ -104,8 +104,8 @@ //! octal. //! //! There are various parameters which do require a particular type, however. -//! Namely, the `{:.*}` syntax, which sets the number of numbers after the -//! decimal in floating-point types: +//! An example is the `{:.*}` syntax, which sets the number of decimal places +//! in floating-point types: //! //! ``` //! let formatted_number = format!("{:.*}", 2, 1.234567); From 226cb9c9bd951d24ea5b686d5dbfcf65bd71855c Mon Sep 17 00:00:00 2001 From: Tshepang Lekhonkhobe Date: Thu, 12 May 2016 23:11:52 +0200 Subject: [PATCH 16/16] doc: to_string not needed since we gots coercion --- src/libcollections/fmt.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcollections/fmt.rs b/src/libcollections/fmt.rs index ce1d6ec5a6478..c8030c1efd62b 100644 --- a/src/libcollections/fmt.rs +++ b/src/libcollections/fmt.rs @@ -527,7 +527,7 @@ use string; /// use std::fmt; /// /// let s = fmt::format(format_args!("Hello, {}!", "world")); -/// assert_eq!(s, "Hello, world!".to_string()); +/// assert_eq!(s, "Hello, world!"); /// ``` /// /// Please note that using [`format!`][format!] might be preferrable. @@ -535,7 +535,7 @@ use string; /// /// ``` /// let s = format!("Hello, {}!", "world"); -/// assert_eq!(s, "Hello, world!".to_string()); +/// assert_eq!(s, "Hello, world!"); /// ``` /// /// [format!]: ../macro.format!.html