diff --git a/Makefile.in b/Makefile.in index 1130ab53d5d..ef1701a61e8 100644 --- a/Makefile.in +++ b/Makefile.in @@ -125,10 +125,7 @@ ifdef TRACE CFG_RUSTC_FLAGS += -Z trace endif ifdef CFG_DISABLE_RPATH -# NOTE: make this CFG_RUSTC_FLAGS after stage0 snapshot -RUSTFLAGS_STAGE1 += -C no-rpath -RUSTFLAGS_STAGE2 += -C no-rpath -RUSTFLAGS_STAGE3 += -C no-rpath +CFG_RUSTC_FLAGS += -C no-rpath endif # The executables crated during this compilation process have no need to include @@ -140,8 +137,7 @@ endif # snapshot will be generated with a statically linked rustc so we only have to # worry about the distribution of one file (with its native dynamic # dependencies) -# -# NOTE: after a snapshot (stage0), put this on stage0 as well +RUSTFLAGS_STAGE0 += -C prefer-dynamic RUSTFLAGS_STAGE1 += -C prefer-dynamic # platform-specific auto-configuration diff --git a/mk/dist.mk b/mk/dist.mk index 6d4e4401eaf..aea263c9619 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 \ diff --git a/mk/tests.mk b/mk/tests.mk index c2b298dbb9c..a8ad51409d9 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -333,21 +333,22 @@ $(foreach host,$(CFG_HOST), \ define TEST_RUNNER -# If NO_REBUILD is set then break the dependencies on extra so we can -# test crates without rebuilding std and extra first +# If NO_REBUILD is set then break the dependencies on everything but +# the source files so we can test crates without rebuilding any of the +# parent crates. ifeq ($(NO_REBUILD),) -STDTESTDEP_$(1)_$(2)_$(3)_$(4) = $$(SREQ$(1)_T_$(2)_H_$(3)) \ +TESTDEP_$(1)_$(2)_$(3)_$(4) = $$(SREQ$(1)_T_$(2)_H_$(3)) \ $$(foreach crate,$$(TARGET_CRATES),\ - $$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$$(crate)) + $$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$$(crate)) \ + $$(CRATE_FULLDEPS_$(1)_T_$(2)_H_$(3)_$(4)) else -STDTESTDEP_$(1)_$(2)_$(3)_$(4) = +TESTDEP_$(1)_$(2)_$(3)_$(4) = $$(RSINPUTS_$(4)) endif $(3)/stage$(1)/test/$(4)test-$(2)$$(X_$(2)): CFG_COMPILER = $(2) $(3)/stage$(1)/test/$(4)test-$(2)$$(X_$(2)): \ - $$(CRATEFILE_$(4)) \ - $$(CRATE_FULLDEPS_$(1)_T_$(2)_H_$(3)_$(4)) \ - $$(STDTESTDEP_$(1)_$(2)_$(3)_$(4)) + $$(CRATEFILE_$(4)) \ + $$(TESTDEP_$(1)_$(2)_$(3)_$(4)) @$$(call E, oxidize: $$@) $$(STAGE$(1)_T_$(2)_H_$(3)) -o $$@ $$< --test \ -L "$$(RT_OUTPUT_DIR_$(2))" \ @@ -684,13 +685,22 @@ $(foreach host,$(CFG_HOST), \ define DEF_CRATE_DOC_TEST +# If NO_REBUILD is set then break the dependencies on everything but +# the source files so we can test crate documentation without +# rebuilding any of the parent crates. +ifeq ($(NO_REBUILD),) +DOCTESTDEP_$(1)_$(2)_$(3)_$(4) = \ + $$(TEST_SREQ$(1)_T_$(2)_H_$(3)) \ + $$(CRATE_FULLDEPS_$(1)_T_$(2)_H_$(3)_$(4)) \ + $$(HBIN$(1)_H_$(3))/rustdoc$$(X_$(3)) +else +DOCTESTDEP_$(1)_$(2)_$(3)_$(4) = $$(RSINPUTS_$(4)) +endif + check-stage$(1)-T-$(2)-H-$(3)-doc-$(4)-exec: $$(call TEST_OK_FILE,$(1),$(2),$(3),doc-$(4)) ifeq ($(2),$$(CFG_BUILD)) -$$(call TEST_OK_FILE,$(1),$(2),$(3),doc-$(4)): \ - $$(TEST_SREQ$(1)_T_$(2)_H_$(3)) \ - $$(CRATE_FULLDEPS_$(1)_T_$(2)_H_$(3)_$(4)) \ - $$(HBIN$(1)_H_$(3))/rustdoc$$(X_$(3)) +$$(call TEST_OK_FILE,$(1),$(2),$(3),doc-$(4)): $$(DOCTESTDEP_$(1)_$(2)_$(3)_$(4)) @$$(call E, run doc-$(4) [$(2)]) $$(Q)$$(HBIN$(1)_H_$(3))/rustdoc$$(X_$(3)) --test \ $$(CRATEFILE_$(4)) --test-args "$$(TESTARGS)" && touch $$@ diff --git a/src/doc/guide-ffi.md b/src/doc/guide-ffi.md index e22f30871ba..053a8612694 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/doc/rust.md b/src/doc/rust.md index 725f15f4aaa..fe0fd8bd84d 100644 --- a/src/doc/rust.md +++ b/src/doc/rust.md @@ -1725,14 +1725,17 @@ mod bar { pub type int8_t = i8; ~~~~ -> **Note:** In future versions of Rust, user-provided extensions to the compiler will be able to interpret attributes. -> When this facility is provided, the compiler will distinguish between language-reserved and user-available attributes. +> **Note:** In future versions of Rust, user-provided extensions to the compiler +> will be able to interpret attributes. When this facility is provided, the +> compiler will distinguish between language-reserved and user-available +> attributes. -At present, only the Rust compiler interprets attributes, so all attribute -names are effectively reserved. Some significant attributes include: +At present, only the Rust compiler interprets attributes, so all attribute names +are effectively reserved. Some significant attributes include: * The `doc` attribute, for documenting code in-place. -* The `cfg` attribute, for conditional-compilation by build-configuration. +* The `cfg` attribute, for conditional-compilation by build-configuration (see + [Conditional compilation](#conditional-compilation)). * The `crate_id` attribute, for describing the package ID of a crate. * The `lang` attribute, for custom definitions of traits and functions that are known to the Rust compiler (see [Language items](#language-items)). @@ -1740,16 +1743,77 @@ names are effectively reserved. Some significant attributes include: * The `test` attribute, for marking functions as unit tests. * The `allow`, `warn`, `forbid`, and `deny` attributes, for controlling lint checks (see [Lint check attributes](#lint-check-attributes)). -* The `deriving` attribute, for automatically generating - implementations of certain traits. +* The `deriving` attribute, for automatically generating implementations of + certain traits. * The `inline` attribute, for expanding functions at caller location (see [Inline attributes](#inline-attributes)). -* The `static_assert` attribute, for asserting that a static bool is true at compiletime -* The `thread_local` attribute, for defining a `static mut` as a thread-local. Note that this is - only a low-level building block, and is not local to a *task*, nor does it provide safety. +* The `static_assert` attribute, for asserting that a static bool is true at + compiletime. +* The `thread_local` attribute, for defining a `static mut` as a thread-local. + Note that this is only a low-level building block, and is not local to a + *task*, nor does it provide safety. Other attributes may be added or removed during development of the language. +### Conditional compilation + +Sometimes one wants to have different compiler outputs from the same code, +depending on build target, such as targeted operating system, or to enable +release builds. + +There are two kinds of configuration options, one that is either defined or not +(`#[cfg(foo)]`), and the other that contains a string that can be checked +against (`#[cfg(bar = "baz")]` (currently only compiler-defined configuration +options can have the latter form). + +~~~~ +// The function is only included in the build when compiling for OSX +#[cfg(target_os = "macos")] +fn macos_only() { + // ... +} + +// This function is only included when either foo or bar is defined +#[cfg(foo)] +#[cfg(bar)] +fn needs_foo_or_bar() { + // ... +} + +// This function is only included when compiling for a unixish OS with a 32-bit +// architecture +#[cfg(unix, target_word_size = "32")] +fn on_32bit_unix() { + // ... +} +~~~~ + +This illustrates some conditional compilation can be achieved using the +`#[cfg(...)]` attribute. Note that `#[cfg(foo, bar)]` is a condition that needs +both `foo` and `bar` to be defined while `#[cfg(foo)] #[cfg(bar)]` only needs +one of `foo` and `bar` to be defined (this resembles in the disjunctive normal +form). Additionally, one can reverse a condition by enclosing it in a +`not(...)`, like e. g. `#[cfg(not(target_os = "win32"))]`. + +To pass a configuration option which triggers a `#[cfg(identifier)]` one can use +`rustc --cfg identifier`. In addition to that, the following configurations are +pre-defined by the compiler: + + * `target_arch = "..."`. Target CPU architecture, such as `"x86"`, `"x86_64"` + `"mips"`, or `"arm"`. + * `target_endian = "..."`. Endianness of the target CPU, either `"little"` or + `"big"`. + * `target_family = "..."`. Operating system family of the target, e. g. + `"unix"` or `"windows"`. The value of this configuration option is defined as + a configuration itself, like `unix` or `windows`. + * `target_os = "..."`. Operating system of the target, examples include + `"win32"`, `"macos"`, `"linux"`, `"android"` or `"freebsd"`. + * `target_word_size = "..."`. Target word size in bits. This is set to `"32"` + for 32-bit CPU targets, and likewise set to `"64"` for 64-bit CPU targets. + * `test`. Only set in test builds (`rustc --test`). + * `unix`. See `target_family`. + * `windows`. See `target_family`. + ### Lint check attributes A lint check names a potentially undesirable coding pattern, such as diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index 6ba1c86fdf2..b41af9eb054 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 35a6ccaa708..fec5b105c4b 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/libextra/lib.rs b/src/libextra/lib.rs index 70a21da6816..c630ac096f6 100644 --- a/src/libextra/lib.rs +++ b/src/libextra/lib.rs @@ -35,20 +35,10 @@ Rust extras are part of the standard Rust distribution. #[deny(missing_doc)]; extern mod sync; -#[cfg(not(stage0))] extern mod serialize; extern mod collections; -#[cfg(stage0)] -pub mod serialize { - #[allow(missing_doc)]; - // Temp re-export until after a snapshot - extern mod serialize = "serialize"; - pub use self::serialize::{Encoder, Decoder, Encodable, Decodable, - EncoderHelpers, DecoderHelpers}; -} - // Utility modules pub mod c_vec; @@ -59,11 +49,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/libnum/bigint.rs b/src/libnum/bigint.rs index 56385c6f43b..8f632ae639d 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; + } + }) + } } diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index 72ae70565a7..957ca3b46c9 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/metadata/loader.rs b/src/librustc/metadata/loader.rs index abcd650ced1..70b93a98135 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 e4eeaa5fded..b8d16f9bb80 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/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 9eec804dd2e..68511362f5f 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/librustc/util/sha2.rs b/src/librustc/util/sha2.rs index 116ec6bba29..940cebf7847 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/librustdoc/clean.rs b/src/librustdoc/clean.rs index ca7f502a2e8..eb0b4597e30 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 024d010f0b9..3e5afc399b9 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/librustuv/lib.rs b/src/librustuv/lib.rs index b463bb7fd73..b71dbe05ad2 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/libextra/base64.rs b/src/libserialize/base64.rs similarity index 97% rename from src/libextra/base64.rs rename to src/libserialize/base64.rs index 556032af1ac..c22eefdb330 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/libserialize/ebml.rs b/src/libserialize/ebml.rs index f08f943306f..3d57a32a830 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/libextra/hex.rs b/src/libserialize/hex.rs similarity index 96% rename from src/libextra/hex.rs rename to src/libserialize/hex.rs index d4e1ae12337..409bf4af809 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 5f473b25369..3b71b2237b1 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; + diff --git a/src/libstd/any.rs b/src/libstd/any.rs index 24da59341cc..3f14db14882 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 7965127007c..651d364dd1b 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/c_str.rs b/src/libstd/c_str.rs index cc6cd7666d6..fe332a60efa 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/cleanup.rs b/src/libstd/cleanup.rs index a43dca94970..dd43d8e2971 100644 --- a/src/libstd/cleanup.rs +++ b/src/libstd/cleanup.rs @@ -57,53 +57,6 @@ fn debug_mem() -> bool { } /// Destroys all managed memory (i.e. @ boxes) held by the current task. -#[cfg(stage0)] -pub unsafe fn annihilate() { - use rt::local_heap::local_free; - - let mut n_total_boxes = 0u; - - // Pass 1: Make all boxes immortal. - // - // In this pass, nothing gets freed, so it does not matter whether - // we read the next field before or after the callback. - each_live_alloc(true, |alloc| { - n_total_boxes += 1; - (*alloc).ref_count = RC_IMMORTAL; - true - }); - - // Pass 2: Drop all boxes. - // - // In this pass, unique-managed boxes may get freed, but not - // managed boxes, so we must read the `next` field *after* the - // callback, as the original value may have been freed. - each_live_alloc(false, |alloc| { - let tydesc = (*alloc).type_desc; - let data = &(*alloc).data as *(); - ((*tydesc).drop_glue)(data as *i8); - true - }); - - // Pass 3: Free all boxes. - // - // In this pass, managed boxes may get freed (but not - // unique-managed boxes, though I think that none of those are - // left), so we must read the `next` field before, since it will - // not be valid after. - each_live_alloc(true, |alloc| { - local_free(alloc as *u8); - true - }); - - if debug_mem() { - // We do logging here w/o allocation. - debug!("total boxes annihilated: {}", n_total_boxes); - } -} - -/// Destroys all managed memory (i.e. @ boxes) held by the current task. -#[cfg(not(stage0))] pub unsafe fn annihilate() { use rt::local_heap::local_free; diff --git a/src/libstd/comm/select.rs b/src/libstd/comm/select.rs index b6b35ccc357..e41fa60aa42 100644 --- a/src/libstd/comm/select.rs +++ b/src/libstd/comm/select.rs @@ -60,21 +60,17 @@ use uint; macro_rules! select { ( - $name1:pat = $port1:ident.$meth1:ident() => $code1:expr, - $($name:pat = $port:ident.$meth:ident() => $code:expr),* + $($name:pat = $port:ident.$meth:ident() => $code:expr),+ ) => ({ use std::comm::Select; let sel = Select::new(); - let mut $port1 = sel.handle(&$port1); - $( let mut $port = sel.handle(&$port); )* + $( let mut $port = sel.handle(&$port); )+ unsafe { - $port1.add(); - $( $port.add(); )* + $( $port.add(); )+ } let ret = sel.wait(); - if ret == $port1.id { let $name1 = $port1.$meth1(); $code1 } - $( else if ret == $port.id { let $name = $port.$meth(); $code } )* - else { unreachable!() } + $( if ret == $port.id() { let $name = $port.$meth(); $code } else )+ + { unreachable!() } }) } @@ -94,7 +90,7 @@ pub struct Select { pub struct Handle<'port, T> { /// The ID of this handle, used to compare against the return value of /// `Select::wait()` - id: uint, + priv id: uint, priv selector: &'port Select, priv next: *mut Handle<'static, ()>, priv prev: *mut Handle<'static, ()>, @@ -150,11 +146,16 @@ impl Select { /// Waits for an event on this port set. The returned valus is *not* and /// index, but rather an id. This id can be queried against any active - /// `Handle` structures (each one has a public `id` field). The handle with + /// `Handle` structures (each one has an `id` method). The handle with /// the matching `id` will have some sort of event available on it. The /// event could either be that data is available or the corresponding /// channel has been closed. pub fn wait(&self) -> uint { + self.wait2(false) + } + + /// Helper method for skipping the preflight checks during testing + fn wait2(&self, do_preflight_checks: bool) -> uint { // Note that this is currently an inefficient implementation. We in // theory have knowledge about all ports in the set ahead of time, so // this method shouldn't really have to iterate over all of them yet @@ -179,7 +180,7 @@ impl Select { let mut amt = 0; for p in self.iter() { amt += 1; - if (*p).packet.can_recv() { + if do_preflight_checks && (*p).packet.can_recv() { return (*p).id; } } @@ -242,6 +243,10 @@ impl Select { } impl<'port, T: Send> Handle<'port, T> { + /// Retrieve the id of this handle. + #[inline] + pub fn id(&self) -> uint { self.id } + /// Receive a value on the underlying port. Has the same semantics as /// `Port.recv` pub fn recv(&mut self) -> T { self.port.recv() } @@ -355,7 +360,7 @@ mod test { ) drop(c2); select! ( - bar = p2.recv_opt() => { assert_eq!(bar, None); }, + bar = p2.recv_opt() => { assert_eq!(bar, None); } ) }) @@ -507,7 +512,7 @@ mod test { let (p2, c2) = Chan::<()>::new(); let (p, c) = Chan::new(); spawn(proc() { - let mut s = Select::new(); + let s = Select::new(); let mut h1 = s.handle(&p1); let mut h2 = s.handle(&p2); unsafe { h2.add(); } @@ -521,4 +526,91 @@ mod test { c2.send(()); p.recv(); }) + + test!(fn preflight1() { + let (p, c) = Chan::new(); + c.send(()); + select!( + () = p.recv() => {} + ) + }) + + test!(fn preflight2() { + let (p, c) = Chan::new(); + c.send(()); + c.send(()); + select!( + () = p.recv() => {} + ) + }) + + test!(fn preflight3() { + let (p, c) = Chan::new(); + drop(c.clone()); + c.send(()); + select!( + () = p.recv() => {} + ) + }) + + test!(fn preflight4() { + let (p, c) = Chan::new(); + c.send(()); + let s = Select::new(); + let mut h = s.handle(&p); + unsafe { h.add(); } + assert_eq!(s.wait2(false), h.id); + }) + + test!(fn preflight5() { + let (p, c) = Chan::new(); + c.send(()); + c.send(()); + let s = Select::new(); + let mut h = s.handle(&p); + unsafe { h.add(); } + assert_eq!(s.wait2(false), h.id); + }) + + test!(fn preflight6() { + let (p, c) = Chan::new(); + drop(c.clone()); + c.send(()); + let s = Select::new(); + let mut h = s.handle(&p); + unsafe { h.add(); } + assert_eq!(s.wait2(false), h.id); + }) + + test!(fn preflight7() { + let (p, c) = Chan::<()>::new(); + drop(c); + let s = Select::new(); + let mut h = s.handle(&p); + unsafe { h.add(); } + assert_eq!(s.wait2(false), h.id); + }) + + test!(fn preflight8() { + let (p, c) = Chan::new(); + c.send(()); + drop(c); + p.recv(); + let s = Select::new(); + let mut h = s.handle(&p); + unsafe { h.add(); } + assert_eq!(s.wait2(false), h.id); + }) + + test!(fn preflight9() { + let (p, c) = Chan::new(); + drop(c.clone()); + c.send(()); + drop(c); + p.recv(); + let s = Select::new(); + let mut h = s.handle(&p); + unsafe { h.add(); } + assert_eq!(s.wait2(false), h.id); + }) } diff --git a/src/libstd/comm/shared.rs b/src/libstd/comm/shared.rs index 30e061bb7b9..77bf2d7a68d 100644 --- a/src/libstd/comm/shared.rs +++ b/src/libstd/comm/shared.rs @@ -398,6 +398,17 @@ impl Packet { cnt == DISCONNECTED || cnt - self.steals > 0 } + // increment the count on the channel (used for selection) + fn bump(&mut self, amt: int) -> int { + match self.cnt.fetch_add(amt, atomics::SeqCst) { + DISCONNECTED => { + self.cnt.store(DISCONNECTED, atomics::SeqCst); + DISCONNECTED + } + n => n + } + } + // Inserts the blocked task for selection on this port, returning it back if // the port already has data on it. // @@ -408,8 +419,8 @@ impl Packet { match self.decrement(task) { Ok(()) => Ok(()), Err(task) => { - let prev = self.cnt.fetch_add(1, atomics::SeqCst); - assert!(prev >= 0); + let prev = self.bump(1); + assert!(prev == DISCONNECTED || prev >= 0); return Err(task); } } @@ -440,11 +451,10 @@ impl Packet { let cnt = self.cnt.load(atomics::SeqCst); if cnt < 0 && cnt != DISCONNECTED {-cnt} else {0} }; - let prev = self.cnt.fetch_add(steals + 1, atomics::SeqCst); + let prev = self.bump(steals + 1); if prev == DISCONNECTED { assert_eq!(self.to_wake.load(atomics::SeqCst), 0); - self.cnt.store(DISCONNECTED, atomics::SeqCst); true } else { let cur = prev + steals + 1; diff --git a/src/libstd/comm/stream.rs b/src/libstd/comm/stream.rs index 0e249a55f87..9c972a3771c 100644 --- a/src/libstd/comm/stream.rs +++ b/src/libstd/comm/stream.rs @@ -333,6 +333,17 @@ impl Packet { } } + // increment the count on the channel (used for selection) + fn bump(&mut self, amt: int) -> int { + match self.cnt.fetch_add(amt, atomics::SeqCst) { + DISCONNECTED => { + self.cnt.store(DISCONNECTED, atomics::SeqCst); + DISCONNECTED + } + n => n + } + } + // Attempts to start selecting on this port. Like a oneshot, this can fail // immediately because of an upgrade. pub fn start_selection(&mut self, task: BlockedTask) -> SelectionResult { @@ -351,8 +362,8 @@ impl Packet { }; // Undo our decrement above, and we should be guaranteed that the // previous value is positive because we're not going to sleep - let prev = self.cnt.fetch_add(1, atomics::SeqCst); - assert!(prev >= 0); + let prev = self.bump(1); + assert!(prev == DISCONNECTED || prev >= 0); return ret; } } @@ -384,13 +395,12 @@ impl Packet { // and in the stream case we can have at most one steal, so just assume // that we had one steal. let steals = 1; - let prev = self.cnt.fetch_add(steals + 1, atomics::SeqCst); + let prev = self.bump(steals + 1); // If we were previously disconnected, then we know for sure that there // is no task in to_wake, so just keep going let has_data = if prev == DISCONNECTED { assert_eq!(self.to_wake.load(atomics::SeqCst), 0); - self.cnt.store(DISCONNECTED, atomics::SeqCst); true // there is data, that data is that we're disconnected } else { let cur = prev + steals + 1; diff --git a/src/libstd/hashmap.rs b/src/libstd/hashmap.rs index 953cc66a2cb..c49294a095f 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/io/extensions.rs b/src/libstd/io/extensions.rs index 240f4c65501..da4697d0e48 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/macros.rs b/src/libstd/macros.rs index be1fdc4594d..14ae7c9900c 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -145,16 +145,18 @@ macro_rules! format( #[macro_export] macro_rules! write( - ($dst:expr, $($arg:tt)*) => ( - format_args!(|args| { ::std::fmt::write($dst, args) }, $($arg)*) - ) + ($dst:expr, $($arg:tt)*) => ({ + let dst: &mut ::std::io::Writer = $dst; + format_args!(|args| { ::std::fmt::write(dst, args) }, $($arg)*) + }) ) #[macro_export] macro_rules! writeln( - ($dst:expr, $($arg:tt)*) => ( - format_args!(|args| { ::std::fmt::writeln($dst, args) }, $($arg)*) - ) + ($dst:expr, $($arg:tt)*) => ({ + let dst: &mut ::std::io::Writer = $dst; + format_args!(|args| { ::std::fmt::writeln(dst, args) }, $($arg)*) + }) ) #[macro_export] diff --git a/src/libstd/ptr.rs b/src/libstd/ptr.rs index 80439d69899..2ba6f7d4fd6 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/reflect.rs b/src/libstd/reflect.rs index 1c22408592a..f88da60ae9b 100644 --- a/src/libstd/reflect.rs +++ b/src/libstd/reflect.rs @@ -441,11 +441,4 @@ impl TyVisitor for MovePtrAdaptor { self.align_to::<&'static u8>(); true } - - // NOTE Remove after next snapshot. - #[cfg(stage0)] - fn visit_type(&mut self) -> bool { - if ! self.inner.visit_type() { return false; } - true - } } diff --git a/src/libstd/repr.rs b/src/libstd/repr.rs index 4ced74a92b7..58c00177b90 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])); @@ -601,10 +602,6 @@ impl<'a> TyVisitor for ReprVisitor<'a> { fn visit_param(&mut self, _i: uint) -> bool { true } fn visit_self(&mut self) -> bool { true } - - // NOTE Remove after next snapshot. - #[cfg(stage0)] - fn visit_type(&mut self) -> bool { true } } pub fn write_repr(writer: &mut io::Writer, object: &T) -> io::IoResult<()> { diff --git a/src/libstd/rt/global_heap.rs b/src/libstd/rt/global_heap.rs index 2f553585f38..4bce16706ee 100644 --- a/src/libstd/rt/global_heap.rs +++ b/src/libstd/rt/global_heap.rs @@ -10,8 +10,6 @@ use libc::{c_void, size_t, free, malloc, realloc}; use ptr::{RawPtr, mut_null}; -#[cfg(stage0)] -use unstable::intrinsics::TyDesc; use unstable::intrinsics::abort; use unstable::raw; use mem::size_of; @@ -75,15 +73,7 @@ pub unsafe fn exchange_malloc(size: uint) -> *u8 { } // FIXME: #7496 -#[cfg(not(test), stage0)] -#[lang="closure_exchange_malloc"] -#[inline] -pub unsafe fn closure_exchange_malloc_(td: *u8, size: uint) -> *u8 { - closure_exchange_malloc(td, size) -} - -// FIXME: #7496 -#[cfg(not(test), not(stage0))] +#[cfg(not(test))] #[lang="closure_exchange_malloc"] #[inline] pub unsafe fn closure_exchange_malloc_(drop_glue: fn(*mut u8), size: uint, align: uint) -> *u8 { @@ -91,24 +81,6 @@ pub unsafe fn closure_exchange_malloc_(drop_glue: fn(*mut u8), size: uint, align } #[inline] -#[cfg(stage0)] -pub unsafe fn closure_exchange_malloc(td: *u8, size: uint) -> *u8 { - let td = td as *TyDesc; - let size = size; - - assert!(td.is_not_null()); - - let total_size = get_box_size(size, (*td).align); - let p = malloc_raw(total_size); - - let alloc = p as *mut raw::Box<()>; - (*alloc).type_desc = td; - - alloc as *u8 -} - -#[inline] -#[cfg(not(stage0))] pub unsafe fn closure_exchange_malloc(drop_glue: fn(*mut u8), size: uint, align: uint) -> *u8 { let total_size = get_box_size(size, align); let p = malloc_raw(total_size); diff --git a/src/libstd/rt/local_heap.rs b/src/libstd/rt/local_heap.rs index 3bee9e48b60..023f712d3a0 100644 --- a/src/libstd/rt/local_heap.rs +++ b/src/libstd/rt/local_heap.rs @@ -21,8 +21,6 @@ use rt::env; use rt::global_heap; use rt::local::Local; use rt::task::Task; -#[cfg(stage0)] -use unstable::intrinsics::TyDesc; use unstable::raw; use vec::ImmutableVector; @@ -61,29 +59,6 @@ impl LocalHeap { } #[inline] - #[cfg(stage0)] - pub fn alloc(&mut self, td: *TyDesc, size: uint) -> *mut Box { - let total_size = global_heap::get_box_size(size, unsafe { (*td).align }); - let alloc = self.memory_region.malloc(total_size); - { - // Make sure that we can't use `mybox` outside of this scope - let mybox: &mut Box = unsafe { cast::transmute(alloc) }; - // Clear out this box, and move it to the front of the live - // allocations list - mybox.type_desc = td; - mybox.ref_count = 1; - mybox.prev = ptr::mut_null(); - mybox.next = self.live_allocs; - if !self.live_allocs.is_null() { - unsafe { (*self.live_allocs).prev = alloc; } - } - self.live_allocs = alloc; - } - return alloc; - } - - #[inline] - #[cfg(not(stage0))] pub fn alloc(&mut self, drop_glue: fn(*mut u8), size: uint, align: uint) -> *mut Box { let total_size = global_heap::get_box_size(size, align); let alloc = self.memory_region.malloc(total_size); @@ -126,41 +101,6 @@ impl LocalHeap { } #[inline] - #[cfg(stage0)] - pub fn free(&mut self, alloc: *mut Box) { - { - // Make sure that we can't use `mybox` outside of this scope - let mybox: &mut Box = unsafe { cast::transmute(alloc) }; - assert!(!mybox.type_desc.is_null()); - - // Unlink it from the linked list - if !mybox.prev.is_null() { - unsafe { (*mybox.prev).next = mybox.next; } - } - if !mybox.next.is_null() { - unsafe { (*mybox.next).prev = mybox.prev; } - } - if self.live_allocs == alloc { - self.live_allocs = mybox.next; - } - - // Destroy the box memory-wise - if self.poison_on_free { - unsafe { - let ptr: *mut u8 = cast::transmute(&mybox.data); - ptr::set_memory(ptr, 0xab, (*mybox.type_desc).size); - } - } - mybox.prev = ptr::mut_null(); - mybox.next = ptr::mut_null(); - mybox.type_desc = ptr::null(); - } - - self.memory_region.free(alloc); - } - - #[inline] - #[cfg(not(stage0))] pub fn free(&mut self, alloc: *mut Box) { { // Make sure that we can't use `mybox` outside of this scope @@ -339,20 +279,6 @@ impl Drop for MemoryRegion { } #[inline] -#[cfg(stage0)] -pub unsafe fn local_malloc(td: *u8, size: uint) -> *u8 { - // FIXME: Unsafe borrow for speed. Lame. - let task: Option<*mut Task> = Local::try_unsafe_borrow(); - match task { - Some(task) => { - (*task).heap.alloc(td as *TyDesc, size) as *u8 - } - None => rtabort!("local malloc outside of task") - } -} - -#[inline] -#[cfg(not(stage0))] pub unsafe fn local_malloc(drop_glue: fn(*mut u8), size: uint, align: uint) -> *u8 { // FIXME: Unsafe borrow for speed. Lame. let task: Option<*mut Task> = Local::try_unsafe_borrow(); diff --git a/src/libstd/str.rs b/src/libstd/str.rs index bc5991c6eeb..0d263d94ccf 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); } } @@ -4164,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()); @@ -4171,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 3aa3e020500..b23dafbca69 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/unstable/intrinsics.rs b/src/libstd/unstable/intrinsics.rs index b9e9c9d5a43..c983d82563c 100644 --- a/src/libstd/unstable/intrinsics.rs +++ b/src/libstd/unstable/intrinsics.rs @@ -160,10 +160,6 @@ pub trait TyVisitor { fn visit_trait(&mut self, name: &str) -> bool; fn visit_param(&mut self, i: uint) -> bool; fn visit_self(&mut self) -> bool; - - // NOTE Remove after next snapshot. - #[cfg(stage0)] - fn visit_type(&mut self) -> bool; } extern "rust-intrinsic" { diff --git a/src/libstd/unstable/lang.rs b/src/libstd/unstable/lang.rs index a85f26720bf..4648f149a9f 100644 --- a/src/libstd/unstable/lang.rs +++ b/src/libstd/unstable/lang.rs @@ -27,14 +27,6 @@ pub fn fail_bounds_check(file: *u8, line: uint, index: uint, len: uint) -> ! { } #[lang="malloc"] -#[cfg(stage0)] -#[inline] -pub unsafe fn local_malloc(td: *u8, size: uint) -> *u8 { - ::rt::local_heap::local_malloc(td, size) -} - -#[lang="malloc"] -#[cfg(not(stage0))] #[inline] pub unsafe fn local_malloc(drop_glue: fn(*mut u8), size: uint, align: uint) -> *u8 { ::rt::local_heap::local_malloc(drop_glue, size, align) diff --git a/src/libstd/unstable/raw.rs b/src/libstd/unstable/raw.rs index 98dde95d3b7..87547997798 100644 --- a/src/libstd/unstable/raw.rs +++ b/src/libstd/unstable/raw.rs @@ -9,21 +9,8 @@ // except according to those terms. use cast; -#[cfg(stage0)] -use unstable::intrinsics::TyDesc; /// The representation of a Rust managed box -#[cfg(stage0)] -pub struct Box { - ref_count: uint, - type_desc: *TyDesc, - prev: *mut Box, - next: *mut Box, - data: T -} - -/// The representation of a Rust managed box -#[cfg(not(stage0))] pub struct Box { ref_count: uint, drop_glue: fn(ptr: *mut u8), diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index 2acafecf957..c67b19933d3 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; @@ -137,7 +139,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 +167,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 +1497,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 +1511,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 +1798,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 +2385,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 +2486,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 +2545,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 +2557,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 } @@ -2640,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 [] } @@ -4049,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; diff --git a/src/libstd/vec_ng.rs b/src/libstd/vec_ng.rs index 90bc5836240..25ba45021b3 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; } diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index d22a1d697fc..02c3a1b985b 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 d146cd4dae3..d79c4cbc96a 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/snapshots.txt b/src/snapshots.txt index 8cf463dd88a..2db884fdb64 100644 --- a/src/snapshots.txt +++ b/src/snapshots.txt @@ -1,3 +1,11 @@ +S 2014-02-12 c62f6ce + freebsd-x86_64 737a423c5f803119ff5a692eac432fa9d0c595a8 + linux-i386 a7e90e27e8b6a3fa79ddc15f0ed217ccbade875d + linux-x86_64 8f5fdf9f07b2afbc55d8d8c06c60aeb532b5ea83 + macos-i386 57bb225f45bc57fef4c34552a2d5814ab4913087 + macos-x86_64 d37b62478aa1c1dd1babb19d1df494d2aaf59c4c + winnt-i386 2c5c5f7228140cd79f120201805504a9e07ad245 + S 2014-02-03 346d378 freebsd-x86_64 d369c1a83a2be6eb42bd0e550a1adc38ffed0804 linux-i386 a6d4ab441f5b285d7aecbb940fa733526b413f34 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 00000000000..eecbb325630 --- /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 00000000000..a71cc465e88 --- /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() {} diff --git a/src/test/run-pass/colorful-write-macros.rs b/src/test/run-pass/colorful-write-macros.rs new file mode 100644 index 00000000000..55bac0a0e07 --- /dev/null +++ b/src/test/run-pass/colorful-write-macros.rs @@ -0,0 +1,28 @@ +// 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(unused_must_use, dead_code)]; + +use std::io::MemWriter; + +struct Foo<'a> { + writer: &'a mut Writer, + other: &'a str, +} + +fn borrowing_writer_from_struct_and_formatting_struct_field(foo: Foo) { + write!(foo.writer, "{}", foo.other); +} + +pub fn main() { + let mut w = MemWriter::new(); + write!(&mut w as &mut Writer, ""); + write!(&mut w, ""); // should coerce +} diff --git a/src/test/run-pass/issue-9918.rs b/src/test/run-pass/issue-9918.rs new file mode 100644 index 00000000000..240a134221d --- /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'); +}