From fc16c3ee338237d53eb30d8a730b4a47933a8fae Mon Sep 17 00:00:00 2001 From: Blake Loring Date: Sat, 4 Jul 2015 23:12:08 +0100 Subject: [PATCH 01/37] Improve the expected constant integer error message Print error followed by expected to make the error more clear --- src/librustc/middle/ty.rs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 3497a8d690479..1f0b56b66266f 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -6414,20 +6414,16 @@ pub fn eval_repeat_count(tcx: &ctxt, count_expr: &ast::Expr) -> usize { found); } Err(err) => { - let err_description = err.description(); - let found = match count_expr.node { + let err_msg = match count_expr.node { ast::ExprPath(None, ast::Path { global: false, ref segments, .. }) if segments.len() == 1 => - format!("{}", "found variable"), - _ => - format!("but {}", err_description), + format!("found variable, expected constant integer for repeat count"), + _ => format!("{}, expected constant integer for repeat count", err.description()), }; - span_err!(tcx.sess, count_expr.span, E0307, - "expected constant integer for repeat count, {}", - found); + span_err!(tcx.sess, count_expr.span, E0307, "{}", err_msg); } } 0 From f395b2b9e85b3b52372ef1a4e063d6332ca26992 Mon Sep 17 00:00:00 2001 From: Blake Loring Date: Sat, 4 Jul 2015 23:32:50 +0100 Subject: [PATCH 02/37] Make the message slightly clearer --- src/librustc/middle/ty.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 38c434115eeed..851fb490c0f42 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -6175,17 +6175,16 @@ impl<'tcx> ctxt<'tcx> { found); } Err(err) => { - let err_description = err.description(); let err_msg = match count_expr.node { ast::ExprPath(None, ast::Path { global: false, ref segments, .. }) if segments.len() == 1 => - format!("found variable, expected constant integer for repeat count"), - _ => format!("{}, expected constant integer for repeat count", err.description()), + format!("found variable"), + _ => format!("{}", err.description()), }; - span_err!(tcx.sess, count_expr.span, E0307, "{}", err_msg); + span_err!(tcx.sess, count_expr.span, E0307, "{}, expected valid constant integer for repeat count", err_msg); } } 0 From 8c5ffd30fb7d50f430346d7849c2b38b8e39c680 Mon Sep 17 00:00:00 2001 From: Blake Loring Date: Sat, 4 Jul 2015 23:34:57 +0100 Subject: [PATCH 03/37] Reduce line length --- src/librustc/middle/ty.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 851fb490c0f42..5b50bbcbc80a6 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -6184,7 +6184,9 @@ impl<'tcx> ctxt<'tcx> { format!("found variable"), _ => format!("{}", err.description()), }; - span_err!(tcx.sess, count_expr.span, E0307, "{}, expected valid constant integer for repeat count", err_msg); + span_err!(tcx.sess, count_expr.span, E0307, + "{}, expected valid constant integer for repeat count", + err_msg); } } 0 From 02dd732702a44b4ec09f788a9da9287f4de75fdb Mon Sep 17 00:00:00 2001 From: Blake Loring Date: Sun, 5 Jul 2015 01:45:32 +0100 Subject: [PATCH 04/37] Self.sess -> txc.sess --- src/librustc/middle/ty.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 5b50bbcbc80a6..ee4817b33be7b 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -6184,7 +6184,7 @@ impl<'tcx> ctxt<'tcx> { format!("found variable"), _ => format!("{}", err.description()), }; - span_err!(tcx.sess, count_expr.span, E0307, + span_err!(self.sess, count_expr.span, E0307, "{}, expected valid constant integer for repeat count", err_msg); } From 48724631d4cbecd96219269af4acc23cdf7bec1f Mon Sep 17 00:00:00 2001 From: Blake Loring Date: Sun, 5 Jul 2015 13:03:39 +0100 Subject: [PATCH 05/37] Remove 'valid' from error --- src/librustc/middle/ty.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index ee4817b33be7b..3c7b677e85887 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -6185,7 +6185,7 @@ impl<'tcx> ctxt<'tcx> { _ => format!("{}", err.description()), }; span_err!(self.sess, count_expr.span, E0307, - "{}, expected valid constant integer for repeat count", + "{}, expected constant integer for repeat count", err_msg); } } From affbc729f44c2ff9c92a75266a5c00215d54c1ed Mon Sep 17 00:00:00 2001 From: Blake Loring Date: Sun, 19 Jul 2015 10:55:03 +0100 Subject: [PATCH 06/37] Modified to add 'found' to error message instead --- src/librustc/middle/ty.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 3c7b677e85887..ec1500d8767ae 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -46,7 +46,7 @@ use metadata::csearch; use middle; use middle::cast; use middle::check_const; -use middle::const_eval::{self, ConstVal}; +use middle::const_eval::{self, ConstVal, ErrKind}; use middle::def::{self, DefMap, ExportMap}; use middle::dependency_format; use middle::fast_reject; @@ -6182,11 +6182,13 @@ impl<'tcx> ctxt<'tcx> { .. }) if segments.len() == 1 => format!("found variable"), - _ => format!("{}", err.description()), + _ => match err.kind { + ErrKind::MiscCatchAll => format!("but found {}", err.description()), + _ => format!("but {}", err.description()) + } }; span_err!(self.sess, count_expr.span, E0307, - "{}, expected constant integer for repeat count", - err_msg); + "expected constant integer for repeat count, {}", err_msg); } } 0 From b684826cab859cc6e16419de448f99a47ce2f8f2 Mon Sep 17 00:00:00 2001 From: Andrew Paseltiner Date: Sun, 19 Jul 2015 15:39:26 -0400 Subject: [PATCH 07/37] add test for #20162 closes #20162 --- src/test/compile-fail/issue-20162.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 src/test/compile-fail/issue-20162.rs diff --git a/src/test/compile-fail/issue-20162.rs b/src/test/compile-fail/issue-20162.rs new file mode 100644 index 0000000000000..d3a87689ac5e1 --- /dev/null +++ b/src/test/compile-fail/issue-20162.rs @@ -0,0 +1,17 @@ +// Copyright 2015 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. + +struct X { x: i32 } + +fn main() { + let mut b: Vec = vec![]; + b.sort(); + //~^ ERROR the trait `core::cmp::Ord` is not implemented for the type `X` +} From 871ccfb5a92468056e5492c7f2e54a244657a3e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Steinbrink?= Date: Mon, 20 Jul 2015 10:33:44 +0200 Subject: [PATCH 08/37] Add a test for #26468 The fix for #26468 was made upstream and landed with the LLVM update in #27076. Closes #26468 --- src/test/run-pass/issue-26468.rs | 38 ++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 src/test/run-pass/issue-26468.rs diff --git a/src/test/run-pass/issue-26468.rs b/src/test/run-pass/issue-26468.rs new file mode 100644 index 0000000000000..9fb8675e84e9d --- /dev/null +++ b/src/test/run-pass/issue-26468.rs @@ -0,0 +1,38 @@ +// Copyright 2015 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. + +#![allow(dead_code)] + +enum FooMode { + Check = 0x1001, +} + +enum BarMode { + Check = 0x2001, +} + +enum Mode { + Foo(FooMode), + Bar(BarMode), +} + +#[inline(never)] +fn broken(mode: &Mode) -> u32 { + for _ in 0..1 { + if let Mode::Foo(FooMode::Check) = *mode { return 17 } + if let Mode::Bar(BarMode::Check) = *mode { return 19 } + } + return 42; +} + +fn main() { + let mode = Mode::Bar(BarMode::Check); + assert_eq!(broken(&mode), 19); +} From 9bb6545124ca70dff4fa68ecd5188c45607bbdec Mon Sep 17 00:00:00 2001 From: Andrew Paseltiner Date: Mon, 20 Jul 2015 08:31:54 -0400 Subject: [PATCH 09/37] add test for #14229 closes #14229 --- src/test/run-pass/issue-14229.rs | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 src/test/run-pass/issue-14229.rs diff --git a/src/test/run-pass/issue-14229.rs b/src/test/run-pass/issue-14229.rs new file mode 100644 index 0000000000000..ee2bbe63750c3 --- /dev/null +++ b/src/test/run-pass/issue-14229.rs @@ -0,0 +1,30 @@ +// Copyright 2015 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. + +trait Foo: Sized { + fn foo(self) {} +} + +trait Bar: Sized { + fn bar(self) {} +} + +struct S; + +impl<'l> Foo for &'l S {} + +impl Bar for T {} + +fn main() { + let s = S; + s.foo(); + (&s).bar(); + s.bar(); +} From 4c73dbddcf4f6bce64424203acad203cfb70072a Mon Sep 17 00:00:00 2001 From: Andrew Paseltiner Date: Mon, 20 Jul 2015 08:39:51 -0400 Subject: [PATCH 10/37] add test for #19404 closes #19404 --- src/test/run-pass/issue-19404.rs | 47 ++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 src/test/run-pass/issue-19404.rs diff --git a/src/test/run-pass/issue-19404.rs b/src/test/run-pass/issue-19404.rs new file mode 100644 index 0000000000000..0eea6ba22cae8 --- /dev/null +++ b/src/test/run-pass/issue-19404.rs @@ -0,0 +1,47 @@ +// Copyright 2015 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. + +#![feature(reflect_marker)] + +use std::any::TypeId; +use std::marker::Reflect; +use std::rc::Rc; + +type Fp = Rc; + +struct Engine; + +trait Component: 'static + Reflect {} +impl Component for Engine {} + +trait Env { + fn get_component_type_id(&self, type_id: TypeId) -> Option>; +} + +impl<'a> Env+'a { + fn get_component(&self) -> Option> { + let x = self.get_component_type_id(TypeId::of::()); + None + } +} + +trait Figment { + fn init(&mut self, env: &Env); +} + +struct MyFigment; + +impl Figment for MyFigment { + fn init(&mut self, env: &Env) { + let engine = env.get_component::(); + } +} + +fn main() {} From 31a62d3b4be308dbfb71dd7114cbb1594a4986f7 Mon Sep 17 00:00:00 2001 From: Paolo Falabella Date: Mon, 20 Jul 2015 17:29:34 +0200 Subject: [PATCH 11/37] s/has gained/has not gained/g I'm pretty sure this was a typo --- src/libcore/iter.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index 4c8511eb1902c..415326a8a616e 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -2555,7 +2555,7 @@ impl RandomAccessIterator for Inspect #[unstable(feature = "iter_unfold")] #[derive(Clone)] #[deprecated(since = "1.2.0", - reason = "has gained enough traction to retain its position \ + reason = "has not gained enough traction to retain its position \ in the standard library")] #[allow(deprecated)] pub struct Unfold { @@ -2567,7 +2567,7 @@ pub struct Unfold { #[unstable(feature = "iter_unfold")] #[deprecated(since = "1.2.0", - reason = "has gained enough traction to retain its position \ + reason = "has not gained enough traction to retain its position \ in the standard library")] #[allow(deprecated)] impl Unfold where F: FnMut(&mut St) -> Option { @@ -3018,7 +3018,7 @@ type IterateState = (F, Option, bool); /// from a given seed value. #[unstable(feature = "iter_iterate")] #[deprecated(since = "1.2.0", - reason = "has gained enough traction to retain its position \ + reason = "has not gained enough traction to retain its position \ in the standard library")] #[allow(deprecated)] pub type Iterate = Unfold, fn(&mut IterateState) -> Option>; @@ -3027,7 +3027,7 @@ pub type Iterate = Unfold, fn(&mut IterateState) /// repeated applications of the given function `f`. #[unstable(feature = "iter_iterate")] #[deprecated(since = "1.2.0", - reason = "has gained enough traction to retain its position \ + reason = "has not gained enough traction to retain its position \ in the standard library")] #[allow(deprecated)] pub fn iterate(seed: T, f: F) -> Iterate where From a7e5c6302b2458a91d4140a6fefea223a4df758d Mon Sep 17 00:00:00 2001 From: Andrew Paseltiner Date: Mon, 20 Jul 2015 12:59:33 -0400 Subject: [PATCH 12/37] add test for #10436 closes #10436 --- src/test/run-pass/issue-10436.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/test/run-pass/issue-10436.rs diff --git a/src/test/run-pass/issue-10436.rs b/src/test/run-pass/issue-10436.rs new file mode 100644 index 0000000000000..81a955b0f22e4 --- /dev/null +++ b/src/test/run-pass/issue-10436.rs @@ -0,0 +1,20 @@ +// Copyright 2015 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. + +fn works(x: T) -> Vec { vec![x] } + +fn also_works(x: T) -> Vec { vec![x] } + +fn main() { + let _: Vec = works(0); + let _: Vec = also_works(0); + let _ = works(0); + let _ = also_works(0); +} From 3ae7b72970104d1269fd1ebc31aaaf50830f3a3b Mon Sep 17 00:00:00 2001 From: Alisdair Owens Date: Mon, 20 Jul 2015 18:14:12 +0100 Subject: [PATCH 13/37] Fix wording nit for E0253 --- src/librustc_resolve/diagnostics.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index a0d06e5e1244a..23d323440c9b3 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -106,8 +106,7 @@ mod foo { use foo::MyTrait::do_something; ``` -In general, it's not legal to directly import methods belonging to a -trait or concrete type. +It's illegal to directly import methods belonging to a trait or concrete type. "##, E0255: r##" From 27fc0f21c48ad9a8788044467c14611b41afeab3 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Mon, 20 Jul 2015 13:16:57 -0400 Subject: [PATCH 14/37] Document iterators in std::io Make them all consistent and link up the documentation. --- src/libstd/io/mod.rs | 39 ++++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 2447473103101..2a0efb9d8a28c 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -1188,9 +1188,12 @@ impl Write for Broadcast { } } -/// Adaptor to chain together two instances of `Read`. +/// Adaptor to chain together two readers. /// -/// For more information, see `Read::chain`. +/// This struct is generally created by calling [`chain()`][chain] on a reader. +/// Please see the documentation of `chain()` for more details. +/// +/// [chain]: trait.Read.html#method.chain #[stable(feature = "rust1", since = "1.0.0")] pub struct Chain { first: T, @@ -1266,7 +1269,10 @@ impl BufRead for Take { /// An adaptor which will emit all read data to a specified writer as well. /// -/// For more information see `Read::tee` +/// This struct is generally created by calling [`tee()`][tee] on a reader. +/// Please see the documentation of `tee()` for more details. +/// +/// [tee]: trait.Read.html#method.tee #[unstable(feature = "io", reason = "awaiting stability of Read::tee")] pub struct Tee { reader: R, @@ -1283,9 +1289,12 @@ impl Read for Tee { } } -/// A bridge from implementations of `Read` to an `Iterator` of `u8`. +/// An iterator over `u8` values of a reader. +/// +/// This struct is generally created by calling [`bytes()`][bytes] on a reader. +/// Please see the documentation of `bytes()` for more details. /// -/// See `Read::bytes` for more information. +/// [bytes]: trait.Read.html#method.bytes #[stable(feature = "rust1", since = "1.0.0")] pub struct Bytes { inner: R, @@ -1305,9 +1314,12 @@ impl Iterator for Bytes { } } -/// A bridge from implementations of `Read` to an `Iterator` of `char`. +/// An iterator over the `char`s of a reader. /// -/// See `Read::chars` for more information. +/// This struct is generally created by calling [`chars()`][chars] on a reader. +/// Please see the documentation of `chars()` for more details. +/// +/// [chars]: trait.Read.html#method.chars #[unstable(feature = "io", reason = "awaiting stability of Read::chars")] pub struct Chars { inner: R, @@ -1389,7 +1401,10 @@ impl fmt::Display for CharsError { /// An iterator over the contents of an instance of `BufRead` split on a /// particular byte. /// -/// See `BufRead::split` for more information. +/// This struct is generally created by calling [`split()`][split] on a +/// `BufRead`. Please see the documentation of `split()` for more details. +/// +/// [split]: trait.BufRead.html#method.split #[stable(feature = "rust1", since = "1.0.0")] pub struct Split { buf: B, @@ -1415,10 +1430,12 @@ impl Iterator for Split { } } -/// An iterator over the lines of an instance of `BufRead` split on a newline -/// byte. +/// An iterator over the lines of an instance of `BufRead`. +/// +/// This struct is generally created by calling [`lines()`][lines] on a +/// `BufRead`. Please see the documentation of `lines()` for more details. /// -/// See `BufRead::lines` for more information. +/// [lines]: trait.BufRead.html#method.lines #[stable(feature = "rust1", since = "1.0.0")] pub struct Lines { buf: B, From 686d32643913040d5074fd632fba6a628ea5807c Mon Sep 17 00:00:00 2001 From: Alisdair Owens Date: Sun, 19 Jul 2015 15:18:09 +0100 Subject: [PATCH 15/37] Add diagnostics for E0172, fix inline error message for E0139 --- src/librustc/middle/intrinsicck.rs | 2 +- src/librustc_typeck/diagnostics.rs | 28 +++++++++++++++++++++++++++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs index c5f6f0126de37..a10e0b8dfc29e 100644 --- a/src/librustc/middle/intrinsicck.rs +++ b/src/librustc/middle/intrinsicck.rs @@ -165,7 +165,7 @@ impl<'a, 'tcx> IntrinsicCheckingVisitor<'a, 'tcx> { if from_tc.interior_param() || to_tc.interior_param() { span_err!(self.tcx.sess, span, E0139, "cannot transmute to or from a type that contains \ - type parameters in its interior"); + unsubstituted type parameters"); return; } diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index a002ed311e8c5..a6c574e29ef93 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -1476,6 +1476,33 @@ return, for example with a `loop` that never breaks or a call to another diverging function (such as `panic!()`). "##, +E0172: r##" +This error means that an attempt was made to specify the type of a variable with +a combination of a concrete type and a trait. Consider the following example: + +``` +fn foo(bar: i32+std::fmt::Display) {} +``` + +The code is trying to specify that we want to receive a signed 32-bit integer +which also implements `Display`. This doesn't make sense: when we pass `i32`, a +concrete type, it implicitly includes all of the traits that it implements. +This includes `Display`, `Debug`, `Clone`, and a host of others. + +If `i32` implements the trait we desire, there's no need to specify the trait +separately. If it does not, then we need to `impl` the trait for `i32` before +passing it into `foo`. Either way, a fixed definition for `foo` will look like +the following: + +``` +fn foo(bar: i32) {} +``` + +To learn more about traits, take a look at the Book: + +https://doc.rust-lang.org/book/traits.html +"##, + E0178: r##" In types, the `+` type operator has low precedence, so it is often necessary to use parentheses. @@ -2196,7 +2223,6 @@ register_diagnostics! { E0164, E0167, E0168, - E0172, E0173, // manual implementations of unboxed closure traits are experimental E0174, // explicit use of unboxed closure methods are experimental E0182, From 7e7ec6b5cd78d16c260b251dfd69cc150332f83d Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Mon, 20 Jul 2015 14:41:00 -0400 Subject: [PATCH 16/37] Document structures in std::io::utils These provide various special readers, so point their docs to their constructor functions in a manner consistent with everything else. --- src/libstd/io/util.rs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/libstd/io/util.rs b/src/libstd/io/util.rs index c0bced26beffa..dc29811ed5ba1 100644 --- a/src/libstd/io/util.rs +++ b/src/libstd/io/util.rs @@ -61,6 +61,11 @@ pub fn copy(reader: &mut R, writer: &mut W) -> io::Result Date: Mon, 20 Jul 2015 15:52:43 -0400 Subject: [PATCH 17/37] Update docs for take and broadcast Better and more consistent links to their creators. --- src/libstd/io/mod.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 2447473103101..25f0c9cf55016 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -1167,7 +1167,10 @@ pub trait BufRead: Read { /// A `Write` adaptor which will write data to multiple locations. /// -/// For more information, see `Write::broadcast`. +/// This struct is generally created by calling [`broadcast()`][broadcast] on a +/// writer. Please see the documentation of `broadcast()` for more details. +/// +/// [broadcast]: trait.Write.html#method.broadcast #[unstable(feature = "io", reason = "awaiting stability of Write::broadcast")] pub struct Broadcast { first: T, @@ -1213,7 +1216,10 @@ impl Read for Chain { /// Reader adaptor which limits the bytes read from an underlying reader. /// -/// For more information, see `Read::take`. +/// This struct is generally created by calling [`take()`][take] on a reader. +/// Please see the documentation of `take()` for more details. +/// +/// [take]: trait.Read.html#method.take #[stable(feature = "rust1", since = "1.0.0")] pub struct Take { inner: T, From a29c8347f2b196c4d5f755d02ab5d65b9be98849 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Mon, 20 Jul 2015 20:12:37 -0400 Subject: [PATCH 18/37] Add travis config to TRPL: release channels This should help people configure travis to test all three channels. --- src/doc/trpl/release-channels.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/doc/trpl/release-channels.md b/src/doc/trpl/release-channels.md index 03e65539a2042..1e203c6553ee1 100644 --- a/src/doc/trpl/release-channels.md +++ b/src/doc/trpl/release-channels.md @@ -43,3 +43,26 @@ This will help alert the team in case there’s an accidental regression. Additionally, testing against nightly can catch regressions even sooner, and so if you don’t mind a third build, we’d appreciate testing against all channels. +As an example, many Rust programmers use [Travis](https://travis-ci.org/) to +test their crates, which is free for open source projects. Travis [supports +Rust directly][travis], and you can use a `.travis.yml` file like this to +test on all channels: + +```yaml +language: rust +rust: + - nightly + - beta + - stable + +matrix: + allow_failures: + - rust: nightly +``` + +[travis]: http://docs.travis-ci.com/user/languages/rust/ + +With this configuration, Travis will test all three channels, but if something +breaks on nightly, it won’t fail your build. A similar configuration is +recommended for any CI system, check the documentation of the one you’re +using for more details. From eb39df0b8f21131228c7de9d5830d79f76916ad5 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Mon, 20 Jul 2015 13:02:02 -0400 Subject: [PATCH 19/37] Improve documentation for std::io::BufWriter Mostly through adding examples. --- src/libstd/io/buffered.rs | 103 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 98 insertions(+), 5 deletions(-) diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index d6561ebb489d7..5aead4ac0a27f 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -252,14 +252,49 @@ impl Seek for BufReader { } } -/// Wraps a Writer and buffers output to it. +/// Wraps a writer and buffers its output. /// -/// It can be excessively inefficient to work directly with a `Write`. For -/// example, every call to `write` on `TcpStream` results in a system call. A -/// `BufWriter` keeps an in memory buffer of data and writes it to the -/// underlying `Write` in large, infrequent batches. +/// It can be excessively inefficient to work directly with something that +/// implements `Write`. For example, every call to `write` on `TcpStream` +/// results in a system call. A `BufWriter` keeps an in-memory buffer of data +/// and writes it to an underlying writer in large, infrequent batches. /// /// The buffer will be written out when the writer is dropped. +/// +/// # Examples +/// +/// Let's write the numbers one through ten to a `TcpStream`: +/// +/// ```no_run +/// use std::io::prelude::*; +/// use std::net::TcpStream; +/// +/// let mut stream = TcpStream::connect("127.0.0.1:34254").unwrap(); +/// +/// for i in 1..10 { +/// stream.write(&[i]).unwrap(); +/// } +/// ``` +/// +/// Because we're not buffering, we write each one in turn, incurring the +/// overhead of a system call per byte written. We can fix this with a +/// `BufWriter`: +/// +/// ```no_run +/// use std::io::prelude::*; +/// use std::io::BufWriter; +/// use std::net::TcpStream; +/// +/// let mut stream = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap()); +/// +/// for i in 1..10 { +/// stream.write(&[i]).unwrap(); +/// } +/// ``` +/// +/// By wrapping the stream with a `BufWriter`, these ten writes are all grouped +/// together by the buffer, and will all be written out in one system call when +/// the `stream` is dropped. #[stable(feature = "rust1", since = "1.0.0")] pub struct BufWriter { inner: Option, @@ -275,12 +310,33 @@ pub struct IntoInnerError(W, Error); impl BufWriter { /// Creates a new `BufWriter` with a default buffer capacity. + /// + /// # Examples + /// + /// ```no_run + /// use std::io::BufWriter; + /// use std::net::TcpStream; + /// + /// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap()); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn new(inner: W) -> BufWriter { BufWriter::with_capacity(DEFAULT_BUF_SIZE, inner) } /// Creates a new `BufWriter` with the specified buffer capacity. + /// + /// # Examples + /// + /// Creating a buffer with a buffer of a hundred bytes. + /// + /// ```no_run + /// use std::io::BufWriter; + /// use std::net::TcpStream; + /// + /// let stream = TcpStream::connect("127.0.0.1:34254").unwrap(); + /// let mut buffer = BufWriter::with_capacity(100, stream); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn with_capacity(cap: usize, inner: W) -> BufWriter { BufWriter { @@ -313,6 +369,18 @@ impl BufWriter { } /// Gets a reference to the underlying writer. + /// + /// # Examples + /// + /// ```no_run + /// use std::io::BufWriter; + /// use std::net::TcpStream; + /// + /// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap()); + /// + /// // we can use reference just like buffer + /// let reference = buffer.get_ref(); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn get_ref(&self) -> &W { self.inner.as_ref().unwrap() } @@ -321,12 +389,37 @@ impl BufWriter { /// # Warning /// /// It is inadvisable to directly write to the underlying writer. + /// + /// # Examples + /// + /// ```no_run + /// use std::io::prelude::*; + /// use std::io::BufWriter; + /// use std::net::TcpStream; + /// + /// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap()); + /// + /// // we can use reference just like buffer + /// let reference = buffer.get_mut(); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn get_mut(&mut self) -> &mut W { self.inner.as_mut().unwrap() } /// Unwraps this `BufWriter`, returning the underlying writer. /// /// The buffer is written out before returning the writer. + /// + /// # Examples + /// + /// ```no_run + /// use std::io::BufWriter; + /// use std::net::TcpStream; + /// + /// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap()); + /// + /// // unwrap the TcpStream and flush the buffer + /// let stream = buffer.into_inner().unwrap(); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn into_inner(mut self) -> Result>> { match self.flush_buf() { From 0eb7303c7062792049c0ec4ff2c42565db6d60ff Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 17 Jul 2015 14:00:03 +0200 Subject: [PATCH 20/37] Add E0403 error explanation --- src/librustc_resolve/diagnostics.rs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index a0d06e5e1244a..2a5a31dcd194e 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -274,6 +274,21 @@ on this topic: http://doc.rust-lang.org/reference.html#use-declarations "## +E0403: r##" +Some type parameters have the same name. Example of erroneous code: + +``` +fn foo(s: T, u: T) {} // error: the name `T` is already used for a type + // parameter in this type parameter list +``` + +Please verify you didn't mispell the type parameters. Example: + +``` +fn foo(s: T, u: Y) {} +``` +"## + } register_diagnostics! { @@ -284,7 +299,6 @@ register_diagnostics! { E0258, E0401, // can't use type parameters from outer function E0402, // cannot use an outer type parameter in this context - E0403, // the name `{}` is already used E0404, // is not a trait E0405, // use of undeclared trait name E0406, // undeclared associated type From cd385cbe34d8a9bad2a6d03c1ef50dd04642a379 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 17 Jul 2015 14:14:41 +0200 Subject: [PATCH 21/37] Add E0405 error explanation --- src/librustc_resolve/diagnostics.rs | 36 ++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 2a5a31dcd194e..428e084064ebd 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -282,10 +282,41 @@ fn foo(s: T, u: T) {} // error: the name `T` is already used for a type // parameter in this type parameter list ``` -Please verify you didn't mispell the type parameters. Example: +Please verify that none of the type params are misspelled, and rename any +clashing parameters. Example: ``` -fn foo(s: T, u: Y) {} +fn foo(s: T, u: Y) {} // ok! +``` +"##, + +E0405: r##" +You tried to implement an undefined trait on an object. Example of +erroneous code: + +``` +struct Foo; + +impl SomeTrait for Foo {} // error: use of undeclared trait name `SomeTrait` +``` + +Please verify that the name of the trait wasn't misspelled and ensure that it +was imported. Example: + +``` +// solution 1: +use some_file::SomeTrait; + +// solution 2: +trait SomeTrait { + // some functions +} + +struct Foo; + +impl SomeTrait for Foo { // ok! + // implements functions +} ``` "## @@ -300,7 +331,6 @@ register_diagnostics! { E0401, // can't use type parameters from outer function E0402, // cannot use an outer type parameter in this context E0404, // is not a trait - E0405, // use of undeclared trait name E0406, // undeclared associated type E0407, // method is not a member of trait E0408, // variable from pattern #1 is not bound in pattern # From bc79f20ccac4ead82fae1464ea0916e78e04616f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 17 Jul 2015 14:55:42 +0200 Subject: [PATCH 22/37] Add E0404 error explanation --- src/librustc_resolve/diagnostics.rs | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 428e084064ebd..d83829150c553 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -290,6 +290,32 @@ fn foo(s: T, u: Y) {} // ok! ``` "##, +E0404: r##" +You tried to implement a non-trait object on an object. Example of erroneous +code: + +``` +struct Foo; +struct Bar; + +impl Foo for Bar {} // error: `Foo` is not a trait +``` + +Please verify you didn't mispelled the trait's name or used the wrong object. +Example: + +``` +trait Foo { + // some functions +} +struct Bar; + +impl Foo for Bar { // ok! + // functions implementation +} +``` +"##, + E0405: r##" You tried to implement an undefined trait on an object. Example of erroneous code: @@ -330,7 +356,6 @@ register_diagnostics! { E0258, E0401, // can't use type parameters from outer function E0402, // cannot use an outer type parameter in this context - E0404, // is not a trait E0406, // undeclared associated type E0407, // method is not a member of trait E0408, // variable from pattern #1 is not bound in pattern # From 95811546e6dabc1946a155c70a4635b9d76dcb8d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 17 Jul 2015 15:54:44 +0200 Subject: [PATCH 23/37] Add E0407 error explanation --- src/librustc_resolve/diagnostics.rs | 41 ++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index d83829150c553..b135d9c0c4ab1 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -317,8 +317,7 @@ impl Foo for Bar { // ok! "##, E0405: r##" -You tried to implement an undefined trait on an object. Example of -erroneous code: +A non-trait was implemented. Example of erroneous code: ``` struct Foo; @@ -344,7 +343,42 @@ impl SomeTrait for Foo { // ok! // implements functions } ``` -"## +"##, + +E0407: r##" +A definition of a method not in the implemented trait was given. Example of +erroneous code: + +``` +trait Foo { + fn a(); +} + +struct Bar; + +impl Foo for Bar { + fn a() {} + fn b() {} // error: method `b` is not a member of trait `Foo` +} +``` + +Please verify you didn't mispelled the method name and you used the good +trait. Example: + +``` +trait Foo { + fn a(); + fn b(); +} + +struct Bar; + +impl Foo for Bar { + fn a() {} + fn b() {} // ok! +} +``` +"##, } @@ -357,7 +391,6 @@ register_diagnostics! { E0401, // can't use type parameters from outer function E0402, // cannot use an outer type parameter in this context E0406, // undeclared associated type - E0407, // method is not a member of trait E0408, // variable from pattern #1 is not bound in pattern # E0409, // variable is bound with different mode in pattern # than in // pattern #1 From c13295bbc3c887581828583ad8c09be8a21227c8 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 17 Jul 2015 16:09:25 +0200 Subject: [PATCH 24/37] Add E0428 error explanation --- src/librustc_resolve/diagnostics.rs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index b135d9c0c4ab1..96bc3576a94fa 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -380,6 +380,24 @@ impl Foo for Bar { ``` "##, +E0428: r##" +A type or module has been defined more than once. Example of erroneous +code: + +``` +struct Bar; +struct Bar; // error: duplicate definition of value `Bar` +``` + +Please verify you didn't mispelled the type/module's name or remove the +duplicated one. Example: + +``` +struct Bar; +struct Bar2; // ok! +``` +"##, + } register_diagnostics! { @@ -415,7 +433,6 @@ register_diagnostics! { E0425, // unresolved name E0426, // use of undeclared label E0427, // cannot use `ref` binding mode with ... - E0428, // duplicate definition of ... E0429, // `self` imports are only allowed within a { } list E0430, // `self` import can only appear once in the list E0431, // `self` import can only appear in an import list with a non-empty From d2aee954fee04e48de4441df41076fe4abf84336 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Mon, 20 Jul 2015 16:46:34 -0400 Subject: [PATCH 25/37] Expand documentation for IntoInnerError Mostly adding examples. --- src/libstd/io/buffered.rs | 74 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 73 insertions(+), 1 deletion(-) diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index d6561ebb489d7..e8c7d1af74e32 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -269,6 +269,27 @@ pub struct BufWriter { /// An error returned by `into_inner` which combines an error that /// happened while writing out the buffer, and the buffered writer object /// which may be used to recover from the condition. +/// +/// # Examples +/// +/// ```no_run +/// use std::io::BufWriter; +/// use std::net::TcpStream; +/// +/// let mut stream = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap()); +/// +/// // do stuff with the stream +/// +/// // we want to get our `TcpStream` back, so let's try: +/// +/// let stream = match stream.into_inner() { +/// Ok(s) => s, +/// Err(e) => { +/// // Here, e is an IntoInnerError +/// panic!("An error occurred"); +/// } +/// }; +/// ``` #[derive(Debug)] #[stable(feature = "rust1", since = "1.0.0")] pub struct IntoInnerError(W, Error); @@ -384,9 +405,34 @@ impl Drop for BufWriter { } impl IntoInnerError { - /// Returns the error which caused the call to `into_inner` to fail. + /// Returns the error which caused the call to `into_inner()` to fail. /// /// This error was returned when attempting to write the internal buffer. + /// + /// # Examples + /// + /// ```no_run + /// use std::io::BufWriter; + /// use std::net::TcpStream; + /// + /// let mut stream = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap()); + /// + /// // do stuff with the stream + /// + /// // we want to get our `TcpStream` back, so let's try: + /// + /// let stream = match stream.into_inner() { + /// Ok(s) => s, + /// Err(e) => { + /// // Here, e is an IntoInnerError, let's log the inner error. + /// // + /// // We'll just 'log' to stdout for this example. + /// println!("{}", e.error()); + /// + /// panic!("An unexpected error occurred."); + /// } + /// }; + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn error(&self) -> &Error { &self.1 } @@ -394,6 +440,32 @@ impl IntoInnerError { /// /// The returned object can be used for error recovery, such as /// re-inspecting the buffer. + /// + /// # Examples + /// + /// ```no_run + /// use std::io::BufWriter; + /// use std::net::TcpStream; + /// + /// let mut stream = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap()); + /// + /// // do stuff with the stream + /// + /// // we want to get our `TcpStream` back, so let's try: + /// + /// let stream = match stream.into_inner() { + /// Ok(s) => s, + /// Err(e) => { + /// // Here, e is a IntoInnerError, let's re-examine the buffer: + /// let buffer = e.into_inner(); + /// + /// // do stuff to try to recover + /// + /// // afterwards, let's just return the stream + /// buffer.into_inner().unwrap() + /// } + /// }; + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn into_inner(self) -> W { self.0 } } From 94b8f2820f3de88f53a64a635d135f2c1c47b117 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Mon, 20 Jul 2015 15:43:57 -0400 Subject: [PATCH 26/37] Improve documentation for std::io::LineWriter Beef up the struct docs, add examples for the methods. --- src/libstd/io/buffered.rs | 124 +++++++++++++++++++++++++++++++++++++- 1 file changed, 121 insertions(+), 3 deletions(-) diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index d6561ebb489d7..32440f8638490 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -417,17 +417,74 @@ impl fmt::Display for IntoInnerError { } } -/// Wraps a Writer and buffers output to it, flushing whenever a newline +/// Wraps a writer and buffers output to it, flushing whenever a newline /// (`0x0a`, `'\n'`) is detected. /// -/// The buffer will be written out when the writer is dropped. +/// The [`BufWriter`][bufwriter] struct wraps a writer and buffers its output. +/// But it only does this batched write when it goes out of scope, or when the +/// internal buffer is full. Sometimes, you'd prefer to write each line as it's +/// completed, rather than the entire buffer at once. Enter `LineWriter`. It +/// does exactly that. +/// +/// [bufwriter]: struct.BufWriter.html +/// +/// If there's still a partial line in the buffer when the `LineWriter` is +/// dropped, it will flush those contents. +/// +/// # Examples +/// +/// We can use `LineWriter` to write one line at a time, significantly +/// reducing the number of actual writes to the file. +/// +/// ``` +/// use std::fs::File; +/// use std::io::prelude::*; +/// use std::io::LineWriter; +/// +/// # fn foo() -> std::io::Result<()> { +/// let road_not_taken = b"I shall be telling this with a sigh +/// Somewhere ages and ages hence: +/// Two roads diverged in a wood, and I - +/// I took the one less traveled by, +/// And that has made all the difference."; +/// +/// let file = try!(File::create("poem.txt")); +/// let mut file = LineWriter::new(file); +/// +/// for &byte in road_not_taken.iter() { +/// file.write(&[byte]).unwrap(); +/// } +/// +/// // let's check we did the right thing. +/// let mut file = try!(File::open("poem.txt")); +/// let mut contents = String::new(); +/// +/// try!(file.read_to_string(&mut contents)); +/// +/// assert_eq!(contents.as_bytes(), &road_not_taken[..]); +/// # Ok(()) +/// # } +/// ``` #[stable(feature = "rust1", since = "1.0.0")] pub struct LineWriter { inner: BufWriter, } impl LineWriter { - /// Creates a new `LineWriter` + /// Creates a new `LineWriter`. + /// + /// # Examples + /// + /// ``` + /// use std::fs::File; + /// use std::io::LineWriter; + /// + /// # fn foo() -> std::io::Result<()> { + /// let file = try!(File::create("poem.txt")); + /// let file = LineWriter::new(file); + /// # Ok(()) + /// # } + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn new(inner: W) -> LineWriter { // Lines typically aren't that long, don't use a giant buffer @@ -436,12 +493,40 @@ impl LineWriter { /// Creates a new `LineWriter` with a specified capacity for the internal /// buffer. + /// + /// # Examples + /// + /// ``` + /// use std::fs::File; + /// use std::io::LineWriter; + /// + /// # fn foo() -> std::io::Result<()> { + /// let file = try!(File::create("poem.txt")); + /// let file = LineWriter::with_capacity(100, file); + /// # Ok(()) + /// # } + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn with_capacity(cap: usize, inner: W) -> LineWriter { LineWriter { inner: BufWriter::with_capacity(cap, inner) } } /// Gets a reference to the underlying writer. + /// + /// # Examples + /// + /// ``` + /// use std::fs::File; + /// use std::io::LineWriter; + /// + /// # fn foo() -> std::io::Result<()> { + /// let file = try!(File::create("poem.txt")); + /// let file = LineWriter::new(file); + /// + /// let reference = file.get_ref(); + /// # Ok(()) + /// # } + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn get_ref(&self) -> &W { self.inner.get_ref() } @@ -449,12 +534,45 @@ impl LineWriter { /// /// Caution must be taken when calling methods on the mutable reference /// returned as extra writes could corrupt the output stream. + /// + /// # Examples + /// + /// ``` + /// use std::fs::File; + /// use std::io::prelude::*; + /// use std::io::LineWriter; + /// + /// # fn foo() -> std::io::Result<()> { + /// let file = try!(File::create("poem.txt")); + /// let mut file = LineWriter::new(file); + /// + /// // we can use reference just like file + /// let reference = file.get_mut(); + /// # Ok(()) + /// # } + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn get_mut(&mut self) -> &mut W { self.inner.get_mut() } /// Unwraps this `LineWriter`, returning the underlying writer. /// /// The internal buffer is written out before returning the writer. + /// + /// # Examples + /// + /// ``` + /// use std::fs::File; + /// use std::io::LineWriter; + /// + /// # fn foo() -> std::io::Result<()> { + /// let file = try!(File::create("poem.txt")); + /// + /// let writer: LineWriter = LineWriter::new(file); + /// + /// let file: File = try!(writer.into_inner()); + /// # Ok(()) + /// # } + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn into_inner(self) -> Result>> { self.inner.into_inner().map_err(|IntoInnerError(buf, e)| { From 2e919b4c5107a584ffcf58e4b39a001275845fec Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 17 Jul 2015 17:21:58 +0200 Subject: [PATCH 27/37] Add E0433 error explanation --- src/librustc_resolve/diagnostics.rs | 54 ++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 13 deletions(-) diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 96bc3576a94fa..21a950060947b 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -272,7 +272,7 @@ See the 'Use Declarations' section of the reference for more information on this topic: http://doc.rust-lang.org/reference.html#use-declarations -"## +"##, E0403: r##" Some type parameters have the same name. Example of erroneous code: @@ -282,7 +282,7 @@ fn foo(s: T, u: T) {} // error: the name `T` is already used for a type // parameter in this type parameter list ``` -Please verify that none of the type params are misspelled, and rename any +Please verify that none of the type parameterss are misspelled, and rename any clashing parameters. Example: ``` @@ -291,8 +291,8 @@ fn foo(s: T, u: Y) {} // ok! "##, E0404: r##" -You tried to implement a non-trait object on an object. Example of erroneous -code: +You tried to implement something which was not a trait on an object. Example of +erroneous code: ``` struct Foo; @@ -301,8 +301,8 @@ struct Bar; impl Foo for Bar {} // error: `Foo` is not a trait ``` -Please verify you didn't mispelled the trait's name or used the wrong object. -Example: +Please verify that you didn't misspell the trait's name or otherwise use the +wrong identifier. Example: ``` trait Foo { @@ -317,7 +317,7 @@ impl Foo for Bar { // ok! "##, E0405: r##" -A non-trait was implemented. Example of erroneous code: +An unknown trait was implemented. Example of erroneous code: ``` struct Foo; @@ -346,8 +346,8 @@ impl SomeTrait for Foo { // ok! "##, E0407: r##" -A definition of a method not in the implemented trait was given. Example of -erroneous code: +A definition of a method not in the implemented trait was given in a trait +implementation. Example of erroneous code: ``` trait Foo { @@ -362,8 +362,8 @@ impl Foo for Bar { } ``` -Please verify you didn't mispelled the method name and you used the good -trait. Example: +Please verify you didn't misspell the method name and you used the correct +trait. First example: ``` trait Foo { @@ -378,6 +378,24 @@ impl Foo for Bar { fn b() {} // ok! } ``` + +Second example: + +``` +trait Foo { + fn a(); +} + +struct Bar; + +impl Foo for Bar { + fn a() {} +} + +impl Bar { + fn b() {} +} +``` "##, E0428: r##" @@ -389,7 +407,7 @@ struct Bar; struct Bar; // error: duplicate definition of value `Bar` ``` -Please verify you didn't mispelled the type/module's name or remove the +Please verify you didn't misspell the type/module's name or remove/rename the duplicated one. Example: ``` @@ -398,6 +416,17 @@ struct Bar2; // ok! ``` "##, +E0433: r##" +Invalid import. Example of erroneous code: + +``` +use something_which_doesnt_exist; +// error: unresolved import `something_which_doesnt_exist` +``` + +Please verify you didn't misspell the import's name. +"##, + } register_diagnostics! { @@ -438,7 +467,6 @@ register_diagnostics! { E0431, // `self` import can only appear in an import list with a non-empty // prefix E0432, // unresolved import - E0433, // failed to resolve E0434, // can't capture dynamic environment in a fn item E0435, // attempt to use a non-constant value in a constant E0437, // type is not a member of trait From e6c058e18c7a63e831a98b41d0d9df0e0c4901b4 Mon Sep 17 00:00:00 2001 From: Aidan Hobson Sayers Date: Thu, 21 May 2015 16:45:38 +0100 Subject: [PATCH 28/37] Rename 'link-args' to 'advanced-linking', add intro --- src/doc/trpl/SUMMARY.md | 2 +- .../trpl/{link-args.md => advanced-linking.md} | 15 +++++++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) rename src/doc/trpl/{link-args.md => advanced-linking.md} (62%) diff --git a/src/doc/trpl/SUMMARY.md b/src/doc/trpl/SUMMARY.md index ca3381ffba465..f1e51591aea0e 100644 --- a/src/doc/trpl/SUMMARY.md +++ b/src/doc/trpl/SUMMARY.md @@ -63,7 +63,7 @@ * [No stdlib](no-stdlib.md) * [Intrinsics](intrinsics.md) * [Lang items](lang-items.md) - * [Link args](link-args.md) + * [Advanced linking](advanced-linking.md) * [Benchmark Tests](benchmark-tests.md) * [Box Syntax and Patterns](box-syntax-and-patterns.md) * [Slice Patterns](slice-patterns.md) diff --git a/src/doc/trpl/link-args.md b/src/doc/trpl/advanced-linking.md similarity index 62% rename from src/doc/trpl/link-args.md rename to src/doc/trpl/advanced-linking.md index cdaef6cd9b510..f54799d9e4a38 100644 --- a/src/doc/trpl/link-args.md +++ b/src/doc/trpl/advanced-linking.md @@ -1,6 +1,13 @@ -% Link args +% Advanced Linking -There is one other way to tell rustc how to customize linking, and that is via +The common cases of linking with Rust have been covered earlier in this book, +but supporting the range of linking possibilities made available by other +languages is important for Rust to achieve seamless interaction with native +libraries. + +# Link args + +There is one other way to tell `rustc` how to customize linking, and that is via the `link_args` attribute. This attribute is applied to `extern` blocks and specifies raw flags which need to get passed to the linker when producing an artifact. An example usage would be: @@ -14,9 +21,9 @@ extern {} ``` Note that this feature is currently hidden behind the `feature(link_args)` gate -because this is not a sanctioned way of performing linking. Right now rustc +because this is not a sanctioned way of performing linking. Right now `rustc` shells out to the system linker, so it makes sense to provide extra command line -arguments, but this will not always be the case. In the future rustc may use +arguments, but this will not always be the case. In the future `rustc` may use LLVM directly to link native libraries, in which case `link_args` will have no meaning. From e5c1884c26cf41a338e903ec60f58bdad49af886 Mon Sep 17 00:00:00 2001 From: Aidan Hobson Sayers Date: Thu, 21 May 2015 16:47:41 +0100 Subject: [PATCH 29/37] Note possiblities of empty extern blocks (based on #12575) --- src/doc/reference.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/doc/reference.md b/src/doc/reference.md index a37e1c146681e..26fd2fd8d20d6 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -1636,6 +1636,10 @@ The type of a function declared in an extern block is `extern "abi" fn(A1, ..., An) -> R`, where `A1...An` are the declared types of its arguments and `R` is the declared return type. +It is valid to add the `link` attribute on an empty extern block. You can use +this to satisfy the linking requirements of extern blocks elsewhere in your code +(including upstream crates) instead of adding the attribute to each extern block. + ## Visibility and Privacy These two terms are often used interchangeably, and what they are attempting to From e6d8434cb3a379d98e16d63ebde2168f03a28e24 Mon Sep 17 00:00:00 2001 From: Andrew Paseltiner Date: Mon, 20 Jul 2015 13:31:04 -0400 Subject: [PATCH 30/37] add test for #14382 closes #14382 --- src/test/run-pass/issue-14382.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 src/test/run-pass/issue-14382.rs diff --git a/src/test/run-pass/issue-14382.rs b/src/test/run-pass/issue-14382.rs new file mode 100644 index 0000000000000..cdb44f6a60675 --- /dev/null +++ b/src/test/run-pass/issue-14382.rs @@ -0,0 +1,24 @@ +// Copyright 2015 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. + +#[derive(Debug)] +struct Matrix4(S); +trait POrd {} + +fn translate>(s: S) -> Matrix4 { Matrix4(s) } + +impl POrd for f32 {} +impl POrd for f64 {} + +fn main() { + let x = 1.0; + let m : Matrix4 = translate(x); + println!("m: {:?}", m); +} From a5c7b96426cbddc1276ab4439ed2cc4a5689abc2 Mon Sep 17 00:00:00 2001 From: Ticki <@> Date: Tue, 21 Jul 2015 21:36:29 +0200 Subject: [PATCH 31/37] Add info about usage of 'unsafe' keyword in bindings to foreign interfaces. --- src/doc/trpl/unsafe.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/doc/trpl/unsafe.md b/src/doc/trpl/unsafe.md index 80b0c87473fa2..897795e91533e 100644 --- a/src/doc/trpl/unsafe.md +++ b/src/doc/trpl/unsafe.md @@ -100,10 +100,14 @@ that you normally can not do. Just three. Here they are: That’s it. It’s important that `unsafe` does not, for example, ‘turn off the borrow checker’. Adding `unsafe` to some random Rust code doesn’t change its -semantics, it won’t just start accepting anything. +semantics, it won’t just start accepting anything. But it will let you write +things that _do_ break some of the rules. -But it will let you write things that _do_ break some of the rules. Let’s go -over these three abilities in order. +You will also encounter the 'unsafe' keyword when writing bindings to foreign +(non-Rust) interfaces. You're encouraged to write a safe, native Rust interface +around the methods provided by the library. + +Let’s go over the basic three abilities listed, in order. ## Access or update a `static mut` From 48870d4f05177aa8e4d8439b71f39283f1880327 Mon Sep 17 00:00:00 2001 From: Ticki <@> Date: Tue, 21 Jul 2015 21:40:11 +0200 Subject: [PATCH 32/37] rust -> Rust --- src/doc/trpl/ffi.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/doc/trpl/ffi.md b/src/doc/trpl/ffi.md index cbedf86371414..753a5a32e8a1b 100644 --- a/src/doc/trpl/ffi.md +++ b/src/doc/trpl/ffi.md @@ -340,7 +340,7 @@ libraries: Note that frameworks are only available on OSX targets. The different `kind` values are meant to differentiate how the native library -participates in linkage. From a linkage perspective, the rust compiler creates +participates in linkage. From a linkage perspective, the Rust compiler creates two flavors of artifacts: partial (rlib/staticlib) and final (dylib/binary). Native dynamic library and framework dependencies are propagated to the final artifact boundary, while static library dependencies are not propagated at @@ -350,9 +350,9 @@ artifact. A few examples of how this model can be used are: * A native build dependency. Sometimes some C/C++ glue is needed when writing - some rust code, but distribution of the C/C++ code in a library format is just + some Rust code, but distribution of the C/C++ code in a library format is just a burden. In this case, the code will be archived into `libfoo.a` and then the - rust crate would declare a dependency via `#[link(name = "foo", kind = + Rust crate would declare a dependency via `#[link(name = "foo", kind = "static")]`. Regardless of the flavor of output for the crate, the native static library @@ -361,7 +361,7 @@ A few examples of how this model can be used are: * A normal dynamic dependency. Common system libraries (like `readline`) are available on a large number of systems, and often a static copy of these - libraries cannot be found. When this dependency is included in a rust crate, + libraries cannot be found. When this dependency is included in a Rust crate, partial targets (like rlibs) will not link to the library, but when the rlib is included in a final target (like a binary), the native library will be linked in. From cf1e078bf65899f466ebe07d29732979a845a718 Mon Sep 17 00:00:00 2001 From: Ticki Date: Tue, 21 Jul 2015 22:09:29 +0200 Subject: [PATCH 33/37] Klabnik nit-picks ;) --- src/doc/trpl/unsafe.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/trpl/unsafe.md b/src/doc/trpl/unsafe.md index 897795e91533e..1b223365bd63a 100644 --- a/src/doc/trpl/unsafe.md +++ b/src/doc/trpl/unsafe.md @@ -103,7 +103,7 @@ borrow checker’. Adding `unsafe` to some random Rust code doesn’t change its semantics, it won’t just start accepting anything. But it will let you write things that _do_ break some of the rules. -You will also encounter the 'unsafe' keyword when writing bindings to foreign +You will also encounter the `unsafe` keyword when writing bindings to foreign (non-Rust) interfaces. You're encouraged to write a safe, native Rust interface around the methods provided by the library. From 7af865b33348730aacc02afeb3233cf8d90bb1f2 Mon Sep 17 00:00:00 2001 From: Aidan Hobson Sayers Date: Thu, 21 May 2015 19:55:51 +0100 Subject: [PATCH 34/37] Static linking --- src/doc/trpl/advanced-linking.md | 127 +++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) diff --git a/src/doc/trpl/advanced-linking.md b/src/doc/trpl/advanced-linking.md index f54799d9e4a38..ea5238c381466 100644 --- a/src/doc/trpl/advanced-linking.md +++ b/src/doc/trpl/advanced-linking.md @@ -30,3 +30,130 @@ meaning. It is highly recommended to *not* use this attribute, and rather use the more formal `#[link(...)]` attribute on `extern` blocks instead. +# Static linking + +Static linking refers to the process of creating output that contain all +required libraries and so don't need libraries installed on every system where +you want to use your compiled project. Pure-Rust dependencies are statically +linked by default so you can use created binaries and libraries without +installing the Rust everywhere. By contrast, native libraries +(e.g. `libc` and `libm`) usually dynamically linked, but it is possible to +change this and statically link them as well. + +Linking is a very platform dependent topic - on some platforms, static linking +may not be possible at all! This section assumes some basic familiarity with +linking on your platform on choice. + +## Linux + +By default, all Rust programs on Linux will link to the system `libc` along with +a number of other libraries. Let's look at an example on a 64-bit linux machine +with GCC and `glibc` (by far the most common `libc` on Linux): + +``` text +$ cat example.rs +fn main() {} +$ rustc example.rs +$ ldd example + linux-vdso.so.1 => (0x00007ffd565fd000) + libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fa81889c000) + libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fa81867e000) + librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007fa818475000) + libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fa81825f000) + libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa817e9a000) + /lib64/ld-linux-x86-64.so.2 (0x00007fa818cf9000) + libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fa817b93000) +``` + +Dynamic linking on Linux can be undesirable if you wish to use new library +features on old systems or target systems which do not have the required +dependencies for your program to run. + +The first step in using static linking is examining the Rust linking arguments +with an option to rustc. Newlines have been added for readability: + +``` text +$ rustc example.rs -Z print-link-args +"cc" + "-Wl,--as-needed" + "-m64" + [...] + "-o" "example" + "example.o" + "-Wl,--whole-archive" "-lmorestack" "-Wl,--no-whole-archive" + "-Wl,--gc-sections" + "-pie" + "-nodefaultlibs" + [...] + "-Wl,--whole-archive" "-Wl,-Bstatic" + "-Wl,--no-whole-archive" "-Wl,-Bdynamic" + "-ldl" "-lpthread" "-lrt" "-lgcc_s" "-lpthread" "-lc" "-lm" "-lcompiler-rt" +``` + +Arguments with a `-L` before them set up the linker search path and arguments +ending with `.rlib` are linking Rust crates statically into your application. +Neither of these are relevent for static linking so have been ommitted. + +The first step in being able to statically link is to obtain an object file. +This can be achieved with `rustc --emit obj example.rs`, and creates a file +called `example.o`, which you can see being passed in the command line above - +rustc automatically deletes it when finished with it by default. As you now have +the object file, you should be able to run the link command obtained with +`print-link-args` to create perform the linking stage yourself. + +In order to statically link, there are a number of changes you must make. Below +is the command required to perform a static link; we will go through them each +in turn. + +``` text +$ rustc example.rs -Z print-link-args +"cc" + "-static" + "-m64" + [...] + "-o" "example" + "example.o" + "-Wl,--whole-archive" "-lmorestack" "-Wl,--no-whole-archive" + "-Wl,--gc-sections" + "-nodefaultlibs" + [...] + "-Wl,--whole-archive" + "-Wl,--no-whole-archive" + "-ldl" "-lpthread" "-lrt" "-lgcc_eh" "-lpthread" "-lc" "-lm" "-lcompiler-rt" +``` + + - `-static` was added - this is the signal to the compiler to use a static + glibc, among other things + - `-Wl,--as-needed` was removed - this can be left in, but is unnecessary + as it only applies to dynamic librares + - `-pie` was removed - this is not compatible with static binaries + - both `-Wl,-B*` options were removed - everything will be linked statically, + so informing the linker of how certain libraries should be linked is not + appropriate + - `-lgcc_s` was changed to `-lgcc_eh` - `gcc_s` is the GCC support library, + which Rust uses for unwinding support. This is only available as a dynamic + library, so we must specify the static version of the library providing + unwinding support. + +By running this command, you will likely see some warnings like + +``` text +warning: Using 'getpwuid_r' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking +``` + +These should be considered carefully! They indicate calls in glibc which +*cannot* be statically linked without significant extra effort. An application +using these calls will find it is not as portable as 'static binary' would imply. +Rust supports targeting musl as an alternative libc to be able to fully +statically link these calls. + +As we are confident that our code does not use these calls, we can now see the +fruits of our labour: + +``` +$ ldd example + not a dynamic executable +``` + +This binary can be copied to virtually any 64-bit Linux machine and work +without requiring external libraries. From 692a2d55662d14ba78ffb6f8dfe0be771170c822 Mon Sep 17 00:00:00 2001 From: Aidan Hobson Sayers Date: Mon, 15 Jun 2015 18:54:37 +0100 Subject: [PATCH 35/37] musl static linking not glibc --- src/doc/trpl/advanced-linking.md | 146 ++++++++++++++----------------- 1 file changed, 68 insertions(+), 78 deletions(-) diff --git a/src/doc/trpl/advanced-linking.md b/src/doc/trpl/advanced-linking.md index ea5238c381466..fdc1afa02ab59 100644 --- a/src/doc/trpl/advanced-linking.md +++ b/src/doc/trpl/advanced-linking.md @@ -40,14 +40,14 @@ installing the Rust everywhere. By contrast, native libraries (e.g. `libc` and `libm`) usually dynamically linked, but it is possible to change this and statically link them as well. -Linking is a very platform dependent topic - on some platforms, static linking +Linking is a very platform dependent topic — on some platforms, static linking may not be possible at all! This section assumes some basic familiarity with -linking on your platform on choice. +linking on your platform of choice. ## Linux By default, all Rust programs on Linux will link to the system `libc` along with -a number of other libraries. Let's look at an example on a 64-bit linux machine +a number of other libraries. Let's look at an example on a 64-bit Linux machine with GCC and `glibc` (by far the most common `libc` on Linux): ``` text @@ -69,91 +69,81 @@ Dynamic linking on Linux can be undesirable if you wish to use new library features on old systems or target systems which do not have the required dependencies for your program to run. -The first step in using static linking is examining the Rust linking arguments -with an option to rustc. Newlines have been added for readability: +Static linking is supported via an alternative `libc`, `musl` - this must be +enabled at Rust compile-time with some prerequisites available. You can compile +your own version of Rust with `musl` enabled and install it into a custom +directory with the instructions below: -``` text -$ rustc example.rs -Z print-link-args -"cc" - "-Wl,--as-needed" - "-m64" - [...] - "-o" "example" - "example.o" - "-Wl,--whole-archive" "-lmorestack" "-Wl,--no-whole-archive" - "-Wl,--gc-sections" - "-pie" - "-nodefaultlibs" - [...] - "-Wl,--whole-archive" "-Wl,-Bstatic" - "-Wl,--no-whole-archive" "-Wl,-Bdynamic" - "-ldl" "-lpthread" "-lrt" "-lgcc_s" "-lpthread" "-lc" "-lm" "-lcompiler-rt" ``` - -Arguments with a `-L` before them set up the linker search path and arguments -ending with `.rlib` are linking Rust crates statically into your application. -Neither of these are relevent for static linking so have been ommitted. - -The first step in being able to statically link is to obtain an object file. -This can be achieved with `rustc --emit obj example.rs`, and creates a file -called `example.o`, which you can see being passed in the command line above - -rustc automatically deletes it when finished with it by default. As you now have -the object file, you should be able to run the link command obtained with -`print-link-args` to create perform the linking stage yourself. - -In order to statically link, there are a number of changes you must make. Below -is the command required to perform a static link; we will go through them each -in turn. - -``` text -$ rustc example.rs -Z print-link-args -"cc" - "-static" - "-m64" - [...] - "-o" "example" - "example.o" - "-Wl,--whole-archive" "-lmorestack" "-Wl,--no-whole-archive" - "-Wl,--gc-sections" - "-nodefaultlibs" - [...] - "-Wl,--whole-archive" - "-Wl,--no-whole-archive" - "-ldl" "-lpthread" "-lrt" "-lgcc_eh" "-lpthread" "-lc" "-lm" "-lcompiler-rt" +$ mkdir musldist +$ PREFIX=$(pwd)/musldist +$ +$ # Build musl +$ wget http://www.musl-libc.org/releases/musl-1.1.10.tar.gz +[...] +$ tar xf musl-1.1.10.tar.gz +$ cd musl-1.1.10/ +musl-1.1.10 $ ./configure --disable-shared --prefix=$PREFIX +[...] +musl-1.1.10 $ make +[...] +musl-1.1.10 $ make install +[...] +musl-1.1.10 $ cd .. +$ du -h musldist/lib/libc.a +2.2M musldist/lib/libc.a +$ +$ # Build libunwind.a +$ wget http://llvm.org/releases/3.6.1/llvm-3.6.1.src.tar.xz +$ tar xf llvm-3.6.1.src.tar.xz +$ cd llvm-3.6.1.src/projects/ +llvm-3.6.1.src/projects $ svn co http://llvm.org/svn/llvm-project/libcxxabi/trunk/ libcxxabi +llvm-3.6.1.src/projects $ svn co http://llvm.org/svn/llvm-project/libunwind/trunk/ libunwind +llvm-3.6.1.src/projects $ sed -i 's#^\(include_directories\).*$#\0\n\1(../libcxxabi/include)#' libunwind/CMakeLists.txt +llvm-3.6.1.src/projects $ mkdir libunwind/build +llvm-3.6.1.src/projects $ cd libunwind/build +llvm-3.6.1.src/projects/libunwind/build $ cmake -DLLVM_PATH=../../.. -DLIBUNWIND_ENABLE_SHARED=0 .. +llvm-3.6.1.src/projects/libunwind/build $ make +llvm-3.6.1.src/projects/libunwind/build $ cp lib/libunwind.a $PREFIX/lib/ +llvm-3.6.1.src/projects/libunwind/build $ cd cd ../../../../ +$ du -h musldist/lib/libunwind.a +164K musldist/lib/libunwind.a +$ +$ # Build musl-enabled rust +$ git clone https://github.com/rust-lang/rust.git muslrust +$ cd muslrust +muslrust $ ./configure --target=x86_64-unknown-linux-musl --musl-root=$PREFIX --prefix=$PREFIX +muslrust $ make +muslrust $ make install +muslrust $ cd .. +$ du -h musldist/bin/rustc +12K musldist/bin/rustc ``` - - `-static` was added - this is the signal to the compiler to use a static - glibc, among other things - - `-Wl,--as-needed` was removed - this can be left in, but is unnecessary - as it only applies to dynamic librares - - `-pie` was removed - this is not compatible with static binaries - - both `-Wl,-B*` options were removed - everything will be linked statically, - so informing the linker of how certain libraries should be linked is not - appropriate - - `-lgcc_s` was changed to `-lgcc_eh` - `gcc_s` is the GCC support library, - which Rust uses for unwinding support. This is only available as a dynamic - library, so we must specify the static version of the library providing - unwinding support. - -By running this command, you will likely see some warnings like +You now have a build of a `musl`-enabled Rust! Because we've installed it to a +custom prefix we need to make sure our system can the binaries and appropriate +libraries when we try and run it: -``` text -warning: Using 'getpwuid_r' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking +``` +$ export PATH=$PREFIX/bin:$PATH +$ export LD_LIBRARY_PATH=$PREFIX/lib:$LD_LIBRARY_PATH ``` -These should be considered carefully! They indicate calls in glibc which -*cannot* be statically linked without significant extra effort. An application -using these calls will find it is not as portable as 'static binary' would imply. -Rust supports targeting musl as an alternative libc to be able to fully -statically link these calls. - -As we are confident that our code does not use these calls, we can now see the -fruits of our labour: +Let's try it out! ``` +$ echo 'fn main() { println!("hi!"); panic!("failed"); }' > example.rs +$ rustc --target=x86_64-unknown-linux-musl example.rs $ ldd example not a dynamic executable +$ ./example +hi! +thread '
' panicked at 'failed', example.rs:1 ``` -This binary can be copied to virtually any 64-bit Linux machine and work -without requiring external libraries. +Success! This binary can be copied to almost any Linux machine with the same +machine architecture and run without issues. + +`cargo build` also permits the `--target` option so you should be able to build +your crates as normal. However, you may need to recompile your native libraries +against `musl` before they can be linked against. From 231438a0644adf55460647d0993fe259896792d5 Mon Sep 17 00:00:00 2001 From: Aidan Hobson Sayers Date: Mon, 15 Jun 2015 18:58:28 +0100 Subject: [PATCH 36/37] Additional notes to link-args --- src/doc/trpl/advanced-linking.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/doc/trpl/advanced-linking.md b/src/doc/trpl/advanced-linking.md index fdc1afa02ab59..affa98915637f 100644 --- a/src/doc/trpl/advanced-linking.md +++ b/src/doc/trpl/advanced-linking.md @@ -22,10 +22,12 @@ extern {} Note that this feature is currently hidden behind the `feature(link_args)` gate because this is not a sanctioned way of performing linking. Right now `rustc` -shells out to the system linker, so it makes sense to provide extra command line +shells out to the system linker (`gcc` on most systems, `link.exe` on MSVC), +so it makes sense to provide extra command line arguments, but this will not always be the case. In the future `rustc` may use LLVM directly to link native libraries, in which case `link_args` will have no -meaning. +meaning. You can achieve the same effect as the `link-args` attribute with the +`-C link-args` argument to `rustc`. It is highly recommended to *not* use this attribute, and rather use the more formal `#[link(...)]` attribute on `extern` blocks instead. From 18f115c2bbc68419bc83677c3875c91b5428cf8e Mon Sep 17 00:00:00 2001 From: Andrew Paseltiner Date: Tue, 21 Jul 2015 16:58:26 -0400 Subject: [PATCH 37/37] update compile-fail test for #21174 to account for #27127 --- src/test/compile-fail/issue-21174.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/compile-fail/issue-21174.rs b/src/test/compile-fail/issue-21174.rs index ec258449cb161..30fd2eb4d2f9a 100644 --- a/src/test/compile-fail/issue-21174.rs +++ b/src/test/compile-fail/issue-21174.rs @@ -15,7 +15,7 @@ trait Trait<'a> { fn foo<'a, T: Trait<'a>>(value: T::A) { let new: T::B = unsafe { std::mem::transmute(value) }; -//~^ ERROR: cannot transmute to or from a type that contains type parameters in its interior [E0139] +//~^ ERROR: cannot transmute to or from a type that contains unsubstituted type parameters [E0139] } fn main() { }