From 4e9724df9f2f5c46dac2ba8c8ddcb124212ac37c Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Tue, 11 Feb 2014 22:43:23 -0800 Subject: [PATCH 1/8] Stop unloading syntax libraries Externally loaded libraries are able to do things that cause references to them to survive past the expansion phase (e.g. creating @-box cycles, launching a task or storing something in task local data). As such, the library has to stay loaded for the lifetime of the process. --- src/libsyntax/ext/base.rs | 8 ----- src/libsyntax/ext/expand.rs | 10 ++++-- .../macro_crate_outlive_expansion_phase.rs | 35 +++++++++++++++++++ .../macro-crate-outlive-expansion-phase.rs | 21 +++++++++++ 4 files changed, 63 insertions(+), 11 deletions(-) create mode 100644 src/test/auxiliary/macro_crate_outlive_expansion_phase.rs create mode 100644 src/test/run-pass-fulldeps/macro-crate-outlive-expansion-phase.rs diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index d22a1d697fcb4..02c3a1b985be3 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -20,7 +20,6 @@ use parse::token::{InternedString, intern, str_to_ident}; use util::small_vector::SmallVector; use std::hashmap::HashMap; -use std::unstable::dynamic_lib::DynamicLibrary; // new-style macro! tt code: // @@ -143,8 +142,6 @@ pub struct BlockInfo { macros_escape : bool, // what are the pending renames? pending_renames : RenameList, - // references for crates loaded in this scope - macro_crates: ~[DynamicLibrary], } impl BlockInfo { @@ -152,7 +149,6 @@ impl BlockInfo { BlockInfo { macros_escape: false, pending_renames: ~[], - macro_crates: ~[], } } } @@ -551,10 +547,6 @@ impl SyntaxEnv { self.find_escape_frame().map.insert(k, v); } - pub fn insert_macro_crate(&mut self, lib: DynamicLibrary) { - self.find_escape_frame().info.macro_crates.push(lib); - } - pub fn info<'a>(&'a mut self) -> &'a mut BlockInfo { &mut self.chain[self.chain.len()-1].info } diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index d146cd4dae392..d79c4cbc96a9b 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.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. // @@ -28,6 +28,7 @@ use visit; use visit::Visitor; use util::small_vector::SmallVector; +use std::cast; use std::vec; use std::unstable::dynamic_lib::DynamicLibrary; use std::os; @@ -469,9 +470,12 @@ fn load_extern_macros(crate: &ast::ViewItem, fld: &mut MacroExpander) { }; fld.extsbox.insert(name, extension); }); - } - fld.extsbox.insert_macro_crate(lib); + // Intentionally leak the dynamic library. We can't ever unload it + // since the library can do things that will outlive the expansion + // phase (e.g. make an @-box cycle or launch a task). + cast::forget(lib); + } } // expand a stmt diff --git a/src/test/auxiliary/macro_crate_outlive_expansion_phase.rs b/src/test/auxiliary/macro_crate_outlive_expansion_phase.rs new file mode 100644 index 0000000000000..eecbb325630d3 --- /dev/null +++ b/src/test/auxiliary/macro_crate_outlive_expansion_phase.rs @@ -0,0 +1,35 @@ +// 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. + +// force-host + +#[feature(macro_registrar)]; + +extern mod syntax; + +use std::any::Any; +use std::local_data; +use syntax::ast::Name; +use syntax::ext::base::SyntaxExtension; + +struct Foo { + foo: int +} + +impl Drop for Foo { + fn drop(&mut self) {} +} + +#[macro_registrar] +pub fn registrar(_: |Name, SyntaxExtension|) { + local_data_key!(foo: ~Any); + local_data::set(foo, ~Foo { foo: 10 } as ~Any); +} + diff --git a/src/test/run-pass-fulldeps/macro-crate-outlive-expansion-phase.rs b/src/test/run-pass-fulldeps/macro-crate-outlive-expansion-phase.rs new file mode 100644 index 0000000000000..a71cc465e88dc --- /dev/null +++ b/src/test/run-pass-fulldeps/macro-crate-outlive-expansion-phase.rs @@ -0,0 +1,21 @@ +// 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. + +// aux-build:macro_crate_outlive_expansion_phase.rs +// ignore-stage1 +// ignore-fast +// ignore-android + +#[feature(phase)]; + +#[phase(syntax)] +extern mod macro_crate_outlive_expansion_phase; + +pub fn main() {} From e9058e0e668065a7458df32a33570c037ff5b7e3 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 12 Feb 2014 11:42:58 -0800 Subject: [PATCH 2/8] Include compiler-rt in the distribution tarballs --- mk/dist.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mk/dist.mk b/mk/dist.mk index 6d4e4401eaff7..aea263c961987 100644 --- a/mk/dist.mk +++ b/mk/dist.mk @@ -12,7 +12,7 @@ PKG_ICO = $(S)src/etc/pkg/rust-logo.ico PKG_EXE = $(PKG_DIR)-install.exe endif -PKG_GITMODULES := $(S)src/libuv $(S)src/llvm $(S)src/gyp +PKG_GITMODULES := $(S)src/libuv $(S)src/llvm $(S)src/gyp $(S)src/compiler-rt PKG_FILES := \ $(S)COPYRIGHT \ From fb595cd758e51a6ab4b29adecfd89a3cf3f8e439 Mon Sep 17 00:00:00 2001 From: Seo Sanghyeon Date: Thu, 13 Feb 2014 00:42:28 +0900 Subject: [PATCH 3/8] Resolve type variables when checking casting to char --- src/librustc/middle/typeck/check/mod.rs | 1 + src/test/run-pass/issue-9918.rs | 13 +++++++++++++ 2 files changed, 14 insertions(+) create mode 100644 src/test/run-pass/issue-9918.rs diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 9eec804dd2e11..68511362f5ffc 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -3035,6 +3035,7 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt, if type_is_c_like_enum(fcx, expr.span, t_e) && t_1_is_trivial { // casts from C-like enums are allowed } else if t_1_is_char { + let te = fcx.infcx().resolve_type_vars_if_possible(te); if ty::get(te).sty != ty::ty_uint(ast::TyU8) { fcx.type_error_message(expr.span, |actual| { format!("only `u8` can be cast as `char`, not `{}`", actual) diff --git a/src/test/run-pass/issue-9918.rs b/src/test/run-pass/issue-9918.rs new file mode 100644 index 0000000000000..240a134221d34 --- /dev/null +++ b/src/test/run-pass/issue-9918.rs @@ -0,0 +1,13 @@ +// 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. + +pub fn main() { + assert_eq!((0 + 0u8) as char, '\0'); +} From 7a564306204c1775a3655f48330ec4320fa6f2cf Mon Sep 17 00:00:00 2001 From: Matthijs van der Vleuten Date: Wed, 12 Feb 2014 13:11:12 +0100 Subject: [PATCH 4/8] doc: rename 'nil' to 'unit' when describing `()` --- src/doc/tutorial.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/doc/tutorial.md b/src/doc/tutorial.md index 91d5e490949a1..61eccb520552b 100644 --- a/src/doc/tutorial.md +++ b/src/doc/tutorial.md @@ -293,7 +293,7 @@ braced block gives the whole block the value of that last expression. Put another way, the semicolon in Rust *ignores the value of an expression*. Thus, if the branches of the `if` had looked like `{ 4; }`, the above example -would simply assign `()` (nil or void) to `price`. But without the semicolon, each +would simply assign `()` (unit or void) to `price`. But without the semicolon, each branch has a different value, and `price` gets the value of the branch that was taken. @@ -352,7 +352,7 @@ before the opening and after the closing quote, and can contain any sequence of characters except their closing delimiter. More on strings [later](#vectors-and-strings). -The nil type, written `()`, has a single value, also written `()`. +The unit type, written `()`, has a single value, also written `()`. ## Operators @@ -852,7 +852,7 @@ fn line(a: int, b: int, x: int) -> int { It's better Rust style to write a return value this way instead of writing an explicit `return`. The utility of `return` comes in when returning early from a function. Functions that do not return a value -are said to return nil, `()`, and both the return type and the return +are said to return unit, `()`, and both the return type and the return value may be omitted from the definition. The following two functions are equivalent. From cdc384354b62c817602bbd2f14e6f3c87853ee9b Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Sun, 9 Feb 2014 23:13:47 +0100 Subject: [PATCH 5/8] Remove a source of O(n^2) running time in bigints. ::num::bigint, Remove a source of O(n^2) running time in `fn shr_bits`. I'll cut to the chase: On my laptop, this brings the running time on `pidigits 2000` (from src/test/bench/shootout-pidigits.rs) from this: ``` % time ./pidigits 2000 > /dev/null real 0m7.695s user 0m7.690s sys 0m0.005s ``` to this: ``` % time ./pidigits 2000 > /dev/null real 0m0.322s user 0m0.318s sys 0m0.004s ``` The previous code was building up a vector by repeatedly making a fresh copy for each element that was unshifted onto the front, yielding quadratic running time. This fixes that by building up the vector in reverse order (pushing elements onto the end) and then reversing it. (Another option would be to build up a zero-initialized vector of the desired length and then installing all of the shifted result elements into their target index, but this was easier to hack up quickly, and yields the desired asymptotic improvement. I have been thinking of adding a `vec::from_fn_rev` to handle this case, maybe I will try that this weekend.) --- src/libnum/bigint.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/libnum/bigint.rs b/src/libnum/bigint.rs index 56385c6f43b4d..8f632ae639dcc 100644 --- a/src/libnum/bigint.rs +++ b/src/libnum/bigint.rs @@ -784,11 +784,12 @@ impl BigUint { if n_bits == 0 || self.data.is_empty() { return (*self).clone(); } let mut borrow = 0; - let mut shifted = ~[]; + let mut shifted_rev = vec::with_capacity(self.data.len()); for elem in self.data.rev_iter() { - shifted = ~[(*elem >> n_bits) | borrow] + shifted; + shifted_rev.push((*elem >> n_bits) | borrow); borrow = *elem << (BigDigit::bits - n_bits); } + let shifted = { shifted_rev.reverse(); shifted_rev }; return BigUint::new(shifted); } @@ -2637,4 +2638,15 @@ mod bench { fib.to_str(); }); } + + #[bench] + fn shr(bh: &mut BenchHarness) { + let n = { let one : BigUint = One::one(); one << 1000 }; + bh.iter(|| { + let mut m = n.clone(); + for _ in range(0, 10) { + m = m >> 1; + } + }) + } } From 643691757fa3d914d00c1ae278e1642ec29ffde4 Mon Sep 17 00:00:00 2001 From: Liigo Zhuang Date: Wed, 12 Feb 2014 08:40:52 +0800 Subject: [PATCH 6/8] Move base64 and hex from libextra to libserialize --- src/libextra/lib.rs | 2 -- src/librustc/back/link.rs | 2 +- src/librustc/util/sha2.rs | 4 ++-- src/{libextra => libserialize}/base64.rs | 12 ++++++------ src/{libextra => libserialize}/hex.rs | 10 ++++++---- src/libserialize/lib.rs | 4 ++++ 6 files changed, 19 insertions(+), 15 deletions(-) rename src/{libextra => libserialize}/base64.rs (97%) rename src/{libextra => libserialize}/hex.rs (96%) diff --git a/src/libextra/lib.rs b/src/libextra/lib.rs index 70a21da6816d8..e0200f48cfeca 100644 --- a/src/libextra/lib.rs +++ b/src/libextra/lib.rs @@ -59,11 +59,9 @@ pub mod url; pub mod json; pub mod tempfile; pub mod time; -pub mod base64; pub mod workcache; pub mod enum_set; pub mod stats; -pub mod hex; #[cfg(unicode)] mod unicode; diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index 72ae70565a750..957ca3b46c9d1 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -34,7 +34,7 @@ use std::run; use std::str; use std::io; use std::io::fs; -use extra::hex::ToHex; +use serialize::hex::ToHex; use extra::tempfile::TempDir; use syntax::abi; use syntax::ast; diff --git a/src/librustc/util/sha2.rs b/src/librustc/util/sha2.rs index 116ec6bba2904..940cebf78471e 100644 --- a/src/librustc/util/sha2.rs +++ b/src/librustc/util/sha2.rs @@ -16,7 +16,7 @@ use std::iter::range_step; use std::num::Zero; use std::vec; use std::vec::bytes::{MutableByteVector, copy_memory}; -use extra::hex::ToHex; +use serialize::hex::ToHex; /// Write a u32 into a vector, which must be 4 bytes long. The value is written in big-endian /// format. @@ -529,7 +529,7 @@ mod tests { use std::vec; use std::rand::isaac::IsaacRng; use std::rand::Rng; - use extra::hex::FromHex; + use serialize::hex::FromHex; // A normal addition - no overflow occurs #[test] diff --git a/src/libextra/base64.rs b/src/libserialize/base64.rs similarity index 97% rename from src/libextra/base64.rs rename to src/libserialize/base64.rs index 556032af1ac84..c22eefdb33020 100644 --- a/src/libextra/base64.rs +++ b/src/libserialize/base64.rs @@ -63,8 +63,8 @@ impl<'a> ToBase64 for &'a [u8] { * # Example * * ```rust - * extern mod extra; - * use extra::base64::{ToBase64, STANDARD}; + * extern mod serialize; + * use serialize::base64::{ToBase64, STANDARD}; * * fn main () { * let str = [52,32].to_base64(STANDARD); @@ -189,8 +189,8 @@ impl<'a> FromBase64 for &'a str { * This converts a string literal to base64 and back. * * ```rust - * extern mod extra; - * use extra::base64::{ToBase64, FromBase64, STANDARD}; + * extern mod serialize; + * use serialize::base64::{ToBase64, FromBase64, STANDARD}; * use std::str; * * fn main () { @@ -261,8 +261,8 @@ impl<'a> FromBase64 for &'a str { #[cfg(test)] mod test { - use test::BenchHarness; - use base64::*; + use extra::test::BenchHarness; + use base64::{Config, FromBase64, ToBase64, STANDARD, URL_SAFE}; #[test] fn test_to_base64_basic() { diff --git a/src/libextra/hex.rs b/src/libserialize/hex.rs similarity index 96% rename from src/libextra/hex.rs rename to src/libserialize/hex.rs index d4e1ae123378e..409bf4af80992 100644 --- a/src/libextra/hex.rs +++ b/src/libserialize/hex.rs @@ -28,7 +28,8 @@ impl<'a> ToHex for &'a [u8] { * # Example * * ```rust - * use extra::hex::ToHex; + * extern mod serialize; + * use serialize::hex::ToHex; * * fn main () { * let str = [52,32].to_hex(); @@ -88,7 +89,8 @@ impl<'a> FromHex for &'a str { * This converts a string literal to hexadecimal and back. * * ```rust - * use extra::hex::{FromHex, ToHex}; + * extern mod serialize; + * use serialize::hex::{FromHex, ToHex}; * use std::str; * * fn main () { @@ -137,8 +139,8 @@ impl<'a> FromHex for &'a str { #[cfg(test)] mod tests { - use test::BenchHarness; - use hex::*; + use extra::test::BenchHarness; + use hex::{FromHex, ToHex}; #[test] pub fn test_to_hex() { diff --git a/src/libserialize/lib.rs b/src/libserialize/lib.rs index 5f473b253697c..3b71b2237b176 100644 --- a/src/libserialize/lib.rs +++ b/src/libserialize/lib.rs @@ -30,4 +30,8 @@ pub use self::serialize::{Decoder, Encoder, Decodable, Encodable, DecoderHelpers, EncoderHelpers}; mod serialize; + +pub mod base64; pub mod ebml; +pub mod hex; + From 2ec30273d9491eb853baa18956d0fef5cfceaf10 Mon Sep 17 00:00:00 2001 From: JeremyLetang Date: Mon, 10 Feb 2014 16:50:42 -0500 Subject: [PATCH 7/8] remove duplicate function from std::ptr (is_null, is_not_null, offset, mut_offset) --- src/doc/guide-ffi.md | 2 +- src/libarena/lib.rs | 7 ++--- src/libextra/c_vec.rs | 4 +-- src/librustc/metadata/loader.rs | 3 +- src/librustc/middle/trans/builder.rs | 5 ++- src/librustuv/lib.rs | 2 +- src/libserialize/ebml.rs | 3 +- src/libstd/c_str.rs | 47 ++++++++++++++-------------- src/libstd/io/extensions.rs | 7 +++-- src/libstd/ptr.rs | 43 ++++++------------------- src/libstd/repr.rs | 3 +- src/libstd/str.rs | 15 +++++---- src/libstd/vec.rs | 21 +++++++------ src/libstd/vec_ng.rs | 5 +-- 14 files changed, 70 insertions(+), 97 deletions(-) diff --git a/src/doc/guide-ffi.md b/src/doc/guide-ffi.md index e22f30871baa8..053a8612694ab 100644 --- a/src/doc/guide-ffi.md +++ b/src/doc/guide-ffi.md @@ -195,7 +195,7 @@ impl Unique { pub fn new(value: T) -> Unique { unsafe { let ptr = malloc(std::mem::size_of::() as size_t) as *mut T; - assert!(!ptr::is_null(ptr)); + assert!(!ptr.is_null()); // `*ptr` is uninitialized, and `*ptr = value` would attempt to destroy it // move_val_init moves a value into this memory without // attempting to drop the original value. diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index 6ba1c86fdf286..b41af9eb05430 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -34,7 +34,6 @@ use std::cast; use std::cell::{Cell, RefCell}; use std::mem; use std::num; -use std::ptr; use std::kinds::marker; use std::rc::Rc; use std::rt::global_heap; @@ -144,7 +143,7 @@ unsafe fn destroy_chunk(chunk: &Chunk) { let fill = chunk.fill.get(); while idx < fill { - let tydesc_data: *uint = transmute(ptr::offset(buf, idx as int)); + let tydesc_data: *uint = transmute(buf.offset(idx as int)); let (tydesc, is_done) = un_bitpack_tydesc_ptr(*tydesc_data); let (size, align) = ((*tydesc).size, (*tydesc).align); @@ -155,7 +154,7 @@ unsafe fn destroy_chunk(chunk: &Chunk) { //debug!("freeing object: idx = {}, size = {}, align = {}, done = {}", // start, size, align, is_done); if is_done { - ((*tydesc).drop_glue)(ptr::offset(buf, start as int) as *i8); + ((*tydesc).drop_glue)(buf.offset(start as int) as *i8); } // Find where the next tydesc lives @@ -261,7 +260,7 @@ impl Arena { // start, n_bytes, align, head.fill); let buf = self.head.as_ptr(); - return (ptr::offset(buf, tydesc_start as int), ptr::offset(buf, start as int)); + return (buf.offset(tydesc_start as int), buf.offset(start as int)); } } diff --git a/src/libextra/c_vec.rs b/src/libextra/c_vec.rs index 35a6ccaa7083c..fec5b105c4b18 100644 --- a/src/libextra/c_vec.rs +++ b/src/libextra/c_vec.rs @@ -119,7 +119,7 @@ impl CVec { pub fn get<'a>(&'a self, ofs: uint) -> &'a T { assert!(ofs < self.len); unsafe { - &*ptr::mut_offset(self.base, ofs as int) + &*self.base.offset(ofs as int) } } @@ -131,7 +131,7 @@ impl CVec { pub fn get_mut<'a>(&'a mut self, ofs: uint) -> &'a mut T { assert!(ofs < self.len); unsafe { - &mut *ptr::mut_offset(self.base, ofs as int) + &mut *self.base.offset(ofs as int) } } diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs index abcd650ced131..70b93a9813535 100644 --- a/src/librustc/metadata/loader.rs +++ b/src/librustc/metadata/loader.rs @@ -30,7 +30,6 @@ use std::io; use std::num; use std::option; use std::os::consts::{macos, freebsd, linux, android, win32}; -use std::ptr; use std::str; use std::vec; use flate; @@ -340,7 +339,7 @@ fn get_metadata_section_imp(os: Os, filename: &Path) -> Option { }); if !version_ok { return None; } - let cvbuf1 = ptr::offset(cvbuf, vlen as int); + let cvbuf1 = cvbuf.offset(vlen as int); debug!("inflating {} bytes of compressed metadata", csz - vlen); vec::raw::buf_as_slice(cvbuf1, csz-vlen, |bytes| { diff --git a/src/librustc/middle/trans/builder.rs b/src/librustc/middle/trans/builder.rs index e4eeaa5fded7f..b8d16f9bb8006 100644 --- a/src/librustc/middle/trans/builder.rs +++ b/src/librustc/middle/trans/builder.rs @@ -21,7 +21,6 @@ use std::cast; use std::hashmap::HashMap; use std::libc::{c_uint, c_ulonglong, c_char}; use syntax::codemap::Span; -use std::ptr::is_not_null; pub struct Builder<'a> { llbuilder: BuilderRef, @@ -492,7 +491,7 @@ impl<'a> Builder<'a> { debug!("Store {} -> {}", self.ccx.tn.val_to_str(val), self.ccx.tn.val_to_str(ptr)); - assert!(is_not_null(self.llbuilder)); + assert!(self.llbuilder.is_not_null()); self.count_insn("store"); unsafe { llvm::LLVMBuildStore(self.llbuilder, val, ptr); @@ -503,7 +502,7 @@ impl<'a> Builder<'a> { debug!("Store {} -> {}", self.ccx.tn.val_to_str(val), self.ccx.tn.val_to_str(ptr)); - assert!(is_not_null(self.llbuilder)); + assert!(self.llbuilder.is_not_null()); self.count_insn("store.volatile"); unsafe { let insn = llvm::LLVMBuildStore(self.llbuilder, val, ptr); diff --git a/src/librustuv/lib.rs b/src/librustuv/lib.rs index b463bb7fd733d..b71dbe05ad2b6 100644 --- a/src/librustuv/lib.rs +++ b/src/librustuv/lib.rs @@ -426,7 +426,7 @@ mod test { unsafe { let base = transmute::<*u8, *mut u8>(buf.base); (*base) = 1; - (*ptr::mut_offset(base, 1)) = 2; + (*base.offset(1)) = 2; } assert!(slice[0] == 1); diff --git a/src/libserialize/ebml.rs b/src/libserialize/ebml.rs index f08f943306fcf..3d57a32a830b2 100644 --- a/src/libserialize/ebml.rs +++ b/src/libserialize/ebml.rs @@ -131,7 +131,6 @@ pub mod reader { } pub fn vuint_at(data: &[u8], start: uint) -> Res { - use std::ptr::offset; use std::mem::from_be32; if data.len() - start < 4 { @@ -163,7 +162,7 @@ pub mod reader { unsafe { let (ptr, _): (*u8, uint) = transmute(data); - let ptr = offset(ptr, start as int); + let ptr = ptr.offset(start as int); let ptr: *i32 = transmute(ptr); let val = from_be32(*ptr) as u32; diff --git a/src/libstd/c_str.rs b/src/libstd/c_str.rs index cc6cd7666d642..fe332a60efa44 100644 --- a/src/libstd/c_str.rs +++ b/src/libstd/c_str.rs @@ -310,7 +310,7 @@ impl<'a> ToCStr for &'a [u8] { let buf = malloc_raw(self_len + 1); ptr::copy_memory(buf, self.as_ptr(), self_len); - *ptr::mut_offset(buf, self_len as int) = 0; + *buf.offset(self_len as int) = 0; CString::new(buf as *libc::c_char, true) } @@ -368,7 +368,7 @@ impl<'a> Iterator for CChars<'a> { if ch == 0 { None } else { - self.ptr = unsafe { ptr::offset(self.ptr, 1) }; + self.ptr = unsafe { self.ptr.offset(1) }; Some(ch) } } @@ -429,18 +429,18 @@ mod tests { fn test_str_to_c_str() { "".to_c_str().with_ref(|buf| { unsafe { - assert_eq!(*ptr::offset(buf, 0), 0); + assert_eq!(*buf.offset(0), 0); } }); "hello".to_c_str().with_ref(|buf| { unsafe { - assert_eq!(*ptr::offset(buf, 0), 'h' as libc::c_char); - assert_eq!(*ptr::offset(buf, 1), 'e' as libc::c_char); - assert_eq!(*ptr::offset(buf, 2), 'l' as libc::c_char); - assert_eq!(*ptr::offset(buf, 3), 'l' as libc::c_char); - assert_eq!(*ptr::offset(buf, 4), 'o' as libc::c_char); - assert_eq!(*ptr::offset(buf, 5), 0); + assert_eq!(*buf.offset(0), 'h' as libc::c_char); + assert_eq!(*buf.offset(1), 'e' as libc::c_char); + assert_eq!(*buf.offset(2), 'l' as libc::c_char); + assert_eq!(*buf.offset(3), 'l' as libc::c_char); + assert_eq!(*buf.offset(4), 'o' as libc::c_char); + assert_eq!(*buf.offset(5), 0); } }) } @@ -450,28 +450,28 @@ mod tests { let b: &[u8] = []; b.to_c_str().with_ref(|buf| { unsafe { - assert_eq!(*ptr::offset(buf, 0), 0); + assert_eq!(*buf.offset(0), 0); } }); let _ = bytes!("hello").to_c_str().with_ref(|buf| { unsafe { - assert_eq!(*ptr::offset(buf, 0), 'h' as libc::c_char); - assert_eq!(*ptr::offset(buf, 1), 'e' as libc::c_char); - assert_eq!(*ptr::offset(buf, 2), 'l' as libc::c_char); - assert_eq!(*ptr::offset(buf, 3), 'l' as libc::c_char); - assert_eq!(*ptr::offset(buf, 4), 'o' as libc::c_char); - assert_eq!(*ptr::offset(buf, 5), 0); + assert_eq!(*buf.offset(0), 'h' as libc::c_char); + assert_eq!(*buf.offset(1), 'e' as libc::c_char); + assert_eq!(*buf.offset(2), 'l' as libc::c_char); + assert_eq!(*buf.offset(3), 'l' as libc::c_char); + assert_eq!(*buf.offset(4), 'o' as libc::c_char); + assert_eq!(*buf.offset(5), 0); } }); let _ = bytes!("foo", 0xff).to_c_str().with_ref(|buf| { unsafe { - assert_eq!(*ptr::offset(buf, 0), 'f' as libc::c_char); - assert_eq!(*ptr::offset(buf, 1), 'o' as libc::c_char); - assert_eq!(*ptr::offset(buf, 2), 'o' as libc::c_char); - assert_eq!(*ptr::offset(buf, 3), 0xff as i8); - assert_eq!(*ptr::offset(buf, 4), 0); + assert_eq!(*buf.offset(0), 'f' as libc::c_char); + assert_eq!(*buf.offset(1), 'o' as libc::c_char); + assert_eq!(*buf.offset(2), 'o' as libc::c_char); + assert_eq!(*buf.offset(3), 0xff as i8); + assert_eq!(*buf.offset(4), 0); } }); } @@ -634,7 +634,6 @@ mod bench { use extra::test::BenchHarness; use libc; use prelude::*; - use ptr; #[inline] fn check(s: &str, c_str: *libc::c_char) { @@ -642,8 +641,8 @@ mod bench { for i in range(0, s.len()) { unsafe { assert_eq!( - *ptr::offset(s_buf, i as int) as libc::c_char, - *ptr::offset(c_str, i as int)); + *s_buf.offset(i as int) as libc::c_char, + *c_str.offset(i as int)); } } } diff --git a/src/libstd/io/extensions.rs b/src/libstd/io/extensions.rs index 240f4c65501dc..da4697d0e4880 100644 --- a/src/libstd/io/extensions.rs +++ b/src/libstd/io/extensions.rs @@ -18,6 +18,7 @@ use iter::Iterator; use option::Option; use io::Reader; use vec::{OwnedVector, ImmutableVector}; +use ptr::RawPtr; /// An iterator that reads a single byte on each iteration, /// until `.read_byte()` returns `None`. @@ -104,7 +105,7 @@ pub fn u64_from_be_bytes(data: &[u8], start: uint, size: uint) -> u64 { - use ptr::{copy_nonoverlapping_memory, offset, mut_offset}; + use ptr::{copy_nonoverlapping_memory}; use mem::from_be64; use vec::MutableVector; @@ -116,9 +117,9 @@ pub fn u64_from_be_bytes(data: &[u8], let mut buf = [0u8, ..8]; unsafe { - let ptr = offset(data.as_ptr(), start as int); + let ptr = data.as_ptr().offset(start as int); let out = buf.as_mut_ptr(); - copy_nonoverlapping_memory(mut_offset(out, (8 - size) as int), ptr, size); + copy_nonoverlapping_memory(out.offset((8 - size) as int), ptr, size); from_be64(*(out as *i64)) as u64 } } diff --git a/src/libstd/ptr.rs b/src/libstd/ptr.rs index 80439d6989921..2ba6f7d4fd64d 100644 --- a/src/libstd/ptr.rs +++ b/src/libstd/ptr.rs @@ -21,23 +21,6 @@ use unstable::intrinsics; #[cfg(not(test))] use cmp::{Eq, Ord}; -/// Calculate the offset from a pointer. -/// The `count` argument is in units of T; e.g. a `count` of 3 -/// represents a pointer offset of `3 * sizeof::()` bytes. -#[inline] -pub unsafe fn offset(ptr: *T, count: int) -> *T { - intrinsics::offset(ptr, count) -} - -/// Calculate the offset from a mut pointer. The count *must* be in bounds or -/// otherwise the loads of this address are undefined. -/// The `count` argument is in units of T; e.g. a `count` of 3 -/// represents a pointer offset of `3 * sizeof::()` bytes. -#[inline] -pub unsafe fn mut_offset(ptr: *mut T, count: int) -> *mut T { - intrinsics::offset(ptr as *T, count) as *mut T -} - /// Return the offset of the first null pointer in `buf`. #[inline] pub unsafe fn buf_len(buf: **T) -> uint { @@ -63,7 +46,7 @@ impl Clone for *mut T { pub unsafe fn position(buf: *T, f: |&T| -> bool) -> uint { let mut i = 0; loop { - if f(&(*offset(buf, i as int))) { return i; } + if f(&(*buf.offset(i as int))) { return i; } else { i += 1; } } } @@ -76,14 +59,6 @@ pub fn null() -> *T { 0 as *T } #[inline] pub fn mut_null() -> *mut T { 0 as *mut T } -/// Returns true if the pointer is equal to the null pointer. -#[inline] -pub fn is_null>(ptr: P) -> bool { ptr.is_null() } - -/// Returns true if the pointer is not equal to the null pointer. -#[inline] -pub fn is_not_null>(ptr: P) -> bool { ptr.is_not_null() } - /** * Copies data from one location to another. * @@ -206,7 +181,7 @@ pub unsafe fn array_each_with_len(arr: **T, len: uint, cb: |*T|) { } //let start_ptr = *arr; for e in range(0, len) { - let n = offset(arr, e as int); + let n = arr.offset(e as int); cb(*n); } debug!("array_each_with_len: after iterate"); @@ -278,7 +253,7 @@ impl RawPtr for *T { /// Calculates the offset from a pointer. The offset *must* be in-bounds of /// the object, or one-byte-past-the-end. #[inline] - unsafe fn offset(self, count: int) -> *T { offset(self, count) } + unsafe fn offset(self, count: int) -> *T { intrinsics::offset(self, count) } } /// Extension methods for mutable pointers @@ -323,7 +298,7 @@ impl RawPtr for *mut T { /// This method should be preferred over `offset` when the guarantee can be /// satisfied, to enable better optimization. #[inline] - unsafe fn offset(self, count: int) -> *mut T { mut_offset(self, count) } + unsafe fn offset(self, count: int) -> *mut T { intrinsics::offset(self as *T, count) as *mut T } } // Equality for pointers @@ -478,14 +453,14 @@ pub mod ptr_tests { let v0 = ~[32000u16, 32001u16, 32002u16]; let mut v1 = ~[0u16, 0u16, 0u16]; - copy_memory(mut_offset(v1.as_mut_ptr(), 1), - offset(v0.as_ptr(), 1), 1); + copy_memory(v1.as_mut_ptr().offset(1), + v0.as_ptr().offset(1), 1); assert!((v1[0] == 0u16 && v1[1] == 32001u16 && v1[2] == 0u16)); copy_memory(v1.as_mut_ptr(), - offset(v0.as_ptr(), 2), 1); + v0.as_ptr().offset(2), 1); assert!((v1[0] == 32002u16 && v1[1] == 32001u16 && v1[2] == 0u16)); - copy_memory(mut_offset(v1.as_mut_ptr(), 2), + copy_memory(v1.as_mut_ptr().offset(2), v0.as_ptr(), 1u); assert!((v1[0] == 32002u16 && v1[1] == 32001u16 && v1[2] == 32000u16)); @@ -525,7 +500,7 @@ pub mod ptr_tests { assert!(p.is_null()); assert!(!p.is_not_null()); - let q = unsafe { offset(p, 1) }; + let q = unsafe { p.offset(1) }; assert!(!q.is_null()); assert!(q.is_not_null()); diff --git a/src/libstd/repr.rs b/src/libstd/repr.rs index 4ced74a92b7c0..dbd1ea8e989ec 100644 --- a/src/libstd/repr.rs +++ b/src/libstd/repr.rs @@ -23,6 +23,7 @@ use io; use iter::Iterator; use option::{Some, None, Option}; use ptr; +use ptr::RawPtr; use reflect; use reflect::{MovePtr, align}; use result::{Ok, Err}; @@ -221,7 +222,7 @@ impl<'a> ReprVisitor<'a> { if_ok!(self, self.writer.write(", ".as_bytes())); } self.visit_ptr_inner(p as *u8, inner); - p = align(unsafe { ptr::offset(p, sz as int) as uint }, al) as *u8; + p = align(unsafe { p.offset(sz as int) as uint }, al) as *u8; left -= dec; } if_ok!(self, self.writer.write([']' as u8])); diff --git a/src/libstd/str.rs b/src/libstd/str.rs index bc5991c6eebd0..def2557d1abbb 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -1242,7 +1242,7 @@ pub mod raw { let mut i = 0; while *curr != 0 { i += 1; - curr = ptr::offset(buf, i); + curr = buf.offset(i); } from_buf_len(buf as *u8, i as uint) } @@ -1272,7 +1272,7 @@ pub mod raw { let mut len = 0u; while *curr != 0u8 { len += 1u; - curr = ptr::offset(s, len as int); + curr = s.offset(len as int); } let v = Slice { data: s, len: len }; assert!(is_utf8(::cast::transmute(v))); @@ -2921,7 +2921,6 @@ impl Default for ~str { mod tests { use iter::AdditiveIterator; use prelude::*; - use ptr; use str::*; #[test] @@ -3549,11 +3548,11 @@ mod tests { fn test_as_ptr() { let buf = "hello".as_ptr(); unsafe { - assert_eq!(*ptr::offset(buf, 0), 'h' as u8); - assert_eq!(*ptr::offset(buf, 1), 'e' as u8); - assert_eq!(*ptr::offset(buf, 2), 'l' as u8); - assert_eq!(*ptr::offset(buf, 3), 'l' as u8); - assert_eq!(*ptr::offset(buf, 4), 'o' as u8); + assert_eq!(*buf.offset(0), 'h' as u8); + assert_eq!(*buf.offset(1), 'e' as u8); + assert_eq!(*buf.offset(2), 'l' as u8); + assert_eq!(*buf.offset(3), 'l' as u8); + assert_eq!(*buf.offset(4), 'o' as u8); } } diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index 2acafecf95720..0f2e391ab6a5a 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -137,7 +137,7 @@ pub fn from_fn(n_elts: uint, op: |uint| -> T) -> ~[T] { &mut i, (), |i, ()| while *i < n_elts { mem::move_val_init( - &mut(*ptr::mut_offset(p, *i as int)), + &mut(*p.offset(*i as int)), op(*i)); *i += 1u; }, @@ -165,7 +165,7 @@ pub fn from_elem(n_elts: uint, t: T) -> ~[T] { &mut i, (), |i, ()| while *i < n_elts { mem::move_val_init( - &mut(*ptr::mut_offset(p, *i as int)), + &mut(*p.offset(*i as int)), t.clone()); *i += 1u; }, @@ -1495,7 +1495,7 @@ impl OwnedVector for ~[T] { let fill = (**repr).fill; (**repr).fill += mem::nonzero_size_of::(); let p = to_unsafe_ptr(&((**repr).data)); - let p = ptr::offset(p, fill as int) as *mut T; + let p = p.offset(fill as int) as *mut T; mem::move_val_init(&mut(*p), t); } } @@ -1509,7 +1509,7 @@ impl OwnedVector for ~[T] { unsafe { // Note: infallible. let self_p = self.as_mut_ptr(); let rhs_p = rhs.as_ptr(); - ptr::copy_memory(ptr::mut_offset(self_p, self_len as int), rhs_p, rhs_len); + ptr::copy_memory(self_p.offset(self_len as int), rhs_p, rhs_len); self.set_len(new_len); rhs.set_len(0); } @@ -1796,11 +1796,11 @@ impl OwnedEqVector for ~[T] { let mut w = 1; while r < ln { - let p_r = ptr::mut_offset(p, r as int); - let p_wm1 = ptr::mut_offset(p, (w - 1) as int); + let p_r = p.offset(r as int); + let p_wm1 = p.offset((w - 1) as int); if *p_r != *p_wm1 { if r != w { - let p_w = ptr::mut_offset(p_wm1, 1); + let p_w = p_wm1.offset(1); mem::swap(&mut *p_r, &mut *p_w); } w += 1; @@ -2383,7 +2383,7 @@ impl<'a,T> MutableVector<'a, T> for &'a mut [T] { #[inline] unsafe fn unsafe_mut_ref(self, index: uint) -> &'a mut T { - cast::transmute(ptr::mut_offset(self.repr().data as *mut T, index as int)) + cast::transmute((self.repr().data as *mut T).offset(index as int)) } #[inline] @@ -2484,6 +2484,7 @@ pub unsafe fn from_buf(ptr: *T, elts: uint) -> ~[T] { pub mod raw { use cast; use ptr; + use ptr::RawPtr; use vec::{with_capacity, MutableVector, OwnedVector}; use unstable::raw::Slice; @@ -2542,7 +2543,7 @@ pub mod raw { pub unsafe fn shift_ptr(slice: &mut Slice) -> *T { if slice.len == 0 { fail!("shift on empty slice"); } let head: *T = slice.data; - slice.data = ptr::offset(slice.data, 1); + slice.data = slice.data.offset(1); slice.len -= 1; head } @@ -2554,7 +2555,7 @@ pub mod raw { */ pub unsafe fn pop_ptr(slice: &mut Slice) -> *T { if slice.len == 0 { fail!("pop on empty slice"); } - let tail: *T = ptr::offset(slice.data, (slice.len - 1) as int); + let tail: *T = slice.data.offset((slice.len - 1) as int); slice.len -= 1; tail } diff --git a/src/libstd/vec_ng.rs b/src/libstd/vec_ng.rs index 90bc583624012..25ba45021b3fa 100644 --- a/src/libstd/vec_ng.rs +++ b/src/libstd/vec_ng.rs @@ -22,7 +22,8 @@ use cast::{forget, transmute}; use rt::global_heap::{malloc_raw, realloc_raw}; use vec::{ImmutableVector, Items, MutableVector}; use unstable::raw::Slice; -use ptr::{offset, read_ptr}; +use ptr::read_ptr; +use ptr::RawPtr; use libc::{free, c_void}; pub struct Vec { @@ -135,7 +136,7 @@ impl Vec { } unsafe { - let end = offset(self.ptr as *T, self.len as int) as *mut T; + let end = (self.ptr as *T).offset(self.len as int) as *mut T; move_val_init(&mut *end, value); self.len += 1; } From 38576046b3f813dd6c7bb453d78f3605f8798d72 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Thu, 13 Feb 2014 06:41:34 +1100 Subject: [PATCH 8/8] Add some missing Show implementations in libstd --- src/librustdoc/clean.rs | 19 +++++++-- src/librustdoc/html/format.rs | 29 +++++++------- src/libstd/any.rs | 26 ++++++++++++ src/libstd/ascii.rs | 13 +++++- src/libstd/hashmap.rs | 75 +++++++++++++++++++++++++++++++++++ src/libstd/str.rs | 2 + src/libstd/unit.rs | 7 ++++ src/libstd/vec.rs | 42 ++++++++++++++++++++ 8 files changed, 193 insertions(+), 20 deletions(-) diff --git a/src/librustdoc/clean.rs b/src/librustdoc/clean.rs index ca7f502a2e82d..eb0b4597e3007 100644 --- a/src/librustdoc/clean.rs +++ b/src/librustdoc/clean.rs @@ -342,7 +342,9 @@ impl Clean for ast::Method { _ => self.decl.inputs.slice_from(1) }; let decl = FnDecl { - inputs: inputs.iter().map(|x| x.clean()).collect(), + inputs: Arguments { + values: inputs.iter().map(|x| x.clean()).collect(), + }, output: (self.decl.output.clean()), cf: self.decl.cf.clean(), attrs: ~[] @@ -378,7 +380,9 @@ impl Clean for ast::TypeMethod { _ => self.decl.inputs.slice_from(1) }; let decl = FnDecl { - inputs: inputs.iter().map(|x| x.clean()).collect(), + inputs: Arguments { + values: inputs.iter().map(|x| x.clean()).collect(), + }, output: (self.decl.output.clean()), cf: self.decl.cf.clean(), attrs: ~[] @@ -472,16 +476,23 @@ impl Clean for ast::ClosureTy { #[deriving(Clone, Encodable, Decodable)] pub struct FnDecl { - inputs: ~[Argument], + inputs: Arguments, output: Type, cf: RetStyle, attrs: ~[Attribute] } +#[deriving(Clone, Encodable, Decodable)] +pub struct Arguments { + values: ~[Argument], +} + impl Clean for ast::FnDecl { fn clean(&self) -> FnDecl { FnDecl { - inputs: self.inputs.iter().map(|x| x.clean()).collect(), + inputs: Arguments { + values: self.inputs.iter().map(|x| x.clean()).collect(), + }, output: (self.output.clean()), cf: self.cf.clean(), attrs: ~[] diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 024d010f0b927..3e5afc399b962 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -404,6 +404,19 @@ impl fmt::Show for clean::Type { } } +impl fmt::Show for clean::Arguments { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + for (i, input) in self.values.iter().enumerate() { + if i > 0 { if_ok!(write!(f.buf, ", ")); } + if input.name.len() > 0 { + if_ok!(write!(f.buf, "{}: ", input.name)); + } + if_ok!(write!(f.buf, "{}", input.type_)); + } + Ok(()) + } +} + impl fmt::Show for clean::FnDecl { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f.buf, "({args}){arrow, select, yes{ -> {ret}} other{}}", @@ -413,20 +426,6 @@ impl fmt::Show for clean::FnDecl { } } -impl fmt::Show for ~[clean::Argument] { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let mut args = ~""; - for (i, input) in self.iter().enumerate() { - if i > 0 { args.push_str(", "); } - if input.name.len() > 0 { - args.push_str(format!("{}: ", input.name)); - } - args.push_str(format!("{}", input.type_)); - } - f.buf.write(args.as_bytes()) - } -} - impl<'a> fmt::Show for Method<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let Method(selfty, d) = *self; @@ -448,7 +447,7 @@ impl<'a> fmt::Show for Method<'a> { args.push_str("&self"); } } - for (i, input) in d.inputs.iter().enumerate() { + for (i, input) in d.inputs.values.iter().enumerate() { if i > 0 || args.len() > 0 { args.push_str(", "); } if input.name.len() > 0 { args.push_str(format!("{}: ", input.name)); diff --git a/src/libstd/any.rs b/src/libstd/any.rs index 24da59341ccdd..3f14db14882ec 100644 --- a/src/libstd/any.rs +++ b/src/libstd/any.rs @@ -21,6 +21,7 @@ //! extension traits (`*Ext`) for the full details. use cast::transmute; +use fmt; use option::{Option, Some, None}; use result::{Result, Ok, Err}; use to_str::ToStr; @@ -158,6 +159,18 @@ impl<'a> ToStr for &'a Any { fn to_str(&self) -> ~str { ~"&Any" } } +impl fmt::Show for ~Any { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("~Any") + } +} + +impl<'a> fmt::Show for &'a Any { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("&Any") + } +} + #[cfg(test)] mod tests { use prelude::*; @@ -377,4 +390,17 @@ mod tests { assert!(a.move::<~Test>().is_err()); assert!(b.move::<~uint>().is_err()); } + + #[test] + fn test_show() { + let a = ~8u as ~Any; + let b = ~Test as ~Any; + assert_eq!(format!("{}", a), ~"~Any"); + assert_eq!(format!("{}", b), ~"~Any"); + + let a = &8u as &Any; + let b = &Test as &Any; + assert_eq!(format!("{}", a), ~"&Any"); + assert_eq!(format!("{}", b), ~"&Any"); + } } diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs index 7965127007c1c..651d364dd1b97 100644 --- a/src/libstd/ascii.rs +++ b/src/libstd/ascii.rs @@ -17,6 +17,7 @@ use str::StrSlice; use str::OwnedStr; use container::Container; use cast; +use fmt; use iter::Iterator; use vec::{ImmutableVector, MutableVector, Vector}; use to_bytes::IterBytes; @@ -134,6 +135,12 @@ impl ToStr for Ascii { } } +impl<'a> fmt::Show for Ascii { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + (self.chr as char).fmt(f) + } +} + /// Trait for converting into an ascii type. pub trait AsciiCast { /// Convert to an ascii type, fail on non-ASCII input. @@ -698,5 +705,9 @@ mod tests { assert_eq!(s, ~"t"); } - + #[test] + fn test_show() { + let c = Ascii { chr: 't' as u8 }; + assert_eq!(format!("{}", c), ~"t"); + } } diff --git a/src/libstd/hashmap.rs b/src/libstd/hashmap.rs index 953cc66a2cbcc..c49294a095f29 100644 --- a/src/libstd/hashmap.rs +++ b/src/libstd/hashmap.rs @@ -56,6 +56,7 @@ use container::{Container, Mutable, Map, MutableMap, Set, MutableSet}; use clone::Clone; use cmp::{Eq, Equiv}; use default::Default; +#[cfg(not(stage0))] use fmt; use hash::Hash; use iter; use iter::{Iterator, FromIterator, Extendable}; @@ -65,6 +66,7 @@ use num; use option::{None, Option, Some}; use rand::Rng; use rand; +#[cfg(not(stage0))] use result::{Ok, Err}; use vec::{ImmutableVector, MutableVector, OwnedVector, Items, MutItems}; use vec_ng; use vec_ng::Vec; @@ -595,6 +597,23 @@ impl Clone for HashMap { } } +#[cfg(not(stage0))] +impl fmt::Show for HashMap { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if_ok!(write!(f.buf, r"\{")) + let mut first = true; + for (key, value) in self.iter() { + if first { + first = false; + } else { + if_ok!(write!(f.buf, ", ")); + } + if_ok!(write!(f.buf, "{}: {}", *key, *value)); + } + write!(f.buf, r"\}") + } +} + /// HashMap iterator #[deriving(Clone)] pub struct Entries<'a, K, V> { @@ -857,6 +876,23 @@ impl Clone for HashSet { } } +#[cfg(not(stage0))] +impl fmt::Show for HashSet { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if_ok!(write!(f.buf, r"\{")) + let mut first = true; + for x in self.iter() { + if first { + first = false; + } else { + if_ok!(write!(f.buf, ", ")); + } + if_ok!(write!(f.buf, "{}", *x)); + } + write!(f.buf, r"\}") + } +} + impl FromIterator for HashSet { fn from_iterator>(iter: &mut T) -> HashSet { let (lower, _) = iter.size_hint(); @@ -890,6 +926,7 @@ pub type SetAlgebraItems<'a, T> = mod test_map { use prelude::*; use super::*; + use fmt; #[test] fn test_create_capacity_zero() { @@ -1121,6 +1158,30 @@ mod test_map { assert_eq!(map.find(&k), Some(&v)); } } + + struct ShowableStruct { + value: int, + } + + impl fmt::Show for ShowableStruct { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f.buf, r"s{}", self.value) + } + } + + #[test] + fn test_show() { + let mut table: HashMap = HashMap::new(); + let empty: HashMap = HashMap::new(); + + table.insert(3, ShowableStruct { value: 4 }); + table.insert(1, ShowableStruct { value: 2 }); + + let table_str = format!("{}", table); + + assert!(table_str == ~"{1: s2, 3: s4}" || table_str == ~"{3: s4, 1: s2}"); + assert_eq!(format!("{}", empty), ~"{}"); + } } #[cfg(test)] @@ -1346,4 +1407,18 @@ mod test_set { assert_eq!(s1, s2); } + + #[test] + fn test_show() { + let mut set: HashSet = HashSet::new(); + let empty: HashSet = HashSet::new(); + + set.insert(1); + set.insert(2); + + let set_str = format!("{}", set); + + assert!(set_str == ~"{1, 2}" || set_str == ~"{2, 1}"); + assert_eq!(format!("{}", empty), ~"{}"); + } } diff --git a/src/libstd/str.rs b/src/libstd/str.rs index def2557d1abbb..0d263d94ccf0f 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -4163,6 +4163,7 @@ mod tests { assert_eq!(s.len(), 5); assert_eq!(s.as_slice(), "abcde"); assert_eq!(s.to_str(), ~"abcde"); + assert_eq!(format!("{}", s), ~"abcde"); assert!(s.lt(&Owned(~"bcdef"))); assert_eq!(Slice(""), Default::default()); @@ -4170,6 +4171,7 @@ mod tests { assert_eq!(o.len(), 5); assert_eq!(o.as_slice(), "abcde"); assert_eq!(o.to_str(), ~"abcde"); + assert_eq!(format!("{}", o), ~"abcde"); assert!(o.lt(&Slice("bcdef"))); assert_eq!(Owned(~""), Default::default()); diff --git a/src/libstd/unit.rs b/src/libstd/unit.rs index 3aa3e020500ea..b23dafbca6970 100644 --- a/src/libstd/unit.rs +++ b/src/libstd/unit.rs @@ -14,6 +14,7 @@ use default::Default; #[cfg(not(test))] use cmp::{Eq, Equal, Ord, Ordering, TotalEq, TotalOrd}; +use fmt; #[cfg(not(test))] impl Eq for () { @@ -46,3 +47,9 @@ impl Default for () { #[inline] fn default() -> () { () } } + +impl fmt::Show for () { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("()") + } +} diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index 0f2e391ab6a5a..c67b19933d37f 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -108,6 +108,7 @@ use container::{Container, Mutable}; use cmp::{Eq, TotalOrd, Ordering, Less, Equal, Greater}; use cmp; use default::Default; +#[cfg(not(stage0))] use fmt; use iter::*; use num::{Integer, CheckedAdd, Saturating, checked_next_power_of_two}; use option::{None, Option, Some}; @@ -115,6 +116,7 @@ use ptr::to_unsafe_ptr; use ptr; use ptr::RawPtr; use rt::global_heap::{malloc_raw, realloc_raw, exchange_free}; +#[cfg(not(stage0))] use result::{Ok, Err}; use mem; use mem::size_of; use kinds::marker; @@ -2641,6 +2643,30 @@ impl DeepClone for ~[A] { } } +#[cfg(not(stage0))] +impl<'a, T: fmt::Show> fmt::Show for &'a [T] { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if_ok!(write!(f.buf, "[")); + let mut is_first = true; + for x in self.iter() { + if is_first { + is_first = false; + } else { + if_ok!(write!(f.buf, ", ")); + } + if_ok!(write!(f.buf, "{}", *x)) + } + write!(f.buf, "]") + } +} + +#[cfg(not(stage0))] +impl fmt::Show for ~[T] { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.as_slice().fmt(f) + } +} + // This works because every lifetime is a sub-lifetime of 'static impl<'a, A> Default for &'a [A] { fn default() -> &'a [A] { &'a [] } @@ -4050,6 +4076,22 @@ mod tests { assert_eq!(values, [1,4,3,2,5]); } + #[test] + fn test_show() { + macro_rules! test_show_vec( + ($x:expr, $x_str:expr) => ({ + let (x, x_str) = ($x, $x_str); + assert_eq!(format!("{}", x), x_str); + assert_eq!(format!("{}", x.as_slice()), x_str); + }) + ) + let empty: ~[int] = ~[]; + test_show_vec!(empty, ~"[]"); + test_show_vec!(~[1], ~"[1]"); + test_show_vec!(~[1, 2, 3], ~"[1, 2, 3]"); + test_show_vec!(~[~[], ~[1u], ~[1u, 1u]], ~"[[], [1], [1, 1]]"); + } + #[test] fn test_vec_default() { use default::Default;