From 39aa668a01fb671cff382a8237ec3993c9cc4c33 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Sun, 29 Mar 2015 17:38:05 -0400 Subject: Added Arc::try_unique --- src/liballoc/arc.rs | 56 +++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 6 deletions(-) (limited to 'src/liballoc') diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index 9b37ddc7ab5..5dcdddfafa4 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -242,6 +242,38 @@ pub fn weak_count(this: &Arc) -> usize { this.inner().weak.load(SeqCst) - #[unstable(feature = "alloc")] pub fn strong_count(this: &Arc) -> usize { this.inner().strong.load(SeqCst) } + +/// Try accessing a mutable reference to the contents behind an unique `Arc`. +/// +/// The access is granted only if this is the only reference to the object. +/// Otherwise, `None` is returned. +/// +/// # Examples +/// +/// ``` +/// # #![feature(alloc)] +/// use std::alloc::arc; +/// +/// let mut four = arc::Arc::new(4); +/// +/// arc::unique(&mut four).map(|num| *num = 5); +/// ``` +#[inline] +#[unstable(feature = "alloc")] +pub fn unique(this: &mut Arc) -> Option<&mut T> { + if strong_count(this) == 1 && weak_count(this) == 0 { + // This unsafety is ok because we're guaranteed that the pointer + // returned is the *only* pointer that will ever be returned to T. Our + // reference count is guaranteed to be 1 at this point, and we required + // the Arc itself to be `mut`, so we're returning the only possible + // reference to the inner data. + let inner = unsafe { &mut **this._ptr }; + Some(&mut inner.data) + }else { + None + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl Clone for Arc { /// Makes a clone of the `Arc`. @@ -312,11 +344,8 @@ impl Arc { self.inner().weak.load(SeqCst) != 1 { *self = Arc::new((**self).clone()) } - // This unsafety is ok because we're guaranteed that the pointer - // returned is the *only* pointer that will ever be returned to T. Our - // reference count is guaranteed to be 1 at this point, and we required - // the Arc itself to be `mut`, so we're returning the only possible - // reference to the inner data. + // As with `unique()`, the unsafety is ok because our reference was + // either unique to begin with, or became one upon cloning the contents. let inner = unsafe { &mut **self._ptr }; &mut inner.data } @@ -659,7 +688,7 @@ mod tests { use std::sync::atomic::Ordering::{Acquire, SeqCst}; use std::thread; use std::vec::Vec; - use super::{Arc, Weak, weak_count, strong_count}; + use super::{Arc, Weak, weak_count, strong_count, unique}; use std::sync::Mutex; struct Canary(*mut atomic::AtomicUsize); @@ -695,6 +724,21 @@ mod tests { assert_eq!((*arc_v)[4], 5); } + #[test] + fn test_arc_unique() { + let mut x = Arc::new(10); + assert!(unique(&mut x).is_some()); + { + let y = x.clone(); + assert!(unique(&mut x).is_none()); + } + { + let z = x.downgrade(); + assert!(unique(&mut x).is_none()); + } + assert!(unique(&mut x).is_some()); + } + #[test] fn test_cowarc_clone_make_unique() { let mut cow0 = Arc::new(75); -- cgit 1.4.1-3-g733a5 From 35c261aea0d891d31b3fda83da653cb1e385681f Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 30 Mar 2015 17:52:00 -0400 Subject: Add `#[fundamental]` annotations into libcore so that `Sized` and the `Fn` traits are considered fundamental, along with `Box` (though that is mostly for show; the real type is `~T` in the compiler). --- src/liballoc/boxed.rs | 1 + src/liballoc/lib.rs | 2 ++ src/libcore/lib.rs | 2 ++ src/libcore/marker.rs | 1 + src/libcore/ops.rs | 3 +++ 5 files changed, 9 insertions(+) (limited to 'src/liballoc') diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 550b25ac3a7..adfe0f461be 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -86,6 +86,7 @@ pub static HEAP: () = (); /// See the [module-level documentation](../../std/boxed/index.html) for more. #[lang = "owned_box"] #[stable(feature = "rust1", since = "1.0.0")] +#[fundamental] pub struct Box(Unique); impl Box { diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index b92dfa9117e..a8be63d6373 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -71,6 +71,8 @@ #![feature(no_std)] #![no_std] #![feature(allocator)] +#![feature(custom_attribute)] +#![feature(fundamental)] #![feature(lang_items, unsafe_destructor)] #![feature(box_syntax)] #![feature(optin_builtin_traits)] diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 5e8b7fba1f1..3a9af50fefb 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -70,8 +70,10 @@ #![feature(unboxed_closures)] #![feature(rustc_attrs)] #![feature(optin_builtin_traits)] +#![feature(fundamental)] #![feature(concat_idents)] #![feature(reflect)] +#![feature(custom_attribute)] #[macro_use] mod macros; diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index f755c912fcd..97bde9fc96e 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -49,6 +49,7 @@ impl !Send for Managed { } #[stable(feature = "rust1", since = "1.0.0")] #[lang="sized"] #[rustc_on_unimplemented = "`{Self}` does not have a constant size known at compile-time"] +#[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable pub trait Sized : MarkerTrait { // Empty. } diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs index 862eb16d0bf..399aec9afd4 100644 --- a/src/libcore/ops.rs +++ b/src/libcore/ops.rs @@ -1117,6 +1117,7 @@ impl<'a, T: ?Sized> DerefMut for &'a mut T { #[lang="fn"] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_paren_sugar] +#[fundamental] // so that regex can rely that `&str: !FnMut` pub trait Fn : FnMut { /// This is called when the call operator is used. extern "rust-call" fn call(&self, args: Args) -> Self::Output; @@ -1126,6 +1127,7 @@ pub trait Fn : FnMut { #[lang="fn_mut"] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_paren_sugar] +#[fundamental] // so that regex can rely that `&str: !FnMut` pub trait FnMut : FnOnce { /// This is called when the call operator is used. extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output; @@ -1135,6 +1137,7 @@ pub trait FnMut : FnOnce { #[lang="fn_once"] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_paren_sugar] +#[fundamental] // so that regex can rely that `&str: !FnMut` pub trait FnOnce { /// The returned type after the call operator is used. type Output; -- cgit 1.4.1-3-g733a5 From 30b2d9e7643de3a267029c2763edb0b44ff2396e Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 30 Mar 2015 17:50:31 -0400 Subject: Fallout in libstd: remove impls now considered to conflict. --- src/liballoc/boxed.rs | 7 ------- src/liballoc/boxed_test.rs | 8 ++++---- src/libcore/any.rs | 8 ++++++++ src/libcore/fmt/mod.rs | 6 ------ 4 files changed, 12 insertions(+), 17 deletions(-) (limited to 'src/liballoc') diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index adfe0f461be..c4541e34cdb 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -278,13 +278,6 @@ impl fmt::Debug for Box { } } -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for Box { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad("Box") - } -} - #[stable(feature = "rust1", since = "1.0.0")] impl Deref for Box { type Target = T; diff --git a/src/liballoc/boxed_test.rs b/src/liballoc/boxed_test.rs index 682d5f407c4..fc44ac4eac6 100644 --- a/src/liballoc/boxed_test.rs +++ b/src/liballoc/boxed_test.rs @@ -55,17 +55,17 @@ fn test_show() { let b = Box::new(Test) as Box; let a_str = format!("{:?}", a); let b_str = format!("{:?}", b); - assert_eq!(a_str, "Box"); - assert_eq!(b_str, "Box"); + assert_eq!(a_str, "Any"); + assert_eq!(b_str, "Any"); static EIGHT: usize = 8; static TEST: Test = Test; let a = &EIGHT as &Any; let b = &TEST as &Any; let s = format!("{:?}", a); - assert_eq!(s, "&Any"); + assert_eq!(s, "Any"); let s = format!("{:?}", b); - assert_eq!(s, "&Any"); + assert_eq!(s, "Any"); } #[test] diff --git a/src/libcore/any.rs b/src/libcore/any.rs index 0ffc4a229b5..320fdd50b35 100644 --- a/src/libcore/any.rs +++ b/src/libcore/any.rs @@ -71,6 +71,7 @@ #![stable(feature = "rust1", since = "1.0.0")] +use fmt; use marker::Send; use mem::transmute; use option::Option::{self, Some, None}; @@ -105,6 +106,13 @@ impl Any for T // Extension methods for Any trait objects. /////////////////////////////////////////////////////////////////////////////// +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for Any { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("Any") + } +} + impl Any { /// Returns true if the boxed type is the same as `T` #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index ffb358cdac8..3f8bbeb1feb 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -12,7 +12,6 @@ #![stable(feature = "rust1", since = "1.0.0")] -use any; use cell::{Cell, RefCell, Ref, RefMut, BorrowState}; use char::CharExt; use iter::Iterator; @@ -997,11 +996,6 @@ macro_rules! tuple { tuple! { T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, } -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a> Debug for &'a (any::Any+'a) { - fn fmt(&self, f: &mut Formatter) -> Result { f.pad("&Any") } -} - #[stable(feature = "rust1", since = "1.0.0")] impl Debug for [T] { fn fmt(&self, f: &mut Formatter) -> Result { -- cgit 1.4.1-3-g733a5 From ed63d32651105e56afceb94cbb86f115db235825 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 1 Apr 2015 10:11:46 -0400 Subject: Add (unstable) FnBox trait as a nicer replacement for `Thunk`. The doc comment includes a test that also shows how it can be used. --- src/liballoc/boxed.rs | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/libstd/lib.rs | 1 + 2 files changed, 76 insertions(+) (limited to 'src/liballoc') diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 550b25ac3a7..8d3a63ceb50 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -355,3 +355,78 @@ impl<'a, 'b> From<&'b str> for Box { } } } + +/// `FnBox` is a version of the `FnOnce` intended for use with boxed +/// closure objects. The idea is that where one would normally store a +/// `Box` in a data structure, you should use +/// `Box`. The two traits behave essentially the same, except +/// that a `FnBox` closure can only be called if it is boxed. (Note +/// that `FnBox` may be deprecated in the future if `Box` +/// closures become directly usable.) +/// +/// ### Example +/// +/// Here is a snippet of code which creates a hashmap full of boxed +/// once closures and then removes them one by one, calling each +/// closure as it is removed. Note that the type of the closures +/// stored in the map is `Box i32>` and not `Box i32>`. +/// +/// ``` +/// #![feature(core)] +/// +/// use std::boxed::FnBox; +/// use std::collections::HashMap; +/// +/// fn make_map() -> HashMap i32>> { +/// let mut map: HashMap i32>> = HashMap::new(); +/// map.insert(1, Box::new(|| 22)); +/// map.insert(2, Box::new(|| 44)); +/// map +/// } +/// +/// fn main() { +/// let mut map = make_map(); +/// for i in &[1, 2] { +/// let f = map.remove(&i).unwrap(); +/// assert_eq!(f(), i * 22); +/// } +/// } +/// ``` +#[cfg(not(stage0))] +#[rustc_paren_sugar] +#[unstable(feature = "core", reason = "Newly introduced")] +pub trait FnBox { + type Output; + + extern "rust-call" fn call_box(self: Box, args: A) -> Self::Output; +} + +#[cfg(not(stage0))] +impl FnBox for F + where F: FnOnce +{ + type Output = F::Output; + + extern "rust-call" fn call_box(self: Box, args: A) -> F::Output { + self.call_once(args) + } +} + +#[cfg(not(stage0))] +impl FnOnce for Box> { + type Output = R; + + extern "rust-call" fn call_once(self, args: A) -> R { + self.call_box(args) + } +} + +#[cfg(not(stage0))] +impl FnOnce for Box+Send> { + type Output = R; + + extern "rust-call" fn call_once(self, args: A) -> R { + self.call_box(args) + } +} diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 41ac3d60df5..3c73ce7634c 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -243,6 +243,7 @@ mod uint_macros; #[path = "num/f64.rs"] pub mod f64; pub mod ascii; + pub mod thunk; /* Common traits */ -- cgit 1.4.1-3-g733a5 From cade32acf6f5ff209ee082d70350d9bc0362985a Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 1 Apr 2015 11:12:30 -0400 Subject: Remove `Thunk` struct and `Invoke` trait; change `Thunk` to be an alias for `Box`. I found the alias was still handy because it is shorter than the fully written type. This is a [breaking-change]: convert code using `Invoke` to use `FnBox`, which is usually pretty straight-forward. Code using thunk mostly works if you change `Thunk::new => Box::new` and `foo.invoke(arg)` to `foo(arg)`. --- src/compiletest/compiletest.rs | 3 +-- src/liballoc/boxed.rs | 12 ++++------- src/librustdoc/test.rs | 3 +-- src/libstd/rt/at_exit_imp.rs | 2 +- src/libstd/rt/mod.rs | 3 +-- src/libstd/sync/future.rs | 5 +++-- src/libstd/sys/common/thread.rs | 3 ++- src/libstd/thread/mod.rs | 28 +++++++++++++++----------- src/libstd/thunk.rs | 42 +++------------------------------------ src/libtest/lib.rs | 29 ++++++++++++++------------- src/test/run-pass/issue-11709.rs | 2 +- src/test/run-pass/issue-11958.rs | 2 +- src/test/run-pass/issue-17897.rs | 6 +++--- src/test/run-pass/issue-18188.rs | 4 ++-- src/test/run-pass/issue-2190-1.rs | 4 ++-- src/test/run-pass/issue-3609.rs | 1 - 16 files changed, 56 insertions(+), 93 deletions(-) (limited to 'src/liballoc') diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs index 7fd09f9e1f5..f00ff9bcbe5 100644 --- a/src/compiletest/compiletest.rs +++ b/src/compiletest/compiletest.rs @@ -31,7 +31,6 @@ extern crate log; use std::env; use std::fs; use std::path::{Path, PathBuf}; -use std::thunk::Thunk; use getopts::{optopt, optflag, reqopt}; use common::Config; use common::{Pretty, DebugInfoGdb, DebugInfoLldb, Codegen}; @@ -351,7 +350,7 @@ pub fn make_test_name(config: &Config, testfile: &Path) -> test::TestName { pub fn make_test_closure(config: &Config, testfile: &Path) -> test::TestFn { let config = (*config).clone(); let testfile = testfile.to_path_buf(); - test::DynTestFn(Thunk::new(move || { + test::DynTestFn(Box::new(move || { runtest::run(config, &testfile) })) } diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 8d3a63ceb50..8e3be7dd05b 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -393,28 +393,25 @@ impl<'a, 'b> From<&'b str> for Box { /// } /// } /// ``` -#[cfg(not(stage0))] #[rustc_paren_sugar] #[unstable(feature = "core", reason = "Newly introduced")] pub trait FnBox { type Output; - extern "rust-call" fn call_box(self: Box, args: A) -> Self::Output; + fn call_box(self: Box, args: A) -> Self::Output; } -#[cfg(not(stage0))] impl FnBox for F where F: FnOnce { type Output = F::Output; - extern "rust-call" fn call_box(self: Box, args: A) -> F::Output { + fn call_box(self: Box, args: A) -> F::Output { self.call_once(args) } } -#[cfg(not(stage0))] -impl FnOnce for Box> { +impl<'a,A,R> FnOnce for Box+'a> { type Output = R; extern "rust-call" fn call_once(self, args: A) -> R { @@ -422,8 +419,7 @@ impl FnOnce for Box> { } } -#[cfg(not(stage0))] -impl FnOnce for Box+Send> { +impl<'a,A,R> FnOnce for Box+Send+'a> { type Output = R; extern "rust-call" fn call_once(self, args: A) -> R { diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index babbe15b17d..f5bee6240d4 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -19,7 +19,6 @@ use std::path::PathBuf; use std::process::Command; use std::str; use std::sync::{Arc, Mutex}; -use std::thunk::Thunk; use testing; use rustc_lint; @@ -366,7 +365,7 @@ impl Collector { ignore: should_ignore, should_panic: testing::ShouldPanic::No, // compiler failures are test failures }, - testfn: testing::DynTestFn(Thunk::new(move|| { + testfn: testing::DynTestFn(Box::new(move|| { runtest(&test, &cratename, libs, diff --git a/src/libstd/rt/at_exit_imp.rs b/src/libstd/rt/at_exit_imp.rs index 9079c0aaffb..beb2870807a 100644 --- a/src/libstd/rt/at_exit_imp.rs +++ b/src/libstd/rt/at_exit_imp.rs @@ -64,7 +64,7 @@ pub fn cleanup() { if queue as usize != 0 { let queue: Box = Box::from_raw(queue); for to_run in *queue { - to_run.invoke(()); + to_run(); } } } diff --git a/src/libstd/rt/mod.rs b/src/libstd/rt/mod.rs index 696c7960c3e..632d9647212 100644 --- a/src/libstd/rt/mod.rs +++ b/src/libstd/rt/mod.rs @@ -21,7 +21,6 @@ use prelude::v1::*; use sys; -use thunk::Thunk; use usize; // Reexport some of our utilities which are expected by other crates. @@ -153,7 +152,7 @@ fn lang_start(main: *const u8, argc: isize, argv: *const *const u8) -> isize { /// that the closure could not be registered, meaning that it is not scheduled /// to be rune. pub fn at_exit(f: F) -> Result<(), ()> { - if at_exit_imp::push(Thunk::new(f)) {Ok(())} else {Err(())} + if at_exit_imp::push(Box::new(f)) {Ok(())} else {Err(())} } /// One-time runtime cleanup. diff --git a/src/libstd/sync/future.rs b/src/libstd/sync/future.rs index b2afe28fed4..2cdde1aca9e 100644 --- a/src/libstd/sync/future.rs +++ b/src/libstd/sync/future.rs @@ -36,6 +36,7 @@ use core::prelude::*; use core::mem::replace; +use boxed::Box; use self::FutureState::*; use sync::mpsc::{Receiver, channel}; use thunk::Thunk; @@ -84,7 +85,7 @@ impl Future { match replace(&mut self.state, Evaluating) { Forced(_) | Evaluating => panic!("Logic error."), Pending(f) => { - self.state = Forced(f.invoke(())); + self.state = Forced(f()); self.get_ref() } } @@ -114,7 +115,7 @@ impl Future { * function. It is not spawned into another task. */ - Future {state: Pending(Thunk::new(f))} + Future {state: Pending(Box::new(f))} } } diff --git a/src/libstd/sys/common/thread.rs b/src/libstd/sys/common/thread.rs index f45daea18a2..1845b6266ed 100644 --- a/src/libstd/sys/common/thread.rs +++ b/src/libstd/sys/common/thread.rs @@ -25,6 +25,7 @@ pub fn start_thread(main: *mut libc::c_void) { unsafe { stack::record_os_managed_stack_bounds(0, usize::MAX); let _handler = stack_overflow::Handler::new(); - Box::from_raw(main as *mut Thunk).invoke(()); + let main: Box = Box::from_raw(main as *mut Thunk); + main(); } } diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 1202b353317..9ab35382845 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -257,7 +257,7 @@ impl Builder { pub fn spawn(self, f: F) -> io::Result where F: FnOnce(), F: Send + 'static { - self.spawn_inner(Thunk::new(f)).map(|i| JoinHandle(i)) + self.spawn_inner(Box::new(f)).map(|i| JoinHandle(i)) } /// Spawn a new child thread that must be joined within a given @@ -279,7 +279,7 @@ impl Builder { pub fn scoped<'a, T, F>(self, f: F) -> io::Result> where T: Send + 'a, F: FnOnce() -> T, F: Send + 'a { - self.spawn_inner(Thunk::new(f)).map(|inner| { + self.spawn_inner(Box::new(f)).map(|inner| { JoinGuard { inner: inner, _marker: PhantomData } }) } @@ -315,7 +315,7 @@ impl Builder { thread_info::set(imp::guard::current(), their_thread); } - let mut output = None; + let mut output: Option = None; let try_result = { let ptr = &mut output; @@ -327,7 +327,11 @@ impl Builder { // 'unwinding' flag in the thread itself. For these reasons, // this unsafety should be ok. unsafe { - unwind::try(move || *ptr = Some(f.invoke(()))) + unwind::try(move || { + let f: Thunk<(), T> = f; + let v: T = f(); + *ptr = Some(v) + }) } }; unsafe { @@ -340,7 +344,7 @@ impl Builder { }; Ok(JoinInner { - native: try!(unsafe { imp::create(stack_size, Thunk::new(main)) }), + native: try!(unsafe { imp::create(stack_size, Box::new(main)) }), thread: my_thread, packet: my_packet, joined: false, @@ -820,7 +824,7 @@ mod test { let x: Box<_> = box 1; let x_in_parent = (&*x) as *const i32 as usize; - spawnfn(Thunk::new(move|| { + spawnfn(Box::new(move|| { let x_in_child = (&*x) as *const i32 as usize; tx.send(x_in_child).unwrap(); })); @@ -832,7 +836,7 @@ mod test { #[test] fn test_avoid_copying_the_body_spawn() { avoid_copying_the_body(|v| { - thread::spawn(move || v.invoke(())); + thread::spawn(move || v()); }); } @@ -840,7 +844,7 @@ mod test { fn test_avoid_copying_the_body_thread_spawn() { avoid_copying_the_body(|f| { thread::spawn(move|| { - f.invoke(()); + f(); }); }) } @@ -849,7 +853,7 @@ mod test { fn test_avoid_copying_the_body_join() { avoid_copying_the_body(|f| { let _ = thread::spawn(move|| { - f.invoke(()) + f() }).join(); }) } @@ -862,13 +866,13 @@ mod test { // valgrind-friendly. try this at home, instead..!) const GENERATIONS: u32 = 16; fn child_no(x: u32) -> Thunk<'static> { - return Thunk::new(move|| { + return Box::new(move|| { if x < GENERATIONS { - thread::spawn(move|| child_no(x+1).invoke(())); + thread::spawn(move|| child_no(x+1)()); } }); } - thread::spawn(|| child_no(0).invoke(())); + thread::spawn(|| child_no(0)()); } #[test] diff --git a/src/libstd/thunk.rs b/src/libstd/thunk.rs index a9cb05b368f..6091794ed42 100644 --- a/src/libstd/thunk.rs +++ b/src/libstd/thunk.rs @@ -12,45 +12,9 @@ #![allow(missing_docs)] #![unstable(feature = "std_misc")] -use alloc::boxed::Box; +use alloc::boxed::{Box, FnBox}; use core::marker::Send; -use core::ops::FnOnce; -pub struct Thunk<'a, A=(),R=()> { - invoke: Box+Send + 'a>, -} +pub type Thunk<'a, A=(), R=()> = + Box + Send + 'a>; -impl<'a, R> Thunk<'a,(),R> { - pub fn new(func: F) -> Thunk<'a,(),R> - where F : FnOnce() -> R, F : Send + 'a - { - Thunk::with_arg(move|()| func()) - } -} - -impl<'a,A,R> Thunk<'a,A,R> { - pub fn with_arg(func: F) -> Thunk<'a,A,R> - where F : FnOnce(A) -> R, F : Send + 'a - { - Thunk { - invoke: Box::::new(func) - } - } - - pub fn invoke(self, arg: A) -> R { - self.invoke.invoke(arg) - } -} - -pub trait Invoke { - fn invoke(self: Box, arg: A) -> R; -} - -impl Invoke for F - where F : FnOnce(A) -> R -{ - fn invoke(self: Box, arg: A) -> R { - let f = *self; - f(arg) - } -} diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index f7e5c9f1dee..879ed03009f 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -62,6 +62,7 @@ use self::OutputLocation::*; use stats::Stats; use getopts::{OptGroup, optflag, optopt}; use serialize::Encodable; +use std::boxed::FnBox; use term::Terminal; use term::color::{Color, RED, YELLOW, GREEN, CYAN}; @@ -79,7 +80,7 @@ use std::path::PathBuf; use std::sync::mpsc::{channel, Sender}; use std::sync::{Arc, Mutex}; use std::thread; -use std::thunk::{Thunk, Invoke}; +use std::thunk::Thunk; use std::time::Duration; // to be used by rustc to compile tests in libtest @@ -158,7 +159,7 @@ pub enum TestFn { StaticBenchFn(fn(&mut Bencher)), StaticMetricFn(fn(&mut MetricMap)), DynTestFn(Thunk<'static>), - DynMetricFn(Box Invoke<&'a mut MetricMap>+'static>), + DynMetricFn(Box), DynBenchFn(Box) } @@ -936,7 +937,7 @@ pub fn run_test(opts: &TestOpts, io::set_print(box Sink(data2.clone())); io::set_panic(box Sink(data2)); } - testfn.invoke(()) + testfn() }).unwrap(); let test_result = calc_result(&desc, result_guard.join()); let stdout = data.lock().unwrap().to_vec(); @@ -957,7 +958,7 @@ pub fn run_test(opts: &TestOpts, } DynMetricFn(f) => { let mut mm = MetricMap::new(); - f.invoke(&mut mm); + f.call_box((&mut mm,)); // TODO unfortunate monitor_ch.send((desc, TrMetrics(mm), Vec::new())).unwrap(); return; } @@ -969,7 +970,7 @@ pub fn run_test(opts: &TestOpts, } DynTestFn(f) => run_test_inner(desc, monitor_ch, opts.nocapture, f), StaticTestFn(f) => run_test_inner(desc, monitor_ch, opts.nocapture, - Thunk::new(move|| f())) + Box::new(move|| f())) } } @@ -1185,7 +1186,7 @@ mod tests { ignore: true, should_panic: ShouldPanic::No, }, - testfn: DynTestFn(Thunk::new(move|| f())), + testfn: DynTestFn(Box::new(move|| f())), }; let (tx, rx) = channel(); run_test(&TestOpts::new(), false, desc, tx); @@ -1202,7 +1203,7 @@ mod tests { ignore: true, should_panic: ShouldPanic::No, }, - testfn: DynTestFn(Thunk::new(move|| f())), + testfn: DynTestFn(Box::new(move|| f())), }; let (tx, rx) = channel(); run_test(&TestOpts::new(), false, desc, tx); @@ -1219,7 +1220,7 @@ mod tests { ignore: false, should_panic: ShouldPanic::Yes(None) }, - testfn: DynTestFn(Thunk::new(move|| f())), + testfn: DynTestFn(Box::new(move|| f())), }; let (tx, rx) = channel(); run_test(&TestOpts::new(), false, desc, tx); @@ -1236,7 +1237,7 @@ mod tests { ignore: false, should_panic: ShouldPanic::Yes(Some("error message")) }, - testfn: DynTestFn(Thunk::new(move|| f())), + testfn: DynTestFn(Box::new(move|| f())), }; let (tx, rx) = channel(); run_test(&TestOpts::new(), false, desc, tx); @@ -1253,7 +1254,7 @@ mod tests { ignore: false, should_panic: ShouldPanic::Yes(Some("foobar")) }, - testfn: DynTestFn(Thunk::new(move|| f())), + testfn: DynTestFn(Box::new(move|| f())), }; let (tx, rx) = channel(); run_test(&TestOpts::new(), false, desc, tx); @@ -1270,7 +1271,7 @@ mod tests { ignore: false, should_panic: ShouldPanic::Yes(None) }, - testfn: DynTestFn(Thunk::new(move|| f())), + testfn: DynTestFn(Box::new(move|| f())), }; let (tx, rx) = channel(); run_test(&TestOpts::new(), false, desc, tx); @@ -1306,7 +1307,7 @@ mod tests { ignore: true, should_panic: ShouldPanic::No, }, - testfn: DynTestFn(Thunk::new(move|| {})), + testfn: DynTestFn(Box::new(move|| {})), }, TestDescAndFn { desc: TestDesc { @@ -1314,7 +1315,7 @@ mod tests { ignore: false, should_panic: ShouldPanic::No, }, - testfn: DynTestFn(Thunk::new(move|| {})), + testfn: DynTestFn(Box::new(move|| {})), }); let filtered = filter_tests(&opts, tests); @@ -1350,7 +1351,7 @@ mod tests { ignore: false, should_panic: ShouldPanic::No, }, - testfn: DynTestFn(Thunk::new(testfn)), + testfn: DynTestFn(Box::new(testfn)), }; tests.push(test); } diff --git a/src/test/run-pass/issue-11709.rs b/src/test/run-pass/issue-11709.rs index da3efb4fea8..3ad78f088f9 100644 --- a/src/test/run-pass/issue-11709.rs +++ b/src/test/run-pass/issue-11709.rs @@ -25,7 +25,7 @@ fn test(slot: &mut Option>) -> () { let a = slot.take(); let _a = match a { // `{let .. a(); }` would break - Some(a) => { let _a = a.invoke(()); }, + Some(a) => { let _a = a(); }, None => (), }; } diff --git a/src/test/run-pass/issue-11958.rs b/src/test/run-pass/issue-11958.rs index ed2009dab1b..def85b47667 100644 --- a/src/test/run-pass/issue-11958.rs +++ b/src/test/run-pass/issue-11958.rs @@ -23,5 +23,5 @@ use std::thunk::Thunk; pub fn main() { let mut x = 1; - let _thunk = Thunk::new(move|| { x = 2; }); + let _thunk = Box::new(move|| { x = 2; }); } diff --git a/src/test/run-pass/issue-17897.rs b/src/test/run-pass/issue-17897.rs index 3fbdb92e906..cf8c54fdd80 100644 --- a/src/test/run-pass/issue-17897.rs +++ b/src/test/run-pass/issue-17897.rs @@ -12,10 +12,10 @@ use std::thunk::Thunk; -fn action(cb: Thunk) -> usize { - cb.invoke(1) +fn action(cb: Thunk<(usize,), usize>) -> usize { + cb(1) } pub fn main() { - println!("num: {}", action(Thunk::with_arg(move |u| u))); + println!("num: {}", action(Box::new(move |u| u))); } diff --git a/src/test/run-pass/issue-18188.rs b/src/test/run-pass/issue-18188.rs index cd28d642551..059d25173c2 100644 --- a/src/test/run-pass/issue-18188.rs +++ b/src/test/run-pass/issue-18188.rs @@ -16,13 +16,13 @@ use std::thunk::Thunk; pub trait Promisable: Send + Sync {} impl Promisable for T {} -pub fn propagate<'a, T, E, F, G>(action: F) -> Thunk<'a,Result, Result> +pub fn propagate<'a, T, E, F, G>(action: F) -> Thunk<'a, (Result,), Result> where T: Promisable + Clone + 'a, E: Promisable + Clone + 'a, F: FnOnce(&T) -> Result + Send + 'a, G: FnOnce(Result) -> Result + 'a { - Thunk::with_arg(move |result: Result| { + Box::new(move |result: Result| { match result { Ok(ref t) => action(t), Err(ref e) => Err(e.clone()), diff --git a/src/test/run-pass/issue-2190-1.rs b/src/test/run-pass/issue-2190-1.rs index b2c21a274cb..5c84c30aa7f 100644 --- a/src/test/run-pass/issue-2190-1.rs +++ b/src/test/run-pass/issue-2190-1.rs @@ -18,11 +18,11 @@ use std::thunk::Thunk; static generations: usize = 1024+256+128+49; fn spawn(f: Thunk<'static>) { - Builder::new().stack_size(32 * 1024).spawn(move|| f.invoke(())); + Builder::new().stack_size(32 * 1024).spawn(move|| f()); } fn child_no(x: usize) -> Thunk<'static> { - Thunk::new(move|| { + Box::new(move|| { if x < generations { spawn(child_no(x+1)); } diff --git a/src/test/run-pass/issue-3609.rs b/src/test/run-pass/issue-3609.rs index 45eb21374e2..2167a3df976 100644 --- a/src/test/run-pass/issue-3609.rs +++ b/src/test/run-pass/issue-3609.rs @@ -13,7 +13,6 @@ use std::thread; use std::sync::mpsc::Sender; -use std::thunk::Invoke; type RingBuffer = Vec ; type SamplesFn = Box; -- cgit 1.4.1-3-g733a5 From 19d3dab31b1fca3abc3ba00173b9148bd70d24b0 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 1 Apr 2015 15:25:47 -0400 Subject: Collect the definition of the `Error` trait into `libstd` for now. This sidesteps a coherence difficulty where `liballoc` had to prove that `&str: !Error`, which didn't involve any local types. --- src/liballoc/boxed.rs | 53 +-------------- src/libcollections/string.rs | 11 ---- src/libcore/error.rs | 56 ---------------- src/libcore/lib.rs | 1 - src/libcore/num/mod.rs | 41 ++++++------ src/libcore/str/mod.rs | 16 ----- src/libstd/error.rs | 152 +++++++++++++++++++++++++++++++++++++++++++ src/libstd/lib.rs | 2 +- 8 files changed, 175 insertions(+), 157 deletions(-) delete mode 100644 src/libcore/error.rs create mode 100644 src/libstd/error.rs (limited to 'src/liballoc') diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index c4541e34cdb..bbf5d7a6042 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -51,15 +51,12 @@ use core::prelude::*; use core::any::Any; use core::cmp::Ordering; use core::default::Default; -use core::error::Error; use core::fmt; use core::hash::{self, Hash}; use core::mem; use core::ops::{Deref, DerefMut}; -use core::ptr::{self, Unique}; -use core::raw::{TraitObject, Slice}; - -use heap; +use core::ptr::{Unique}; +use core::raw::{TraitObject}; /// A value that represents the heap. This is the default place that the `box` /// keyword allocates into when no place is supplied. @@ -303,49 +300,3 @@ impl DoubleEndedIterator for Box { #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for Box {} -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, E: Error + 'a> From for Box { - fn from(err: E) -> Box { - Box::new(err) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, E: Error + Send + 'a> From for Box { - fn from(err: E) -> Box { - Box::new(err) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, 'b> From<&'b str> for Box { - fn from(err: &'b str) -> Box { - #[derive(Debug)] - struct StringError(Box); - impl Error for StringError { - fn description(&self) -> &str { &self.0 } - } - impl fmt::Display for StringError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.0.fmt(f) - } - } - - // Unfortunately `String` is located in libcollections, so we construct - // a `Box` manually here. - unsafe { - let alloc = if err.len() == 0 { - 0 as *mut u8 - } else { - let ptr = heap::allocate(err.len(), 1); - if ptr.is_null() { ::oom(); } - ptr as *mut u8 - }; - ptr::copy(err.as_bytes().as_ptr(), alloc, err.len()); - Box::new(StringError(mem::transmute(Slice { - data: alloc, - len: err.len(), - }))) - } - } -} diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index d8d7ad9887a..7a772532091 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -17,7 +17,6 @@ use core::prelude::*; use core::default::Default; -use core::error::Error; use core::fmt; use core::hash; use core::iter::{IntoIterator, FromIterator}; @@ -723,11 +722,6 @@ impl fmt::Display for FromUtf8Error { } } -#[stable(feature = "rust1", since = "1.0.0")] -impl Error for FromUtf8Error { - fn description(&self) -> &str { "invalid utf-8" } -} - #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Display for FromUtf16Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -735,11 +729,6 @@ impl fmt::Display for FromUtf16Error { } } -#[stable(feature = "rust1", since = "1.0.0")] -impl Error for FromUtf16Error { - fn description(&self) -> &str { "invalid utf-16" } -} - #[stable(feature = "rust1", since = "1.0.0")] impl FromIterator for String { fn from_iter>(iter: I) -> String { diff --git a/src/libcore/error.rs b/src/libcore/error.rs deleted file mode 100644 index 24035b7d9a8..00000000000 --- a/src/libcore/error.rs +++ /dev/null @@ -1,56 +0,0 @@ -// 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. - -//! Traits for working with Errors. -//! -//! # The `Error` trait -//! -//! `Error` is a trait representing the basic expectations for error values, -//! i.e. values of type `E` in `Result`. At a minimum, errors must provide -//! a description, but they may optionally provide additional detail (via -//! `Display`) and cause chain information: -//! -//! ``` -//! use std::fmt::Display; -//! -//! trait Error: Display { -//! fn description(&self) -> &str; -//! -//! fn cause(&self) -> Option<&Error> { None } -//! } -//! ``` -//! -//! The `cause` method is generally used when errors cross "abstraction -//! boundaries", i.e. when a one module must report an error that is "caused" -//! by an error from a lower-level module. This setup makes it possible for the -//! high-level module to provide its own errors that do not commit to any -//! particular implementation, but also reveal some of its implementation for -//! debugging via `cause` chains. - -#![stable(feature = "rust1", since = "1.0.0")] - -use prelude::*; -use fmt::{Debug, Display}; - -/// Base functionality for all errors in Rust. -#[stable(feature = "rust1", since = "1.0.0")] -pub trait Error: Debug + Display { - /// A short description of the error. - /// - /// The description should not contain newlines or sentence-ending - /// punctuation, to facilitate embedding in larger user-facing - /// strings. - #[stable(feature = "rust1", since = "1.0.0")] - fn description(&self) -> &str; - - /// The lower-level cause of this error, if any. - #[stable(feature = "rust1", since = "1.0.0")] - fn cause(&self) -> Option<&Error> { None } -} diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 3a9af50fefb..2189e2c3ad1 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -147,7 +147,6 @@ pub mod slice; pub mod str; pub mod hash; pub mod fmt; -pub mod error; #[doc(primitive = "bool")] mod bool { diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index a4829ed96b3..7daa1a9f420 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -20,7 +20,6 @@ use self::wrapping::{OverflowingOps, WrappingOps}; use char::CharExt; use clone::Clone; use cmp::{PartialEq, Eq, PartialOrd, Ord}; -use error::Error; use fmt; use intrinsics; use iter::Iterator; @@ -2948,16 +2947,9 @@ enum IntErrorKind { Underflow, } -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Display for ParseIntError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.description().fmt(f) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Error for ParseIntError { - fn description(&self) -> &str { +impl ParseIntError { + #[unstable(feature = "core", reason = "available through Error trait")] + pub fn description(&self) -> &str { match self.kind { IntErrorKind::Empty => "cannot parse integer from empty string", IntErrorKind::InvalidDigit => "invalid digit found in string", @@ -2967,6 +2959,13 @@ impl Error for ParseIntError { } } +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for ParseIntError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.description().fmt(f) + } +} + /// An error which can be returned when parsing a float. #[derive(Debug, Clone, PartialEq)] #[stable(feature = "rust1", since = "1.0.0")] @@ -2978,19 +2977,19 @@ enum FloatErrorKind { Invalid, } -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Display for ParseFloatError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.description().fmt(f) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Error for ParseFloatError { - fn description(&self) -> &str { +impl ParseFloatError { + #[unstable(feature = "core", reason = "available through Error trait")] + pub fn description(&self) -> &str { match self.kind { FloatErrorKind::Empty => "cannot parse float from empty string", FloatErrorKind::Invalid => "invalid float literal", } } } + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for ParseFloatError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.description().fmt(f) + } +} diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 934c4515614..4c366d32718 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -22,7 +22,6 @@ use char::CharExt; use clone::Clone; use cmp::{self, Eq}; use default::Default; -use error::Error; use fmt; use iter::ExactSizeIterator; use iter::{Map, Iterator, DoubleEndedIterator}; @@ -192,11 +191,6 @@ impl fmt::Display for ParseBoolError { } } -#[stable(feature = "rust1", since = "1.0.0")] -impl Error for ParseBoolError { - fn description(&self) -> &str { "failed to parse bool" } -} - /* Section: Creating a string */ @@ -241,16 +235,6 @@ pub unsafe fn from_utf8_unchecked<'a>(v: &'a [u8]) -> &'a str { mem::transmute(v) } -#[stable(feature = "rust1", since = "1.0.0")] -impl Error for Utf8Error { - fn description(&self) -> &str { - match *self { - Utf8Error::TooShort => "invalid utf-8: not enough bytes", - Utf8Error::InvalidByte(..) => "invalid utf-8: corrupt contents", - } - } -} - #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Display for Utf8Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { diff --git a/src/libstd/error.rs b/src/libstd/error.rs new file mode 100644 index 00000000000..150ffcdd77a --- /dev/null +++ b/src/libstd/error.rs @@ -0,0 +1,152 @@ +// 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. + +//! Traits for working with Errors. +//! +//! # The `Error` trait +//! +//! `Error` is a trait representing the basic expectations for error values, +//! i.e. values of type `E` in `Result`. At a minimum, errors must provide +//! a description, but they may optionally provide additional detail (via +//! `Display`) and cause chain information: +//! +//! ``` +//! use std::fmt::Display; +//! +//! trait Error: Display { +//! fn description(&self) -> &str; +//! +//! fn cause(&self) -> Option<&Error> { None } +//! } +//! ``` +//! +//! The `cause` method is generally used when errors cross "abstraction +//! boundaries", i.e. when a one module must report an error that is "caused" +//! by an error from a lower-level module. This setup makes it possible for the +//! high-level module to provide its own errors that do not commit to any +//! particular implementation, but also reveal some of its implementation for +//! debugging via `cause` chains. + +#![stable(feature = "rust1", since = "1.0.0")] + +// A note about crates and the facade: +// +// Originally, the `Error` trait was defined in libcore, and the impls +// were scattered about. However, coherence objected to this +// arrangement, because to create the blanket impls for `Box` required +// knowing that `&str: !Error`, and we have no means to deal with that +// sort of conflict just now. Therefore, for the time being, we have +// moved the `Error` trait into libstd. As we evolve a sol'n to the +// coherence challenge (e.g., specialization, neg impls, etc) we can +// reconsider what crate these items belong in. + +use boxed::Box; +use convert::From; +use fmt::{self, Debug, Display}; +use marker::Send; +use num; +use option::Option; +use option::Option::None; +use str; +use string::{self, String}; + +/// Base functionality for all errors in Rust. +#[stable(feature = "rust1", since = "1.0.0")] +pub trait Error: Debug + Display { + /// A short description of the error. + /// + /// The description should not contain newlines or sentence-ending + /// punctuation, to facilitate embedding in larger user-facing + /// strings. + #[stable(feature = "rust1", since = "1.0.0")] + fn description(&self) -> &str; + + /// The lower-level cause of this error, if any. + #[stable(feature = "rust1", since = "1.0.0")] + fn cause(&self) -> Option<&Error> { None } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, E: Error + 'a> From for Box { + fn from(err: E) -> Box { + Box::new(err) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, E: Error + Send + 'a> From for Box { + fn from(err: E) -> Box { + Box::new(err) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, 'b> From<&'b str> for Box { + fn from(err: &'b str) -> Box { + #[derive(Debug)] + struct StringError(String); + + impl Error for StringError { + fn description(&self) -> &str { &self.0 } + } + + impl Display for StringError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + Display::fmt(&self.0, f) + } + } + + Box::new(StringError(String::from_str(err))) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Error for str::ParseBoolError { + fn description(&self) -> &str { "failed to parse bool" } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Error for str::Utf8Error { + fn description(&self) -> &str { + match *self { + str::Utf8Error::TooShort => "invalid utf-8: not enough bytes", + str::Utf8Error::InvalidByte(..) => "invalid utf-8: corrupt contents", + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Error for num::ParseIntError { + fn description(&self) -> &str { + self.description() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Error for num::ParseFloatError { + fn description(&self) -> &str { + self.description() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Error for string::FromUtf8Error { + fn description(&self) -> &str { + "invalid utf-8" + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Error for string::FromUtf16Error { + fn description(&self) -> &str { + "invalid utf-16" + } +} + diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 41ac3d60df5..807f0c5753e 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -183,7 +183,7 @@ pub use core::raw; pub use core::simd; pub use core::result; pub use core::option; -pub use core::error; +pub mod error; #[cfg(not(test))] pub use alloc::boxed; pub use alloc::rc; -- cgit 1.4.1-3-g733a5 From 0304e15e5c39654346e827c2bb25ca41ed310c86 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 1 Apr 2015 14:04:20 -0700 Subject: Test fixes and rebase conflicts, round 1 --- src/liballoc/arc.rs | 5 ++++- src/librustdoc/clean/mod.rs | 6 ++++-- 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'src/liballoc') diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index 73d109f3c8d..f87c450eda5 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -252,11 +252,14 @@ pub fn strong_count(this: &Arc) -> usize { this.inner().strong.load(SeqCst /// /// ``` /// # #![feature(alloc)] -/// use std::alloc::arc; +/// extern crate alloc; +/// # fn main() { +/// use alloc::arc; /// /// let mut four = arc::Arc::new(4); /// /// arc::unique(&mut four).map(|num| *num = 5); +/// # } /// ``` #[inline] #[unstable(feature = "alloc")] diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index e4d9fac5b9c..e0ed83f4019 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2392,7 +2392,7 @@ fn resolve_type(cx: &DocContext, }; match def { - def::DefSelfTy(..) => { + def::DefSelfTy(..) if path.segments.len() == 1 => { return Generic(token::get_name(special_idents::type_self.name).to_string()); } def::DefPrimTy(p) => match p { @@ -2412,7 +2412,9 @@ fn resolve_type(cx: &DocContext, ast::TyFloat(ast::TyF32) => return Primitive(F32), ast::TyFloat(ast::TyF64) => return Primitive(F64), }, - def::DefTyParam(_, _, _, n) => return Generic(token::get_name(n).to_string()), + def::DefTyParam(_, _, _, n) => { + return Generic(token::get_name(n).to_string()) + } _ => {} }; let did = register_def(&*cx, def); -- cgit 1.4.1-3-g733a5