From e1b77b07099a8c60a9f83550ca413cb75f186010 Mon Sep 17 00:00:00 2001 From: Nafis Date: Sat, 6 Dec 2014 08:17:49 +1000 Subject: [PATCH 01/29] fix 404 --- src/doc/guide.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/guide.md b/src/doc/guide.md index c2d43a20ec46c..916898de459f7 100644 --- a/src/doc/guide.md +++ b/src/doc/guide.md @@ -3681,8 +3681,8 @@ Here's the second note, which lets us know where the first borrow would be over. This is useful, because if we wait to try to borrow `x` after this borrow is over, then everything will work. -For more advanced patterns, please consult the [Lifetime -Guide](guide-lifetimes.html). You'll also learn what this type signature with +For more advanced patterns, please consult the [Ownership +Guide](guide-ownership.html). You'll also learn what this type signature with the `'a` syntax is: ```{rust,ignore} From 7bf7bd6a75c38ed71df69cb9149eb7fdce23ced5 Mon Sep 17 00:00:00 2001 From: Aidan Cully Date: Fri, 5 Dec 2014 17:20:44 -0500 Subject: [PATCH 02/29] work around portability issue on FreeBSD, in which the key returned from pthread_key_create can be 0. --- src/libstd/sys/common/thread_local.rs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/libstd/sys/common/thread_local.rs b/src/libstd/sys/common/thread_local.rs index 370d74cc5e189..b33e74248d275 100644 --- a/src/libstd/sys/common/thread_local.rs +++ b/src/libstd/sys/common/thread_local.rs @@ -185,7 +185,23 @@ impl StaticKey { } unsafe fn lazy_init(&self) -> uint { - let key = imp::create(self.dtor); + // POSIX allows the key created here to be 0, but the compare_and_swap + // below relies on using 0 as a sentinel value to check who won the + // race to set the shared TLS key. As far as I know, there is no + // guaranteed value that cannot be returned as a posix_key_create key, + // so there is no value we can initialize the inner key with to + // prove that it has not yet been set. As such, we'll continue using a + // value of 0, but with some gyrations to make sure we have a non-0 + // value returned from the creation routine. + // TODO: this is clearly a hack, and should be cleaned up. + let key1 = imp::create(self.dtor); + let key = if key1 != 0 { + key1 + } else { + let key2 = imp::create(self.dtor); + imp::destroy(key1); + key2 + }; assert!(key != 0); match self.inner.key.compare_and_swap(0, key as uint, atomic::SeqCst) { // The CAS succeeded, so we've created the actual key From c394a6c238a2e981f9092e142029ec5b465c1dcd Mon Sep 17 00:00:00 2001 From: Aidan Cully Date: Fri, 5 Dec 2014 18:39:58 -0500 Subject: [PATCH 03/29] prefer "FIXME" to "TODO". --- src/libstd/sys/common/thread_local.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/sys/common/thread_local.rs b/src/libstd/sys/common/thread_local.rs index b33e74248d275..3eb0e3f46cb90 100644 --- a/src/libstd/sys/common/thread_local.rs +++ b/src/libstd/sys/common/thread_local.rs @@ -193,7 +193,7 @@ impl StaticKey { // prove that it has not yet been set. As such, we'll continue using a // value of 0, but with some gyrations to make sure we have a non-0 // value returned from the creation routine. - // TODO: this is clearly a hack, and should be cleaned up. + // FIXME: this is clearly a hack, and should be cleaned up. let key1 = imp::create(self.dtor); let key = if key1 != 0 { key1 From 8ebc1c9fd88640b1833e0743b649a957f3337720 Mon Sep 17 00:00:00 2001 From: Luqman Aden Date: Fri, 5 Dec 2014 18:35:16 -0500 Subject: [PATCH 04/29] librustc: Fix debuginfo for captured variables in non-FnOnce unboxed closures. --- src/librustc_trans/trans/closure.rs | 4 +- src/librustc_trans/trans/debuginfo.rs | 6 ++- .../var-captured-in-stack-closure.rs | 49 ++++++++++++++++--- 3 files changed, 48 insertions(+), 11 deletions(-) diff --git a/src/librustc_trans/trans/closure.rs b/src/librustc_trans/trans/closure.rs index bb4df00bd944a..106c272a779b6 100644 --- a/src/librustc_trans/trans/closure.rs +++ b/src/librustc_trans/trans/closure.rs @@ -286,7 +286,6 @@ fn load_environment<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, debuginfo::create_captured_var_metadata( bcx, def_id.node, - cdata_ty, env_pointer_alloca, i, captured_by_ref, @@ -326,7 +325,7 @@ fn load_unboxed_closure_environment<'blk, 'tcx>( // Store the pointer to closure data in an alloca for debug info because that's what the // llvm.dbg.declare intrinsic expects let env_pointer_alloca = if bcx.sess().opts.debuginfo == FullDebugInfo { - let alloc = alloc_ty(bcx, ty::mk_mut_ptr(bcx.tcx(), self_type), "__debuginfo_env_ptr"); + let alloc = alloca(bcx, val_ty(llenv), "__debuginfo_env_ptr"); Store(bcx, llenv, alloc); Some(alloc) } else { @@ -355,7 +354,6 @@ fn load_unboxed_closure_environment<'blk, 'tcx>( debuginfo::create_captured_var_metadata( bcx, def_id.node, - self_type, env_pointer_alloca, i, captured_by_ref, diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs index 555cb0004892f..09cfbde43e507 100644 --- a/src/librustc_trans/trans/debuginfo.rs +++ b/src/librustc_trans/trans/debuginfo.rs @@ -882,7 +882,6 @@ pub fn create_local_var_metadata(bcx: Block, local: &ast::Local) { /// Adds the created metadata nodes directly to the crate's IR. pub fn create_captured_var_metadata<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, node_id: ast::NodeId, - env_data_type: Ty<'tcx>, env_pointer: ValueRef, env_index: uint, captured_by_ref: bool, @@ -928,7 +927,10 @@ pub fn create_captured_var_metadata<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let variable_type = node_id_type(bcx, node_id); let scope_metadata = bcx.fcx.debug_context.get_ref(cx, span).fn_metadata; - let llvm_env_data_type = type_of::type_of(cx, env_data_type); + // env_pointer is the alloca containing the pointer to the environment, + // so it's type is **EnvironmentType. In order to find out the type of + // the environment we have to "dereference" two times. + let llvm_env_data_type = val_ty(env_pointer).element_type().element_type(); let byte_offset_of_var_in_env = machine::llelement_offset(cx, llvm_env_data_type, env_index); diff --git a/src/test/debuginfo/var-captured-in-stack-closure.rs b/src/test/debuginfo/var-captured-in-stack-closure.rs index 92a3d358f5c74..761d0f0be8f58 100644 --- a/src/test/debuginfo/var-captured-in-stack-closure.rs +++ b/src/test/debuginfo/var-captured-in-stack-closure.rs @@ -28,6 +28,19 @@ // gdb-command:print *owned // gdb-check:$5 = 6 +// gdb-command:continue + +// gdb-command:print variable +// gdb-check:$6 = 2 +// gdb-command:print constant +// gdb-check:$7 = 2 +// gdb-command:print a_struct +// gdb-check:$8 = {a = -3, b = 4.5, c = 5} +// gdb-command:print *struct_ref +// gdb-check:$9 = {a = -3, b = 4.5, c = 5} +// gdb-command:print *owned +// gdb-check:$10 = 6 + // === LLDB TESTS ================================================================================== @@ -44,6 +57,20 @@ // lldb-command:print *owned // lldb-check:[...]$4 = 6 +// lldb-command:continue + +// lldb-command:print variable +// lldb-check:[...]$5 = 2 +// lldb-command:print constant +// lldb-check:[...]$6 = 2 +// lldb-command:print a_struct +// lldb-check:[...]$7 = Struct { a: -3, b: 4.5, c: 5 } +// lldb-command:print *struct_ref +// lldb-check:[...]$8 = Struct { a: -3, b: 4.5, c: 5 } +// lldb-command:print *owned +// lldb-check:[...]$9 = 6 + +#![feature(unboxed_closures)] #![allow(unused_variables)] struct Struct { @@ -65,12 +92,22 @@ fn main() { let struct_ref = &a_struct; let owned = box 6; - let closure = || { - zzz(); // #break - variable = constant + a_struct.a + struct_ref.a + *owned; - }; - - closure(); + { + let closure = || { + zzz(); // #break + variable = constant + a_struct.a + struct_ref.a + *owned; + }; + + closure(); + } + + { + let mut unboxed_closure = |&mut:| { + zzz(); // #break + variable = constant + a_struct.a + struct_ref.a + *owned; + }; + unboxed_closure(); + } } fn zzz() {()} From 363ed2f7adf8a1c17befda0a7d0a3bfbc3bdf435 Mon Sep 17 00:00:00 2001 From: Matt Windsor Date: Sat, 6 Dec 2014 00:30:03 +0000 Subject: [PATCH 05/29] Correct minor typos on the ownership guide. liftimes -> lifetimes --- src/doc/guide-ownership.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/doc/guide-ownership.md b/src/doc/guide-ownership.md index c1180f7e6a93a..06fe0652519e0 100644 --- a/src/doc/guide-ownership.md +++ b/src/doc/guide-ownership.md @@ -231,7 +231,7 @@ fn add_one(num: &int) -> int { Rust has a feature called 'lifetime elision,' which allows you to not write lifetime annotations in certain circumstances. This is one of them. Without -eliding the liftimes, `add_one` looks like this: +eliding the lifetimes, `add_one` looks like this: ```rust fn add_one<'a>(num: &'a int) -> int { @@ -254,7 +254,7 @@ This part _declares_ our lifetimes. This says that `add_one` has one lifetime, fn add_two<'a, 'b>(...) ``` -Then in our parameter list, we use the liftimes we've named: +Then in our parameter list, we use the lifetimes we've named: ```{rust,ignore} ...(num: &'a int) -> ... @@ -279,7 +279,7 @@ fn main() { } ``` -As you can see, `struct`s can also have liftimes. In a similar way to functions, +As you can see, `struct`s can also have lifetimes. In a similar way to functions, ```{rust} struct Foo<'a> { @@ -295,7 +295,7 @@ x: &'a int, # } ``` -uses it. So why do we need a liftime here? We need to ensure that any reference +uses it. So why do we need a lifetime here? We need to ensure that any reference to a `Foo` cannot outlive the reference to an `int` it contains. ## Thinking in scopes From 796e4b8a885b44342cad8363661069783d3b7fed Mon Sep 17 00:00:00 2001 From: mdinger Date: Fri, 5 Dec 2014 20:14:28 -0500 Subject: [PATCH 06/29] Typo --- src/doc/guide-ownership.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/doc/guide-ownership.md b/src/doc/guide-ownership.md index c1180f7e6a93a..1030802030fbe 100644 --- a/src/doc/guide-ownership.md +++ b/src/doc/guide-ownership.md @@ -93,7 +93,7 @@ must have a deallocation for each allocation. Rust handles this for you. It knows that our handle, `x`, is the owning reference to our box. Rust knows that `x` will go out of scope at the end of the block, and so it inserts a call to deallocate the memory at the end of the scope. Because the compiler does this -for us, it's impossible to forget. We always exaclty one deallocations paired +for us, it's impossible to forget. We always have exactly one deallocation paired with each of our allocations. This is pretty straightforward, but what happens when we want to pass our box @@ -186,11 +186,11 @@ This function takes ownership, because it takes a `Box`, which owns its contents. But then we give ownership right back. In the physical world, you can give one of your possessions to someone for a -short period of time. You still own your posession, you're just letting someone +short period of time. You still own your possession, you're just letting someone else use it for a while. We call that 'lending' something to someone, and that person is said to be 'borrowing' that something from you. -Rust's ownershp system also allows an owner to lend out a handle for a limited +Rust's ownership system also allows an owner to lend out a handle for a limited period. This is also called 'borrowing.' Here's a version of `add_one` which borrows its argument rather than taking ownership: @@ -231,7 +231,7 @@ fn add_one(num: &int) -> int { Rust has a feature called 'lifetime elision,' which allows you to not write lifetime annotations in certain circumstances. This is one of them. Without -eliding the liftimes, `add_one` looks like this: +eliding the lifetimes, `add_one` looks like this: ```rust fn add_one<'a>(num: &'a int) -> int { @@ -254,7 +254,7 @@ This part _declares_ our lifetimes. This says that `add_one` has one lifetime, fn add_two<'a, 'b>(...) ``` -Then in our parameter list, we use the liftimes we've named: +Then in our parameter list, we use the lifetimes we've named: ```{rust,ignore} ...(num: &'a int) -> ... @@ -279,7 +279,7 @@ fn main() { } ``` -As you can see, `struct`s can also have liftimes. In a similar way to functions, +As you can see, `struct`s can also have lifetimes. In a similar way to functions, ```{rust} struct Foo<'a> { @@ -295,7 +295,7 @@ x: &'a int, # } ``` -uses it. So why do we need a liftime here? We need to ensure that any reference +uses it. So why do we need a lifetime here? We need to ensure that any reference to a `Foo` cannot outlive the reference to an `int` it contains. ## Thinking in scopes From e8524198e3931373f5e097dece21e36d21c4a537 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Fri, 5 Dec 2014 15:53:30 -0800 Subject: [PATCH 07/29] Feature-gate explicit unboxed closure method calls & manual impls, detect UFCS drop and allow UFCS methods to have explicit type parameters. Work towards #18875. Since code could previously call the methods & implement the traits manually, this is a [breaking-change] Closes #19586. Closes #19375. --- src/libcore/lib.rs | 2 +- src/librustc_typeck/check/callee.rs | 46 +++++++++++++++++++ src/librustc_typeck/check/method/confirm.rs | 11 ++--- src/librustc_typeck/check/mod.rs | 13 +++++- src/librustc_typeck/coherence/mod.rs | 25 ++++++++++ src/librustc_typeck/diagnostics.rs | 6 ++- .../compile-fail/explicit-call-to-dtor.rs | 2 +- .../explicit-call-to-supertrait-dtor.rs | 2 +- ...ture-gate-unboxed-closures-manual-impls.rs | 26 +++++++++++ ...ture-gate-unboxed-closures-method-calls.rs | 19 ++++++++ ...eature-gate-unboxed-closures-ufcs-calls.rs | 19 ++++++++ src/test/compile-fail/illegal-ufcs-drop.rs | 20 ++++++++ src/test/run-pass/ufcs-type-params.rs | 22 +++++++++ 13 files changed, 199 insertions(+), 14 deletions(-) create mode 100644 src/librustc_typeck/check/callee.rs create mode 100644 src/test/compile-fail/feature-gate-unboxed-closures-manual-impls.rs create mode 100644 src/test/compile-fail/feature-gate-unboxed-closures-method-calls.rs create mode 100644 src/test/compile-fail/feature-gate-unboxed-closures-ufcs-calls.rs create mode 100644 src/test/compile-fail/illegal-ufcs-drop.rs create mode 100644 src/test/run-pass/ufcs-type-params.rs diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 5ad9462daf274..51bf7ba0a2aec 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -59,7 +59,7 @@ #![allow(unknown_features)] #![feature(globs, intrinsics, lang_items, macro_rules, phase)] #![feature(simd, unsafe_destructor, slicing_syntax)] -#![feature(default_type_params)] +#![feature(default_type_params, unboxed_closures)] #![deny(missing_docs)] mod macros; diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs new file mode 100644 index 0000000000000..ee93c896433a1 --- /dev/null +++ b/src/librustc_typeck/check/callee.rs @@ -0,0 +1,46 @@ +// Copyright 2014 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. + +use syntax::ast; +use syntax::codemap::Span; +use CrateCtxt; + +/// Check that it is legal to call methods of the trait corresponding +/// to `trait_id` (this only cares about the trait, not the specific +/// method that is called) +pub fn check_legal_trait_for_method_call(ccx: &CrateCtxt, span: Span, trait_id: ast::DefId) { + let tcx = ccx.tcx; + let did = Some(trait_id); + let li = &tcx.lang_items; + + if did == li.drop_trait() { + span_err!(tcx.sess, span, E0040, "explicit use of destructor method"); + } else if !tcx.sess.features.borrow().unboxed_closures { + // the #[feature(unboxed_closures)] feature isn't + // activated so we need to enforce the closure + // restrictions. + + let method = if did == li.fn_trait() { + "call" + } else if did == li.fn_mut_trait() { + "call_mut" + } else if did == li.fn_once_trait() { + "call_once" + } else { + return // not a closure method, everything is OK. + }; + + span_err!(tcx.sess, span, E0174, + "explicit use of unboxed closure method `{}` is experimental", + method); + span_help!(tcx.sess, span, + "add `#![feature(unboxed_closures)]` to the crate attributes to enable"); + } +} diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 1fe73f0478d56..b6a9e2cbc59ea 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -10,7 +10,7 @@ use super::probe; -use check::{mod, FnCtxt, NoPreference, PreferMutLvalue}; +use check::{mod, FnCtxt, NoPreference, PreferMutLvalue, callee}; use middle::subst::{mod, Subst}; use middle::traits; use middle::ty::{mod, Ty}; @@ -90,7 +90,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { let self_ty = self.adjust_self_ty(unadjusted_self_ty, &pick.adjustment); // Make sure nobody calls `drop()` explicitly. - self.enforce_drop_trait_limitations(&pick); + self.enforce_illegal_method_limitations(&pick); // Create substitutions for the method's type parameters. let (rcvr_substs, method_origin) = @@ -624,14 +624,11 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { self.fcx.infcx() } - fn enforce_drop_trait_limitations(&self, pick: &probe::Pick) { + fn enforce_illegal_method_limitations(&self, pick: &probe::Pick) { // Disallow calls to the method `drop` defined in the `Drop` trait. match pick.method_ty.container { ty::TraitContainer(trait_def_id) => { - if Some(trait_def_id) == self.tcx().lang_items.drop_trait() { - span_err!(self.tcx().sess, self.span, E0040, - "explicit call to destructor"); - } + callee::check_legal_trait_for_method_call(self.fcx.ccx, self.span, trait_def_id) } ty::ImplContainer(..) => { // Since `drop` is a trait method, we expect that any diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index a0f3f2734d976..dc6de01ff90eb 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -130,6 +130,7 @@ pub mod demand; pub mod method; pub mod wf; mod closure; +mod callee; /// Fields that are part of a `FnCtxt` which are inherited by /// closures defined within the function. For example: @@ -5088,8 +5089,17 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, } // Case 3. Reference to a method. - def::DefStaticMethod(..) => { + def::DefStaticMethod(_, providence) | + def::DefMethod(_, _, providence) => { assert!(path.segments.len() >= 2); + + match providence { + def::FromTrait(trait_did) => { + callee::check_legal_trait_for_method_call(fcx.ccx, span, trait_did) + } + def::FromImpl(_) => {} + } + segment_spaces = Vec::from_elem(path.segments.len() - 2, None); segment_spaces.push(Some(subst::TypeSpace)); segment_spaces.push(Some(subst::FnSpace)); @@ -5101,7 +5111,6 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, def::DefMod(..) | def::DefForeignMod(..) | def::DefLocal(..) | - def::DefMethod(..) | def::DefUse(..) | def::DefRegion(..) | def::DefLabel(..) | diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index b8642ddde4082..8fd383802d1f0 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -211,6 +211,9 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { trait_ref.repr(self.crate_context.tcx), token::get_ident(item.ident)); + enforce_trait_manually_implementable(self.crate_context.tcx, + item.span, + trait_ref.def_id); self.add_trait_impl(trait_ref.def_id, impl_did); } @@ -476,6 +479,28 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { } } +fn enforce_trait_manually_implementable(tcx: &ty::ctxt, sp: Span, trait_def_id: ast::DefId) { + if tcx.sess.features.borrow().unboxed_closures { + // the feature gate allows all of them + return + } + let did = Some(trait_def_id); + let li = &tcx.lang_items; + + let trait_name = if did == li.fn_trait() { + "Fn" + } else if did == li.fn_mut_trait() { + "FnMut" + } else if did == li.fn_once_trait() { + "FnOnce" + } else { + return // everything OK + }; + span_err!(tcx.sess, sp, E0173, "manual implementations of `{}` are experimental", trait_name); + span_help!(tcx.sess, sp, + "add `#![feature(unboxed_closures)]` to the crate attributes to enable"); +} + fn subst_receiver_types_in_method_ty<'tcx>(tcx: &ty::ctxt<'tcx>, impl_id: ast::DefId, impl_poly_type: &ty::Polytype<'tcx>, diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 36e81f18103b8..e026fbd05c7f0 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -53,7 +53,7 @@ register_diagnostics!( E0035, E0036, E0038, - E0040, + E0040, // explicit use of destructor method E0044, E0045, E0046, @@ -147,5 +147,7 @@ register_diagnostics!( E0168, E0169, E0171, - E0172 + E0172, + E0173, // manual implementations of unboxed closure traits are experimental + E0174 // explicit use of unboxed closure methods are experimental ) diff --git a/src/test/compile-fail/explicit-call-to-dtor.rs b/src/test/compile-fail/explicit-call-to-dtor.rs index 3f69cb6e51ea2..6b334dd6ecdfc 100644 --- a/src/test/compile-fail/explicit-call-to-dtor.rs +++ b/src/test/compile-fail/explicit-call-to-dtor.rs @@ -20,5 +20,5 @@ impl Drop for Foo { fn main() { let x = Foo { x: 3 }; - x.drop(); //~ ERROR explicit call to destructor + x.drop(); //~ ERROR explicit use of destructor method } diff --git a/src/test/compile-fail/explicit-call-to-supertrait-dtor.rs b/src/test/compile-fail/explicit-call-to-supertrait-dtor.rs index 3d987bf4c58a2..d0dd0e68da6bd 100644 --- a/src/test/compile-fail/explicit-call-to-supertrait-dtor.rs +++ b/src/test/compile-fail/explicit-call-to-supertrait-dtor.rs @@ -24,7 +24,7 @@ impl Drop for Foo { impl Bar for Foo { fn blah(&self) { - self.drop(); //~ ERROR explicit call to destructor + self.drop(); //~ ERROR explicit use of destructor method } } diff --git a/src/test/compile-fail/feature-gate-unboxed-closures-manual-impls.rs b/src/test/compile-fail/feature-gate-unboxed-closures-manual-impls.rs new file mode 100644 index 0000000000000..8999da5b17555 --- /dev/null +++ b/src/test/compile-fail/feature-gate-unboxed-closures-manual-impls.rs @@ -0,0 +1,26 @@ +// Copyright 2014 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)] + +struct Foo; +impl Fn<(), ()> for Foo { //~ ERROR manual implementations of `Fn` are experimental + extern "rust-call" fn call(&self, args: ()) -> () {} +} +struct Bar; +impl FnMut<(), ()> for Bar { //~ ERROR manual implementations of `FnMut` are experimental + extern "rust-call" fn call_mut(&self, args: ()) -> () {} +} +struct Baz; +impl FnOnce<(), ()> for Baz { //~ ERROR manual implementations of `FnOnce` are experimental + extern "rust-call" fn call_once(&self, args: ()) -> () {} +} + +fn main() {} diff --git a/src/test/compile-fail/feature-gate-unboxed-closures-method-calls.rs b/src/test/compile-fail/feature-gate-unboxed-closures-method-calls.rs new file mode 100644 index 0000000000000..5a066c441cfe5 --- /dev/null +++ b/src/test/compile-fail/feature-gate-unboxed-closures-method-calls.rs @@ -0,0 +1,19 @@ +// Copyright 2014 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)] + +fn foo>(mut f: F) { + f.call(()); //~ ERROR explicit use of unboxed closure method `call` + f.call_mut(()); //~ ERROR explicit use of unboxed closure method `call_mut` + f.call_once(()); //~ ERROR explicit use of unboxed closure method `call_once` +} + +fn main() {} diff --git a/src/test/compile-fail/feature-gate-unboxed-closures-ufcs-calls.rs b/src/test/compile-fail/feature-gate-unboxed-closures-ufcs-calls.rs new file mode 100644 index 0000000000000..8efaf00c9c848 --- /dev/null +++ b/src/test/compile-fail/feature-gate-unboxed-closures-ufcs-calls.rs @@ -0,0 +1,19 @@ +// Copyright 2014 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)] + +fn foo>(mut f: F, mut g: F) { + Fn::call(&g, ()); //~ ERROR explicit use of unboxed closure method `call` + FnMut::call_mut(&mut g, ()); //~ ERROR explicit use of unboxed closure method `call_mut` + FnOnce::call_once(g, ()); //~ ERROR explicit use of unboxed closure method `call_once` +} + +fn main() {} diff --git a/src/test/compile-fail/illegal-ufcs-drop.rs b/src/test/compile-fail/illegal-ufcs-drop.rs new file mode 100644 index 0000000000000..f4c653bd57323 --- /dev/null +++ b/src/test/compile-fail/illegal-ufcs-drop.rs @@ -0,0 +1,20 @@ +// Copyright 2014 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 Foo; + +impl Drop for Foo { + fn drop(&mut self) {} +} + +fn main() { + Drop::drop(&mut Foo) //~ ERROR explicit use of destructor method +} diff --git a/src/test/run-pass/ufcs-type-params.rs b/src/test/run-pass/ufcs-type-params.rs new file mode 100644 index 0000000000000..f4ad78da4877e --- /dev/null +++ b/src/test/run-pass/ufcs-type-params.rs @@ -0,0 +1,22 @@ +// Copyright 2014 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 { + fn get(&self) -> T; +} + +impl Foo for i32 { + fn get(&self) -> i32 { *self } +} + +fn main() { + let x: i32 = 1; + Foo::::get(&x) +} From b800ce160899b2c2350c45c25844640c46dd49cf Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Fri, 5 Dec 2014 19:01:07 -0800 Subject: [PATCH 08/29] Implement lifetime elision for Foo(...) -> ... type sugar. This means that `Fn(&A) -> (&B, &C)` is equivalent to `for<'a> Fn(&'a A) -> (&'a B, &'a C)` similar to the lifetime elision of lower-case `fn` in types and declarations. Closes #18992. --- src/librustc_typeck/astconv.rs | 121 ++++++++++++------ .../unboxed-closure-sugar-equiv.rs | 6 +- .../unboxed-closure-sugar-lifetime-elision.rs | 34 +++++ 3 files changed, 117 insertions(+), 44 deletions(-) create mode 100644 src/test/compile-fail/unboxed-closure-sugar-lifetime-elision.rs diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index d95ad9a11c87f..7f1aad8ca77c5 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -386,20 +386,81 @@ fn convert_angle_bracketed_parameters<'tcx, AC, RS>(this: &AC, (regions, types) } +/// Returns the appropriate lifetime to use for any output lifetimes +/// (if one exists) and a vector of the (pattern, number of lifetimes) +/// corresponding to each input type/pattern. +fn find_implied_output_region(input_tys: &[Ty], input_pats: Vec) + -> (Option, Vec<(String, uint)>) +{ + let mut lifetimes_for_params: Vec<(String, uint)> = Vec::new(); + let mut possible_implied_output_region = None; + + for (input_type, input_pat) in input_tys.iter().zip(input_pats.into_iter()) { + let mut accumulator = Vec::new(); + ty::accumulate_lifetimes_in_type(&mut accumulator, *input_type); + + if accumulator.len() == 1 { + // there's a chance that the unique lifetime of this + // iteration will be the appropriate lifetime for output + // parameters, so lets store it. + possible_implied_output_region = Some(accumulator[0]) + } + + lifetimes_for_params.push((input_pat, accumulator.len())); + } + + let implied_output_region = if lifetimes_for_params.iter().map(|&(_, n)| n).sum() == 1 { + assert!(possible_implied_output_region.is_some()); + possible_implied_output_region + } else { + None + }; + (implied_output_region, lifetimes_for_params) +} + +fn convert_ty_with_lifetime_elision<'tcx,AC>(this: &AC, + implied_output_region: Option, + param_lifetimes: Vec<(String, uint)>, + ty: &ast::Ty) + -> Ty<'tcx> + where AC: AstConv<'tcx> +{ + match implied_output_region { + Some(implied_output_region) => { + let rb = SpecificRscope::new(implied_output_region); + ast_ty_to_ty(this, &rb, ty) + } + None => { + // All regions must be explicitly specified in the output + // if the lifetime elision rules do not apply. This saves + // the user from potentially-confusing errors. + let rb = UnelidableRscope::new(param_lifetimes); + ast_ty_to_ty(this, &rb, ty) + } + } +} + fn convert_parenthesized_parameters<'tcx,AC>(this: &AC, data: &ast::ParenthesizedParameterData) -> Vec> where AC: AstConv<'tcx> { let binding_rscope = BindingRscope::new(); - let inputs = data.inputs.iter() .map(|a_t| ast_ty_to_ty(this, &binding_rscope, &**a_t)) - .collect(); + .collect::>>(); + + let input_params = Vec::from_elem(inputs.len(), String::new()); + let (implied_output_region, + params_lifetimes) = find_implied_output_region(&*inputs, input_params); + let input_ty = ty::mk_tup(this.tcx(), inputs); let output = match data.output { - Some(ref output_ty) => ast_ty_to_ty(this, &binding_rscope, &**output_ty), + Some(ref output_ty) => convert_ty_with_lifetime_elision(this, + implied_output_region, + params_lifetimes, + &**output_ty), None => ty::mk_nil(this.tcx()), }; @@ -1059,55 +1120,33 @@ fn ty_of_method_or_bare_fn<'a, 'tcx, AC: AstConv<'tcx>>( let self_and_input_tys: Vec = self_ty.into_iter().chain(input_tys).collect(); - let mut lifetimes_for_params: Vec<(String, Vec)> = Vec::new(); // Second, if there was exactly one lifetime (either a substitution or a // reference) in the arguments, then any anonymous regions in the output // have that lifetime. - if implied_output_region.is_none() { - let mut self_and_input_tys_iter = self_and_input_tys.iter(); - if self_ty.is_some() { + let lifetimes_for_params = if implied_output_region.is_none() { + let input_tys = if self_ty.is_some() { // Skip the first argument if `self` is present. - drop(self_and_input_tys_iter.next()) - } - - for (input_type, input_pat) in self_and_input_tys_iter.zip(input_pats.into_iter()) { - let mut accumulator = Vec::new(); - ty::accumulate_lifetimes_in_type(&mut accumulator, *input_type); - lifetimes_for_params.push((input_pat, accumulator)); - } - - if lifetimes_for_params.iter().map(|&(_, ref x)| x.len()).sum() == 1 { - implied_output_region = - Some(lifetimes_for_params.iter() - .filter_map(|&(_, ref x)| - if x.len() == 1 { Some(x[0]) } else { None }) - .next().unwrap()); - } - } + self_and_input_tys.slice_from(1) + } else { + self_and_input_tys.slice_from(0) + }; - let param_lifetimes: Vec<(String, uint)> = lifetimes_for_params.into_iter() - .map(|(n, v)| (n, v.len())) - .filter(|&(_, l)| l != 0) - .collect(); + let (ior, lfp) = find_implied_output_region(input_tys, input_pats); + implied_output_region = ior; + lfp + } else { + vec![] + }; let output_ty = match decl.output { ast::Return(ref output) if output.node == ast::TyInfer => ty::FnConverging(this.ty_infer(output.span)), ast::Return(ref output) => - ty::FnConverging(match implied_output_region { - Some(implied_output_region) => { - let rb = SpecificRscope::new(implied_output_region); - ast_ty_to_ty(this, &rb, &**output) - } - None => { - // All regions must be explicitly specified in the output - // if the lifetime elision rules do not apply. This saves - // the user from potentially-confusing errors. - let rb = UnelidableRscope::new(param_lifetimes); - ast_ty_to_ty(this, &rb, &**output) - } - }), + ty::FnConverging(convert_ty_with_lifetime_elision(this, + implied_output_region, + lifetimes_for_params, + &**output)), ast::NoReturn(_) => ty::FnDiverging }; diff --git a/src/test/compile-fail/unboxed-closure-sugar-equiv.rs b/src/test/compile-fail/unboxed-closure-sugar-equiv.rs index 6f875efdef7ea..308b33f9b4db1 100644 --- a/src/test/compile-fail/unboxed-closure-sugar-equiv.rs +++ b/src/test/compile-fail/unboxed-closure-sugar-equiv.rs @@ -44,9 +44,9 @@ fn test<'a,'b>() { eq::< for<'a,'b> Foo<(&'a int,&'b uint),uint>, Foo(&int,&uint) -> uint >(); - // FIXME(#18992) Test lifetime elision in `()` form: - // eq::< for<'a,'b> Foo<(&'a int,), &'a int>, - // Foo(&int) -> &int >(); + // lifetime elision + eq::< for<'a,'b> Foo<(&'a int,), &'a int>, + Foo(&int) -> &int >(); // Errors expected: eq::< Foo<(),()>, Foo(char) >(); diff --git a/src/test/compile-fail/unboxed-closure-sugar-lifetime-elision.rs b/src/test/compile-fail/unboxed-closure-sugar-lifetime-elision.rs new file mode 100644 index 0000000000000..e08d84944c02a --- /dev/null +++ b/src/test/compile-fail/unboxed-closure-sugar-lifetime-elision.rs @@ -0,0 +1,34 @@ +// Copyright 2014 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. + +// Test that the unboxed closure sugar can be used with an arbitrary +// struct type and that it is equivalent to the same syntax using +// angle brackets. This test covers only simple types and in +// particular doesn't test bound regions. + +#![feature(unboxed_closures)] +#![allow(dead_code)] + +trait Foo { + fn dummy(&self, t: T, u: U); +} + +trait Eq for Sized? { } +impl Eq for X { } +fn eq>() { } + +fn main() { + eq::< for<'a> Foo<(&'a int,), &'a int>, + Foo(&int) -> &int >(); + eq::< for<'a> Foo<(&'a int,), (&'a int, &'a int)>, + Foo(&int) -> (&int, &int) >(); + + let _: Foo(&int, &uint) -> &uint; //~ ERROR missing lifetime specifier +} From 9cb26e2db052601db95e242c7c29caa744886b11 Mon Sep 17 00:00:00 2001 From: jbranchaud Date: Fri, 5 Dec 2014 23:50:13 -0600 Subject: [PATCH 09/29] Add a doctest for BTreeMap's iter method. --- src/libcollections/btree/map.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index 8a6d26c26bf3c..f6d196d2f582d 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -1026,6 +1026,24 @@ impl<'a, K: Ord, V> OccupiedEntry<'a, K, V> { impl BTreeMap { /// Gets an iterator over the entries of the map. + /// + /// # Example + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut map = BTreeMap::new(); + /// map.insert(1u, "a"); + /// map.insert(2u, "b"); + /// map.insert(3u, "c"); + /// + /// for (key, value) in map.iter() { + /// println!("{}: {}", key, value); + /// } + /// + /// let (first_key, first_value) = map.iter().next().unwrap(); + /// assert_eq!((*first_key, *first_value), (1u, "a")); + /// ``` #[unstable = "matches collection reform specification, waiting for dust to settle"] pub fn iter<'a>(&'a self) -> Entries<'a, K, V> { let len = self.len(); From de8f48b10ae13bfd30671d43f3f9e4e3225efd34 Mon Sep 17 00:00:00 2001 From: Vadim Chugunov Date: Sat, 6 Dec 2014 01:32:57 -0800 Subject: [PATCH 10/29] - Support gcc-less installation on Windows. To do so in unattended mode run:`.exe /TYPE=compact /SILENT`. - Do not require admin privileges to install. --- mk/dist.mk | 5 +++-- src/etc/make-win-dist.py | 18 ++++++++++++------ src/etc/pkg/rust.iss | 8 +++++++- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/mk/dist.mk b/mk/dist.mk index 718b5bf6df604..0b9cd86c61fe4 100644 --- a/mk/dist.mk +++ b/mk/dist.mk @@ -123,7 +123,8 @@ PKG_EXE = dist/$(PKG_NAME)-$(CFG_BUILD).exe $(PKG_EXE): rust.iss modpath.iss upgrade.iss LICENSE.txt rust-logo.ico \ $(CSREQ3_T_$(CFG_BUILD)_H_$(CFG_BUILD)) \ dist-prepare-win - $(CFG_PYTHON) $(S)src/etc/make-win-dist.py tmp/dist/win $(CFG_BUILD) + $(Q)rm -rf tmp/dist/win/gcc + $(CFG_PYTHON) $(S)src/etc/make-win-dist.py tmp/dist/win/rust tmp/dist/win/gcc $(CFG_BUILD) @$(call E, ISCC: $@) $(Q)$(CFG_ISCC) $< @@ -131,7 +132,7 @@ $(eval $(call DEF_PREPARE,win)) dist-prepare-win: PREPARE_HOST=$(CFG_BUILD) dist-prepare-win: PREPARE_TARGETS=$(CFG_BUILD) -dist-prepare-win: PREPARE_DEST_DIR=tmp/dist/win +dist-prepare-win: PREPARE_DEST_DIR=tmp/dist/win/rust dist-prepare-win: PREPARE_DIR_CMD=$(DEFAULT_PREPARE_DIR_CMD) dist-prepare-win: PREPARE_BIN_CMD=$(DEFAULT_PREPARE_BIN_CMD) dist-prepare-win: PREPARE_LIB_CMD=$(DEFAULT_PREPARE_LIB_CMD) diff --git a/src/etc/make-win-dist.py b/src/etc/make-win-dist.py index 53f648e29ae11..7fb86f904a20b 100644 --- a/src/etc/make-win-dist.py +++ b/src/etc/make-win-dist.py @@ -8,6 +8,12 @@ # option. This file may not be copied, modified, or distributed # except according to those terms. +# Script parameters: +# argv[1] = rust component root, +# argv[2] = gcc component root, +# argv[3] = target triple +# The first two correspond to the two installable components defined in the setup script. + import sys, os, shutil, subprocess def find_files(files, path): @@ -22,7 +28,7 @@ def find_files(files, path): raise Exception("Could not find '%s' in %s" % (fname, path)) return found -def make_win_dist(dist_root, target_triple): +def make_win_dist(rust_root, gcc_root, target_triple): # Ask gcc where it keeps its stuff gcc_out = subprocess.check_output(["gcc.exe", "-print-search-dirs"]) bin_path = os.environ["PATH"].split(os.pathsep) @@ -90,29 +96,29 @@ def make_win_dist(dist_root, target_triple): target_libs = find_files(target_libs, lib_path) # Copy runtime dlls next to rustc.exe - dist_bin_dir = os.path.join(dist_root, "bin") + dist_bin_dir = os.path.join(rust_root, "bin") for src in rustc_dlls: shutil.copy(src, dist_bin_dir) # Copy platform tools to platform-specific bin directory - target_bin_dir = os.path.join(dist_root, "bin", "rustlib", target_triple, "bin") + target_bin_dir = os.path.join(gcc_root, "bin", "rustlib", target_triple, "bin") if not os.path.exists(target_bin_dir): os.makedirs(target_bin_dir) for src in target_tools: shutil.copy(src, target_bin_dir) # Copy platform libs to platform-spcific lib directory - target_lib_dir = os.path.join(dist_root, "bin", "rustlib", target_triple, "lib") + target_lib_dir = os.path.join(gcc_root, "bin", "rustlib", target_triple, "lib") if not os.path.exists(target_lib_dir): os.makedirs(target_lib_dir) for src in target_libs: shutil.copy(src, target_lib_dir) # Copy license files - lic_dir = os.path.join(dist_root, "bin", "third-party") + lic_dir = os.path.join(rust_root, "bin", "third-party") if os.path.exists(lic_dir): shutil.rmtree(lic_dir) # copytree() won't overwrite existing files shutil.copytree(os.path.join(os.path.dirname(__file__), "third-party"), lic_dir) if __name__=="__main__": - make_win_dist(sys.argv[1], sys.argv[2]) + make_win_dist(sys.argv[1], sys.argv[2], sys.argv[3]) diff --git a/src/etc/pkg/rust.iss b/src/etc/pkg/rust.iss index fe2107943c576..c57a7ab6c7059 100644 --- a/src/etc/pkg/rust.iss +++ b/src/etc/pkg/rust.iss @@ -14,6 +14,7 @@ AppPublisherURL=http://www.rust-lang.org VersionInfoVersion={#CFG_VERSION_WIN} LicenseFile=LICENSE.txt +PrivilegesRequired=lowest DisableWelcomePage=true DisableProgramGroupPage=true DisableReadyPage=true @@ -37,8 +38,13 @@ Uninstallable=yes [Tasks] Name: modifypath; Description: &Add {app}\bin to your PATH (recommended) +[Components] +Name: rust; Description: "Rust compiler and standard crates"; Types: full compact custom; Flags: fixed +Name: gcc; Description: "Linker and platform libraries"; Types: full + [Files] -Source: "tmp/dist/win/*.*" ; DestDir: "{app}"; Flags: ignoreversion recursesubdirs +Source: "tmp/dist/win/rust/*.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: rust +Source: "tmp/dist/win/gcc/*.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: gcc [Code] const From 87424c6a32e883b3d7328fc78341aa79ff1e3abb Mon Sep 17 00:00:00 2001 From: "NODA, Kai" Date: Sun, 7 Dec 2014 07:05:13 +0800 Subject: [PATCH 11/29] Fix false positive alerts from a run-pass test on Command. Reported as a part of rust-lang/rust#19120 The logic of rust-lang/rust@74fb798a200dc82cf5b4a18065e3ea565229adc3 was flawed because when a CI tool run the test parallely with other tasks, they all belong to a single session family and the test may pick up irrelevant zombie processes before they are reaped by the CI tool depending on timing. Also, panic! inside a loop over all children makes the logic simpler. By not destructing the return values of Command::spawn() until find_zombies() finishes, I believe we can conduct a slightly stricter test. Signed-off-by: NODA, Kai --- .../run-pass/wait-forked-but-failed-child.rs | 68 ++++++++----------- 1 file changed, 28 insertions(+), 40 deletions(-) diff --git a/src/test/run-pass/wait-forked-but-failed-child.rs b/src/test/run-pass/wait-forked-but-failed-child.rs index f482b2e1e703b..577e114945c66 100644 --- a/src/test/run-pass/wait-forked-but-failed-child.rs +++ b/src/test/run-pass/wait-forked-but-failed-child.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-test - extern crate libc; use std::io::process::Command; @@ -18,51 +16,38 @@ use std::iter::IteratorExt; use libc::funcs::posix88::unistd; -// "ps -A -o pid,sid,command" with GNU ps should output something like this: -// PID SID COMMAND -// 1 1 /sbin/init +// The output from "ps -A -o pid,ppid,args" should look like this: +// PID PPID COMMAND +// 1 0 /sbin/init // 2 0 [kthreadd] -// 3 0 [ksoftirqd/0] // ... -// 12562 9237 ./spawn-failure -// 12563 9237 [spawn-failure] -// 12564 9237 [spawn-failure] +// 6076 9064 /bin/zsh +// ... +// 7164 6076 ./spawn-failure +// 7165 7164 [spawn-failure] +// 7166 7164 [spawn-failure] // ... -// 12592 9237 [spawn-failure] -// 12593 9237 ps -A -o pid,sid,command -// 12884 12884 /bin/zsh -// 12922 12922 /bin/zsh +// 7197 7164 [spawn-failure] +// 7198 7164 ps -A -o pid,ppid,command // ... #[cfg(unix)] fn find_zombies() { - // http://man.freebsd.org/ps(1) - // http://man7.org/linux/man-pages/man1/ps.1.html - #[cfg(not(target_os = "macos"))] - const FIELDS: &'static str = "pid,sid,command"; - - // https://developer.apple.com/library/mac/documentation/Darwin/ - // Reference/ManPages/man1/ps.1.html - #[cfg(target_os = "macos")] - const FIELDS: &'static str = "pid,sess,command"; - - let my_sid = unsafe { unistd::getsid(0) }; + let my_pid = unsafe { unistd::getpid() }; - let ps_cmd_output = Command::new("ps").args(&["-A", "-o", FIELDS]).output().unwrap(); + // http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ps.html + let ps_cmd_output = Command::new("ps").args(&["-A", "-o", "pid,ppid,args"]).output().unwrap(); let ps_output = String::from_utf8_lossy(ps_cmd_output.output.as_slice()); - let found = ps_output.split('\n').enumerate().any(|(line_no, line)| - 0 < line_no && 0 < line.len() && - my_sid == from_str(line.split(' ').filter(|w| 0 < w.len()).nth(1) - .expect("1st column should be Session ID") - ).expect("Session ID string into integer") && - line.contains("defunct") && { - println!("Zombie child {}", line); - true + for (line_no, line) in ps_output.split('\n').enumerate() { + if 0 < line_no && 0 < line.len() && + my_pid == from_str(line.split(' ').filter(|w| 0 < w.len()).nth(1) + .expect("1st column should be PPID") + ).expect("PPID string into integer") && + line.contains("defunct") { + panic!("Zombie child {}", line); } - ); - - assert!( ! found, "Found at least one zombie child"); + } } #[cfg(windows)] @@ -71,10 +56,13 @@ fn find_zombies() { } fn main() { let too_long = format!("/NoSuchCommand{:0300}", 0u8); - for _ in range(0u32, 100) { - let invalid = Command::new(too_long.as_slice()).spawn(); - assert!(invalid.is_err()); - } + let _failures = Vec::from_fn(100, |_i| { + let cmd = Command::new(too_long.as_slice()); + let failed = cmd.spawn(); + assert!(failed.is_err(), "Make sure the command fails to spawn(): {}", cmd); + failed + }); find_zombies(); + // then _failures goes out of scope } From 2171c95553e1cf225e9e6e799ebecfb959ff2277 Mon Sep 17 00:00:00 2001 From: jbranchaud Date: Sat, 6 Dec 2014 17:36:32 -0600 Subject: [PATCH 12/29] Add missing semicolon to hello world program in intro. --- src/doc/intro.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/intro.md b/src/doc/intro.md index 01697a3e0cbc3..2e1d7d9d613c5 100644 --- a/src/doc/intro.md +++ b/src/doc/intro.md @@ -64,7 +64,7 @@ Here's what's in `src/main.rs`: ```{rust} fn main() { - println!("Hello, world!") + println!("Hello, world!"); } ``` From 8ba56052330c69b6bb5bb9c477ff2d3894e5911d Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Sun, 7 Dec 2014 04:18:56 -0500 Subject: [PATCH 13/29] remove usage of notrust from the docs Fixes #19599 --- src/doc/guide-crates.md | 2 +- src/doc/guide-error-handling.md | 4 +- src/doc/guide-ownership.md | 4 +- src/doc/guide-pointers.md | 18 +++--- src/doc/guide-strings.md | 6 +- src/doc/guide.md | 102 ++++++++++++++++---------------- src/doc/intro.md | 4 +- src/librand/chacha.rs | 2 +- src/librustc/metadata/loader.rs | 6 +- src/libstd/rand/mod.rs | 2 +- 10 files changed, 75 insertions(+), 75 deletions(-) diff --git a/src/doc/guide-crates.md b/src/doc/guide-crates.md index 50d76371cc51e..4d3e5e7d8fa66 100644 --- a/src/doc/guide-crates.md +++ b/src/doc/guide-crates.md @@ -452,7 +452,7 @@ fn main() { Rust will give us a compile-time error: -```{notrust,ignore} +```{ignore} Compiling phrases v0.0.1 (file:///home/you/projects/phrases) /home/you/projects/phrases/src/main.rs:4:5: 4:40 error: a value named `hello` has already been imported in this module /home/you/projects/phrases/src/main.rs:4 use phrases::japanese::greetings::hello; diff --git a/src/doc/guide-error-handling.md b/src/doc/guide-error-handling.md index e2a706e59f0f1..6bb91845f5dd8 100644 --- a/src/doc/guide-error-handling.md +++ b/src/doc/guide-error-handling.md @@ -76,7 +76,7 @@ fn main() { This will give us an error: -```{notrust,ignore} +```{ignore} error: non-exhaustive patterns: `_` not covered [E0004] ``` @@ -189,7 +189,7 @@ panic!("boom"); gives -```{notrust,ignore} +```{ignore} task '
' panicked at 'boom', hello.rs:2 ``` diff --git a/src/doc/guide-ownership.md b/src/doc/guide-ownership.md index c1180f7e6a93a..dd4de65225aa3 100644 --- a/src/doc/guide-ownership.md +++ b/src/doc/guide-ownership.md @@ -130,7 +130,7 @@ fn add_one(mut num: Box) { This does not compile, and gives us an error: -```{notrust,ignore} +```{ignore} error: use of moved value: `x` println!("{}", x); ^ @@ -406,7 +406,7 @@ fn main() { We try to make four `Wheel`s, each with a `Car` that it's attached to. But the compiler knows that on the second iteration of the loop, there's a problem: -```{notrust,ignore} +```{ignore} error: use of moved value: `car` Wheel { size: 360, owner: car }; ^~~ diff --git a/src/doc/guide-pointers.md b/src/doc/guide-pointers.md index f6216760d6477..dbb8d6b007d35 100644 --- a/src/doc/guide-pointers.md +++ b/src/doc/guide-pointers.md @@ -84,7 +84,7 @@ println!("{}", x + z); This gives us an error: -```{notrust,ignore} +```{ignore} hello.rs:6:24: 6:25 error: mismatched types: expected `int` but found `&int` (expected int but found &-ptr) hello.rs:6 println!("{}", x + z); ^ @@ -132,7 +132,7 @@ Pointers are useful in languages that are pass-by-value, rather than pass-by-reference. Basically, languages can make two choices (this is made up syntax, it's not Rust): -```{notrust,ignore} +```{ignore} func foo(x) { x = 5 } @@ -152,7 +152,7 @@ and therefore, can change its value. At the comment, `i` will be `5`. So what do pointers have to do with this? Well, since pointers point to a location in memory... -```{notrust,ignore} +```{ignore} func foo(&int x) { *x = 5 } @@ -179,7 +179,7 @@ but here are problems with pointers in other languages: Uninitialized pointers can cause a problem. For example, what does this program do? -```{notrust,ignore} +```{ignore} &int x; *x = 5; // whoops! ``` @@ -191,7 +191,7 @@ knows. This might be harmless, and it might be catastrophic. When you combine pointers and functions, it's easy to accidentally invalidate the memory the pointer is pointing to. For example: -```{notrust,ignore} +```{ignore} func make_pointer(): &int { x = 5; @@ -213,7 +213,7 @@ As one last example of a big problem with pointers, **aliasing** can be an issue. Two pointers are said to alias when they point at the same location in memory. Like this: -```{notrust,ignore} +```{ignore} func mutate(&int i, int j) { *i = j; } @@ -398,7 +398,7 @@ fn main() { It gives this error: -```{notrust,ignore} +```{ignore} test.rs:5:8: 5:10 error: cannot assign to `*x` because it is borrowed test.rs:5 *x -= 1; ^~ @@ -522,7 +522,7 @@ boxes, though. As a rough approximation, you can treat this Rust code: As being similar to this C code: -```{notrust,ignore} +```{ignore} { int *x; x = (int *)malloc(sizeof(int)); @@ -626,7 +626,7 @@ fn main() { This prints: -```{notrust,ignore} +```{ignore} Cons(1, box Cons(2, box Cons(3, box Nil))) ``` diff --git a/src/doc/guide-strings.md b/src/doc/guide-strings.md index 071c9ff013c59..43cc8483bcec5 100644 --- a/src/doc/guide-strings.md +++ b/src/doc/guide-strings.md @@ -181,7 +181,7 @@ for l in s.graphemes(true) { This prints: -```{notrust,ignore} +```{text} u͔ n͈̰̎ i̙̮͚̦ @@ -207,7 +207,7 @@ for l in s.chars() { This prints: -```{notrust,ignore} +```{text} u ͔ n @@ -252,7 +252,7 @@ for l in s.bytes() { This will print: -```{notrust,ignore} +```{text} 117 205 148 diff --git a/src/doc/guide.md b/src/doc/guide.md index 3f3b533bbd59b..56471ebf99663 100644 --- a/src/doc/guide.md +++ b/src/doc/guide.md @@ -355,7 +355,7 @@ just `cargo build` and it'll work the right way. You'll also notice that Cargo has created a new file: `Cargo.lock`. -```{ignore,notrust} +```{ignore} [root] name = "hello_world" version = "0.0.1" @@ -426,7 +426,7 @@ x = 10i; It will give you this error: -```{ignore,notrust} +```{ignore} error: re-assignment of immutable variable `x` x = 10i; ^~~~~~~ @@ -486,7 +486,7 @@ fn main() { You can use `cargo build` on the command line to build it. You'll get a warning, but it will still print "Hello, world!": -```{ignore,notrust} +```{ignore} Compiling hello_world v0.0.1 (file:///home/you/projects/hello_world) src/main.rs:2:9: 2:10 warning: unused variable: `x`, #[warn(unused_variable)] on by default src/main.rs:2 let x: int; @@ -664,7 +664,7 @@ let y: int = if x == 5i { 10i; } else { 15i; }; Note the semicolons after the 10 and 15. Rust will give us the following error: -```{ignore,notrust} +```{ignore} error: mismatched types: expected `int` but found `()` (expected int but found ()) ``` @@ -747,7 +747,7 @@ fn print_number(x, y) { You get this error: -```{ignore,notrust} +```{ignore} hello.rs:5:18: 5:19 error: expected `:` but found `,` hello.rs:5 fn print_number(x, y) { ``` @@ -779,7 +779,7 @@ fn add_one(x: int) -> int { We would get an error: -```{ignore,notrust} +```{ignore} error: not all control paths return a value fn add_one(x: int) -> int { x + 1; @@ -1197,7 +1197,7 @@ So what's the big advantage here? Well, there are a few. First of all, `match` enforces 'exhaustiveness checking.' Do you see that last arm, the one with the underscore (`_`)? If we remove that arm, Rust will give us an error: -```{ignore,notrust} +```{ignore} error: non-exhaustive patterns: `_` not covered ``` @@ -1344,7 +1344,7 @@ for x in range(0i, 10i) { In slightly more abstract terms, -```{ignore,notrust} +```{ignore} for var in expression { code } @@ -1849,7 +1849,7 @@ Before we move on, let me show you one more Cargo command: `run`. `cargo run` is kind of like `cargo build`, but it also then runs the produced executable. Try it out: -```{notrust,ignore} +```{ignore} $ cargo run Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game) Running `target/guessing_game` @@ -1947,7 +1947,7 @@ for this example, it is not important. Let's try to compile this using `cargo build`: -```{notrust,no_run} +```{no_run} $ cargo build Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game) src/main.rs:7:26: 7:34 error: the type of this value must be known in this context @@ -1995,7 +1995,7 @@ fn main() { Try running our new program a few times: -```{notrust,ignore} +```{ignore} $ cargo run Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game) Running `target/guessing_game` @@ -2048,7 +2048,7 @@ fn main() { And trying it out: -```{notrust,ignore} +```{ignore} $ cargo run Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game) Running `target/guessing_game` @@ -2103,7 +2103,7 @@ fn cmp(a: int, b: int) -> Ordering { If we try to compile, we'll get some errors: -```{notrust,ignore} +```{ignore} $ cargo build Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game) src/main.rs:20:15: 20:20 error: mismatched types: expected `int` but found `collections::string::String` (expected int but found struct collections::string::String) @@ -2157,7 +2157,7 @@ fn cmp(a: uint, b: uint) -> Ordering { And try compiling again: -```{notrust,ignore} +```{ignore} $ cargo build Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game) src/main.rs:20:15: 20:20 error: mismatched types: expected `uint` but found `collections::string::String` (expected uint but found struct collections::string::String) @@ -2170,7 +2170,7 @@ This error is similar to the last one: we expected to get a `uint`, but we got a `String` instead! That's because our `input` variable is coming from the standard input, and you can guess anything. Try it: -```{notrust,ignore} +```{ignore} $ ./target/guessing_game Guess the number! The secret number is: 73 @@ -2254,7 +2254,7 @@ fn cmp(a: uint, b: uint) -> Ordering { Let's try it out! -```{notrust,ignore} +```{ignore} $ cargo build Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game) src/main.rs:22:15: 22:24 error: mismatched types: expected `uint` but found `core::option::Option` (expected uint but found enum core::option::Option) @@ -2313,7 +2313,7 @@ fn cmp(a: uint, b: uint) -> Ordering { We use a `match` to either give us the `uint` inside of the `Option`, or we print an error message and return. Let's give this a shot: -```{notrust,ignore} +```{ignore} $ cargo run Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game) Running `target/guessing_game` @@ -2378,7 +2378,7 @@ fn cmp(a: uint, b: uint) -> Ordering { Let's try it! -```{notrust,ignore} +```{ignore} $ cargo run Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game) Running `target/guessing_game` @@ -2455,7 +2455,7 @@ fn cmp(a: uint, b: uint) -> Ordering { And try it out. But wait, didn't we just add an infinite loop? Yup. Remember that `return`? If we give a non-number answer, we'll `return` and quit. Observe: -```{notrust,ignore} +```{ignore} $ cargo run Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game) Running `target/guessing_game` @@ -2587,7 +2587,7 @@ fn cmp(a: uint, b: uint) -> Ordering { Now we should be good! Let's try: -```{notrust,ignore} +```{ignore} $ cargo run Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game) Running `target/guessing_game` @@ -2703,7 +2703,7 @@ $ cd modules Let's double check our work by compiling: -```{bash,notrust} +```{bash} $ cargo run Compiling modules v0.0.1 (file:///home/you/projects/modules) Running `target/modules` @@ -2765,7 +2765,7 @@ mod hello { It gives an error: -```{notrust,ignore} +```{ignore} Compiling modules v0.0.1 (file:///home/you/projects/modules) src/main.rs:2:5: 2:23 error: function `print_hello` is private src/main.rs:2 hello::print_hello(); @@ -2789,7 +2789,7 @@ mod hello { Usage of the `pub` keyword is sometimes called 'exporting', because we're making the function available for other modules. This will work: -```{notrust,ignore} +```{ignore} $ cargo run Compiling modules v0.0.1 (file:///home/you/projects/modules) Running `target/modules` @@ -2923,7 +2923,7 @@ $ cd testing And try it out: -```{notrust,ignore} +```{ignore} $ cargo run Compiling testing v0.0.1 (file:///home/you/projects/testing) Running `target/testing` @@ -2955,7 +2955,7 @@ you give them descriptive names. You'll see why in a moment. We then use a macro, `assert!`, to assert that something is true. In this case, we're giving it `false`, so this test should fail. Let's try it! -```{notrust,ignore} +```{ignore} $ cargo test Compiling testing v0.0.1 (file:///home/you/projects/testing) /home/you/projects/testing/src/main.rs:1:1: 3:2 warning: function is never used: `main`, #[warn(dead_code)] on by default @@ -2984,7 +2984,7 @@ task '
' failed at 'Some tests failed', /home/you/src/rust/src/libtest/lib. Lots of output! Let's break this down: -```{notrust,ignore} +```{ignore} $ cargo test Compiling testing v0.0.1 (file:///home/you/projects/testing) ``` @@ -2992,7 +2992,7 @@ $ cargo test You can run all of your tests with `cargo test`. This runs both your tests in `tests`, as well as the tests you put inside of your crate. -```{notrust,ignore} +```{ignore} /home/you/projects/testing/src/main.rs:1:1: 3:2 warning: function is never used: `main`, #[warn(dead_code)] on by default /home/you/projects/testing/src/main.rs:1 fn main() { /home/you/projects/testing/src/main.rs:2 println!("Hello, world!") @@ -3006,7 +3006,7 @@ case, Rust is warning us that we've written some code that's never used: our We'll turn this lint off for just this function soon. For now, just ignore this output. -```{notrust,ignore} +```{ignore} Running target/lib-654ce120f310a3a5 running 1 test @@ -3018,7 +3018,7 @@ with good names? This is why. Here, it says 'test foo' because we called our test 'foo.' If we had given it a good name, it'd be more clear which test failed, especially as we accumulate more tests. -```{notrust,ignore} +```{ignore} failures: ---- foo stdout ---- @@ -3049,7 +3049,7 @@ fn foo() { And then try to run our tests again: -```{notrust,ignore} +```{ignore} $ cargo test Compiling testing v0.0.1 (file:///home/you/projects/testing) Running target/lib-654ce120f310a3a5 @@ -3089,7 +3089,7 @@ include `main` when it's _not_ true. So we use `not` to negate things: With this attribute we won't get the warning (even though `src/main.rs` gets recompiled this time): -```{notrust,ignore} +```{ignore} $ cargo test Compiling testing v0.0.1 (file:///home/you/projects/testing) Running target/lib-654ce120f310a3a5 @@ -3120,7 +3120,7 @@ fn math_checks_out() { And try to run the test: -```{notrust,ignore} +```{ignore} $ cargo test Compiling testing v0.0.1 (file:///home/you/projects/testing) /home/you/projects/testing/tests/lib.rs:3:18: 3:38 error: unresolved name `add_three_times_four`. @@ -3180,7 +3180,7 @@ fn math_checks_out() { Let's give it a run: -```{ignore,notrust} +```{ignore} $ cargo test Compiling testing v0.0.1 (file:///home/you/projects/testing) Running target/lib-654ce120f310a3a5 @@ -3229,7 +3229,7 @@ fn times_four(x: int) -> int { x * 4 } If you run `cargo test`, you should get the same output: -```{ignore,notrust} +```{ignore} $ cargo test Compiling testing v0.0.1 (file:///home/you/projects/testing) Running target/lib-654ce120f310a3a5 @@ -3283,7 +3283,7 @@ fn test_add_three() { We'd get this error: -```{notrust,ignore} +```{ignore} Compiling testing v0.0.1 (file:///home/you/projects/testing) /home/you/projects/testing/tests/lib.rs:3:5: 3:24 error: function `add_three` is private /home/you/projects/testing/tests/lib.rs:3 use testing::add_three; @@ -3325,7 +3325,7 @@ mod test { Let's give it a shot: -```{ignore,notrust} +```{ignore} $ cargo test Compiling testing v0.0.1 (file:///home/you/projects/testing) Running target/lib-654ce120f310a3a5 @@ -3455,7 +3455,7 @@ let y = &mut x; Rust will complain: -```{ignore,notrust} +```{ignore} error: cannot borrow immutable local variable `x` as mutable let y = &mut x; ^ @@ -3482,7 +3482,7 @@ let z = &mut x; It gives us this error: -```{notrust,ignore} +```{ignore} error: cannot borrow `x` as mutable more than once at a time let z = &mut x; ^ @@ -3628,7 +3628,7 @@ let z = &mut x; The error: -```{notrust,ignore} +```{ignore} error: cannot borrow `x` as mutable more than once at a time let z = &mut x; ^ @@ -3646,7 +3646,7 @@ note: previous borrow ends here This error comes in three parts. Let's go over each in turn. -```{notrust,ignore} +```{ignore} error: cannot borrow `x` as mutable more than once at a time let z = &mut x; ^ @@ -3655,7 +3655,7 @@ error: cannot borrow `x` as mutable more than once at a time This error states the restriction: you cannot lend out something mutable more than once at the same time. The borrow checker knows the rules! -```{notrust,ignore} +```{ignore} note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends let y = &mut x; ^ @@ -3667,7 +3667,7 @@ the first mutable borrow occurred. The error showed us the second. So now we see both parts of the problem. It also alludes to rule #3, by reminding us that we can't change `x` until the borrow is over. -```{notrust,ignore} +```{ignore} note: previous borrow ends here fn main() { let mut x = 5i; @@ -3770,7 +3770,7 @@ let y = &mut x; This gives us this error: -```{notrust,ignore} +```{ignore} error: cannot use `*x` because it was mutably borrowed *x; ^~ @@ -4595,7 +4595,7 @@ element reference has the closure it's been given as an argument called on it. So this would give us the numbers from `2-100`. Well, almost! If you compile the example, you'll get a warning: -```{notrust,ignore} +```{ignore} warning: unused result which must be used: iterator adaptors are lazy and do nothing unless consumed, #[warn(unused_must_use)] on by default range(1i, 100i).map(|x| x + 1i); @@ -4625,7 +4625,7 @@ for i in std::iter::count(1i, 5i).take(5) { This will print -```{notrust,ignore} +```{ignore} 1 6 11 @@ -4838,7 +4838,7 @@ We can then use `T` inside the rest of the signature: `x` has type `T`, and half of the `Result` has type `T`. However, if we try to compile that example, we'll get an error: -```{notrust,ignore} +```{ignore} error: binary operation `==` cannot be applied to type `T` ``` @@ -4894,7 +4894,7 @@ we use `impl Trait for Item`, rather than just `impl Item`. So what's the big deal? Remember the error we were getting with our generic `inverse` function? -```{notrust,ignore} +```{ignore} error: binary operation `==` cannot be applied to type `T` ``` @@ -4909,7 +4909,7 @@ fn print_area(shape: T) { Rust complains: -```{notrust,ignore} +```{ignore} error: type `T` does not implement any method in scope named `area` ``` @@ -4985,7 +4985,7 @@ fn main() { This program outputs: -```{notrust,ignore} +```{ignore} This shape has an area of 3.141593 This shape has an area of 1 ``` @@ -4999,7 +4999,7 @@ print_area(5i); We get a compile-time error: -```{notrust,ignore} +```{ignore} error: failed to find an implementation of trait main::HasArea for int ``` @@ -5066,7 +5066,7 @@ fn main() { Now that we've moved the structs and traits into their own module, we get an error: -```{notrust,ignore} +```{ignore} error: type `shapes::Circle` does not implement any method in scope named `area` ``` diff --git a/src/doc/intro.md b/src/doc/intro.md index 01697a3e0cbc3..f14de7b9c4683 100644 --- a/src/doc/intro.md +++ b/src/doc/intro.md @@ -313,7 +313,7 @@ print `"Hello"`, or does Rust crash? Neither. It refuses to compile: -```{notrust,ignore} +```{ignore} $ cargo run Compiling hello_world v0.0.1 (file:///Users/you/src/hello_world) main.rs:8:5: 8:6 error: cannot borrow `v` as mutable because it is also borrowed as immutable @@ -428,7 +428,7 @@ fn main() { It gives us this error: -```{notrust,ignore} +```{ignore} 6:71 error: capture of moved value: `numbers` for j in range(0, 3) { numbers[j] += 1 } ^~~~~~~ diff --git a/src/librand/chacha.rs b/src/librand/chacha.rs index 2693f18364430..c374b606e73a9 100644 --- a/src/librand/chacha.rs +++ b/src/librand/chacha.rs @@ -115,7 +115,7 @@ impl ChaChaRng { /// security proof for a more involved example of this. /// /// The modified word layout is: - /// ```notrust + /// ```ignore /// constant constant constant constant /// key key key key /// key key key key diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs index bd0446dd67ff2..9d9c7eef9a66f 100644 --- a/src/librustc/metadata/loader.rs +++ b/src/librustc/metadata/loader.rs @@ -120,7 +120,7 @@ //! //! The compiler accepts a flag of this form a number of times: //! -//! ```notrust +//! ```ignore //! --extern crate-name=path/to/the/crate.rlib //! ``` //! @@ -152,7 +152,7 @@ //! //! and the compiler would be invoked as: //! -//! ```notrust +//! ```ignore //! rustc a.rs --extern b1=path/to/libb1.rlib --extern b2=path/to/libb2.rlib //! ``` //! @@ -178,7 +178,7 @@ //! dependencies, not the upstream transitive dependencies. Consider this //! dependency graph: //! -//! ```notrust +//! ```ignore //! A.1 A.2 //! | | //! | | diff --git a/src/libstd/rand/mod.rs b/src/libstd/rand/mod.rs index 413d9267152eb..3005ef1680376 100644 --- a/src/libstd/rand/mod.rs +++ b/src/libstd/rand/mod.rs @@ -80,7 +80,7 @@ //! circle, both centered at the origin. Since the area of a unit circle is π, //! we have: //! -//! ```notrust +//! ```text //! (area of unit circle) / (area of square) = π / 4 //! ``` //! From 131f20279e856f66d1d3727e440462aa44f8fa65 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Sun, 7 Dec 2014 07:30:15 -0500 Subject: [PATCH 14/29] Correct the reference with regards to floats Fixes #19595. --- src/doc/reference.md | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/doc/reference.md b/src/doc/reference.md index 9ac4469d54983..afa54763ce61d 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -496,9 +496,8 @@ Examples of integer literals of various forms: A _floating-point literal_ has one of two forms: -* Two _decimal literals_ separated by a period - character `U+002E` (`.`), with an optional _exponent_ trailing after the - second decimal literal. +* A _decimal literal_ followed by a period character `U+002E` (`.`). This is + optionally followed by another decimal literal, with an optional _exponent_. * A single _decimal literal_ followed by an _exponent_. By default, a floating-point literal has a generic type, and, like integer @@ -509,12 +508,17 @@ types), which explicitly determine the type of the literal. Examples of floating-point literals of various forms: ``` -123.0f64; // type f64 -0.1f64; // type f64 -0.1f32; // type f32 -12E+99_f64; // type f64 +123.0f64; // type f64 +0.1f64; // type f64 +0.1f32; // type f32 +12E+99_f64; // type f64 +let x: f64 = 2.; // type f64 ``` +This last example is different because it is not possible to use the suffix +syntax with a floating point literal ending in a period. `2.f64` would attempt +to call a method named `f64` on `2`. + ##### Boolean literals The two values of the boolean type are written `true` and `false`. From e2947720729a6666c0b4b24b1e6009e9e638adb7 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Sun, 7 Dec 2014 07:55:30 -0500 Subject: [PATCH 15/29] Add enum namespacing to the Guide. Closes #19556. --- src/doc/guide.md | 49 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/src/doc/guide.md b/src/doc/guide.md index 3f3b533bbd59b..5e04200482339 100644 --- a/src/doc/guide.md +++ b/src/doc/guide.md @@ -1160,6 +1160,55 @@ Where a `StringResult` is either an `StringOK`, with the result of a computation `ErrorReason` with a `String` explaining what caused the computation to fail. These kinds of `enum`s are actually very useful and are even part of the standard library. +Enum variants are namespaced under the enum names. For example, here is an example of using +our `StringResult`: + +```rust +# enum StringResult { +# StringOK(String), +# ErrorReason(String), +# } +fn respond(greeting: &str) -> StringResult { + if greeting == "Hello" { + StringResult::StringOK("Good morning!".to_string()) + } else { + StringResult::ErrorReason("I didn't understand you!".to_string()) + } +} +``` + +Notice that we need both the enum name and the variant name: `StringResult::StringOK`, but +we didn't need to with `Ordering`, we just said `Greater` rather than `Ordering::Greater`. +There's a reason: the Rust prelude imports the variants of `Ordering` as well as the enum +itself. We can use the `use` keyword to do something similar with `StringResult`: + +```rust +use StringResult::StringOK; +use StringResult::ErrorReason; + +enum StringResult { + StringOK(String), + ErrorReason(String), +} + +# fn main() {} + +fn respond(greeting: &str) -> StringResult { + if greeting == "Hello" { + StringOK("Good morning!".to_string()) + } else { + ErrorReason("I didn't understand you!".to_string()) + } +} +``` + +We'll learn more about `use` later, but it's used to bring names into scope. `use` declarations +must come before anything else, which looks a little strange in this example, since we `use` +the variants before we define them. Anyway, in the body of `respond`, we can just say `StringOK` +now, rather than the full `StringResult::StringOK`. Importing variants can be convenient, but can +also cause name conflicts, so do this with caution. It's considered good style to rarely import +variants for this reason. + As you can see `enum`s with values are quite a powerful tool for data representation, and can be even more useful when they're generic across types. But before we get to generics, let's talk about how to use them with pattern matching, a tool that will From 58f12743c2ae4e3045b07e8509c089ac97c21452 Mon Sep 17 00:00:00 2001 From: Peter Atashian Date: Sun, 7 Dec 2014 13:25:51 -0500 Subject: [PATCH 16/29] Make MemoryMap use HANDLE on Windows. Also fixes some conflicting module names. Signed-off-by: Peter Atashian --- src/libstd/os.rs | 72 +++++++++++++++++------------------- src/libstd/sys/windows/fs.rs | 2 +- 2 files changed, 35 insertions(+), 39 deletions(-) diff --git a/src/libstd/os.rs b/src/libstd/os.rs index ba9bcc05546cd..25842450068b2 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -159,7 +159,7 @@ pub fn getcwd() -> IoResult { } #[cfg(windows)] -pub mod windows { +pub mod windoze { use libc::types::os::arch::extra::DWORD; use libc; use option::Option; @@ -385,7 +385,7 @@ pub fn getenv_as_bytes(n: &str) -> Option> { pub fn getenv(n: &str) -> Option { unsafe { with_env_lock(|| { - use os::windows::{fill_utf16_buf_and_decode}; + use os::windoze::{fill_utf16_buf_and_decode}; let mut n: Vec = n.utf16_units().collect(); n.push(0); fill_utf16_buf_and_decode(|buf, sz| { @@ -712,7 +712,7 @@ pub fn self_exe_name() -> Option { #[cfg(windows)] fn load_self() -> Option> { unsafe { - use os::windows::fill_utf16_buf_and_decode; + use os::windoze::fill_utf16_buf_and_decode; fill_utf16_buf_and_decode(|buf, sz| { libc::GetModuleFileNameW(0u as libc::DWORD, buf, sz) }).map(|s| s.into_string().into_bytes()) @@ -1207,7 +1207,11 @@ pub enum MapOption { /// Create a map for a specific address range. Corresponds to `MAP_FIXED` on /// POSIX. MapAddr(*const u8), + /// Create a memory mapping for a file with a given HANDLE. + #[cfg(windows)] + MapFd(libc::HANDLE), /// Create a memory mapping for a file with a given fd. + #[cfg(not(windows))] MapFd(c_int), /// When using `MapFd`, the start of the map is `uint` bytes from the start /// of the file. @@ -1401,7 +1405,7 @@ impl MemoryMap { let mut readable = false; let mut writable = false; let mut executable = false; - let mut fd: c_int = -1; + let mut handle: HANDLE = libc::INVALID_HANDLE_VALUE; let mut offset: uint = 0; let len = round_up(min_len, page_size()); @@ -1411,23 +1415,23 @@ impl MemoryMap { MapWritable => { writable = true; }, MapExecutable => { executable = true; } MapAddr(addr_) => { lpAddress = addr_ as LPVOID; }, - MapFd(fd_) => { fd = fd_; }, + MapFd(handle_) => { handle = handle_; }, MapOffset(offset_) => { offset = offset_; }, MapNonStandardFlags(..) => {} } } let flProtect = match (executable, readable, writable) { - (false, false, false) if fd == -1 => libc::PAGE_NOACCESS, + (false, false, false) if handle == libc::INVALID_HANDLE_VALUE => libc::PAGE_NOACCESS, (false, true, false) => libc::PAGE_READONLY, (false, true, true) => libc::PAGE_READWRITE, - (true, false, false) if fd == -1 => libc::PAGE_EXECUTE, + (true, false, false) if handle == libc::INVALID_HANDLE_VALUE => libc::PAGE_EXECUTE, (true, true, false) => libc::PAGE_EXECUTE_READ, (true, true, true) => libc::PAGE_EXECUTE_READWRITE, _ => return Err(ErrUnsupProt) }; - if fd == -1 { + if handle == libc::INVALID_HANDLE_VALUE { if offset != 0 { return Err(ErrUnsupOffset); } @@ -1455,7 +1459,7 @@ impl MemoryMap { // we should never get here. }; unsafe { - let hFile = libc::get_osfhandle(fd) as HANDLE; + let hFile = handle; let mapping = libc::CreateFileMappingW(hFile, ptr::null_mut(), flProtect, @@ -1979,55 +1983,47 @@ mod tests { #[test] fn memory_map_file() { - use result::Result::{Ok, Err}; use os::*; - use libc::*; - use io::fs; - - #[cfg(unix)] - fn lseek_(fd: c_int, size: uint) { - unsafe { - assert!(lseek(fd, size as off_t, SEEK_SET) == size as off_t); - } + use io::fs::{File, unlink}; + use io::SeekStyle::SeekSet; + use io::FileMode::Open; + use io::FileAccess::ReadWrite; + use libc::HANDLE; + + #[cfg(not(windows))] + fn get_fd(file: &File) -> c_int { + use os::unix::AsRawFd; + file.as_raw_fd() } + #[cfg(windows)] - fn lseek_(fd: c_int, size: uint) { - unsafe { - assert!(lseek(fd, size as c_long, SEEK_SET) == size as c_long); - } + fn get_fd(file: &File) -> HANDLE { + use os::windows::AsRawHandle; + file.as_raw_handle() } let mut path = tmpdir(); path.push("mmap_file.tmp"); let size = MemoryMap::granularity() * 2; + let mut file = File::open_mode(&path, Open, ReadWrite).unwrap(); + file.seek(size as i64, SeekSet); + file.write_u8(0); - let fd = unsafe { - let fd = path.with_c_str(|path| { - open(path, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR) - }); - lseek_(fd, size); - "x".with_c_str(|x| assert!(write(fd, x as *const c_void, 1) == 1)); - fd - }; - let chunk = match MemoryMap::new(size / 2, &[ + let chunk = MemoryMap::new(size / 2, &[ MapReadable, MapWritable, - MapFd(fd), + MapFd(get_fd(&file)), MapOffset(size / 2) - ]) { - Ok(chunk) => chunk, - Err(msg) => panic!("{}", msg) - }; + ]).unwrap(); assert!(chunk.len > 0); unsafe { *chunk.data = 0xbe; assert!(*chunk.data == 0xbe); - close(fd); } drop(chunk); - fs::unlink(&path).unwrap(); + unlink(&path).unwrap(); } #[test] diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index 9402c63dcf558..731fdc0871f6d 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -15,7 +15,7 @@ use libc::{mod, c_int}; use c_str::CString; use mem; -use os::windows::fill_utf16_buf_and_decode; +use os::windoze::fill_utf16_buf_and_decode; use path; use ptr; use str; From c8bd9d2beb863d08cfca3503aef67a9cc7b7fd7e Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Sun, 7 Dec 2014 14:12:01 -0500 Subject: [PATCH 17/29] Remove mention of Dequeue in collections docs. https://botbot.me/mozilla/rust/2014-12-07/?msg=27003846&page=20 --- src/libcollections/dlist.rs | 3 --- src/libcollections/ring_buf.rs | 3 +-- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/libcollections/dlist.rs b/src/libcollections/dlist.rs index 39cdf0c456413..edef37d4b8567 100644 --- a/src/libcollections/dlist.rs +++ b/src/libcollections/dlist.rs @@ -11,9 +11,6 @@ //! A doubly-linked list with owned nodes. //! //! The `DList` allows pushing and popping elements at either end. -//! -//! `DList` implements the trait `Deque`. It should be imported with -//! `use collections::Deque`. // DList is constructed like a singly-linked list over the field `next`. // including the last link being None; each Node owns its `next` field. diff --git a/src/libcollections/ring_buf.rs b/src/libcollections/ring_buf.rs index e11ba35367e2e..695eda11216a4 100644 --- a/src/libcollections/ring_buf.rs +++ b/src/libcollections/ring_buf.rs @@ -11,7 +11,6 @@ //! This crate implements a double-ended queue with `O(1)` amortized inserts and removals from both //! ends of the container. It also has `O(1)` indexing like a vector. The contained elements are //! not required to be copyable, and the queue will be sendable if the contained type is sendable. -//! Its interface `Deque` is defined in `collections`. use core::prelude::*; @@ -35,7 +34,7 @@ static MINIMUM_CAPACITY: uint = 2u; // FIXME(conventions): implement shrink_to_fit. Awkward with the current design, but it should // be scrapped anyway. Defer to rewrite? -/// `RingBuf` is a circular buffer that implements `Deque`. +/// `RingBuf` is a circular buffer. pub struct RingBuf { // tail and head are pointers into the buffer. Tail always points // to the first element that could be read, Head always points From d7d5ccf9bb3bc63f347d8d5441092f20a3fe7088 Mon Sep 17 00:00:00 2001 From: bluss Date: Sun, 7 Dec 2014 21:31:24 +0100 Subject: [PATCH 18/29] string: Use the iterator size_hint() in .extend() --- src/libcollections/string.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index fbb0bb5c4ce86..961fca0f02b9a 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -732,6 +732,8 @@ impl FromIterator for String { #[experimental = "waiting on Extend stabilization"] impl Extend for String { fn extend>(&mut self, mut iterator: I) { + let (lower_bound, _) = iterator.size_hint(); + self.reserve(lower_bound); for ch in iterator { self.push(ch) } From 5ba7c5da62bae732bf466191dbeb5f699ba44d70 Mon Sep 17 00:00:00 2001 From: bluss Date: Sun, 7 Dec 2014 21:32:00 +0100 Subject: [PATCH 19/29] string: Implement FromIterator<&str> and Extend<&str> for String &str is a "particle" of a string already, see the graphemes iterator, so it seems natural that we should be able to use it with Extend. --- src/libcollections/string.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index 961fca0f02b9a..ed578f3f515b6 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -729,6 +729,15 @@ impl FromIterator for String { } } +#[experimental = "waiting on FromIterator stabilization"] +impl<'a> FromIterator<&'a str> for String { + fn from_iter>(iterator: I) -> String { + let mut buf = String::new(); + buf.extend(iterator); + buf + } +} + #[experimental = "waiting on Extend stabilization"] impl Extend for String { fn extend>(&mut self, mut iterator: I) { @@ -740,6 +749,18 @@ impl Extend for String { } } +#[experimental = "waiting on Extend stabilization"] +impl<'a> Extend<&'a str> for String { + fn extend>(&mut self, mut iterator: I) { + // A guess that at least one byte per iterator element will be needed. + let (lower_bound, _) = iterator.size_hint(); + self.reserve(lower_bound); + for s in iterator { + self.push_str(s) + } + } +} + impl PartialEq for String { #[inline] fn eq(&self, other: &String) -> bool { PartialEq::eq(&**self, &**other) } From 8dcdd1e76a6524de7da8423bc9f224fe8a822bc8 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Sat, 6 Dec 2014 11:56:55 -0500 Subject: [PATCH 20/29] syntax: use UFCS in the expansion of `#[deriving(Ord)]` cc #18755 --- src/libsyntax/ext/deriving/cmp/totalord.rs | 29 +++++++++++++++++++--- src/test/run-pass/issue-18738.rs | 6 ++--- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/libsyntax/ext/deriving/cmp/totalord.rs b/src/libsyntax/ext/deriving/cmp/totalord.rs index 83af45462ec6e..6900773f44d4b 100644 --- a/src/libsyntax/ext/deriving/cmp/totalord.rs +++ b/src/libsyntax/ext/deriving/cmp/totalord.rs @@ -66,12 +66,19 @@ pub fn cs_cmp(cx: &mut ExtCtxt, span: Span, cx.ident_of("cmp"), cx.ident_of("Equal"))); + let cmp_path = vec![ + cx.ident_of("std"), + cx.ident_of("cmp"), + cx.ident_of("Ord"), + cx.ident_of("cmp"), + ]; + /* Builds: - let __test = self_field1.cmp(&other_field2); + let __test = ::std::cmp::Ord::cmp(&self_field1, &other_field1); if other == ::std::cmp::Ordering::Equal { - let __test = self_field2.cmp(&other_field2); + let __test = ::std::cmp::Ord::cmp(&self_field2, &other_field2); if __test == ::std::cmp::Ordering::Equal { ... } else { @@ -83,11 +90,11 @@ pub fn cs_cmp(cx: &mut ExtCtxt, span: Span, FIXME #6449: These `if`s could/should be `match`es. */ - cs_same_method_fold( + cs_fold( // foldr nests the if-elses correctly, leaving the first field // as the outermost one, and the last as the innermost. false, - |cx, span, old, new| { + |cx, span, old, self_f, other_fs| { // let __test = new; // if __test == ::std::cmp::Ordering::Equal { // old @@ -95,6 +102,20 @@ pub fn cs_cmp(cx: &mut ExtCtxt, span: Span, // __test // } + let new = { + let other_f = match other_fs { + [ref o_f] => o_f, + _ => cx.span_bug(span, "not exactly 2 arguments in `deriving(PartialOrd)`"), + }; + + let args = vec![ + cx.expr_addr_of(span, self_f), + cx.expr_addr_of(span, other_f.clone()), + ]; + + cx.expr_call_global(span, cmp_path.clone(), args) + }; + let assign = cx.stmt_let(span, false, test_id, new); let cond = cx.expr_binary(span, ast::BiEq, diff --git a/src/test/run-pass/issue-18738.rs b/src/test/run-pass/issue-18738.rs index 7958b9ec117cb..35bd68d803a2e 100644 --- a/src/test/run-pass/issue-18738.rs +++ b/src/test/run-pass/issue-18738.rs @@ -8,18 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[deriving(PartialEq, PartialOrd)] +#[deriving(Eq, PartialEq, PartialOrd, Ord)] enum Test<'a> { Int(&'a int), Slice(&'a [u8]), } -#[deriving(PartialEq, PartialOrd)] +#[deriving(Eq, PartialEq, PartialOrd, Ord)] struct Version { vendor_info: &'static str } -#[deriving(PartialEq, PartialOrd)] +#[deriving(Eq, PartialEq, PartialOrd, Ord)] struct Foo(&'static str); fn main() {} From 56c4e97e83ebe9d7553e2a66e67595fbd6a2246e Mon Sep 17 00:00:00 2001 From: bluss Date: Sun, 7 Dec 2014 21:43:11 +0100 Subject: [PATCH 21/29] string: Add test for FromIterator and Extend --- src/libcollections/string.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index ed578f3f515b6..1af6d27953db1 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -1330,6 +1330,20 @@ mod tests { "[[], [1], [1, 1]]".to_string()); } + #[test] + fn test_from_iterator() { + let s = "ศไทย中华Việt Nam".to_string(); + let t = "ศไทย中华"; + let u = "Việt Nam"; + + let a: String = s.chars().collect(); + assert_eq!(s, a.as_slice()); + + let mut b = t.to_string(); + b.extend(u.chars()); + assert_eq!(s, b.as_slice()); + } + #[bench] fn bench_with_capacity(b: &mut Bencher) { b.iter(|| { From a81346966d7e0480a50a2821fa5f95253342ecb0 Mon Sep 17 00:00:00 2001 From: bluss Date: Sun, 7 Dec 2014 21:45:47 +0100 Subject: [PATCH 22/29] string: Add test for FromIterator<&str> and Extend<&str> --- src/libcollections/string.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index 1af6d27953db1..0f567caaee17b 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -1337,11 +1337,18 @@ mod tests { let u = "Việt Nam"; let a: String = s.chars().collect(); - assert_eq!(s, a.as_slice()); + assert_eq!(s, a); let mut b = t.to_string(); b.extend(u.chars()); - assert_eq!(s, b.as_slice()); + assert_eq!(s, b); + + let c: String = vec![t, u].into_iter().collect(); + assert_eq!(s, c); + + let mut d = t.to_string(); + d.extend(vec![u].into_iter()); + assert_eq!(s, d); } #[bench] From 956c5811111a02628d464d5c8d1be8eca06c5092 Mon Sep 17 00:00:00 2001 From: Jon Haddad Date: Sun, 7 Dec 2014 11:35:06 -0800 Subject: [PATCH 23/29] documentation incorrectly described from_utf8 Docs said from_utf8 accepts a vector when it actually accepts a slice of bytes. --- src/libcore/str.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/str.rs b/src/libcore/str.rs index 1d59567cbe447..f81356938ea2b 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -76,7 +76,7 @@ impl FromStr for bool { Section: Creating a string */ -/// Converts a vector to a string slice without performing any allocations. +/// Converts a slice of bytes to a string slice without performing any allocations. /// /// Once the slice has been validated as utf-8, it is transmuted in-place and /// returned as a '&str' instead of a '&[u8]' From ad7dacd9eb39ae8dba6badb41de03821f9dd7707 Mon Sep 17 00:00:00 2001 From: Aaron Weiss Date: Mon, 8 Dec 2014 15:56:10 -0500 Subject: [PATCH 24/29] Implemented BorrowFrom> for T. --- src/liballoc/rc.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 53891583edb20..217c898e661a0 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -141,6 +141,7 @@ #![stable] +use core::borrow::BorrowFrom; use core::cell::Cell; use core::clone::Clone; use core::cmp::{PartialEq, PartialOrd, Eq, Ord, Ordering}; @@ -349,6 +350,12 @@ impl Rc { } } +impl BorrowFrom> for T { + fn borrow_from(owned: &Rc) -> &T { + &**owned + } +} + #[experimental = "Deref is experimental."] impl Deref for Rc { #[inline(always)] From 9af324a673443367c5b58a182804982c11f73981 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Mon, 8 Dec 2014 12:58:01 -0500 Subject: [PATCH 25/29] Remove Result and Option reexports Brief note: This does *not* affect anything in the prelude Part of #19253 All this does is remove the reexporting of Result and Option from their respective modules. More core reexports might be removed, but these ones are the safest to remove since these enums (and their variants) are included in the prelude. [breaking-change] --- src/libcore/option.rs | 2 +- src/libcore/result.rs | 2 +- src/libstd/dynamic_lib.rs | 3 +++ src/libstd/sync/poison.rs | 2 +- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 8ba41c3575fff..6c3932a0c2ee0 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -143,7 +143,7 @@ #![stable] -pub use self::Option::*; +use self::Option::*; use cmp::{Eq, Ord}; use default::Default; diff --git a/src/libcore/result.rs b/src/libcore/result.rs index 0cf8e6affd71e..0686f7bdee2dc 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -230,7 +230,7 @@ #![stable] -pub use self::Result::*; +use self::Result::*; use std::fmt::Show; use slice; diff --git a/src/libstd/dynamic_lib.rs b/src/libstd/dynamic_lib.rs index aa0c8b53c2e89..c3398746fd7e3 100644 --- a/src/libstd/dynamic_lib.rs +++ b/src/libstd/dynamic_lib.rs @@ -21,9 +21,11 @@ use iter::IteratorExt; use mem; use ops::*; use option::*; +use option::Option::{None, Some}; use os; use path::{Path,GenericPath}; use result::*; +use result::Result::{Err, Ok}; use slice::{AsSlice,SlicePrelude}; use str; use string::String; @@ -212,6 +214,7 @@ pub mod dl { use libc; use ptr; use result::*; + use result::Result::{Err, Ok}; use string::String; pub unsafe fn open_external(filename: T) -> *mut u8 { diff --git a/src/libstd/sync/poison.rs b/src/libstd/sync/poison.rs index eb46fd771477e..ee1515566204b 100644 --- a/src/libstd/sync/poison.rs +++ b/src/libstd/sync/poison.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use option::None; +use option::Option::None; use rustrt::task::Task; use rustrt::local::Local; From 553ab271a31a9573fb6e95d03d8f4d00e17d6511 Mon Sep 17 00:00:00 2001 From: Arcterus Date: Sat, 6 Dec 2014 02:35:26 -0800 Subject: [PATCH 26/29] serialize: base64: allow LF in addition to CRLF and optimize slightly It is useful to have configurable newlines in base64 as the standard leaves that for the implementation to decide. GNU `base64` apparently uses LF, which meant in `uutils` we had to manually convert the CRLF to LF. This made the program very slow for large inputs. [breaking-change] --- src/libserialize/base64.rs | 92 ++++++++++++++++++++++++++------------ src/libserialize/lib.rs | 2 +- 2 files changed, 64 insertions(+), 30 deletions(-) diff --git a/src/libserialize/base64.rs b/src/libserialize/base64.rs index dd5039c9b8283..1cb8fdd025d38 100644 --- a/src/libserialize/base64.rs +++ b/src/libserialize/base64.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -14,6 +14,7 @@ pub use self::FromBase64Error::*; pub use self::CharacterSet::*; +pub use self::Newline::*; use std::fmt; use std::error; @@ -28,10 +29,22 @@ pub enum CharacterSet { impl Copy for CharacterSet {} +/// Available newline types +pub enum Newline { + /// A linefeed (i.e. Unix-style newline) + LF, + /// A carriage return and a linefeed (i.e. Windows-style newline) + CRLF +} + +impl Copy for Newline {} + /// Contains configuration parameters for `to_base64`. pub struct Config { /// Character set to use pub char_set: CharacterSet, + /// Newline to use + pub newline: Newline, /// True to pad output with `=` characters pub pad: bool, /// `Some(len)` to wrap lines at `len`, `None` to disable line wrapping @@ -42,15 +55,15 @@ impl Copy for Config {} /// Configuration for RFC 4648 standard base64 encoding pub static STANDARD: Config = - Config {char_set: Standard, pad: true, line_length: None}; + Config {char_set: Standard, newline: CRLF, pad: true, line_length: None}; /// Configuration for RFC 4648 base64url encoding pub static URL_SAFE: Config = - Config {char_set: UrlSafe, pad: false, line_length: None}; + Config {char_set: UrlSafe, newline: CRLF, pad: false, line_length: None}; /// Configuration for RFC 2045 MIME base64 encoding pub static MIME: Config = - Config {char_set: Standard, pad: true, line_length: Some(76)}; + Config {char_set: Standard, newline: CRLF, pad: true, line_length: Some(76)}; static STANDARD_CHARS: &'static[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\ abcdefghijklmnopqrstuvwxyz\ @@ -87,24 +100,29 @@ impl ToBase64 for [u8] { UrlSafe => URLSAFE_CHARS }; - let mut v = Vec::new(); + // In general, this Vec only needs (4/3) * self.len() memory, but + // addition is faster than multiplication and division. + let mut v = Vec::with_capacity(self.len() + self.len()); let mut i = 0; let mut cur_length = 0; let len = self.len(); - while i < len - (len % 3) { - match config.line_length { - Some(line_length) => - if cur_length >= line_length { - v.push(b'\r'); - v.push(b'\n'); - cur_length = 0; - }, - None => () + let mod_len = len % 3; + let cond_len = len - mod_len; + while i < cond_len { + let (first, second, third) = (self[i], self[i + 1], self[i + 2]); + if let Some(line_length) = config.line_length { + if cur_length >= line_length { + v.push_all(match config.newline { + LF => b"\n", + CRLF => b"\r\n" + }); + cur_length = 0; + } } - let n = (self[i] as u32) << 16 | - (self[i + 1] as u32) << 8 | - (self[i + 2] as u32); + let n = (first as u32) << 16 | + (second as u32) << 8 | + (third as u32); // This 24-bit number gets separated into four 6-bit numbers. v.push(bytes[((n >> 18) & 63) as uint]); @@ -116,20 +134,20 @@ impl ToBase64 for [u8] { i += 3; } - if len % 3 != 0 { - match config.line_length { - Some(line_length) => - if cur_length >= line_length { - v.push(b'\r'); - v.push(b'\n'); - }, - None => () + if mod_len != 0 { + if let Some(line_length) = config.line_length { + if cur_length >= line_length { + v.push_all(match config.newline { + LF => b"\n", + CRLF => b"\r\n" + }); + } } } // Heh, would be cool if we knew this was exhaustive // (the dream of bounded integer types) - match len % 3 { + match mod_len { 0 => (), 1 => { let n = (self[i] as u32) << 16; @@ -232,7 +250,7 @@ impl FromBase64 for str { impl FromBase64 for [u8] { fn from_base64(&self) -> Result, FromBase64Error> { - let mut r = Vec::new(); + let mut r = Vec::with_capacity(self.len()); let mut buf: u32 = 0; let mut modulus = 0i; @@ -288,7 +306,7 @@ impl FromBase64 for [u8] { mod tests { extern crate test; use self::test::Bencher; - use base64::{Config, FromBase64, ToBase64, STANDARD, URL_SAFE}; + use base64::{Config, FromBase64, ToBase64, STANDARD, URL_SAFE, LF}; #[test] fn test_to_base64_basic() { @@ -302,7 +320,7 @@ mod tests { } #[test] - fn test_to_base64_line_break() { + fn test_to_base64_crlf_line_break() { assert!(![0u8, ..1000].to_base64(Config {line_length: None, ..STANDARD}) .contains("\r\n")); assert_eq!("foobar".as_bytes().to_base64(Config {line_length: Some(4), @@ -310,6 +328,18 @@ mod tests { "Zm9v\r\nYmFy"); } + #[test] + fn test_to_base64_lf_line_break() { + assert!(![0u8, ..1000].to_base64(Config {line_length: None, newline: LF, + ..STANDARD}) + .as_slice() + .contains("\n")); + assert_eq!("foobar".as_bytes().to_base64(Config {line_length: Some(4), + newline: LF, + ..STANDARD}), + "Zm9v\nYmFy".to_string()); + } + #[test] fn test_to_base64_padding() { assert_eq!("f".as_bytes().to_base64(Config {pad: false, ..STANDARD}), "Zg"); @@ -344,6 +374,10 @@ mod tests { b"foobar"); assert_eq!("Zm9vYg==\r\n".from_base64().unwrap(), b"foob"); + assert_eq!("Zm9v\nYmFy".from_base64().unwrap(), + b"foobar"); + assert_eq!("Zm9vYg==\n".from_base64().unwrap(), + b"foob"); } #[test] diff --git a/src/libserialize/lib.rs b/src/libserialize/lib.rs index 9711d5c7209be..1cff4c334e743 100644 --- a/src/libserialize/lib.rs +++ b/src/libserialize/lib.rs @@ -23,7 +23,7 @@ Core encoding and decoding interfaces. html_root_url = "http://doc.rust-lang.org/nightly/", html_playground_url = "http://play.rust-lang.org/")] #![allow(unknown_features)] -#![feature(macro_rules, default_type_params, phase, slicing_syntax, globs)] +#![feature(macro_rules, default_type_params, phase, slicing_syntax, globs, if_let)] // test harness access #[cfg(test)] From a943a7a4e5cef797b8fdb946f3925a6ef705ca98 Mon Sep 17 00:00:00 2001 From: Arcterus Date: Sat, 6 Dec 2014 10:58:18 -0800 Subject: [PATCH 27/29] serialize: base64: improve newline handling speed --- src/libserialize/base64.rs | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/src/libserialize/base64.rs b/src/libserialize/base64.rs index 1cb8fdd025d38..17bb3dadaebc8 100644 --- a/src/libserialize/base64.rs +++ b/src/libserialize/base64.rs @@ -14,7 +14,6 @@ pub use self::FromBase64Error::*; pub use self::CharacterSet::*; -pub use self::Newline::*; use std::fmt; use std::error; @@ -55,15 +54,15 @@ impl Copy for Config {} /// Configuration for RFC 4648 standard base64 encoding pub static STANDARD: Config = - Config {char_set: Standard, newline: CRLF, pad: true, line_length: None}; + Config {char_set: Standard, newline: Newline::CRLF, pad: true, line_length: None}; /// Configuration for RFC 4648 base64url encoding pub static URL_SAFE: Config = - Config {char_set: UrlSafe, newline: CRLF, pad: false, line_length: None}; + Config {char_set: UrlSafe, newline: Newline::CRLF, pad: false, line_length: None}; /// Configuration for RFC 2045 MIME base64 encoding pub static MIME: Config = - Config {char_set: Standard, newline: CRLF, pad: true, line_length: Some(76)}; + Config {char_set: Standard, newline: Newline::CRLF, pad: true, line_length: Some(76)}; static STANDARD_CHARS: &'static[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\ abcdefghijklmnopqrstuvwxyz\ @@ -108,14 +107,15 @@ impl ToBase64 for [u8] { let len = self.len(); let mod_len = len % 3; let cond_len = len - mod_len; + let newline = match config.newline { + Newline::LF => b"\n", + Newline::CRLF => b"\r\n" + }; while i < cond_len { let (first, second, third) = (self[i], self[i + 1], self[i + 2]); if let Some(line_length) = config.line_length { if cur_length >= line_length { - v.push_all(match config.newline { - LF => b"\n", - CRLF => b"\r\n" - }); + v.push_all(newline); cur_length = 0; } } @@ -137,10 +137,7 @@ impl ToBase64 for [u8] { if mod_len != 0 { if let Some(line_length) = config.line_length { if cur_length >= line_length { - v.push_all(match config.newline { - LF => b"\n", - CRLF => b"\r\n" - }); + v.push_all(newline); } } } @@ -306,7 +303,7 @@ impl FromBase64 for [u8] { mod tests { extern crate test; use self::test::Bencher; - use base64::{Config, FromBase64, ToBase64, STANDARD, URL_SAFE, LF}; + use base64::{Config, Newline, FromBase64, ToBase64, STANDARD, URL_SAFE}; #[test] fn test_to_base64_basic() { @@ -330,12 +327,13 @@ mod tests { #[test] fn test_to_base64_lf_line_break() { - assert!(![0u8, ..1000].to_base64(Config {line_length: None, newline: LF, + assert!(![0u8, ..1000].to_base64(Config {line_length: None, + newline: Newline::LF, ..STANDARD}) .as_slice() .contains("\n")); assert_eq!("foobar".as_bytes().to_base64(Config {line_length: Some(4), - newline: LF, + newline: Newline::LF, ..STANDARD}), "Zm9v\nYmFy".to_string()); } From a119ad83c73c7e1c99c7e21fb2ab21bd9521077a Mon Sep 17 00:00:00 2001 From: Arcterus Date: Tue, 9 Dec 2014 00:21:43 -0800 Subject: [PATCH 28/29] serialize: base64: remove some .as_bytes() from the tests --- src/libserialize/base64.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libserialize/base64.rs b/src/libserialize/base64.rs index 17bb3dadaebc8..59faf75c0c30c 100644 --- a/src/libserialize/base64.rs +++ b/src/libserialize/base64.rs @@ -320,8 +320,8 @@ mod tests { fn test_to_base64_crlf_line_break() { assert!(![0u8, ..1000].to_base64(Config {line_length: None, ..STANDARD}) .contains("\r\n")); - assert_eq!("foobar".as_bytes().to_base64(Config {line_length: Some(4), - ..STANDARD}), + assert_eq!(b"foobar".to_base64(Config {line_length: Some(4), + ..STANDARD}), "Zm9v\r\nYmFy"); } @@ -332,10 +332,10 @@ mod tests { ..STANDARD}) .as_slice() .contains("\n")); - assert_eq!("foobar".as_bytes().to_base64(Config {line_length: Some(4), - newline: Newline::LF, - ..STANDARD}), - "Zm9v\nYmFy".to_string()); + assert_eq!(b"foobar".to_base64(Config {line_length: Some(4), + newline: Newline::LF, + ..STANDARD}), + "Zm9v\nYmFy"); } #[test] From 1a61fe4280b476bb2131f76414c32676b91e163c Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 9 Dec 2014 10:26:04 -0800 Subject: [PATCH 29/29] Test fixes and rebase conflicts from the rollup --- src/doc/guide-crates.md | 16 ++--- src/doc/guide-error-handling.md | 6 +- src/doc/guide-ownership.md | 4 +- src/doc/guide-pointers.md | 4 +- src/doc/guide.md | 70 +++++++++---------- src/doc/intro.md | 8 +-- src/libcore/cmp.rs | 2 +- src/libcore/option.rs | 3 + src/libstd/os.rs | 6 +- ...-return-type-requires-explicit-lifetime.rs | 1 - src/test/run-pass/ufcs-type-params.rs | 2 +- 11 files changed, 62 insertions(+), 60 deletions(-) diff --git a/src/doc/guide-crates.md b/src/doc/guide-crates.md index 4d3e5e7d8fa66..b567c747d6ff9 100644 --- a/src/doc/guide-crates.md +++ b/src/doc/guide-crates.md @@ -32,7 +32,7 @@ two languages for those phrases to be in. We'll use this module layout: +---------+ | +-----------+ | +---| farewells | +---------+ | +-----------+ -| phrases |---+ +| phrases |---+ +---------+ | +-----------+ | +---| greetings | +----------+ | +-----------+ @@ -219,7 +219,7 @@ Put this in `src/english/greetings.rs`: fn hello() -> String { "Hello!".to_string() -} +} ``` Put this in `src/english/farewells.rs`: @@ -229,7 +229,7 @@ Put this in `src/english/farewells.rs`: fn goodbye() -> String { "Goodbye.".to_string() -} +} ``` Put this in `src/japanese/greetings.rs`: @@ -239,7 +239,7 @@ Put this in `src/japanese/greetings.rs`: fn hello() -> String { "こんにちは".to_string() -} +} ``` Of course, you can copy and paste this from this web page, or just type @@ -253,7 +253,7 @@ Put this in `src/japanese/farewells.rs`: fn goodbye() -> String { "さようなら".to_string() -} +} ``` (This is "Sayoonara", if you're curious.) @@ -381,11 +381,11 @@ $ cargo run /home/you/projects/phrases/src/japanese/greetings.rs:1:1: 3:2 warning: code is never used: `hello`, #[warn(dead_code)] on by default /home/you/projects/phrases/src/japanese/greetings.rs:1 fn hello() -> String { /home/you/projects/phrases/src/japanese/greetings.rs:2 "こんにちは".to_string() -/home/you/projects/phrases/src/japanese/greetings.rs:3 } +/home/you/projects/phrases/src/japanese/greetings.rs:3 } /home/you/projects/phrases/src/japanese/farewells.rs:1:1: 3:2 warning: code is never used: `goodbye`, #[warn(dead_code)] on by default /home/you/projects/phrases/src/japanese/farewells.rs:1 fn goodbye() -> String { /home/you/projects/phrases/src/japanese/farewells.rs:2 "さようなら".to_string() -/home/you/projects/phrases/src/japanese/farewells.rs:3 } +/home/you/projects/phrases/src/japanese/farewells.rs:3 } Running `target/phrases` Hello in English: Hello! Goodbye in English: Goodbye. @@ -452,7 +452,7 @@ fn main() { Rust will give us a compile-time error: -```{ignore} +```{notrust} Compiling phrases v0.0.1 (file:///home/you/projects/phrases) /home/you/projects/phrases/src/main.rs:4:5: 4:40 error: a value named `hello` has already been imported in this module /home/you/projects/phrases/src/main.rs:4 use phrases::japanese::greetings::hello; diff --git a/src/doc/guide-error-handling.md b/src/doc/guide-error-handling.md index 6bb91845f5dd8..71ca8913ab34b 100644 --- a/src/doc/guide-error-handling.md +++ b/src/doc/guide-error-handling.md @@ -2,7 +2,7 @@ > The best-laid plans of mice and men > Often go awry -> +> > "Tae a Moose", Robert Burns Sometimes, things just go wrong. It's important to have a plan for when the @@ -76,7 +76,7 @@ fn main() { This will give us an error: -```{ignore} +```{notrust} error: non-exhaustive patterns: `_` not covered [E0004] ``` @@ -189,7 +189,7 @@ panic!("boom"); gives -```{ignore} +```{notrust} task '
' panicked at 'boom', hello.rs:2 ``` diff --git a/src/doc/guide-ownership.md b/src/doc/guide-ownership.md index ff156d9605ed7..aebafebf98ed3 100644 --- a/src/doc/guide-ownership.md +++ b/src/doc/guide-ownership.md @@ -130,7 +130,7 @@ fn add_one(mut num: Box) { This does not compile, and gives us an error: -```{ignore} +```{notrust} error: use of moved value: `x` println!("{}", x); ^ @@ -406,7 +406,7 @@ fn main() { We try to make four `Wheel`s, each with a `Car` that it's attached to. But the compiler knows that on the second iteration of the loop, there's a problem: -```{ignore} +```{notrust} error: use of moved value: `car` Wheel { size: 360, owner: car }; ^~~ diff --git a/src/doc/guide-pointers.md b/src/doc/guide-pointers.md index dbb8d6b007d35..206df711c1a53 100644 --- a/src/doc/guide-pointers.md +++ b/src/doc/guide-pointers.md @@ -84,7 +84,7 @@ println!("{}", x + z); This gives us an error: -```{ignore} +```{notrust} hello.rs:6:24: 6:25 error: mismatched types: expected `int` but found `&int` (expected int but found &-ptr) hello.rs:6 println!("{}", x + z); ^ @@ -398,7 +398,7 @@ fn main() { It gives this error: -```{ignore} +```{notrust} test.rs:5:8: 5:10 error: cannot assign to `*x` because it is borrowed test.rs:5 *x -= 1; ^~ diff --git a/src/doc/guide.md b/src/doc/guide.md index 810d3990812ce..21043cfef1480 100644 --- a/src/doc/guide.md +++ b/src/doc/guide.md @@ -426,7 +426,7 @@ x = 10i; It will give you this error: -```{ignore} +```{notrust} error: re-assignment of immutable variable `x` x = 10i; ^~~~~~~ @@ -486,7 +486,7 @@ fn main() { You can use `cargo build` on the command line to build it. You'll get a warning, but it will still print "Hello, world!": -```{ignore} +```{notrust} Compiling hello_world v0.0.1 (file:///home/you/projects/hello_world) src/main.rs:2:9: 2:10 warning: unused variable: `x`, #[warn(unused_variable)] on by default src/main.rs:2 let x: int; @@ -664,7 +664,7 @@ let y: int = if x == 5i { 10i; } else { 15i; }; Note the semicolons after the 10 and 15. Rust will give us the following error: -```{ignore} +```{notrust} error: mismatched types: expected `int` but found `()` (expected int but found ()) ``` @@ -747,7 +747,7 @@ fn print_number(x, y) { You get this error: -```{ignore} +```{notrust} hello.rs:5:18: 5:19 error: expected `:` but found `,` hello.rs:5 fn print_number(x, y) { ``` @@ -1246,7 +1246,7 @@ So what's the big advantage here? Well, there are a few. First of all, `match` enforces 'exhaustiveness checking.' Do you see that last arm, the one with the underscore (`_`)? If we remove that arm, Rust will give us an error: -```{ignore} +```{notrust} error: non-exhaustive patterns: `_` not covered ``` @@ -1898,7 +1898,7 @@ Before we move on, let me show you one more Cargo command: `run`. `cargo run` is kind of like `cargo build`, but it also then runs the produced executable. Try it out: -```{ignore} +```{notrust} $ cargo run Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game) Running `target/guessing_game` @@ -1996,7 +1996,7 @@ for this example, it is not important. Let's try to compile this using `cargo build`: -```{no_run} +```{notrust} $ cargo build Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game) src/main.rs:7:26: 7:34 error: the type of this value must be known in this context @@ -2044,7 +2044,7 @@ fn main() { Try running our new program a few times: -```{ignore} +```{notrust} $ cargo run Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game) Running `target/guessing_game` @@ -2097,7 +2097,7 @@ fn main() { And trying it out: -```{ignore} +```{notrust} $ cargo run Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game) Running `target/guessing_game` @@ -2152,7 +2152,7 @@ fn cmp(a: int, b: int) -> Ordering { If we try to compile, we'll get some errors: -```{ignore} +```{notrust} $ cargo build Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game) src/main.rs:20:15: 20:20 error: mismatched types: expected `int` but found `collections::string::String` (expected int but found struct collections::string::String) @@ -2206,7 +2206,7 @@ fn cmp(a: uint, b: uint) -> Ordering { And try compiling again: -```{ignore} +```{notrust} $ cargo build Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game) src/main.rs:20:15: 20:20 error: mismatched types: expected `uint` but found `collections::string::String` (expected uint but found struct collections::string::String) @@ -2219,7 +2219,7 @@ This error is similar to the last one: we expected to get a `uint`, but we got a `String` instead! That's because our `input` variable is coming from the standard input, and you can guess anything. Try it: -```{ignore} +```{notrust} $ ./target/guessing_game Guess the number! The secret number is: 73 @@ -2303,7 +2303,7 @@ fn cmp(a: uint, b: uint) -> Ordering { Let's try it out! -```{ignore} +```{notrust} $ cargo build Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game) src/main.rs:22:15: 22:24 error: mismatched types: expected `uint` but found `core::option::Option` (expected uint but found enum core::option::Option) @@ -2362,7 +2362,7 @@ fn cmp(a: uint, b: uint) -> Ordering { We use a `match` to either give us the `uint` inside of the `Option`, or we print an error message and return. Let's give this a shot: -```{ignore} +```{notrust} $ cargo run Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game) Running `target/guessing_game` @@ -2427,7 +2427,7 @@ fn cmp(a: uint, b: uint) -> Ordering { Let's try it! -```{ignore} +```{notrust} $ cargo run Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game) Running `target/guessing_game` @@ -2504,7 +2504,7 @@ fn cmp(a: uint, b: uint) -> Ordering { And try it out. But wait, didn't we just add an infinite loop? Yup. Remember that `return`? If we give a non-number answer, we'll `return` and quit. Observe: -```{ignore} +```{notrust} $ cargo run Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game) Running `target/guessing_game` @@ -2636,7 +2636,7 @@ fn cmp(a: uint, b: uint) -> Ordering { Now we should be good! Let's try: -```{ignore} +```{notrust} $ cargo run Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game) Running `target/guessing_game` @@ -2814,7 +2814,7 @@ mod hello { It gives an error: -```{ignore} +```{notrust} Compiling modules v0.0.1 (file:///home/you/projects/modules) src/main.rs:2:5: 2:23 error: function `print_hello` is private src/main.rs:2 hello::print_hello(); @@ -2838,7 +2838,7 @@ mod hello { Usage of the `pub` keyword is sometimes called 'exporting', because we're making the function available for other modules. This will work: -```{ignore} +```{notrust} $ cargo run Compiling modules v0.0.1 (file:///home/you/projects/modules) Running `target/modules` @@ -2972,7 +2972,7 @@ $ cd testing And try it out: -```{ignore} +```{notrust} $ cargo run Compiling testing v0.0.1 (file:///home/you/projects/testing) Running `target/testing` @@ -3004,7 +3004,7 @@ you give them descriptive names. You'll see why in a moment. We then use a macro, `assert!`, to assert that something is true. In this case, we're giving it `false`, so this test should fail. Let's try it! -```{ignore} +```{notrust} $ cargo test Compiling testing v0.0.1 (file:///home/you/projects/testing) /home/you/projects/testing/src/main.rs:1:1: 3:2 warning: function is never used: `main`, #[warn(dead_code)] on by default @@ -3041,7 +3041,7 @@ $ cargo test You can run all of your tests with `cargo test`. This runs both your tests in `tests`, as well as the tests you put inside of your crate. -```{ignore} +```{notrust} /home/you/projects/testing/src/main.rs:1:1: 3:2 warning: function is never used: `main`, #[warn(dead_code)] on by default /home/you/projects/testing/src/main.rs:1 fn main() { /home/you/projects/testing/src/main.rs:2 println!("Hello, world!") @@ -3067,7 +3067,7 @@ with good names? This is why. Here, it says 'test foo' because we called our test 'foo.' If we had given it a good name, it'd be more clear which test failed, especially as we accumulate more tests. -```{ignore} +```{notrust} failures: ---- foo stdout ---- @@ -3169,7 +3169,7 @@ fn math_checks_out() { And try to run the test: -```{ignore} +```{notrust} $ cargo test Compiling testing v0.0.1 (file:///home/you/projects/testing) /home/you/projects/testing/tests/lib.rs:3:18: 3:38 error: unresolved name `add_three_times_four`. @@ -3332,7 +3332,7 @@ fn test_add_three() { We'd get this error: -```{ignore} +```{notrust} Compiling testing v0.0.1 (file:///home/you/projects/testing) /home/you/projects/testing/tests/lib.rs:3:5: 3:24 error: function `add_three` is private /home/you/projects/testing/tests/lib.rs:3 use testing::add_three; @@ -3504,7 +3504,7 @@ let y = &mut x; Rust will complain: -```{ignore} +```{notrust} error: cannot borrow immutable local variable `x` as mutable let y = &mut x; ^ @@ -3531,7 +3531,7 @@ let z = &mut x; It gives us this error: -```{ignore} +```{notrust} error: cannot borrow `x` as mutable more than once at a time let z = &mut x; ^ @@ -3677,7 +3677,7 @@ let z = &mut x; The error: -```{ignore} +```{notrust} error: cannot borrow `x` as mutable more than once at a time let z = &mut x; ^ @@ -3695,7 +3695,7 @@ note: previous borrow ends here This error comes in three parts. Let's go over each in turn. -```{ignore} +```{notrust} error: cannot borrow `x` as mutable more than once at a time let z = &mut x; ^ @@ -3704,7 +3704,7 @@ error: cannot borrow `x` as mutable more than once at a time This error states the restriction: you cannot lend out something mutable more than once at the same time. The borrow checker knows the rules! -```{ignore} +```{notrust} note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends let y = &mut x; ^ @@ -3819,7 +3819,7 @@ let y = &mut x; This gives us this error: -```{ignore} +```{notrust} error: cannot use `*x` because it was mutably borrowed *x; ^~ @@ -4887,7 +4887,7 @@ We can then use `T` inside the rest of the signature: `x` has type `T`, and half of the `Result` has type `T`. However, if we try to compile that example, we'll get an error: -```{ignore} +```{notrust} error: binary operation `==` cannot be applied to type `T` ``` @@ -4943,7 +4943,7 @@ we use `impl Trait for Item`, rather than just `impl Item`. So what's the big deal? Remember the error we were getting with our generic `inverse` function? -```{ignore} +```{notrust} error: binary operation `==` cannot be applied to type `T` ``` @@ -4958,7 +4958,7 @@ fn print_area(shape: T) { Rust complains: -```{ignore} +```{notrust} error: type `T` does not implement any method in scope named `area` ``` @@ -5115,7 +5115,7 @@ fn main() { Now that we've moved the structs and traits into their own module, we get an error: -```{ignore} +```{notrust} error: type `shapes::Circle` does not implement any method in scope named `area` ``` diff --git a/src/doc/intro.md b/src/doc/intro.md index 5574b047d9647..e2cccef5b4a1d 100644 --- a/src/doc/intro.md +++ b/src/doc/intro.md @@ -58,7 +58,7 @@ authors = ["Your Name "] ``` This is called a **manifest**, and it contains all of the metadata that Cargo -needs to compile your project. +needs to compile your project. Here's what's in `src/main.rs`: @@ -207,7 +207,7 @@ and two... ```{bash} $ g++ hello.cpp -Wall -Werror -$ ./a.out +$ ./a.out Segmentation fault (core dumped) ``` @@ -313,7 +313,7 @@ print `"Hello"`, or does Rust crash? Neither. It refuses to compile: -```{ignore} +```{notrust} $ cargo run Compiling hello_world v0.0.1 (file:///Users/you/src/hello_world) main.rs:8:5: 8:6 error: cannot borrow `v` as mutable because it is also borrowed as immutable @@ -428,7 +428,7 @@ fn main() { It gives us this error: -```{ignore} +```{notrust} 6:71 error: capture of moved value: `numbers` for j in range(0, 3) { numbers[j] += 1 } ^~~~~~~ diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 87fa44cea664f..4235531c199a2 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -44,7 +44,7 @@ pub use self::Ordering::*; use kinds::{Copy, Sized}; -use option::{Option, Some, None}; +use option::Option::{mod, Some, None}; /// Trait for values that can be compared for equality and inequality. /// diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 5e2d6266f0ec3..0697dfbb0f2e4 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -143,6 +143,9 @@ #![stable] +#[cfg(stage0)] +pub use self::Option::*; +#[cfg(not(stage0))] use self::Option::*; use cmp::{Eq, Ord}; diff --git a/src/libstd/os.rs b/src/libstd/os.rs index 689ee9349e875..6c91010f4cb35 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -1995,21 +1995,21 @@ mod tests { #[test] fn memory_map_file() { + use libc; use os::*; use io::fs::{File, unlink}; use io::SeekStyle::SeekSet; use io::FileMode::Open; use io::FileAccess::ReadWrite; - use libc::HANDLE; #[cfg(not(windows))] - fn get_fd(file: &File) -> c_int { + fn get_fd(file: &File) -> libc::c_int { use os::unix::AsRawFd; file.as_raw_fd() } #[cfg(windows)] - fn get_fd(file: &File) -> HANDLE { + fn get_fd(file: &File) -> libc::HANDLE { use os::windows::AsRawHandle; file.as_raw_handle() } diff --git a/src/test/compile-fail/lifetime-elision-return-type-requires-explicit-lifetime.rs b/src/test/compile-fail/lifetime-elision-return-type-requires-explicit-lifetime.rs index 5d96176434239..817582a877fa9 100644 --- a/src/test/compile-fail/lifetime-elision-return-type-requires-explicit-lifetime.rs +++ b/src/test/compile-fail/lifetime-elision-return-type-requires-explicit-lifetime.rs @@ -33,7 +33,6 @@ fn h(_x: &Foo) -> &int { //~ ERROR missing lifetime specifier fn i(_x: int) -> &int { //~ ERROR missing lifetime specifier //~^ HELP this function's return type contains a borrowed value -//~^^ HELP consider giving it a 'static lifetime panic!() } diff --git a/src/test/run-pass/ufcs-type-params.rs b/src/test/run-pass/ufcs-type-params.rs index f4ad78da4877e..ccd5a225222da 100644 --- a/src/test/run-pass/ufcs-type-params.rs +++ b/src/test/run-pass/ufcs-type-params.rs @@ -18,5 +18,5 @@ impl Foo for i32 { fn main() { let x: i32 = 1; - Foo::::get(&x) + Foo::::get(&x); }