From 6b429d07c96c3e7cb3130c070d99651f29bded6c Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Tue, 11 Feb 2014 22:43:23 -0800 Subject: [PATCH 01/14] 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 745aa7482ace9f62fcd08ff7a9195fd484527c94 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 12 Feb 2014 11:42:58 -0800 Subject: [PATCH 02/14] 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 606c23a78920c03758e200004fd9d1f4257f0325 Mon Sep 17 00:00:00 2001 From: Seo Sanghyeon Date: Thu, 13 Feb 2014 00:42:28 +0900 Subject: [PATCH 03/14] 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 7dc187afd8a19dad05dbf1a689e6b6f400f7bc0a Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Sun, 9 Feb 2014 23:13:47 +0100 Subject: [PATCH 04/14] 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 8a5b938b3bb408c24f0f1d6fbd6bd0ba011f60a1 Mon Sep 17 00:00:00 2001 From: Liigo Zhuang Date: Wed, 12 Feb 2014 08:40:52 +0800 Subject: [PATCH 05/14] 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 957fcb3f54d4a3ee2d9ed67a532bb48e34753094 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Thu, 13 Feb 2014 06:41:34 +1100 Subject: [PATCH 06/14] 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 bc5991c6eebd0..4daa3f8a36ad2 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -4164,6 +4164,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 +4172,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 2acafecf95720..75993cdada24d 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; @@ -2640,6 +2642,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 +4075,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; From 866d6cc33d06050b546abbe5930546ff17d96493 Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Thu, 13 Feb 2014 00:38:14 +0100 Subject: [PATCH 07/14] Add documentation for conditional-compilation This documents in-source conditions using #[cfg(...)] and configurations pre-defined by the compiler. Fix #7962. --- src/doc/rust.md | 84 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 74 insertions(+), 10 deletions(-) diff --git a/src/doc/rust.md b/src/doc/rust.md index 725f15f4aaad9..fe0fd8bd84d5c 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 From 411a01feb302dd64b669658562f2052decc80f19 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Thu, 13 Feb 2014 14:10:29 +1100 Subject: [PATCH 08/14] std::comm: replace Handle.id with a method. The `id` shouldn't be changed by external code, and exposing it publicly allows to be accidentally changed. Also, remove the first element special case in the `select!` macro. --- src/libstd/comm/select.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/libstd/comm/select.rs b/src/libstd/comm/select.rs index b6b35ccc35790..2a8a874b7984e 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,7 +146,7 @@ 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. @@ -242,6 +238,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 +355,7 @@ mod test { ) drop(c2); select! ( - bar = p2.recv_opt() => { assert_eq!(bar, None); }, + bar = p2.recv_opt() => { assert_eq!(bar, None); } ) }) From 065e121fc2675631e27b761d2ad5df3ee0c95976 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 12 Feb 2014 20:51:42 -0800 Subject: [PATCH 09/14] Relax an assertion in start_selection() It asserted that the previous count was always nonnegative, but DISCONNECTED is a valid value for it to see. In order to continue to remember to store DISCONNECTED after DISCONNECTED was seen, I also added a helper method. Closes #12226 --- src/libstd/comm/select.rs | 96 ++++++++++++++++++++++++++++++++++++++- src/libstd/comm/shared.rs | 18 ++++++-- src/libstd/comm/stream.rs | 18 ++++++-- 3 files changed, 122 insertions(+), 10 deletions(-) diff --git a/src/libstd/comm/select.rs b/src/libstd/comm/select.rs index 2a8a874b7984e..3efd72be7b1c5 100644 --- a/src/libstd/comm/select.rs +++ b/src/libstd/comm/select.rs @@ -151,6 +151,11 @@ impl Select { /// 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 @@ -175,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; } } @@ -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 30e061bb7b916..77bf2d7a68d36 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 0e249a55f8707..9c972a3771c1a 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; From 44e6883d1462ed4072b1d6a3ce6702bc14065045 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Thu, 13 Feb 2014 19:35:43 +1100 Subject: [PATCH 10/14] mk: make NO_REBUILD more forceful and more general. Previously crates like `green` and `native` would still depend on their parents when running `make check-stage2-green NO_REBUILD=1`, this ensures that they only depend on their source files. Also, apply NO_REBUILD to the crate doc tests, so, for example, `check-stage2-doc-std` will use an already compiled `rustdoc` directly. --- mk/tests.mk | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/mk/tests.mk b/mk/tests.mk index c2b298dbb9c20..a8ad51409d916 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 $$@ From 1c5295c0bf6e69a772120ec6a56e0fdb3021ded4 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 12 Feb 2014 16:40:17 -0800 Subject: [PATCH 11/14] Register new snapshots --- Makefile.in | 8 +--- src/libextra/lib.rs | 10 ----- src/libstd/cleanup.rs | 47 -------------------- src/libstd/reflect.rs | 7 --- src/libstd/repr.rs | 4 -- src/libstd/rt/global_heap.rs | 30 +------------ src/libstd/rt/local_heap.rs | 74 ------------------------------- src/libstd/unstable/intrinsics.rs | 4 -- src/libstd/unstable/lang.rs | 8 ---- src/libstd/unstable/raw.rs | 13 ------ src/snapshots.txt | 8 ++++ 11 files changed, 11 insertions(+), 202 deletions(-) diff --git a/Makefile.in b/Makefile.in index 1130ab53d5d24..ef1701a61e80b 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/src/libextra/lib.rs b/src/libextra/lib.rs index e0200f48cfeca..c630ac096f622 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; diff --git a/src/libstd/cleanup.rs b/src/libstd/cleanup.rs index a43dca9497030..dd43d8e2971a8 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/reflect.rs b/src/libstd/reflect.rs index 1c22408592a74..f88da60ae9b79 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 4ced74a92b7c0..dc745ff548f02 100644 --- a/src/libstd/repr.rs +++ b/src/libstd/repr.rs @@ -601,10 +601,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 2f553585f38ce..4bce16706ee60 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 3bee9e48b602e..023f712d3a08a 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/unstable/intrinsics.rs b/src/libstd/unstable/intrinsics.rs index b9e9c9d5a436f..c983d82563caf 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 a85f26720bf17..4648f149a9fed 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 98dde95d3b7cc..87547997798f5 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/snapshots.txt b/src/snapshots.txt index 8cf463dd88a80..2db884fdb6436 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 From 60bc76fb78d226078a901efd94f61463c0d93b9a Mon Sep 17 00:00:00 2001 From: JeremyLetang Date: Mon, 10 Feb 2014 16:50:42 -0500 Subject: [PATCH 12/14] 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 dc745ff548f02..58c00177b9016 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 4daa3f8a36ad2..0d263d94ccf0f 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 75993cdada24d..c67b19933d37f 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -139,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; }, @@ -167,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; }, @@ -1497,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); } } @@ -1511,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); } @@ -1798,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; @@ -2385,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] @@ -2486,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; @@ -2544,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 } @@ -2556,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 } 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 76c313ceb15228a8683ca1dd03ce277ed0b69d4c Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 13 Feb 2014 04:31:19 -0800 Subject: [PATCH 13/14] Lift $dst outside the closure in write! If you were writing to something along the lines of `self.foo` then with the new closure rules it meant that you were borrowing `self` for the entirety of the closure, meaning that you couldn't format other fields of `self` at the same time as writing to a buffer contained in `self`. By lifting the borrow outside of the closure the borrow checker can better understand that you're only borrowing one of the fields at a time. This had to use type ascription as well in order to preserve trait object coercions. --- src/libstd/macros.rs | 14 ++++++----- src/test/run-pass/colorful-write-macros.rs | 28 ++++++++++++++++++++++ 2 files changed, 36 insertions(+), 6 deletions(-) create mode 100644 src/test/run-pass/colorful-write-macros.rs diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index be1fdc4594d05..14ae7c9900c46 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/test/run-pass/colorful-write-macros.rs b/src/test/run-pass/colorful-write-macros.rs new file mode 100644 index 0000000000000..55bac0a0e078c --- /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 +} From 640b22852f59e4505cedfd02c01cc343d5ec0d9e Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 13 Feb 2014 12:50:46 -0800 Subject: [PATCH 14/14] Rebase conflicts from this giant stack of patches List of PRs contained in this rollup: Closes #12167 r=alexcrichton Closes #12200 r=alexcrichton Closes #12206 r=pcwalton Closes #12209 r=huonw Closes #12211 r=pcwalton Closes #12217 r=brson Closes #12218 r=alexcrichton Closes #12220 r=alexcrichton Closes #12222 r=kballard Closes #12225 r=alexcrichton Closes #12227 r=kballard Closes #12237 r=alexcrichton Closes #12240 r=kballard --- src/libstd/comm/select.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libstd/comm/select.rs b/src/libstd/comm/select.rs index 3efd72be7b1c5..e41fa60aa42e6 100644 --- a/src/libstd/comm/select.rs +++ b/src/libstd/comm/select.rs @@ -531,7 +531,7 @@ mod test { let (p, c) = Chan::new(); c.send(()); select!( - () = p.recv() => {}, + () = p.recv() => {} ) }) @@ -540,7 +540,7 @@ mod test { c.send(()); c.send(()); select!( - () = p.recv() => {}, + () = p.recv() => {} ) }) @@ -549,7 +549,7 @@ mod test { drop(c.clone()); c.send(()); select!( - () = p.recv() => {}, + () = p.recv() => {} ) })