diff --git a/Makefile.in b/Makefile.in index ca82f2960227..baae56c4f409 100644 --- a/Makefile.in +++ b/Makefile.in @@ -111,7 +111,7 @@ ifdef SAVE_TEMPS CFG_RUSTC_FLAGS += --save-temps endif ifdef ASM_COMMENTS - CFG_RUSTC_FLAGS += -z asm-comments + CFG_RUSTC_FLAGS += -Z asm-comments endif ifdef TIME_PASSES CFG_RUSTC_FLAGS += -Z time-passes @@ -208,7 +208,6 @@ CFG_STDLIB_$(1) :=$(call CFG_LIB_NAME_$(1),std) CFG_EXTRALIB_$(1) :=$(call CFG_LIB_NAME_$(1),extra) CFG_LIBRUSTC_$(1) :=$(call CFG_LIB_NAME_$(1),rustc) CFG_LIBSYNTAX_$(1) :=$(call CFG_LIB_NAME_$(1),syntax) -CFG_LIBFUZZER_$(1) :=$(call CFG_LIB_NAME_$(1),fuzzer) CFG_LIBRUSTPKG_$(1) :=$(call CFG_LIB_NAME_$(1),rustpkg) CFG_LIBRUSTDOC_$(1) :=$(call CFG_LIB_NAME_$(1),rustdoc) CFG_LIBRUSTI_$(1) :=$(call CFG_LIB_NAME_$(1),rusti) @@ -218,7 +217,6 @@ EXTRALIB_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),extra) STDLIB_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),std) LIBRUSTC_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),rustc) LIBSYNTAX_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),syntax) -LIBFUZZER_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),fuzzer) LIBRUSTPKG_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),rustpkg) LIBRUSTDOC_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),rustdoc) LIBRUSTI_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),rusti) @@ -227,7 +225,6 @@ EXTRALIB_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),extra) STDLIB_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),std) LIBRUSTC_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),rustc) LIBSYNTAX_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),syntax) -LIBFUZZER_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),fuzzer) LIBRUSTPKG_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),rustpkg) LIBRUSTDOC_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),rustdoc) LIBRUSTI_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),rusti) @@ -402,12 +399,10 @@ SREQ$(1)_T_$(2)_H_$(3) = \ # Prerequisites for a working stageN compiler and libraries, for a specific target CSREQ$(1)_T_$(2)_H_$(3) = \ $$(TSREQ$(1)_T_$(2)_H_$(3)) \ - $$(HBIN$(1)_H_$(3))/fuzzer$$(X_$(3)) \ $$(HBIN$(1)_H_$(3))/rustpkg$$(X_$(3)) \ $$(HBIN$(1)_H_$(3))/rustdoc$$(X_$(3)) \ $$(HBIN$(1)_H_$(3))/rusti$$(X_$(3)) \ $$(HBIN$(1)_H_$(3))/rust$$(X_$(3)) \ - $$(HLIB$(1)_H_$(3))/$(CFG_LIBFUZZER_$(3)) \ $$(HLIB$(1)_H_$(3))/$(CFG_LIBRUSTPKG_$(3)) \ $$(HLIB$(1)_H_$(3))/$(CFG_LIBRUSTDOC_$(3)) \ $$(HLIB$(1)_H_$(3))/$(CFG_LIBRUSTI_$(3)) \ @@ -416,7 +411,6 @@ CSREQ$(1)_T_$(2)_H_$(3) = \ $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_EXTRALIB_$(2)) \ $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBSYNTAX_$(2)) \ $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTC_$(2)) \ - $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBFUZZER_$(2)) \ $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTPKG_$(2)) \ $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTDOC_$(2)) \ $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTI_$(2)) \ diff --git a/RELEASES.txt b/RELEASES.txt index 5bf160d62487..d099b1336dfd 100644 --- a/RELEASES.txt +++ b/RELEASES.txt @@ -4,36 +4,90 @@ Version 0.7 (July 2013) * ??? changes, numerous bugfixes * Syntax changes - * `#[deriving(Encodable)]`, `#[deriving(Decodable)]` + * `use mod` is no longer valid. + * `fail!` and `assert!` accept `~str`, `&'static str` or `fmt!`-style + argument list. + * `Encodable`, `Decodable`, `TotalOrd`, `TotalEq`, `DeepClone` can all + be automatically derived with `#[deriving(...)]`. + * The `Durable` trait is replaced with the `'static` bounds. + * At long last, 'argument modes' no longer exist. + * The `bytes!` macro returns a vector of bytes for string, u8, char, + and unsuffixed integer literals. * Semantic changes + * The borrow checker has been rewritten with flow-sensitivity, fixing + many bugs and inconveniences. * The `self` parameter no longer implicitly means `&'self self`, and can be explicitly marked with a lifetime. * Structs with the `#[packed]` attribute have byte alignment and no padding between fields. + * The `for` loop protocol now requires `for`-iterators to return `bool` + so they compose better. + * `Option<~T>` is now represented as a nullable pointer. + * `@mut` does dynamic borrow checks correctly. + * Macros TODO + * The `main` function is only detected at the topmost level of the crate. + The `#[main]` attribute is still valid anywhere. + * Struct fields may no longer be mutable. Use inherited mutability. + * The `#[non_owned]` attribute makes a type that would otherwise be + `Owned`, not. TODO this may change to non_send before 0.7 + * The `#[mutable]` attribute makes a type that would otherwise be + `Const`, note. TODO this may change to non_freeze before 0.7 + * Unbounded recursion will abort the process after reaching the limit + specified by the `RUST_MAX_STACK` environment variable. + * The `vecs_implicitly_copyable` lint mode has been removed. Vectors + are never implicitly copyable. * Libraries - - **Note: in 0.7 `core` was renamed `std` and `std` to `extra. - These notes use the new crate names.** - * The `core` crate was renamed to `std`. * The `std` crate was renamed to `extra`. * `std::mut` removed. + * std: The prelude no longer reexports any modules, only types and traits. + * std: Prelude additions: `print`, `println`, `FromStr`, `ApproxEq`, `Equiv`, + `Iterator`, `IteratorUtil`, many numeric traits, many tuple traits. * std: `iterator` module for external iterator objects. + * std: new numeric traits: `Fractional`, `Real`, `RealExt`, `Integer`, `Ratio`, + `Algebraic`, `Trigonometric`, `Exponential`, `Primitive`. + * std: Tuple traits and accessors defined for up to 12-tuples, e.g. + `(0, 1, 2).n2()` or `(0, 1, 2).n2_ref()`. * std: many types implement `Clone` - tuples, @, @mut. TODO * std: `path` type renamed to `Path`. * std: Many standalone functions removed in favor of methods in - `vec`, `str`, TODO. In the future methods will also work as functions. + `vec`, `str`. In the future methods will also work as functions. + * std: `reinterpret_cast` removed. Used `transmute`. + * std: ascii string handling in `std::ascii`. + * std: `Rand` is implemented for ~/@. + * std: `run` module for spawning processes overhauled. + * std: Various atomic types added to `unstable::atomic`. + * std: `LinearMap` and `LinearSet` renamed to `HashMap` and `HashSet`. + * std: Added `os::mkdir_recursive`. + * std: Added `os::glob` function performs filesystems globs. + * std: `FuzzyEq` renamed to `ApproxEq`. + * std: `Map` now defines `pop` and `swap` methods. + * extra: `flate` module moved from `std` to `extra`. * extra: `FileInput` implements `std::io::Reader`. * extra: `Complex` number type and `complex` module. * extra: `Rational` number type and `rational` module. * extra: `BigInt`, `BigUint` implement numeric and comparison traits. + * extra: `term` uses terminfo now, is more correct. + + * Tooling + * `unused_unsafe` lint mode for detecting unnecessary `unsafe` blocks. + * `unused_mut` lint mode for identifying unused `mut` qualifiers. + * The `rusti` command has been rewritten and a number of bugs addressed. + * rustc outputs in color on more terminals. + * rustc accepts a `--link-args` flag to pass arguments to the linker. + * rustc accepts a `-Z print-link-args` flag for debugging linkage. + * Compiling with `-g` will make the binary record information about + dynamic borrowcheck failures for debugging. + * rustdoc has a nicer stylesheet. + * Various improvements to rustdoc. * Other - * `unused_unsafe` lint mode for detecting unnecessary `unsafe` blocks. * More and improved library documentation. - * The `rusti` command has been rewritten and a number of bugs addressed. + * Various improvements on ARM and Android. + * Various improvements to MIPS backend. + * jemalloc is the Rust allocator. Version 0.6 (April 2013) ------------------------ diff --git a/doc/rust.css b/doc/rust.css index 35581a8d4edf..ed9ea446aa87 100644 --- a/doc/rust.css +++ b/doc/rust.css @@ -12,41 +12,38 @@ body { } h1 { - font-size: 20pt; - margin-top: 2em; + font-size: 24pt; + margin-top: 1.6em; padding-left: 0.4em; line-height: 1.6em; background-color:#FFF2CE; border-radius: 0.2em; - border: 1px solid rgba(0, 0, 0, 0.15); } h2 { - font-size: 15pt; - margin-top: 2em; - padding-left: 0.4em; + font-size: 16pt; + margin-top: 1.6em; + padding: 0.2em 0.5em; background-color:#FFF2CE; border-radius: 0.4em; - border: 1px solid rgba(0, 0, 0, 0.15); } h2 code { color: #097334; - font-size: 15pt; + font-size: 16pt; } h3 { - font-size: 13pt; + font-size: 14pt; color: black; background-color:#D9E7FF; border-radius: 0.4em; - border: 1px solid rgba(0, 0, 0, 0.15); - padding: 0 0.4em 0 0.4em; + padding: 0.2em 0.5em; } h3 code { color: #541800; - font-size: 13pt; + font-size: 14pt; font-style: italic; } diff --git a/doc/rust.md b/doc/rust.md index 3c0828def154..9edbc44d6c21 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -2826,7 +2826,7 @@ Within the body of an item that has type parameter declarations, the names of it ~~~~~~~ fn map(f: &fn(A) -> B, xs: &[A]) -> ~[B] { if xs.len() == 0 { return ~[]; } - let first: B = f(xs[0]); + let first: B = f(copy xs[0]); let rest: ~[B] = map(f, xs.slice(1, xs.len())); return ~[first] + rest; } diff --git a/doc/tutorial-tasks.md b/doc/tutorial-tasks.md index b00cd665271f..2e3ce40c9f7d 100644 --- a/doc/tutorial-tasks.md +++ b/doc/tutorial-tasks.md @@ -359,7 +359,7 @@ fn pnorm(nums: &~[float], p: uint) -> float { fn main() { let numbers = vec::from_fn(1000000, |_| rand::random::()); - println(fmt!("Inf-norm = %?", numbers.max())); + println(fmt!("Inf-norm = %?", *numbers.iter().max().unwrap())); let numbers_arc = ARC(numbers); diff --git a/doc/tutorial.md b/doc/tutorial.md index a45803611666..f69f569faee4 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -1941,12 +1941,14 @@ fn head_bad(v: &[T]) -> T { ~~~~ However, we can tell the compiler that the `head` function is only for -copyable types: that is, those that have the `Copy` trait. +copyable types: that is, those that have the `Copy` trait. In that +case, we can explicitly create a second copy of the value we are +returning using the `copy` keyword: ~~~~ // This does fn head(v: &[T]) -> T { - v[0] + copy v[0] } ~~~~ @@ -2039,17 +2041,12 @@ themselves contain type parameters. A trait for generalized sequence types might look like the following: ~~~~ -# use std::vec; trait Seq { - fn len(&self) -> uint; - fn iter(&self, b: &fn(v: &T)); + fn length(&self) -> uint; } impl Seq for ~[T] { - fn len(&self) -> uint { self.len() } - fn iter(&self, b: &fn(v: &T)) { - for vec::each(*self) |elt| { b(elt); } - } + fn length(&self) -> uint { self.len() } } ~~~~ @@ -2142,7 +2139,7 @@ as in this version of `print_all` that copies elements. fn print_all(printable_things: ~[T]) { let mut i = 0; while i < printable_things.len() { - let copy_of_thing = printable_things[i]; + let copy_of_thing = copy printable_things[i]; copy_of_thing.print(); i += 1; } diff --git a/mk/clean.mk b/mk/clean.mk index 9a074b29d8b1..23efbb3ee15c 100644 --- a/mk/clean.mk +++ b/mk/clean.mk @@ -63,13 +63,11 @@ define CLEAN_HOST_STAGE_N clean$(1)_H_$(2): $(Q)rm -f $$(HBIN$(1)_H_$(2))/rustc$(X_$(2)) - $(Q)rm -f $$(HBIN$(1)_H_$(2))/fuzzer$(X_$(2)) $(Q)rm -f $$(HBIN$(1)_H_$(2))/rustpkg$(X_$(2)) $(Q)rm -f $$(HBIN$(1)_H_$(2))/serializer$(X_$(2)) $(Q)rm -f $$(HBIN$(1)_H_$(2))/rustdoc$(X_$(2)) $(Q)rm -f $$(HBIN$(1)_H_$(2))/rusti$(X_$(2)) $(Q)rm -f $$(HBIN$(1)_H_$(2))/rust$(X_$(2)) - $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_LIBFUZZER_$(2)) $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_LIBRUSTPKG_$(2)) $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_LIBRUSTDOC_$(2)) $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_RUNTIME_$(2)) @@ -83,7 +81,6 @@ clean$(1)_H_$(2): $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(EXTRALIB_GLOB_$(2)) $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(LIBRUSTC_GLOB_$(2)) $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(LIBSYNTAX_GLOB_$(2)) - $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(LIBFUZZER_GLOB_$(2)) $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(LIBRUSTPKG_GLOB_$(2)) $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(LIBRUSTDOC_GLOB_$(2)) $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(LIBRUSTI_GLOB_$(2)) @@ -101,13 +98,11 @@ define CLEAN_TARGET_STAGE_N clean$(1)_T_$(2)_H_$(3): $(Q)rm -f $$(TBIN$(1)_T_$(2)_H_$(3))/rustc$(X_$(2)) - $(Q)rm -f $$(TBIN$(1)_T_$(2)_H_$(3))/fuzzer$(X_$(2)) $(Q)rm -f $$(TBIN$(1)_T_$(2)_H_$(3))/rustpkg$(X_$(2)) $(Q)rm -f $$(TBIN$(1)_T_$(2)_H_$(3))/serializer$(X_$(2)) $(Q)rm -f $$(TBIN$(1)_T_$(2)_H_$(3))/rustdoc$(X_$(2)) $(Q)rm -f $$(TBIN$(1)_T_$(2)_H_$(3))/rusti$(X_$(2)) $(Q)rm -f $$(TBIN$(1)_T_$(2)_H_$(3))/rust$(X_$(2)) - $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBFUZZER_$(2)) $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTPKG_$(2)) $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTDOC_$(2)) $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_RUNTIME_$(2)) @@ -121,7 +116,6 @@ clean$(1)_T_$(2)_H_$(3): $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(EXTRALIB_GLOB_$(2)) $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(LIBRUSTC_GLOB_$(2)) $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(LIBSYNTAX_GLOB_$(2)) - $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(LIBFUZZER_GLOB_$(2)) $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(LIBRUSTPKG_GLOB_$(2)) $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(LIBRUSTDOC_GLOB_$(2)) $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(LIBRUSTI_GLOB_$(2)) diff --git a/mk/dist.mk b/mk/dist.mk index 96f35031de93..912b692a247e 100644 --- a/mk/dist.mk +++ b/mk/dist.mk @@ -32,7 +32,6 @@ PKG_FILES := \ librustc \ compiletest \ etc \ - libfuzzer \ libextra \ libstd \ libsyntax \ diff --git a/mk/pp.mk b/mk/pp.mk index 0a24d9e87979..f86bbb7f2812 100644 --- a/mk/pp.mk +++ b/mk/pp.mk @@ -17,7 +17,6 @@ else $(wildcard $(addprefix $(S)src/rustc/,*.rs */*.rs */*/*.rs)) \ $(wildcard $(S)src/test/*/*.rs \ $(S)src/test/*/*/*.rs) \ - $(wildcard $(S)src/fuzzer/*.rs) \ $(wildcard $(S)src/rustpkg/*.rs) \ $(wildcard $(S)src/rusti/*.rs) \ $(wildcard $(S)src/rust/*.rs) diff --git a/mk/rt.mk b/mk/rt.mk index 1c498aacdddc..da950dffab5b 100644 --- a/mk/rt.mk +++ b/mk/rt.mk @@ -158,10 +158,10 @@ rt/$(1)/stage$(2)/arch/$$(HOST_$(1))/libmorestack.a: $$(MORESTACK_OBJ_$(1)_$(2)) $$(Q)$(AR_$(1)) rcs $$@ $$< rt/$(1)/stage$(2)/$(CFG_RUNTIME_$(1)): $$(RUNTIME_OBJS_$(1)_$(2)) $$(MKFILE_DEPS) \ - $$(RUNTIME_DEF_$(1)_$(2)) $$(LIBUV_LIB_$(1)_$(2)) $$(JEMALLOC_LIB_$(1)_$(2)) + $$(RUNTIME_DEF_$(1)_$(2)) $$(LIBUV_LIB_$(1)_$(2)) @$$(call E, link: $$@) $$(Q)$$(call CFG_LINK_CXX_$(1),$$@, $$(RUNTIME_OBJS_$(1)_$(2)) \ - $$(JEMALLOC_LIB_$(1)_$(2)) $$(CFG_GCCISH_POST_LIB_FLAGS_$(1)) $$(LIBUV_LIB_$(1)_$(2)) \ + $$(CFG_GCCISH_POST_LIB_FLAGS_$(1)) $$(LIBUV_LIB_$(1)_$(2)) \ $$(CFG_LIBUV_LINK_FLAGS_$(1)),$$(RUNTIME_DEF_$(1)_$(2)),$$(CFG_RUNTIME_$(1))) # FIXME: For some reason libuv's makefiles can't figure out the diff --git a/mk/tools.mk b/mk/tools.mk index 018da2a64016..8319d8d4e483 100644 --- a/mk/tools.mk +++ b/mk/tools.mk @@ -11,9 +11,6 @@ # Rules for non-core tools built with the compiler, both for target # and host architectures -FUZZER_LIB := $(S)src/libfuzzer/fuzzer.rc -FUZZER_INPUTS := $(wildcard $(addprefix $(S)src/libfuzzer/, *.rs)) - # The test runner that runs the cfail/rfail/rpass and bxench tests COMPILETEST_CRATE := $(S)src/compiletest/compiletest.rc COMPILETEST_INPUTS := $(wildcard $(S)src/compiletest/*rs) @@ -38,21 +35,6 @@ RUST_INPUTS := $(wildcard $(S)src/librust/*.rs) # have tools that need to built for other targets. define TOOLS_STAGE_N_TARGET -$$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBFUZZER_$(4)): \ - $$(FUZZER_LIB) $$(FUZZER_INPUTS) \ - $$(TSREQ$(1)_T_$(4)_H_$(3)) \ - $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_STDLIB_$(4)) \ - $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_EXTRALIB_$(4)) \ - $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBRUSTC_$(4)) - @$$(call E, compile_and_link: $$@) - $$(STAGE$(1)_T_$(4)_H_$(3)) -o $$@ $$< && touch $$@ - -$$(TBIN$(1)_T_$(4)_H_$(3))/fuzzer$$(X_$(4)): \ - $$(DRIVER_CRATE) \ - $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBFUZZER_$(4)) - @$$(call E, compile_and_link: $$@) - $$(STAGE$(1)_T_$(4)_H_$(3)) --cfg fuzzer -o $$@ $$< - $$(TBIN$(1)_T_$(4)_H_$(3))/compiletest$$(X_$(4)): \ $$(COMPILETEST_CRATE) $$(COMPILETEST_INPUTS) \ $$(TSREQ$(1)_T_$(4)_H_$(3)) \ @@ -128,27 +110,6 @@ endef define TOOLS_STAGE_N_HOST - -# Promote the stageN target to stageN+1 host -# FIXME: Shouldn't need to depend on host/librustc.so once -# rpath is working -$$(HLIB$(2)_H_$(4))/$(CFG_LIBFUZZER_$(4)): \ - $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBFUZZER_$(4)) \ - $$(HLIB$(2)_H_$(4))/$(CFG_LIBRUSTC_$(4)) \ - $$(HSREQ$(2)_H_$(4)) - @$$(call E, cp: $$@) - $$(Q)cp $$< $$@ - $$(Q)cp -R $$(TLIB$(1)_T_$(4)_H_$(3))/$(LIBFUZZER_GLOB_$(4)) \ - $$(wildcard $$(TLIB$(1)_T_$(4)_H_$(3))/$(LIBFUZZER_DSYM_GLOB_$(4))) \ - $$(HLIB$(2)_H_$(4)) - -$$(HBIN$(2)_H_$(4))/fuzzer$$(X_$(4)): \ - $$(TBIN$(1)_T_$(4)_H_$(3))/fuzzer$$(X_$(4)) \ - $$(HLIB$(2)_H_$(4))/$(CFG_LIBFUZZER_$(4)) \ - $$(HSREQ$(2)_H_$(4)) - @$$(call E, cp: $$@) - $$(Q)cp $$< $$@ - $$(HBIN$(2)_H_$(4))/compiletest$$(X_$(4)): \ $$(TBIN$(1)_T_$(4)_H_$(3))/compiletest$$(X_$(4)) \ $$(HSREQ$(2)_H_$(4)) diff --git a/src/README.txt b/src/README.txt index 1b06c4259fc6..f229068731f4 100644 --- a/src/README.txt +++ b/src/README.txt @@ -4,8 +4,8 @@ Source layout: librustc/ The self-hosted compiler -libcore/ The core library (imported and linked by default) -libstd/ The standard library (slightly more peripheral code) +libstd/ The standard library (imported and linked by default) +libextra/ The "extras" library (slightly more peripheral code) libsyntax/ The Rust parser and pretty-printer rt/ The runtime system diff --git a/src/compiletest/procsrv.rs b/src/compiletest/procsrv.rs index b5404e38ec96..93fe258d167e 100644 --- a/src/compiletest/procsrv.rs +++ b/src/compiletest/procsrv.rs @@ -23,7 +23,7 @@ fn target_env(lib_path: &str, prog: &str) -> ~[(~str,~str)] { assert!(prog.ends_with(".exe")); let aux_path = prog.slice(0u, prog.len() - 4u).to_owned() + ".libaux"; - env = do vec::map(env) |pair| { + env = do env.map() |pair| { let (k,v) = copy *pair; if k == ~"PATH" { (~"PATH", v + ";" + lib_path + ";" + aux_path) } else { (k,v) } diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs index 891935dcadd0..e0ceb79a37df 100644 --- a/src/compiletest/runtest.rs +++ b/src/compiletest/runtest.rs @@ -24,7 +24,6 @@ use util::logv; use core::io; use core::os; -use core::str; use core::uint; use core::vec; diff --git a/src/driver/driver.rs b/src/driver/driver.rs index 97e01d1bcdc0..ccedd3adbaa9 100644 --- a/src/driver/driver.rs +++ b/src/driver/driver.rs @@ -16,9 +16,6 @@ extern mod core(name = "std", vers = "0.7-pre"); #[cfg(rustpkg)] extern mod this(name = "rustpkg"); -#[cfg(fuzzer)] -extern mod this(name = "fuzzer"); - #[cfg(rustdoc)] extern mod this(name = "rustdoc"); diff --git a/src/etc/snapshot.py b/src/etc/snapshot.py index 123987d4b1ea..608dbdcca5d2 100644 --- a/src/etc/snapshot.py +++ b/src/etc/snapshot.py @@ -26,29 +26,29 @@ download_unpack_base = os.path.join(download_dir_base, "unpack") snapshot_files = { "linux": ["bin/rustc", - "lib/libcore-*.so", "lib/libstd-*.so", + "lib/libextra-*.so", "lib/librustc-*.so", "lib/libsyntax-*.so", "lib/librustrt.so", "lib/librustllvm.so"], "macos": ["bin/rustc", - "lib/libcore-*.dylib", "lib/libstd-*.dylib", + "lib/libextra-*.dylib", "lib/librustc-*.dylib", "lib/libsyntax-*.dylib", "lib/librustrt.dylib", "lib/librustllvm.dylib"], "winnt": ["bin/rustc.exe", - "bin/core-*.dll", "bin/std-*.dll", + "bin/extra-*.dll", "bin/rustc-*.dll", "bin/syntax-*.dll", "bin/rustrt.dll", "bin/rustllvm.dll"], "freebsd": ["bin/rustc", - "lib/libcore-*.so", "lib/libstd-*.so", + "lib/libextra-*.so", "lib/librustc-*.so", "lib/libsyntax-*.so", "lib/librustrt.so", diff --git a/src/libextra/arc.rs b/src/libextra/arc.rs index b1bec1f95dbd..661224b0a803 100644 --- a/src/libextra/arc.rs +++ b/src/libextra/arc.rs @@ -58,7 +58,7 @@ pub struct Condvar<'self> { impl<'self> Condvar<'self> { /// Atomically exit the associated ARC and block until a signal is sent. - #[inline(always)] + #[inline] pub fn wait(&self) { self.wait_on(0) } /** @@ -67,7 +67,7 @@ impl<'self> Condvar<'self> { * * wait() is equivalent to wait_on(0). */ - #[inline(always)] + #[inline] pub fn wait_on(&self, condvar_id: uint) { assert!(!*self.failed); self.cond.wait_on(condvar_id); @@ -76,28 +76,28 @@ impl<'self> Condvar<'self> { } /// Wake up a blocked task. Returns false if there was no blocked task. - #[inline(always)] + #[inline] pub fn signal(&self) -> bool { self.signal_on(0) } /** * Wake up a blocked task on a specified condvar (as * sync::cond.signal_on). Returns false if there was no blocked task. */ - #[inline(always)] + #[inline] pub fn signal_on(&self, condvar_id: uint) -> bool { assert!(!*self.failed); self.cond.signal_on(condvar_id) } /// Wake up all blocked tasks. Returns the number of tasks woken. - #[inline(always)] + #[inline] pub fn broadcast(&self) -> uint { self.broadcast_on(0) } /** * Wake up all blocked tasks on a specified condvar (as * sync::cond.broadcast_on). Returns the number of tasks woken. */ - #[inline(always)] + #[inline] pub fn broadcast_on(&self, condvar_id: uint) -> uint { assert!(!*self.failed); self.cond.broadcast_on(condvar_id) @@ -198,22 +198,20 @@ impl MutexARC { * any tasks that subsequently try to access it (including those already * blocked on the mutex) will also fail immediately. */ - #[inline(always)] + #[inline] pub unsafe fn access(&self, blk: &fn(x: &mut T) -> U) -> U { - unsafe { - let state = self.x.get(); - // Borrowck would complain about this if the function were - // not already unsafe. See borrow_rwlock, far below. - do (&(*state).lock).lock { - check_poison(true, (*state).failed); - let _z = PoisonOnFail(&mut (*state).failed); - blk(&mut (*state).data) - } + let state = self.x.get(); + // Borrowck would complain about this if the function were + // not already unsafe. See borrow_rwlock, far below. + do (&(*state).lock).lock { + check_poison(true, (*state).failed); + let _z = PoisonOnFail(&mut (*state).failed); + blk(&mut (*state).data) } } /// As access(), but with a condvar, as sync::mutex.lock_cond(). - #[inline(always)] + #[inline] pub unsafe fn access_cond<'x, 'c, U>(&self, blk: &fn(x: &'x mut T, c: &'c Condvar) -> U) @@ -231,7 +229,7 @@ impl MutexARC { } // Common code for {mutex.access,rwlock.write}{,_cond}. -#[inline(always)] +#[inline] #[doc(hidden)] fn check_poison(is_mutex: bool, failed: bool) { if failed { @@ -322,7 +320,7 @@ impl RWARC { * that other tasks won't block forever. As MutexARC.access, it will also * poison the ARC, so subsequent readers and writers will both also fail. */ - #[inline(always)] + #[inline] pub fn write(&self, blk: &fn(x: &mut T) -> U) -> U { unsafe { let state = self.x.get(); @@ -335,7 +333,7 @@ impl RWARC { } /// As write(), but with a condvar, as sync::rwlock.write_cond(). - #[inline(always)] + #[inline] pub fn write_cond<'x, 'c, U>(&self, blk: &fn(x: &'x mut T, c: &'c Condvar) -> U) -> U { diff --git a/src/libextra/arena.rs b/src/libextra/arena.rs index 2926d5958f16..db4cf564babc 100644 --- a/src/libextra/arena.rs +++ b/src/libextra/arena.rs @@ -119,7 +119,7 @@ pub fn Arena() -> Arena { arena_with_size(32u) } -#[inline(always)] +#[inline] fn round_up_to(base: uint, align: uint) -> uint { (base + (align - 1)) & !(align - 1) } @@ -156,12 +156,12 @@ unsafe fn destroy_chunk(chunk: &Chunk) { // initialized in the arena in the low bit of the tydesc pointer. This // is necessary in order to properly do cleanup if a failure occurs // during an initializer. -#[inline(always)] +#[inline] unsafe fn bitpack_tydesc_ptr(p: *TypeDesc, is_done: bool) -> uint { let p_bits: uint = transmute(p); p_bits | (is_done as uint) } -#[inline(always)] +#[inline] unsafe fn un_bitpack_tydesc_ptr(p: uint) -> (*TypeDesc, bool) { (transmute(p & !1), p & 1 == 1) } @@ -179,7 +179,7 @@ impl Arena { return self.alloc_pod_inner(n_bytes, align); } - #[inline(always)] + #[inline] fn alloc_pod_inner(&mut self, n_bytes: uint, align: uint) -> *u8 { unsafe { // XXX: Borrow check @@ -199,7 +199,7 @@ impl Arena { } } - #[inline(always)] + #[inline] fn alloc_pod<'a, T>(&'a mut self, op: &fn() -> T) -> &'a T { unsafe { let tydesc = sys::get_type_desc::(); @@ -223,7 +223,7 @@ impl Arena { return self.alloc_nonpod_inner(n_bytes, align); } - #[inline(always)] + #[inline] fn alloc_nonpod_inner(&mut self, n_bytes: uint, align: uint) -> (*u8, *u8) { unsafe { @@ -246,7 +246,7 @@ impl Arena { } } - #[inline(always)] + #[inline] fn alloc_nonpod<'a, T>(&'a mut self, op: &fn() -> T) -> &'a T { unsafe { let tydesc = sys::get_type_desc::(); @@ -268,7 +268,7 @@ impl Arena { } // The external interface - #[inline(always)] + #[inline] pub fn alloc<'a, T>(&'a mut self, op: &fn() -> T) -> &'a T { unsafe { // XXX: Borrow check diff --git a/src/libextra/base64.rs b/src/libextra/base64.rs index f4754b3e4cbe..5bf4dd517a5b 100644 --- a/src/libextra/base64.rs +++ b/src/libextra/base64.rs @@ -229,8 +229,6 @@ impl<'self> FromBase64 for &'self str { #[cfg(test)] mod tests { - use core::str; - #[test] fn test_to_base64() { assert_eq!("".to_base64(), ~""); diff --git a/src/libextra/bitv.rs b/src/libextra/bitv.rs index e3a15f76c786..647fa81c7185 100644 --- a/src/libextra/bitv.rs +++ b/src/libextra/bitv.rs @@ -23,7 +23,7 @@ struct SmallBitv { } /// a mask that has a 1 for each defined bit in a small_bitv, assuming n bits -#[inline(always)] +#[inline] fn small_mask(nbits: uint) -> uint { (1 << nbits) - 1 } @@ -33,7 +33,7 @@ impl SmallBitv { SmallBitv {bits: bits} } - #[inline(always)] + #[inline] pub fn bits_op(&mut self, right_bits: uint, nbits: uint, @@ -46,32 +46,32 @@ impl SmallBitv { mask & old_b != mask & new_b } - #[inline(always)] + #[inline] pub fn union(&mut self, s: &SmallBitv, nbits: uint) -> bool { self.bits_op(s.bits, nbits, |u1, u2| u1 | u2) } - #[inline(always)] + #[inline] pub fn intersect(&mut self, s: &SmallBitv, nbits: uint) -> bool { self.bits_op(s.bits, nbits, |u1, u2| u1 & u2) } - #[inline(always)] + #[inline] pub fn become(&mut self, s: &SmallBitv, nbits: uint) -> bool { self.bits_op(s.bits, nbits, |_u1, u2| u2) } - #[inline(always)] + #[inline] pub fn difference(&mut self, s: &SmallBitv, nbits: uint) -> bool { self.bits_op(s.bits, nbits, |u1, u2| u1 & !u2) } - #[inline(always)] + #[inline] pub fn get(&self, i: uint) -> bool { (self.bits & (1 << i)) != 0 } - #[inline(always)] + #[inline] pub fn set(&mut self, i: uint, x: bool) { if x { self.bits |= 1< bool { let mask = small_mask(nbits); mask & self.bits == mask & b.bits } - #[inline(always)] + #[inline] pub fn clear(&mut self) { self.bits = 0; } - #[inline(always)] + #[inline] pub fn set_all(&mut self) { self.bits = !0; } - #[inline(always)] + #[inline] pub fn is_true(&self, nbits: uint) -> bool { small_mask(nbits) & !self.bits == 0 } - #[inline(always)] + #[inline] pub fn is_false(&self, nbits: uint) -> bool { small_mask(nbits) & self.bits == 0 } - #[inline(always)] + #[inline] pub fn invert(&mut self) { self.bits = !self.bits; } } @@ -115,7 +115,7 @@ struct BigBitv { * a mask that has a 1 for each defined bit in the nth element of a big_bitv, * assuming n bits. */ -#[inline(always)] +#[inline] fn big_mask(nbits: uint, elem: uint) -> uint { let rmd = nbits % uint::bits; let nelems = nbits/uint::bits + if rmd == 0 {0} else {1}; @@ -132,7 +132,7 @@ impl BigBitv { BigBitv {storage: storage} } - #[inline(always)] + #[inline] pub fn process(&mut self, b: &BigBitv, nbits: uint, @@ -154,35 +154,35 @@ impl BigBitv { changed } - #[inline(always)] + #[inline] pub fn each_storage(&mut self, op: &fn(v: &mut uint) -> bool) -> bool { uint::range(0, self.storage.len(), |i| op(&mut self.storage[i])) } - #[inline(always)] + #[inline] pub fn invert(&mut self) { for self.each_storage |w| { *w = !*w } } - #[inline(always)] + #[inline] pub fn union(&mut self, b: &BigBitv, nbits: uint) -> bool { self.process(b, nbits, |w1, w2| w1 | w2) } - #[inline(always)] + #[inline] pub fn intersect(&mut self, b: &BigBitv, nbits: uint) -> bool { self.process(b, nbits, |w1, w2| w1 & w2) } - #[inline(always)] + #[inline] pub fn become(&mut self, b: &BigBitv, nbits: uint) -> bool { self.process(b, nbits, |_, w| w) } - #[inline(always)] + #[inline] pub fn difference(&mut self, b: &BigBitv, nbits: uint) -> bool { self.process(b, nbits, |w1, w2| w1 & !w2) } - #[inline(always)] + #[inline] pub fn get(&self, i: uint) -> bool { let w = i / uint::bits; let b = i % uint::bits; @@ -190,7 +190,7 @@ impl BigBitv { x == 1 } - #[inline(always)] + #[inline] pub fn set(&mut self, i: uint, x: bool) { let w = i / uint::bits; let b = i % uint::bits; @@ -199,7 +199,7 @@ impl BigBitv { else { self.storage[w] & !flag }; } - #[inline(always)] + #[inline] pub fn equals(&self, b: &BigBitv, nbits: uint) -> bool { let len = b.storage.len(); for uint::iterate(0, len) |i| { @@ -229,7 +229,7 @@ fn die() -> ! { } impl Bitv { - #[inline(always)] + #[inline] fn do_op(&mut self, op: Op, other: &Bitv) -> bool { if self.nbits != other.nbits { die(); @@ -279,7 +279,7 @@ impl Bitv { * Sets `self` to the union of `self` and `v1`. Both bitvectors must be * the same length. Returns 'true' if `self` changed. */ - #[inline(always)] + #[inline] pub fn union(&mut self, v1: &Bitv) -> bool { self.do_op(Union, v1) } /** @@ -288,7 +288,7 @@ impl Bitv { * Sets `self` to the intersection of `self` and `v1`. Both bitvectors * must be the same length. Returns 'true' if `self` changed. */ - #[inline(always)] + #[inline] pub fn intersect(&mut self, v1: &Bitv) -> bool { self.do_op(Intersect, v1) } @@ -299,11 +299,11 @@ impl Bitv { * Both bitvectors must be the same length. Returns `true` if `self` was * changed */ - #[inline(always)] + #[inline] pub fn assign(&mut self, v: &Bitv) -> bool { self.do_op(Assign, v) } /// Retrieve the value at index `i` - #[inline(always)] + #[inline] pub fn get(&self, i: uint) -> bool { assert!((i < self.nbits)); match self.rep { @@ -317,7 +317,7 @@ impl Bitv { * * `i` must be less than the length of the bitvector. */ - #[inline(always)] + #[inline] pub fn set(&mut self, i: uint, x: bool) { assert!((i < self.nbits)); match self.rep { @@ -332,7 +332,7 @@ impl Bitv { * Both bitvectors must be the same length. Returns `true` if both * bitvectors contain identical elements. */ - #[inline(always)] + #[inline] pub fn equal(&self, v1: &Bitv) -> bool { if self.nbits != v1.nbits { return false; } match self.rep { @@ -348,7 +348,7 @@ impl Bitv { } /// Set all bits to 0 - #[inline(always)] + #[inline] pub fn clear(&mut self) { match self.rep { Small(ref mut b) => b.clear(), @@ -357,7 +357,7 @@ impl Bitv { } /// Set all bits to 1 - #[inline(always)] + #[inline] pub fn set_all(&mut self) { match self.rep { Small(ref mut b) => b.set_all(), @@ -365,7 +365,7 @@ impl Bitv { } /// Invert all bits - #[inline(always)] + #[inline] pub fn invert(&mut self) { match self.rep { Small(ref mut b) => b.invert(), @@ -381,13 +381,13 @@ impl Bitv { * * Returns `true` if `v0` was changed. */ - #[inline(always)] + #[inline] pub fn difference(&mut self, v: &Bitv) -> bool { self.do_op(Difference, v) } /// Returns true if all bits are 1 - #[inline(always)] + #[inline] pub fn is_true(&self) -> bool { match self.rep { Small(ref b) => b.is_true(self.nbits), @@ -398,7 +398,7 @@ impl Bitv { } } - #[inline(always)] + #[inline] pub fn each(&self, f: &fn(bool) -> bool) -> bool { let mut i = 0; while i < self.nbits { @@ -508,7 +508,7 @@ impl Bitv { impl Clone for Bitv { /// Makes a copy of a bitvector - #[inline(always)] + #[inline] fn clone(&self) -> Bitv { match self.rep { Small(ref b) => { @@ -562,7 +562,7 @@ impl ops::Index for Bitv { } } -#[inline(always)] +#[inline] fn iterate_bits(base: uint, bits: uint, f: &fn(uint) -> bool) -> bool { if bits == 0 { return true; @@ -623,7 +623,7 @@ impl BitvSet { return Bitv{ nbits:cap, rep: Big(~bitv) }; } - #[inline(always)] + #[inline] fn other_op(&mut self, other: &BitvSet, f: &fn(uint, uint) -> uint) { fn nbits(mut w: uint) -> uint { let mut bits = 0; diff --git a/src/libextra/c_vec.rs b/src/libextra/c_vec.rs index 7cc7b659ed9d..fd48e7d5958d 100644 --- a/src/libextra/c_vec.rs +++ b/src/libextra/c_vec.rs @@ -122,7 +122,7 @@ pub unsafe fn c_vec_with_dtor(base: *mut T, len: uint, dtor: @fn()) */ pub fn get(t: CVec, ofs: uint) -> T { assert!(ofs < len(t)); - return unsafe { *ptr::mut_offset(t.base, ofs) }; + return unsafe { copy *ptr::mut_offset(t.base, ofs) }; } /** diff --git a/src/libextra/deque.rs b/src/libextra/deque.rs index 89e23a3a77ff..c8bb984736a1 100644 --- a/src/libextra/deque.rs +++ b/src/libextra/deque.rs @@ -264,31 +264,31 @@ mod tests { fn test_parameterized(a: T, b: T, c: T, d: T) { let mut deq = Deque::new(); assert_eq!(deq.len(), 0); - deq.add_front(a); - deq.add_front(b); - deq.add_back(c); + deq.add_front(copy a); + deq.add_front(copy b); + deq.add_back(copy c); assert_eq!(deq.len(), 3); - deq.add_back(d); + deq.add_back(copy d); assert_eq!(deq.len(), 4); - assert_eq!(*deq.peek_front(), b); - assert_eq!(*deq.peek_back(), d); - assert_eq!(deq.pop_front(), b); - assert_eq!(deq.pop_back(), d); - assert_eq!(deq.pop_back(), c); - assert_eq!(deq.pop_back(), a); + assert_eq!(copy *deq.peek_front(), copy b); + assert_eq!(copy *deq.peek_back(), copy d); + assert_eq!(deq.pop_front(), copy b); + assert_eq!(deq.pop_back(), copy d); + assert_eq!(deq.pop_back(), copy c); + assert_eq!(deq.pop_back(), copy a); assert_eq!(deq.len(), 0); - deq.add_back(c); + deq.add_back(copy c); assert_eq!(deq.len(), 1); - deq.add_front(b); + deq.add_front(copy b); assert_eq!(deq.len(), 2); - deq.add_back(d); + deq.add_back(copy d); assert_eq!(deq.len(), 3); - deq.add_front(a); + deq.add_front(copy a); assert_eq!(deq.len(), 4); - assert_eq!(*deq.get(0), a); - assert_eq!(*deq.get(1), b); - assert_eq!(*deq.get(2), c); - assert_eq!(*deq.get(3), d); + assert_eq!(copy *deq.get(0), copy a); + assert_eq!(copy *deq.get(1), copy b); + assert_eq!(copy *deq.get(2), copy c); + assert_eq!(copy *deq.get(3), copy d); } #[deriving(Eq)] diff --git a/src/libextra/dlist.rs b/src/libextra/dlist.rs index c3e2beb122f0..953803c6843f 100644 --- a/src/libextra/dlist.rs +++ b/src/libextra/dlist.rs @@ -111,7 +111,8 @@ pub fn from_elem(data: T) -> @mut DList { /// Creates a new dlist from a vector of elements, maintaining the same order pub fn from_vec(vec: &[T]) -> @mut DList { do vec.iter().fold(DList()) |list,data| { - list.push(*data); // Iterating left-to-right -- add newly to the tail. + // Iterating left-to-right -- add newly to the tail. + list.push(copy *data); list } } @@ -159,7 +160,7 @@ impl DList { } // Link two nodes together. If either of them are 'none', also sets // the head and/or tail pointers appropriately. - #[inline(always)] + #[inline] fn link(&mut self, before: DListLink, after: DListLink) { match before { Some(neighbour) => neighbour.next = after, @@ -460,35 +461,35 @@ impl DList { impl DList { /// Remove data from the head of the list. O(1). pub fn pop(@mut self) -> Option { - self.pop_n().map(|nobe| nobe.data) + self.pop_n().map(|nobe| copy nobe.data) } /// Remove data from the tail of the list. O(1). pub fn pop_tail(@mut self) -> Option { - self.pop_tail_n().map(|nobe| nobe.data) + self.pop_tail_n().map(|nobe| copy nobe.data) } /// Get data at the list's head. O(1). pub fn peek(@mut self) -> Option { - self.peek_n().map(|nobe| nobe.data) + self.peek_n().map(|nobe| copy nobe.data) } /// Get data at the list's tail. O(1). pub fn peek_tail(@mut self) -> Option { - self.peek_tail_n().map (|nobe| nobe.data) + self.peek_tail_n().map (|nobe| copy nobe.data) } /// Get data at the list's head, failing if empty. O(1). - pub fn head(@mut self) -> T { self.head_n().data } + pub fn head(@mut self) -> T { copy self.head_n().data } /// Get data at the list's tail, failing if empty. O(1). - pub fn tail(@mut self) -> T { self.tail_n().data } + pub fn tail(@mut self) -> T { copy self.tail_n().data } /// Get the elements of the list as a vector. O(n). pub fn to_vec(@mut self) -> ~[T] { let mut v = vec::with_capacity(self.size); for old_iter::eachi(&self) |index,data| { - v[index] = *data; + v[index] = copy *data; } v } @@ -531,7 +532,7 @@ impl BaseIter for @mut DList { return true; } - #[inline(always)] + #[inline] fn size_hint(&self) -> Option { Some(self.len()) } } diff --git a/src/libextra/flatpipes.rs b/src/libextra/flatpipes.rs index c0f619c1b858..9a8ee3959364 100644 --- a/src/libextra/flatpipes.rs +++ b/src/libextra/flatpipes.rs @@ -516,7 +516,6 @@ pub mod bytepipes { use core::comm::{Port, Chan}; use core::comm; use core::io::{Writer, Reader, ReaderUtil}; - use core::vec; pub struct ReaderBytePort { reader: R @@ -583,12 +582,12 @@ pub mod bytepipes { impl BytePort for PipeBytePort { fn try_recv(&self, count: uint) -> Option<~[u8]> { - if vec::uniq_len(&const *self.buf) >= count { + if self.buf.len() >= count { let mut bytes = ::core::util::replace(&mut *self.buf, ~[]); *self.buf = bytes.slice(count, bytes.len()).to_owned(); bytes.truncate(count); return Some(bytes); - } else if vec::uniq_len(&const *self.buf) > 0 { + } else if !self.buf.is_empty() { let mut bytes = ::core::util::replace(&mut *self.buf, ~[]); assert!(count > bytes.len()); match self.try_recv(count - bytes.len()) { @@ -598,7 +597,7 @@ pub mod bytepipes { } None => return None } - } else if vec::uniq_len(&const *self.buf) == 0 { + } else /* empty */ { match self.port.try_recv() { Some(buf) => { assert!(!buf.is_empty()); @@ -607,8 +606,6 @@ pub mod bytepipes { } None => return None } - } else { - ::core::util::unreachable() } } } diff --git a/src/libextra/future.rs b/src/libextra/future.rs index 40cfeebd5dcd..4652e1d64770 100644 --- a/src/libextra/future.rs +++ b/src/libextra/future.rs @@ -57,7 +57,7 @@ priv enum FutureState { impl Future { pub fn get(&mut self) -> A { //! Get the value of the future. - *(self.get_ref()) + copy *(self.get_ref()) } } diff --git a/src/libextra/list.rs b/src/libextra/list.rs index 68d9bb4e1ae3..34c35e0d7fde 100644 --- a/src/libextra/list.rs +++ b/src/libextra/list.rs @@ -27,7 +27,7 @@ pub enum MutList { /// Create a list from a vector pub fn from_vec(v: &[T]) -> @List { - v.rev_iter().fold(@Nil::, |t, h| @Cons(*h, t)) + v.rev_iter().fold(@Nil::, |t, h| @Cons(copy *h, t)) } /** @@ -61,7 +61,7 @@ pub fn find(ls: @List, f: &fn(&T) -> bool) -> Option { loop { ls = match *ls { Cons(ref hd, tl) => { - if f(hd) { return Some(*hd); } + if f(hd) { return Some(copy *hd); } tl } Nil => return None diff --git a/src/libextra/net_tcp.rs b/src/libextra/net_tcp.rs index d95807f2b91c..51d744955b81 100644 --- a/src/libextra/net_tcp.rs +++ b/src/libextra/net_tcp.rs @@ -181,90 +181,88 @@ pub fn connect(input_ip: ip::IpAddr, port: uint, debug!("stream_handle_ptr outside interact %?", stream_handle_ptr); do iotask::interact(iotask) |loop_ptr| { - unsafe { - debug!("in interact cb for tcp client connect.."); - debug!("stream_handle_ptr in interact %?", - stream_handle_ptr); - match uv::ll::tcp_init( loop_ptr, stream_handle_ptr) { - 0i32 => { - debug!("tcp_init successful"); - debug!("dealing w/ ipv4 connection.."); - let connect_req_ptr: *uv::ll::uv_connect_t = - &(*socket_data_ptr).connect_req; - let addr_str = ip::format_addr(&input_ip); - let connect_result = match input_ip { - ip::Ipv4(ref addr) => { - // have to "recreate" the - // sockaddr_in/6 since the ip_addr - // discards the port info.. should - // probably add an additional rust - // type that actually is closer to - // what the libuv API expects (ip str - // + port num) - debug!("addr: %?", addr); - let in_addr = uv::ll::ip4_addr(addr_str, - port as int); - uv::ll::tcp_connect( - connect_req_ptr, - stream_handle_ptr, - &in_addr, - tcp_connect_on_connect_cb) - } - ip::Ipv6(ref addr) => { - debug!("addr: %?", addr); - let in_addr = uv::ll::ip6_addr(addr_str, - port as int); - uv::ll::tcp_connect6( - connect_req_ptr, - stream_handle_ptr, - &in_addr, - tcp_connect_on_connect_cb) - } - }; - match connect_result { - 0i32 => { - debug!("tcp_connect successful: \ - stream %x, - socket data %x", - stream_handle_ptr as uint, - socket_data_ptr as uint); - // reusable data that we'll have for the - // duration.. - uv::ll::set_data_for_uv_handle( - stream_handle_ptr, - socket_data_ptr as - *libc::c_void); - // just so the connect_cb can send the - // outcome.. - uv::ll::set_data_for_req(connect_req_ptr, - conn_data_ptr); - debug!("leaving tcp_connect interact cb..."); - // let tcp_connect_on_connect_cb send on - // the result_ch, now.. - } - _ => { - // immediate connect - // failure.. probably a garbage ip or - // somesuch - let err_data = - uv::ll::get_last_err_data(loop_ptr); - let result_ch = (*conn_data_ptr) - .result_ch.clone(); - result_ch.send(ConnFailure(err_data)); - uv::ll::set_data_for_uv_handle( - stream_handle_ptr, - conn_data_ptr); - uv::ll::close(stream_handle_ptr, - stream_error_close_cb); - } + debug!("in interact cb for tcp client connect.."); + debug!("stream_handle_ptr in interact %?", + stream_handle_ptr); + match uv::ll::tcp_init( loop_ptr, stream_handle_ptr) { + 0i32 => { + debug!("tcp_init successful"); + debug!("dealing w/ ipv4 connection.."); + let connect_req_ptr: *uv::ll::uv_connect_t = + &(*socket_data_ptr).connect_req; + let addr_str = ip::format_addr(&input_ip); + let connect_result = match input_ip { + ip::Ipv4(ref addr) => { + // have to "recreate" the + // sockaddr_in/6 since the ip_addr + // discards the port info.. should + // probably add an additional rust + // type that actually is closer to + // what the libuv API expects (ip str + // + port num) + debug!("addr: %?", addr); + let in_addr = uv::ll::ip4_addr(addr_str, + port as int); + uv::ll::tcp_connect( + connect_req_ptr, + stream_handle_ptr, + &in_addr, + tcp_connect_on_connect_cb) + } + ip::Ipv6(ref addr) => { + debug!("addr: %?", addr); + let in_addr = uv::ll::ip6_addr(addr_str, + port as int); + uv::ll::tcp_connect6( + connect_req_ptr, + stream_handle_ptr, + &in_addr, + tcp_connect_on_connect_cb) + } + }; + match connect_result { + 0i32 => { + debug!("tcp_connect successful: \ + stream %x, + socket data %x", + stream_handle_ptr as uint, + socket_data_ptr as uint); + // reusable data that we'll have for the + // duration.. + uv::ll::set_data_for_uv_handle( + stream_handle_ptr, + socket_data_ptr as + *libc::c_void); + // just so the connect_cb can send the + // outcome.. + uv::ll::set_data_for_req(connect_req_ptr, + conn_data_ptr); + debug!("leaving tcp_connect interact cb..."); + // let tcp_connect_on_connect_cb send on + // the result_ch, now.. + } + _ => { + // immediate connect + // failure.. probably a garbage ip or + // somesuch + let err_data = + uv::ll::get_last_err_data(loop_ptr); + let result_ch = (*conn_data_ptr) + .result_ch.clone(); + result_ch.send(ConnFailure(err_data)); + uv::ll::set_data_for_uv_handle( + stream_handle_ptr, + conn_data_ptr); + uv::ll::close(stream_handle_ptr, + stream_error_close_cb); } } - _ => { - // failure to create a tcp handle - let err_data = uv::ll::get_last_err_data(loop_ptr); - let result_ch = (*conn_data_ptr).result_ch.clone(); - result_ch.send(ConnFailure(err_data)); - } + } + _ => { + // failure to create a tcp handle + let err_data = uv::ll::get_last_err_data(loop_ptr); + let result_ch = (*conn_data_ptr).result_ch.clone(); + result_ch.send(ConnFailure(err_data)); } } } @@ -879,8 +877,7 @@ impl io::Reader for TcpSocketBuf { // If possible, copy up to `len` bytes from the internal // `data.buf` into `buf` - let nbuffered = vec::uniq_len(&const self.data.buf) - - self.data.buf_off; + let nbuffered = self.data.buf.len() - self.data.buf_off; let needed = len - count; if nbuffered > 0 { unsafe { @@ -934,7 +931,7 @@ impl io::Reader for TcpSocketBuf { } fn read_byte(&self) -> int { loop { - if vec::uniq_len(&const self.data.buf) > self.data.buf_off { + if self.data.buf.len() > self.data.buf_off { let c = self.data.buf[self.data.buf_off]; self.data.buf_off += 1; return c as int @@ -1016,14 +1013,12 @@ fn tear_down_socket_data(socket_data: @TcpSocketData) { let close_data_ptr: *TcpSocketCloseData = &close_data; let stream_handle_ptr = (*socket_data).stream_handle_ptr; do iotask::interact(&(*socket_data).iotask) |loop_ptr| { - unsafe { - debug!( - "interact dtor for tcp_socket stream %? loop %?", - stream_handle_ptr, loop_ptr); - uv::ll::set_data_for_uv_handle(stream_handle_ptr, - close_data_ptr); - uv::ll::close(stream_handle_ptr, tcp_socket_dtor_close_cb); - } + debug!( + "interact dtor for tcp_socket stream %? loop %?", + stream_handle_ptr, loop_ptr); + uv::ll::set_data_for_uv_handle(stream_handle_ptr, + close_data_ptr); + uv::ll::close(stream_handle_ptr, tcp_socket_dtor_close_cb); }; closed_po.recv(); //the line below will most likely crash @@ -1083,19 +1078,17 @@ fn read_stop_common_impl(socket_data: *TcpSocketData) -> let stream_handle_ptr = (*socket_data).stream_handle_ptr; let (stop_po, stop_ch) = stream::>(); do iotask::interact(&(*socket_data).iotask) |loop_ptr| { - unsafe { - debug!("in interact cb for tcp::read_stop"); - match uv::ll::read_stop(stream_handle_ptr - as *uv::ll::uv_stream_t) { - 0i32 => { - debug!("successfully called uv_read_stop"); - stop_ch.send(None); - } - _ => { - debug!("failure in calling uv_read_stop"); - let err_data = uv::ll::get_last_err_data(loop_ptr); - stop_ch.send(Some(err_data.to_tcp_err())); - } + debug!("in interact cb for tcp::read_stop"); + match uv::ll::read_stop(stream_handle_ptr + as *uv::ll::uv_stream_t) { + 0i32 => { + debug!("successfully called uv_read_stop"); + stop_ch.send(None); + } + _ => { + debug!("failure in calling uv_read_stop"); + let err_data = uv::ll::get_last_err_data(loop_ptr); + stop_ch.send(Some(err_data.to_tcp_err())); } } } @@ -1115,22 +1108,20 @@ fn read_start_common_impl(socket_data: *TcpSocketData) let (start_po, start_ch) = stream::>(); debug!("in tcp::read_start before interact loop"); do iotask::interact(&(*socket_data).iotask) |loop_ptr| { - unsafe { - debug!("in tcp::read_start interact cb %?", - loop_ptr); - match uv::ll::read_start(stream_handle_ptr - as *uv::ll::uv_stream_t, - on_alloc_cb, - on_tcp_read_cb) { - 0i32 => { - debug!("success doing uv_read_start"); - start_ch.send(None); - } - _ => { - debug!("error attempting uv_read_start"); - let err_data = uv::ll::get_last_err_data(loop_ptr); - start_ch.send(Some(err_data)); - } + debug!("in tcp::read_start interact cb %?", + loop_ptr); + match uv::ll::read_start(stream_handle_ptr + as *uv::ll::uv_stream_t, + on_alloc_cb, + on_tcp_read_cb) { + 0i32 => { + debug!("success doing uv_read_start"); + start_ch.send(None); + } + _ => { + debug!("error attempting uv_read_start"); + let err_data = uv::ll::get_last_err_data(loop_ptr); + start_ch.send(Some(err_data)); } } } @@ -1167,24 +1158,22 @@ fn write_common_impl(socket_data_ptr: *TcpSocketData, }; let write_data_ptr: *WriteReqData = &write_data; do iotask::interact(&(*socket_data_ptr).iotask) |loop_ptr| { - unsafe { - debug!("in interact cb for tcp::write %?", - loop_ptr); - match uv::ll::write(write_req_ptr, - stream_handle_ptr, - write_buf_vec_ptr, - tcp_write_complete_cb) { - 0i32 => { - debug!("uv_write() invoked successfully"); - uv::ll::set_data_for_req(write_req_ptr, - write_data_ptr); - } - _ => { - debug!("error invoking uv_write()"); - let err_data = uv::ll::get_last_err_data(loop_ptr); - let result_ch = (*write_data_ptr).result_ch.clone(); - result_ch.send(TcpWriteError(err_data.to_tcp_err())); - } + debug!("in interact cb for tcp::write %?", + loop_ptr); + match uv::ll::write(write_req_ptr, + stream_handle_ptr, + write_buf_vec_ptr, + tcp_write_complete_cb) { + 0i32 => { + debug!("uv_write() invoked successfully"); + uv::ll::set_data_for_req(write_req_ptr, + write_data_ptr); + } + _ => { + debug!("error invoking uv_write()"); + let err_data = uv::ll::get_last_err_data(loop_ptr); + let result_ch = (*write_data_ptr).result_ch.clone(); + result_ch.send(TcpWriteError(err_data.to_tcp_err())); } } } diff --git a/src/libextra/num/complex.rs b/src/libextra/num/complex.rs index 1bb364f3a1c3..c626260043ee 100644 --- a/src/libextra/num/complex.rs +++ b/src/libextra/num/complex.rs @@ -80,19 +80,17 @@ impl Cmplx { } } -#[cfg(not(stage0))] // Fixed by #4228 impl Cmplx { /// Calculate |self| - #[inline(always)] + #[inline] pub fn norm(&self) -> T { self.re.hypot(&self.im) } } -#[cfg(not(stage0))] // Fixed by #4228 impl Cmplx { /// Calculate the principal Arg of self. - #[inline(always)] + #[inline] pub fn arg(&self) -> T { self.im.atan2(&self.re) } @@ -222,6 +220,8 @@ mod test { } #[test] + #[ignore(cfg(target_arch = "x86"))] + // FIXME #7158: (maybe?) currently failing on x86. fn test_norm() { fn test(c: Complex, ns: float) { assert_eq!(c.norm_sqr(), ns); diff --git a/src/libextra/num/rational.rs b/src/libextra/num/rational.rs index ebb88a134818..b2b966928e9a 100644 --- a/src/libextra/num/rational.rs +++ b/src/libextra/num/rational.rs @@ -36,19 +36,19 @@ pub type BigRational = Ratio; impl Ratio { /// Create a ratio representing the integer `t`. - #[inline(always)] + #[inline] pub fn from_integer(t: T) -> Ratio { Ratio::new_raw(t, One::one()) } /// Create a ratio without checking for `denom == 0` or reducing. - #[inline(always)] + #[inline] pub fn new_raw(numer: T, denom: T) -> Ratio { Ratio { numer: numer, denom: denom } } /// Create a new Ratio. Fails if `denom == 0`. - #[inline(always)] + #[inline] pub fn new(numer: T, denom: T) -> Ratio { if denom == Zero::zero() { fail!("denominator == 0"); @@ -206,7 +206,7 @@ impl } } - #[inline(always)] + #[inline] fn round(&self) -> Ratio { if *self < Zero::zero() { Ratio::from_integer((self.numer - self.denom + One::one()) / self.denom) @@ -215,7 +215,7 @@ impl } } - #[inline(always)] + #[inline] fn trunc(&self) -> Ratio { Ratio::from_integer(self.numer / self.denom) } diff --git a/src/libextra/priority_queue.rs b/src/libextra/priority_queue.rs index 601b7685f3ca..efbf23f11b15 100644 --- a/src/libextra/priority_queue.rs +++ b/src/libextra/priority_queue.rs @@ -35,10 +35,10 @@ impl BaseIter for PriorityQueue { impl Container for PriorityQueue { /// Returns the length of the queue - fn len(&const self) -> uint { vec::uniq_len(&const self.data) } + fn len(&self) -> uint { self.data.len() } /// Returns true if a queue contains no elements - fn is_empty(&const self) -> bool { self.len() == 0 } + fn is_empty(&self) -> bool { self.len() == 0 } } impl Mutable for PriorityQueue { diff --git a/src/libextra/rc.rs b/src/libextra/rc.rs index 96ad629ea837..b90b0983dc24 100644 --- a/src/libextra/rc.rs +++ b/src/libextra/rc.rs @@ -60,7 +60,7 @@ pub fn rc_from_const(value: T) -> Rc { } impl Rc { - #[inline(always)] + #[inline] pub fn borrow<'r>(&'r self) -> &'r T { unsafe { cast::copy_lifetime(self, &(*self.ptr).value) } } diff --git a/src/libextra/rope.rs b/src/libextra/rope.rs index 12539cd4759d..fed73256c002 100644 --- a/src/libextra/rope.rs +++ b/src/libextra/rope.rs @@ -1271,7 +1271,6 @@ mod tests { use rope::*; - use core::str; use core::uint; use core::vec; diff --git a/src/libextra/semver.rs b/src/libextra/semver.rs index 462461439e67..cb372dd920da 100644 --- a/src/libextra/semver.rs +++ b/src/libextra/semver.rs @@ -29,7 +29,7 @@ pub enum Identifier { } impl cmp::Ord for Identifier { - #[inline(always)] + #[inline] fn lt(&self, other: &Identifier) -> bool { match (self, other) { (&Numeric(a), &Numeric(b)) => a < b, @@ -38,22 +38,22 @@ impl cmp::Ord for Identifier { (&AlphaNumeric(_), _) => false } } - #[inline(always)] + #[inline] fn le(&self, other: &Identifier) -> bool { ! (other < self) } - #[inline(always)] + #[inline] fn gt(&self, other: &Identifier) -> bool { other < self } - #[inline(always)] + #[inline] fn ge(&self, other: &Identifier) -> bool { ! (self < other) } } impl ToStr for Identifier { - #[inline(always)] + #[inline] fn to_str(&self) -> ~str { match self { &Numeric(n) => n.to_str(), @@ -73,7 +73,7 @@ pub struct Version { } impl ToStr for Version { - #[inline(always)] + #[inline] fn to_str(&self) -> ~str { let s = fmt!("%u.%u.%u", self.major, self.minor, self.patch); let s = if self.pre.is_empty() { @@ -90,7 +90,7 @@ impl ToStr for Version { } impl cmp::Ord for Version { - #[inline(always)] + #[inline] fn lt(&self, other: &Version) -> bool { self.major < other.major || @@ -123,15 +123,15 @@ impl cmp::Ord for Version { self.build < other.build) } - #[inline(always)] + #[inline] fn le(&self, other: &Version) -> bool { ! (other < self) } - #[inline(always)] + #[inline] fn gt(&self, other: &Version) -> bool { other < self } - #[inline(always)] + #[inline] fn ge(&self, other: &Version) -> bool { ! (self < other) } diff --git a/src/libextra/sha1.rs b/src/libextra/sha1.rs index 908e497b9591..7c4b3f4ce39f 100644 --- a/src/libextra/sha1.rs +++ b/src/libextra/sha1.rs @@ -24,7 +24,6 @@ use core::prelude::*; -use core::str; use core::uint; use core::vec; @@ -93,7 +92,7 @@ pub fn sha1() -> @Sha1 { } fn process_msg_block(st: &mut Sha1State) { assert_eq!(st.h.len(), digest_buf_len); - assert_eq!(vec::uniq_len(st.work_buf), work_buf_len); + assert_eq!(st.work_buf.len(), work_buf_len); let mut t: int; // Loop counter let w = st.work_buf; @@ -279,8 +278,6 @@ pub fn sha1() -> @Sha1 { mod tests { use sha1; - use core::vec; - #[test] fn test() { struct Test { diff --git a/src/libextra/smallintmap.rs b/src/libextra/smallintmap.rs index 7f566bc16e73..aee087d3764d 100644 --- a/src/libextra/smallintmap.rs +++ b/src/libextra/smallintmap.rs @@ -32,9 +32,9 @@ pub struct SmallIntMap { impl Container for SmallIntMap { /// Return the number of elements in the map - fn len(&const self) -> uint { + fn len(&self) -> uint { let mut sz = 0; - for uint::range(0, vec::uniq_len(&const self.v)) |i| { + for uint::range(0, self.v.len()) |i| { match self.v[i] { Some(_) => sz += 1, None => {} @@ -44,7 +44,7 @@ impl Container for SmallIntMap { } /// Return true if the map contains no elements - fn is_empty(&const self) -> bool { self.len() == 0 } + fn is_empty(&self) -> bool { self.len() == 0 } } impl Mutable for SmallIntMap { @@ -179,7 +179,7 @@ impl SmallIntMap { ff: &fn(uint, V, V) -> V) -> bool { let new_val = match self.find(&key) { None => val, - Some(orig) => ff(key, *orig, val) + Some(orig) => ff(key, copy *orig, val) }; self.insert(key, new_val) } @@ -199,12 +199,12 @@ pub struct SmallIntSet { impl Container for SmallIntSet { /// Return the number of elements in the map - fn len(&const self) -> uint { + fn len(&self) -> uint { self.map.len() } /// Return true if the map contains no elements - fn is_empty(&const self) -> bool { self.len() == 0 } + fn is_empty(&self) -> bool { self.len() == 0 } } impl Mutable for SmallIntSet { @@ -294,11 +294,6 @@ mod tests { use super::SmallIntMap; - use core::local_data; - use core::rand; - use core::uint; - use core::vec; - #[test] fn test_find_mut() { let mut m = SmallIntMap::new(); diff --git a/src/libextra/sort.rs b/src/libextra/sort.rs index 0189e0db6d4e..3e81216fc3a1 100644 --- a/src/libextra/sort.rs +++ b/src/libextra/sort.rs @@ -37,7 +37,7 @@ pub fn merge_sort(v: &[T], le: Le) -> ~[T] { let v_len = end - begin; if v_len == 0 { return ~[]; } - if v_len == 1 { return ~[v[begin]]; } + if v_len == 1 { return ~[copy v[begin]]; } let mid = v_len / 2 + begin; let a = (begin, mid); @@ -53,9 +53,9 @@ pub fn merge_sort(v: &[T], le: Le) -> ~[T] { let mut b_ix = 0; while a_ix < a_len && b_ix < b_len { if le(&a[a_ix], &b[b_ix]) { - rs.push(a[a_ix]); + rs.push(copy a[a_ix]); a_ix += 1; - } else { rs.push(b[b_ix]); b_ix += 1; } + } else { rs.push(copy b[b_ix]); b_ix += 1; } } rs.push_all(vec::slice(a, a_ix, a_len)); rs.push_all(vec::slice(b, b_ix, b_len)); @@ -106,7 +106,7 @@ pub fn quick_sort(arr: &mut [T], compare_func: Le) { fn qsort3(arr: &mut [T], left: int, right: int) { if right <= left { return; } - let v: T = arr[right]; + let v: T = copy arr[right]; let mut i: int = left - 1; let mut j: int = right; let mut p: int = i; @@ -233,7 +233,7 @@ fn binarysort(array: &mut [T], start: uint) { if start == 0 { start += 1; } while start < size { - let pivot = array[start]; + let pivot = copy array[start]; let mut left = 0; let mut right = start; assert!(left <= right); @@ -470,7 +470,7 @@ impl MergeState { let mut tmp = ~[]; for uint::range(base1, base1+len1) |i| { - tmp.push(array[i]); + tmp.push(copy array[i]); } let mut c1 = 0; @@ -580,7 +580,7 @@ impl MergeState { let mut tmp = ~[]; for uint::range(base2, base2+len2) |i| { - tmp.push(array[i]); + tmp.push(copy array[i]); } let mut c1 = base1 + len1 - 1; @@ -725,18 +725,18 @@ impl MergeState { } } -#[inline(always)] +#[inline] fn copy_vec(dest: &mut [T], s1: uint, from: &[T]) { assert!(s1+from.len() <= dest.len()); for from.eachi |i, v| { - dest[s1+i] = *v; + dest[s1+i] = copy *v; } } -#[inline(always)] +#[inline] fn shift_vec(dest: &mut [T], s1: uint, s2: uint, @@ -751,7 +751,6 @@ fn shift_vec(dest: &mut [T], mod test_qsort3 { use sort::*; - use core::vec; fn check_sort(v1: &mut [int], v2: &mut [int]) { let len = v1.len(); @@ -861,8 +860,6 @@ mod tests { use sort::*; - use core::vec; - fn check_sort(v1: &[int], v2: &[int]) { let len = v1.len(); pub fn le(a: &int, b: &int) -> bool { *a <= *b } @@ -1048,7 +1045,7 @@ mod big_tests { fn multiplyVec(arr: &[T], num: uint) -> ~[T] { let size = arr.len(); let res = do vec::from_fn(num) |i| { - arr[i % size] + copy arr[i % size] }; res } diff --git a/src/libextra/stats.rs b/src/libextra/stats.rs index 4af47fa806f8..3a1de5de01d6 100644 --- a/src/libextra/stats.rs +++ b/src/libextra/stats.rs @@ -12,7 +12,6 @@ use core::prelude::*; -use core::vec; use core::f64; use core::cmp; use core::num; diff --git a/src/libextra/std.rc b/src/libextra/std.rc index 83c0bb516b43..d4c85ef51362 100644 --- a/src/libextra/std.rc +++ b/src/libextra/std.rc @@ -10,34 +10,32 @@ /*! -The Rust standard library. +Rust extras. -The Rust standand library provides a number of useful features that are -not required in or otherwise suitable for the core library. +The `extra` crate is a set of useful modules for a variety of +purposes, including collections, numerics, I/O, serialization, +and concurrency. + +Rust extras are part of the standard Rust distribution. */ #[link(name = "extra", vers = "0.7-pre", uuid = "122bed0b-c19b-4b82-b0b7-7ae8aead7297", - url = "https://github.com/mozilla/rust/tree/master/src/libstd")]; + url = "https://github.com/mozilla/rust/tree/master/src/libextra")]; -#[comment = "The Rust standard library"]; +#[comment = "Rust extras"]; #[license = "MIT/ASL2"]; #[crate_type = "lib"]; #[deny(non_camel_case_types)]; #[deny(missing_doc)]; -// NOTE: remove these two attributes after the next snapshot -#[no_core]; // for stage0 -#[allow(unrecognized_lint)]; // otherwise stage0 is seriously ugly - #[no_std]; extern mod core(name = "std", vers = "0.7-pre"); -use core::{str, unstable}; use core::str::{StrSlice, OwnedStr}; pub use core::os; @@ -127,7 +125,7 @@ pub mod test; pub mod serialize; // A curious inner-module that's not exported that contains the binding -// 'extra' so that macro-expanded references to std::serialize and such +// 'extra' so that macro-expanded references to extra::serialize and such // can be resolved within libextra. #[doc(hidden)] pub mod std { diff --git a/src/libextra/sync.rs b/src/libextra/sync.rs index 5930bf50ff78..f5d0b6946d33 100644 --- a/src/libextra/sync.rs +++ b/src/libextra/sync.rs @@ -363,7 +363,7 @@ impl<'self> Condvar<'self> { // Checks whether a condvar ID was out of bounds, and fails if so, or does // something else next on success. -#[inline(always)] +#[inline] #[doc(hidden)] fn check_cvar_bounds(out_of_bounds: Option, id: uint, act: &str, blk: &fn() -> U) -> U { diff --git a/src/libextra/tempfile.rs b/src/libextra/tempfile.rs index c239e65e2d9a..39dcee5eff31 100644 --- a/src/libextra/tempfile.rs +++ b/src/libextra/tempfile.rs @@ -36,7 +36,6 @@ mod tests { use tempfile::mkdtemp; use core::os; - use core::str; #[test] fn test_mkdtemp() { diff --git a/src/libextra/terminfo/parm.rs b/src/libextra/terminfo/parm.rs index c395b57219c2..11f0fc23be51 100644 --- a/src/libextra/terminfo/parm.rs +++ b/src/libextra/terminfo/parm.rs @@ -224,9 +224,9 @@ pub fn expand(cap: &[u8], params: &[Param], vars: &mut Variables) } } else { return Err(~"stack is empty") }, 'i' => match (copy mparams[0], copy mparams[1]) { - (Number(ref mut x), Number(ref mut y)) => { - *x += 1; - *y += 1; + (Number(x), Number(y)) => { + mparams[0] = Number(x+1); + mparams[1] = Number(y+1); }, (_, _) => return Err(~"first two params not numbers with %i") }, @@ -352,6 +352,7 @@ pub fn expand(cap: &[u8], params: &[Param], vars: &mut Variables) #[cfg(test)] mod test { use super::*; + use core::result::Ok; #[test] fn test_basic_setabf() { @@ -366,6 +367,16 @@ mod test { bytes!("21").to_owned()); } + #[test] + fn test_op_i() { + let mut vars = Variables::new(); + assert_eq!(expand(bytes!("%p1%d%p2%d%p3%d%i%p1%d%p2%d%p3%d"), + [Number(1),Number(2),Number(3)], &mut vars), + Ok(bytes!("123233").to_owned())); + assert_eq!(expand(bytes!("%p1%d%p2%d%i%p1%d%p2%d"), [], &mut vars), + Ok(bytes!("0011").to_owned())); + } + #[test] fn test_param_stack_failure_conditions() { let mut varstruct = Variables::new(); diff --git a/src/libextra/terminfo/parser/compiled.rs b/src/libextra/terminfo/parser/compiled.rs index 81b6083db014..66649c62fcaf 100644 --- a/src/libextra/terminfo/parser/compiled.rs +++ b/src/libextra/terminfo/parser/compiled.rs @@ -313,7 +313,6 @@ pub fn parse(file: @Reader, longnames: bool) -> Result<~TermInfo, ~str> { #[cfg(test)] mod test { use super::*; - use p = core::path::Path; #[test] fn test_veclens() { diff --git a/src/libextra/test.rs b/src/libextra/test.rs index 406dfb086eac..64c6a822a86e 100644 --- a/src/libextra/test.rs +++ b/src/libextra/test.rs @@ -26,20 +26,11 @@ use core::either; use core::io; use core::option; use core::result; -use core::str; use core::task; use core::to_str::ToStr; use core::uint; use core::vec; -pub mod rustrt { - use core::libc::size_t; - - #[abi = "cdecl"] - pub extern { - pub unsafe fn rust_sched_threads() -> size_t; - } -} // The name of a test. By convention this follows the rules for rust // paths; i.e. it should be a series of identifiers separated by double @@ -365,7 +356,7 @@ pub fn run_tests_console(opts: &TestOpts, fn print_failures(st: &ConsoleTestState) { st.out.write_line("\nfailures:"); let mut failures = ~[]; - for uint::range(0, vec::uniq_len(&const st.failures)) |i| { + for uint::range(0, st.failures.len()) |i| { let name = copy st.failures[i].name; failures.push(name.to_str()); } @@ -489,11 +480,10 @@ static sched_overcommit : uint = 1; static sched_overcommit : uint = 4u; fn get_concurrency() -> uint { - unsafe { - let threads = rustrt::rust_sched_threads() as uint; - if threads == 1 { 1 } - else { threads * sched_overcommit } - } + use core::rt; + let threads = rt::util::default_sched_threads(); + if threads == 1 { 1 } + else { threads * sched_overcommit } } #[allow(non_implicitly_copyable_typarams)] @@ -542,7 +532,7 @@ pub fn filter_tests( // Sort the tests alphabetically fn lteq(t1: &TestDescAndFn, t2: &TestDescAndFn) -> bool { - str::le(t1.desc.name.to_str(), t2.desc.name.to_str()) + t1.desc.name.to_str() < t2.desc.name.to_str() } sort::quick_sort(filtered, lteq); diff --git a/src/libextra/time.rs b/src/libextra/time.rs index 50592d5f7309..005238a564e8 100644 --- a/src/libextra/time.rs +++ b/src/libextra/time.rs @@ -275,7 +275,7 @@ priv fn do_strptime(s: &str, format: &str) -> Result { let mut i = 0u; let len = strs.len(); while i < len { - match strs[i] { // can't use let due to stage0 bugs + match strs[i] { // can't use let due to let-pattern bugs (ref needle, value) => { if match_str(ss, pos, *needle) { return Some((value, pos + needle.len())); diff --git a/src/libextra/treemap.rs b/src/libextra/treemap.rs index f98758f64afe..f857581c17dd 100644 --- a/src/libextra/treemap.rs +++ b/src/libextra/treemap.rs @@ -75,13 +75,13 @@ fn lt(a: &TreeMap, } impl Ord for TreeMap { - #[inline(always)] + #[inline] fn lt(&self, other: &TreeMap) -> bool { lt(self, other) } - #[inline(always)] + #[inline] fn le(&self, other: &TreeMap) -> bool { !lt(other, self) } - #[inline(always)] + #[inline] fn ge(&self, other: &TreeMap) -> bool { !lt(self, other) } - #[inline(always)] + #[inline] fn gt(&self, other: &TreeMap) -> bool { lt(other, self) } } @@ -145,7 +145,7 @@ impl Map for TreeMap { } /// Return a mutable reference to the value corresponding to the key - #[inline(always)] + #[inline] fn find_mut<'a>(&'a mut self, key: &K) -> Option<&'a mut V> { find_mut(&mut self.root, key) } @@ -236,7 +236,7 @@ impl<'self, K, V> Iterator<(&'self K, &'self V)> for TreeMapIterator<'self, K, V impl<'self, T> Iterator<&'self T> for TreeSetIterator<'self, T> { /// Advance the iterator to the next node (in order). If there are no more nodes, return `None`. - #[inline(always)] + #[inline] fn next(&mut self) -> Option<&'self T> { do self.iter.next().map |&(value, _)| { value } } @@ -251,69 +251,69 @@ pub struct TreeSet { impl BaseIter for TreeSet { /// Visit all values in order - #[inline(always)] + #[inline] fn each(&self, f: &fn(&T) -> bool) -> bool { self.map.each_key(f) } - #[inline(always)] + #[inline] fn size_hint(&self) -> Option { Some(self.len()) } } impl ReverseIter for TreeSet { /// Visit all values in reverse order - #[inline(always)] + #[inline] fn each_reverse(&self, f: &fn(&T) -> bool) -> bool { self.map.each_key_reverse(f) } } impl Eq for TreeSet { - #[inline(always)] + #[inline] fn eq(&self, other: &TreeSet) -> bool { self.map == other.map } - #[inline(always)] + #[inline] fn ne(&self, other: &TreeSet) -> bool { self.map != other.map } } impl Ord for TreeSet { - #[inline(always)] + #[inline] fn lt(&self, other: &TreeSet) -> bool { self.map < other.map } - #[inline(always)] + #[inline] fn le(&self, other: &TreeSet) -> bool { self.map <= other.map } - #[inline(always)] + #[inline] fn ge(&self, other: &TreeSet) -> bool { self.map >= other.map } - #[inline(always)] + #[inline] fn gt(&self, other: &TreeSet) -> bool { self.map > other.map } } impl Container for TreeSet { /// Return the number of elements in the set - #[inline(always)] + #[inline] fn len(&const self) -> uint { self.map.len() } /// Return true if the set contains no elements - #[inline(always)] + #[inline] fn is_empty(&const self) -> bool { self.map.is_empty() } } impl Mutable for TreeSet { /// Clear the set, removing all values. - #[inline(always)] + #[inline] fn clear(&mut self) { self.map.clear() } } impl Set for TreeSet { /// Return true if the set contains a value - #[inline(always)] + #[inline] fn contains(&self, value: &T) -> bool { self.map.contains_key(value) } /// Add a value to the set. Return true if the value was not already /// present in the set. - #[inline(always)] + #[inline] fn insert(&mut self, value: T) -> bool { self.map.insert(value, ()) } /// Remove a value from the set. Return true if the value was /// present in the set. - #[inline(always)] + #[inline] fn remove(&mut self, value: &T) -> bool { self.map.remove(value) } /// Return true if the set has no elements in common with `other`. @@ -336,7 +336,7 @@ impl Set for TreeSet { } /// Return true if the set is a subset of another - #[inline(always)] + #[inline] fn is_subset(&self, other: &TreeSet) -> bool { other.is_superset(self) } @@ -490,12 +490,12 @@ impl Set for TreeSet { impl TreeSet { /// Create an empty TreeSet - #[inline(always)] + #[inline] pub fn new() -> TreeSet { TreeSet{map: TreeMap::new()} } /// Get a lazy iterator over the values in the set. /// Requires that it be frozen (immutable). - #[inline(always)] + #[inline] pub fn iter<'a>(&'a self) -> TreeSetIterator<'a, T> { TreeSetIterator{iter: self.map.iter()} } @@ -518,7 +518,7 @@ struct TreeNode { impl TreeNode { /// Creates a new tree node. - #[inline(always)] + #[inline] pub fn new(key: K, value: V) -> TreeNode { TreeNode{key: key, value: value, left: None, right: None, level: 1} } @@ -710,7 +710,6 @@ mod test_treemap { use core::rand::RngUtil; use core::rand; - use core::str; use core::vec; #[test] diff --git a/src/libextra/workcache.rs b/src/libextra/workcache.rs index b2fd998b73fd..12a26606f36e 100644 --- a/src/libextra/workcache.rs +++ b/src/libextra/workcache.rs @@ -104,7 +104,7 @@ struct WorkKey { } impl to_bytes::IterBytes for WorkKey { - #[inline(always)] + #[inline] fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { self.kind.iter_bytes(lsb0, f) && self.name.iter_bytes(lsb0, f) } diff --git a/src/libfuzzer/ast_match.rs b/src/libfuzzer/ast_match.rs deleted file mode 100644 index 7d623919ff93..000000000000 --- a/src/libfuzzer/ast_match.rs +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::prelude::*; - -use vec; - -fn vec_equal(v: ~[T], - u: ~[T], - element_equality_test: @fn(&&T, &&T) -> bool) -> - bool { - let Lv = v.len(); - if Lv != u.len() { return false; } - let i = 0u; - while i < Lv { - if !element_equality_test(v[i], u[i]) { return false; } - i += 1u; - } - return true; -} - -fn builtin_equal(&&a: T, &&b: T) -> bool { return a == b; } -fn builtin_equal_int(&&a: int, &&b: int) -> bool { return a == b; } - -fn main() { - assert!((builtin_equal(5, 5))); - assert!((!builtin_equal(5, 4))); - assert!((!vec_equal(~[5, 5], ~[5], bind builtin_equal(_, _)))); - assert!((!vec_equal(~[5, 5], ~[5], builtin_equal_int))); - assert!((!vec_equal(~[5, 5], ~[5, 4], builtin_equal_int))); - assert!((!vec_equal(~[5, 5], ~[4, 5], builtin_equal_int))); - assert!((vec_equal(~[5, 5], ~[5, 5], builtin_equal_int))); - - error!("Pass"); -} diff --git a/src/libfuzzer/cycles.rs b/src/libfuzzer/cycles.rs deleted file mode 100644 index 2256325fa437..000000000000 --- a/src/libfuzzer/cycles.rs +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use core::prelude::*; - -use extra; -use extra::rand; -use uint::range; - -// random uint less than n -fn under(r : rand::rng, n : uint) -> uint { - assert!(n != 0u); r.next() as uint % n -} - -// random choice from a vec -fn choice(r : rand::rng, v : ~[const T]) -> T { - assert!(v.len() != 0u); v[under(r, v.len())] -} - -// k in n chance of being true -fn likelihood(r : rand::rng, k : uint, n : uint) -> bool { under(r, n) < k } - - -static iters : uint = 1000u; -static vlen : uint = 100u; - -enum maybe_pointy { - none, - p(@pointy) -} - -type pointy = { - mut a : maybe_pointy, - mut b : ~maybe_pointy, - mut c : @maybe_pointy, - - mut f : @fn()->(), - mut g : ~fn()->(), - - mut m : ~[maybe_pointy], - mut n : ~[maybe_pointy], - mut o : {x : int, y : maybe_pointy} -}; -// To add: objects; traits; anything type-parameterized? - -fn empty_pointy() -> @pointy { - return @{ - mut a : none, - mut b : ~none, - mut c : @none, - - mut f : || {}, - mut g : || {}, - - mut m : ~[], - mut n : ~[], - mut o : {x : 0, y : none} - } -} - -fn nopP(_x : @pointy) { } -fn nop(_x: T) { } - -fn test_cycles(r : rand::rng, k: uint, n: uint) -{ - let mut v : ~[@pointy] = ~[]; - - // Create a graph with no edges - range(0u, vlen) {|_i| - v.push(empty_pointy()); - } - - // Fill in the graph with random edges, with density k/n - range(0u, vlen) {|i| - if (likelihood(r, k, n)) { v[i].a = p(choice(r, v)); } - if (likelihood(r, k, n)) { v[i].b = ~p(choice(r, v)); } - if (likelihood(r, k, n)) { v[i].c = @p(choice(r, v)); } - - if (likelihood(r, k, n)) { v[i].f = bind nopP(choice(r, v)); } - //if (false) { v[i].g = bind (|_: @pointy| { })( - // choice(r, v)); } - // https://github.com/mozilla/rust/issues/1899 - - if (likelihood(r, k, n)) { v[i].m = [p(choice(r, v))]; } - if (likelihood(r, k, n)) { v[i].n.push(mut p(choice(r, v))); } - if (likelihood(r, k, n)) { v[i].o = {x: 0, y: p(choice(r, v))}; } - } - - // Drop refs one at a time - range(0u, vlen) {|i| - v[i] = empty_pointy() - } -} - -fn main() -{ - let r = rand::rng(); - range(0u, iters) {|i| - test_cycles(r, i, iters); - } -} diff --git a/src/libfuzzer/fuzzer.rc b/src/libfuzzer/fuzzer.rc deleted file mode 100644 index 4e2103fcd704..000000000000 --- a/src/libfuzzer/fuzzer.rc +++ /dev/null @@ -1,713 +0,0 @@ -// Copyright 2012-2013 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. - - -#[link(name = "fuzzer", - vers = "0.7-pre", - uuid = "d6418797-2736-4833-bd82-d3c684b7c1b0", - url = "https://github.com/mozilla/rust/tree/master/src/libfuzzer")]; - -#[comment = "The Rust fuzzer library"]; -#[license = "MIT/ASL2"]; -#[crate_type = "lib"]; - -#[allow(non_camel_case_types)]; - -#[no_std]; - -extern mod std(name = "std", vers = "0.7-pre"); -extern mod extra(name = "extra", vers = "0.7-pre"); - -extern mod syntax(vers = "0.7-pre"); - -use std::prelude::*; - -use std::int; -use std::io; -use std::option; -use std::os; -use std::result; -use std::run; -use std::str; -use std::uint; - -use syntax::diagnostic; -use syntax::parse::token::ident_interner; -use syntax::parse::token; -use syntax::parse; -use syntax::print::pprust; -use syntax::{ast, fold, visit, codemap}; - -#[deriving(Eq)] -pub enum test_mode { tm_converge, tm_run, } - -pub struct Context { mode: test_mode } // + rng - -pub fn write_file(filename: &Path, content: &str) { - result::get(&io::file_writer(filename, [io::Create, io::Truncate])) - .write_str(content); -} - -pub fn contains(haystack: &str, needle: &str) -> bool { - haystack.contains(needle) -} - -pub fn find_rust_files(files: &mut ~[Path], path: &Path) { - if path.filetype() == Some(~".rs") && !contains(path.to_str(), "utf8") { - // ignoring "utf8" tests because something is broken - files.push(path.clone()); - } else if os::path_is_dir(path) - && !contains(path.to_str(), "compile-fail") - && !contains(path.to_str(), "build") { - for os::list_dir_path(path).each |p| { - find_rust_files(&mut *files, *p); - } - } -} - - -pub fn common_exprs() -> ~[@ast::expr] { - fn dse(e: ast::expr_) -> @ast::expr { - @ast::expr { - id: 0, - node: e, - span: codemap::dummy_sp(), - } - } - - fn dsl(l: ast::lit_) -> ast::lit { - codemap::spanned { node: l, span: codemap::dummy_sp() } - } - - ~[dse(ast::expr_break(option::None)), - dse(ast::expr_again(option::None)), - dse(ast::expr_ret(option::None)), - dse(ast::expr_lit(@dsl(ast::lit_nil))), - dse(ast::expr_lit(@dsl(ast::lit_bool(false)))), - dse(ast::expr_lit(@dsl(ast::lit_bool(true)))), - dse(ast::expr_unary(-1, ast::box(ast::m_imm), - dse(ast::expr_lit(@dsl(ast::lit_bool(true)))))), - dse(ast::expr_unary(-1, ast::uniq(ast::m_imm), - dse(ast::expr_lit(@dsl(ast::lit_bool(true)))))) - ] -} - -pub fn safe_to_steal_expr(e: @ast::expr, tm: test_mode) -> bool { - safe_to_use_expr(e, tm) -} - -pub fn safe_to_use_expr(e: @ast::expr, tm: test_mode) -> bool { - match tm { - tm_converge => { - match e.node { - // If the fuzzer moves a block-ending-in-semicolon into callee - // position, the pretty-printer can't preserve this even by - // parenthesizing!! See email to marijn. - ast::expr_if(*) | ast::expr_block(*) - | ast::expr_match(*) | ast::expr_while(*) => { false } - - // https://github.com/mozilla/rust/issues/929 - ast::expr_cast(*) | ast::expr_binary(*) | ast::expr_assign(*) | - ast::expr_assign_op(*) => { false } - - ast::expr_ret(option::None) => { false } - - // https://github.com/mozilla/rust/issues/953 - //ast::expr_fail(option::Some(_)) => { false } - - // https://github.com/mozilla/rust/issues/928 - //ast::expr_cast(_, _) { false } - - // https://github.com/mozilla/rust/issues/1458 - ast::expr_call(*) => { false } - - _ => { true } - } - } - tm_run => { true } - } -} - -pub fn safe_to_steal_ty(t: @ast::Ty, tm: test_mode) -> bool { - // Restrictions happen to be the same. - safe_to_replace_ty(&t.node, tm) -} - -// Not type-parameterized: https://github.com/mozilla/rust/issues/898 (FIXED) -pub fn stash_expr_if(c: @fn(@ast::expr, test_mode)->bool, - es: @mut ~[@ast::expr], - e: @ast::expr, - tm: test_mode) { - if c(e, tm) { - *es = *es + [e]; - } else { - /* now my indices are wrong :( */ - } -} - -pub fn stash_ty_if(c: @fn(@ast::Ty, test_mode) -> bool, - es: @mut ~[@ast::Ty], - e: @ast::Ty, - tm: test_mode) { - if c(e, tm) { - es.push(e); - } else { - /* now my indices are wrong :( */ - } -} - -pub struct StolenStuff { - exprs: ~[@ast::expr], - tys: ~[@ast::Ty] -} - -pub fn steal(crate: @ast::crate, tm: test_mode) -> StolenStuff { - let exprs = @mut ~[]; - let tys = @mut ~[]; - let v = visit::mk_simple_visitor(@visit::SimpleVisitor { - visit_expr: |a| stash_expr_if(safe_to_steal_expr, exprs, a, tm), - visit_ty: |a| stash_ty_if(safe_to_steal_ty, tys, a, tm), - .. *visit::default_simple_visitor() - }); - visit::visit_crate(crate, ((), v)); - StolenStuff { - exprs: (*exprs).clone(), - tys: (*tys).clone(), - } -} - - -pub fn safe_to_replace_expr(e: &ast::expr_, _tm: test_mode) -> bool { - match *e { - // https://github.com/mozilla/rust/issues/652 - ast::expr_if(*) => false, - ast::expr_block(_) => false, - - // expr_call is also missing a constraint - ast::expr_fn_block(*) => false, - - _ => true, - } -} - -pub fn safe_to_replace_ty(t: &ast::ty_, _tm: test_mode) -> bool { - match *t { - ast::ty_infer => { false } // always implicit, always top level - ast::ty_bot => { false } // in source, can only appear - // as the out type of a function - ast::ty_mac(_) => { false } - _ => { true } - } -} - -// Replace the |i|th expr (in fold order) of |crate| with |newexpr|. -pub fn replace_expr_in_crate(crate: @ast::crate, - i: uint, - newexpr: @ast::expr, - tm: test_mode) - -> @ast::crate { - let j: @mut uint = @mut 0u; - fn fold_expr_rep(j_: @mut uint, - i_: uint, - newexpr_: &ast::expr_, - original: &ast::expr_, - fld: @fold::ast_fold, - tm_: test_mode) - -> ast::expr_ { - *j_ += 1; - if i_ + 1 == *j_ && safe_to_replace_expr(original, tm_) { - copy *newexpr_ - } else { - fold::noop_fold_expr(original, fld) - } - } - let afp = @fold::AstFoldFns { - fold_expr: fold::wrap(|a,b| { - fold_expr_rep(j, i, &newexpr.node, a, b, tm) - }), - .. *fold::default_ast_fold() - }; - let af = fold::make_fold(afp); - let crate2: @ast::crate = @af.fold_crate(crate); - crate2 -} - - -// Replace the |i|th ty (in fold order) of |crate| with |newty|. -pub fn replace_ty_in_crate(crate: @ast::crate, - i: uint, - newty: @ast::Ty, - tm: test_mode) - -> @ast::crate { - let j: @mut uint = @mut 0u; - fn fold_ty_rep(j_: @mut uint, - i_: uint, - newty_: &ast::ty_, - original: &ast::ty_, - fld: @fold::ast_fold, - tm_: test_mode) - -> ast::ty_ { - *j_ += 1; - if i_ + 1 == *j_ && safe_to_replace_ty(original, tm_) { - copy *newty_ - } else { - fold::noop_fold_ty(original, fld) - } - } - let afp = @fold::AstFoldFns { - fold_ty: fold::wrap(|a,b| fold_ty_rep(j, i, &newty.node, a, b, tm)), - .. *fold::default_ast_fold() - }; - let af = fold::make_fold(afp); - let crate2: @ast::crate = @af.fold_crate(crate); - crate2 -} - -pub fn under(n: uint, it: &fn(uint)) { - let mut i: uint = 0u; - while i < n { it(i); i += 1u; } -} - -pub fn as_str(f: @fn(x: @io::Writer)) -> ~str { - io::with_str_writer(f) -} - -pub fn check_variants_of_ast(crate: @ast::crate, - codemap: @codemap::CodeMap, - filename: &Path, - cx: Context) { - let stolen = steal(crate, cx.mode); - let extra_exprs = do common_exprs().filtered |&a| { - safe_to_use_expr(a, cx.mode) - }; - check_variants_T(crate, - codemap, - filename, - ~"expr", - extra_exprs + stolen.exprs, - pprust::expr_to_str, - replace_expr_in_crate, - cx); - check_variants_T(crate, - codemap, - filename, - ~"ty", - stolen.tys, - pprust::ty_to_str, - replace_ty_in_crate, - cx); -} - -pub fn check_variants_T(crate: @ast::crate, - codemap: @codemap::CodeMap, - filename: &Path, - thing_label: ~str, - things: &[T], - stringifier: @fn(T, @ident_interner) -> ~str, - replacer: @fn(@ast::crate, - uint, - T, - test_mode) - -> @ast::crate, - cx: Context) { - error!("%s contains %u %s objects", filename.to_str(), - things.len(), thing_label); - - // Assuming we're not generating any token_trees - let intr = syntax::parse::token::mk_fake_ident_interner(); - - let L = things.len(); - - if L < 100 { - do under(uint::min(L, 20)) |i| { - error!("Replacing... #%?", uint::to_str(i)); - let fname = str::to_owned(filename.to_str()); - do under(uint::min(L, 30)) |j| { - let fname = fname.to_str(); - error!("With... %?", stringifier(things[j], intr)); - let crate2 = replacer(crate, i, things[j], cx.mode); - // It would be best to test the *crate* for stability, but - // testing the string for stability is easier and ok for now. - let handler = diagnostic::mk_handler(None); - let str3 = do io::with_str_reader("") |rdr| { - let fname = fname.to_str(); - let string = do as_str |a| { - let span_handler = - diagnostic::mk_span_handler(handler, codemap); - pprust::print_crate(codemap, - intr, - span_handler, - crate2, - fname.to_managed(), - rdr, - a, - pprust::no_ann(), - false) - }; - string.to_managed() - }; - match cx.mode { - tm_converge => check_roundtrip_convergence(str3, 1), - tm_run => { - let file_label = fmt!("rusttmp/%s_%s_%u_%u", - last_part(filename.to_str()), - thing_label, - i, - j); - let safe_to_run = !(content_is_dangerous_to_run(str3) - || has_raw_pointers(crate2)); - check_whole_compiler(str3, - &Path(file_label), - safe_to_run); - } - } - } - } - } -} - -pub fn last_part(filename: ~str) -> ~str { - let ix = filename.rfind('/').get(); - filename.slice(ix + 1u, filename.len() - 3u).to_owned() -} - -pub enum happiness { - passed, - cleanly_rejected(~str), - known_bug(~str), - failed(~str), -} - -// We'd find more bugs if we could take an AST here, but -// - that would find many "false positives" or unimportant bugs -// - that would be tricky, requiring use of tasks or serialization -// or randomness. -// This seems to find plenty of bugs as it is :) -pub fn check_whole_compiler(code: &str, - suggested_filename_prefix: &Path, - allow_running: bool) { - let filename = &suggested_filename_prefix.with_filetype("rs"); - write_file(filename, code); - - let compile_result = check_compiling(filename); - - let run_result = match (compile_result, allow_running) { - (passed, true) => { check_running(suggested_filename_prefix) } - (h, _) => { h } - }; - - match run_result { - passed | cleanly_rejected(_) | known_bug(_) => { - removeIfExists(suggested_filename_prefix); - removeIfExists(&suggested_filename_prefix.with_filetype("rs")); - removeDirIfExists(&suggested_filename_prefix.with_filetype("dSYM")); - } - failed(s) => { - error!("check_whole_compiler failure: %?", s); - error!("Saved as: %?", filename.to_str()); - } - } -} - -pub fn removeIfExists(filename: &Path) { - // So sketchy! - assert!(!contains(filename.to_str(), " ")); - run::process_status("bash", [~"-c", ~"rm " + filename.to_str()]); -} - -pub fn removeDirIfExists(filename: &Path) { - // So sketchy! - assert!(!contains(filename.to_str(), " ")); - run::process_status("bash", [~"-c", ~"rm -r " + filename.to_str()]); -} - -pub fn check_running(exe_filename: &Path) -> happiness { - let p = run::process_output( - "/Users/jruderman/scripts/timed_run_rust_program.py", - [exe_filename.to_str()]); - let comb = str::from_bytes(p.output) + "\n" + str::from_bytes(p.error); - if comb.len() > 1u { - error!("comb comb comb: %?", comb); - } - - if contains(comb, "Assertion failed:") { - failed(~"C++ assertion failure") - } else if contains(comb, "leaked memory in rust main loop") { - // might also use exit code 134 - //failed("Leaked") - known_bug(~"https://github.com/mozilla/rust/issues/910") - } else if contains(comb, "src/rt/") { - failed(~"Mentioned src/rt/") - } else if contains(comb, "malloc") { - failed(~"Mentioned malloc") - } else { - match p.status { - 0 => { passed } - 100 => { cleanly_rejected(~"running: explicit fail") } - 101 | 247 => { cleanly_rejected(~"running: timed out") } - 245 | 246 | 138 | 252 => { - known_bug(~"https://github.com/mozilla/rust/issues/1466") - } - 136 | 248 => { - known_bug( - ~"SIGFPE - https://github.com/mozilla/rust/issues/944") - } - rc => { - failed(~"Rust program ran but exited with status " + - int::to_str(rc)) - } - } - } -} - -pub fn check_compiling(filename: &Path) -> happiness { - let p = run::process_output( - "/Users/jruderman/code/rust/build/x86_64-apple-darwin/stage1/bin/rustc", - [filename.to_str()]); - - let out = str::from_bytes(p.output); - let err = str::from_bytes(p.error); - - //error!("Status: %d", p.status); - if p.status == 0 { - passed - } else if !err.is_empty() { - if err.contains("error:") { - cleanly_rejected(~"rejected with span_error") - } else { - error!("Stderr: %?", err); - failed(~"Unfamiliar error message") - } - } else if out.contains("Assertion") && out.contains("failed") { - error!("Stdout: %?", out); - failed(~"Looks like an llvm assertion failure") - } else if out.contains("internal compiler error unimplemented") { - known_bug(~"Something unimplemented") - } else if out.contains("internal compiler error") { - error!("Stdout: %?", out); - failed(~"internal compiler error") - - } else { - error!("%?", p.status); - error!("!Stdout: %?", out); - failed(~"What happened?") - } -} - - -pub fn parse_and_print(code: @str) -> @str { - let filename = Path("tmp.rs"); - let sess = parse::new_parse_sess(option::None); - write_file(&filename, code); - let crate = parse::parse_crate_from_source_str(filename.to_str().to_managed(), - code, - ~[], - sess); - do io::with_str_reader(code) |rdr| { - let filename = filename.to_str(); - do as_str |a| { - pprust::print_crate(sess.cm, - // Assuming there are no token_trees - token::mk_fake_ident_interner(), - copy sess.span_diagnostic, - crate, - filename.to_managed(), - rdr, - a, - pprust::no_ann(), - false) - }.to_managed() - } -} - -pub fn has_raw_pointers(c: @ast::crate) -> bool { - let has_rp = @mut false; - fn visit_ty(flag: @mut bool, t: @ast::Ty) { - match t.node { - ast::ty_ptr(_) => { *flag = true; } - _ => { } - } - } - let v = - visit::mk_simple_visitor(@visit::SimpleVisitor { - visit_ty: |a| visit_ty(has_rp, a), - .. *visit::default_simple_visitor()}); - visit::visit_crate(c, ((), v)); - return *has_rp; -} - -pub fn content_is_dangerous_to_run(code: &str) -> bool { - let dangerous_patterns = - ~[~"xfail-test", - ~"import", // espeically fs, run - ~"extern", - ~"unsafe", - ~"log"]; // python --> rust pipe deadlock? - - for dangerous_patterns.each |p| { if contains(code, *p) { return true; } } - return false; -} - -pub fn content_is_dangerous_to_compile(code: &str) -> bool { - let dangerous_patterns = - ~[~"xfail-test"]; - - for dangerous_patterns.each |p| { if contains(code, *p) { return true; } } - return false; -} - -pub fn content_might_not_converge(code: &str) -> bool { - let confusing_patterns = - ~[~"xfail-test", - ~"xfail-pretty", - ~"self", // crazy rules enforced by parser not typechecker? - ~"spawn", // precedence issues? - ~"bind", // precedence issues? - ~" be ", // don't want to replace its child with a non-call: - // "Non-call expression in tail call" - ~"\n\n\n\n\n" // https://github.com/mozilla/rust/issues/850 - ]; - - for confusing_patterns.each |p| { if contains(code, *p) { return true; } } - return false; -} - -pub fn file_might_not_converge(filename: &Path) -> bool { - let confusing_files = ~[ - ~"expr-alt.rs", // pretty-printing "(a = b) = c" - // vs "a = b = c" and wrapping - ~"block-arg-in-ternary.rs", // wrapping - ~"move-3-unique.rs", // 0 becomes (0), but both seem reasonable. wtf? - ~"move-3.rs" // 0 becomes (0), but both seem reasonable. wtf? - ]; - - - for confusing_files.each |f| { - if contains(filename.to_str(), *f) { - return true; - } - } - - return false; -} - -pub fn check_roundtrip_convergence(code: @str, maxIters: uint) { - let mut i = 0u; - let mut newv = code; - let mut oldv = code; - - while i < maxIters { - oldv = newv; - if content_might_not_converge(oldv) { return; } - newv = parse_and_print(oldv); - if oldv == newv { break; } - i += 1u; - } - - if oldv == newv { - error!("Converged after %u iterations", i); - } else { - error!("Did not converge after %u iterations!", i); - write_file(&Path("round-trip-a.rs"), oldv); - write_file(&Path("round-trip-b.rs"), newv); - run::process_status("diff", [~"-w", ~"-u", ~"round-trip-a.rs", ~"round-trip-b.rs"]); - fail!("Mismatch"); - } -} - -pub fn check_convergence(files: &[Path]) { - error!("pp convergence tests: %u files", files.len()); - for files.each |file| { - if !file_might_not_converge(file) { - let s = result::get(&io::read_whole_file_str(file)).to_managed(); - if !content_might_not_converge(s) { - error!("pp converge: %s", file.to_str()); - // Change from 7u to 2u once - // https://github.com/mozilla/rust/issues/850 is fixed - check_roundtrip_convergence(s, 7u); - } - } - } -} - -pub fn check_variants(files: &[Path], cx: Context) { - for files.each |file| { - if cx.mode == tm_converge && - file_might_not_converge(file) { - error!("Skipping convergence test based on\ - file_might_not_converge"); - loop; - } - - let s = result::get(&io::read_whole_file_str(file)).to_managed(); - if s.contains_char('#') { - loop; // Macros are confusing - } - if cx.mode == tm_converge && content_might_not_converge(s) { - loop; - } - if cx.mode == tm_run && content_is_dangerous_to_compile(s) { - loop; - } - - let file_str = file.to_str(); - - error!("check_variants: %?", file_str); - let sess = parse::new_parse_sess(None); - let crate = parse::parse_crate_from_source_str(file_str.to_managed(), - s, - ~[], - sess); - io::with_str_reader(s, |rdr| { - let file_str = file_str.to_str(); - error!("%s", - as_str(|a| { - pprust::print_crate( - sess.cm, - // Assuming no token_trees - token::mk_fake_ident_interner(), - copy sess.span_diagnostic, - crate, - file_str.to_managed(), - rdr, - a, - pprust::no_ann(), - false) - })) - }); - check_variants_of_ast(crate, sess.cm, file, cx); - } -} - -pub fn main() { - let args = os::args(); - if args.len() != 2u { - error!("usage: %s ", args[0]); - return; - } - let mut files = ~[]; - let root = Path(args[1]); - - find_rust_files(&mut files, &root); - error!("== check_convergence =="); - check_convergence(files); - error!("== check_variants: converge =="); - check_variants(files, Context { mode: tm_converge }); - error!("== check_variants: run =="); - check_variants(files, Context { mode: tm_run }); - - error!("Fuzzer done"); -} - -// For bootstrapping purposes... -pub mod core { - pub use std::cmp; - pub use std::sys; -} diff --git a/src/libfuzzer/ivec_fuzz.rs b/src/libfuzzer/ivec_fuzz.rs deleted file mode 100644 index 8f019a14eedb..000000000000 --- a/src/libfuzzer/ivec_fuzz.rs +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright 2012 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. - -/* - -Idea: provide functions for 'exhaustive' and 'random' modification of vecs. - - two functions, "return all edits" and "return a random edit" = move- - leaning toward this model or two functions, "return the number of - possible edits" and "return edit #n" - -It would be nice if this could be data-driven, so the two functions -could share information: - type vec_modifier = rec(fn ( v, uint i) -> ~[T] fun, uint lo, uint di); - const ~[vec_modifier] vec_modifiers = ~[rec(fun=vec_omit, 0u, 1u), ...]/~; -But that gives me "error: internal compiler error unimplemented consts -that's not a plain literal". -https://github.com/graydon/rust/issues/570 - -vec_edits is not an iter because iters might go away. - -*/ - -use std::prelude::*; - -use vec::slice; -use vec::len; - -fn vec_omit(v: ~[T], i: uint) -> ~[T] { - slice(v, 0u, i) + slice(v, i + 1u, len(v)) -} -fn vec_dup(v: ~[T], i: uint) -> ~[T] { - slice(v, 0u, i) + [v[i]] + slice(v, i, len(v)) -} -fn vec_swadj(v: ~[T], i: uint) -> ~[T] { - slice(v, 0u, i) + [v[i + 1u], v[i]] + slice(v, i + 2u, len(v)) -} -fn vec_prefix(v: ~[T], i: uint) -> ~[T] { slice(v, 0u, i) } -fn vec_suffix(v: ~[T], i: uint) -> ~[T] { slice(v, i, len(v)) } - -fn vec_poke(v: ~[T], i: uint, x: T) -> ~[T] { - slice(v, 0u, i) + ~[x] + slice(v, i + 1u, len(v)) -} -fn vec_insert(v: ~[T], i: uint, x: T) -> ~[T] { - slice(v, 0u, i) + ~[x] + slice(v, i, len(v)) -} - -// Iterates over 0...length, skipping the specified number on each side. -fn ix(skip_low: uint, skip_high: uint, length: uint, it: block(uint)) { - let i: uint = skip_low; - while i + skip_high <= length { it(i); i += 1u; } -} - -// Returns a bunch of modified versions of v, some of which introduce -// new elements (borrowed from xs). -fn vec_edits(v: ~[T], xs: ~[T]) -> ~[~[T]] { - let edits: ~[~[T]] = ~[]; - let Lv: uint = len(v); - - if Lv != 1u { - // When Lv == 1u, this is redundant with omit. - edits.push(~[]); - } - if Lv >= 3u { - // When Lv == 2u, this is redundant with swap. - edits.push(vec::reversed(v)); - } - ix(0u, 1u, Lv) {|i| edits += ~[vec_omit(v, i)]; } - ix(0u, 1u, Lv) {|i| edits += ~[vec_dup(v, i)]; } - ix(0u, 2u, Lv) {|i| edits += ~[vec_swadj(v, i)]; } - ix(1u, 2u, Lv) {|i| edits += ~[vec_prefix(v, i)]; } - ix(2u, 1u, Lv) {|i| edits += ~[vec_suffix(v, i)]; } - - ix(0u, 1u, len(xs)) {|j| - ix(0u, 1u, Lv) {|i| - edits.push(vec_poke(v, i, xs[j])); - } - ix(0u, 0u, Lv) {|i| - edits.push(vec_insert(v, i, xs[j])); - } - } - - edits -} - -// Would be nice if this were built in: -// https://github.com/graydon/rust/issues/424 -fn vec_to_str(v: ~[int]) -> str { - let i = 0u; - let s = "["; - while i < len(v) { - s += int::str(v[i]); - if i + 1u < len(v) { s += ", "; } - i += 1u; - } - return s + "]"; -} - -fn show_edits(a: ~[int], xs: ~[int]) { - log(error, "=== Edits of " + vec_to_str(a) + " ==="); - let b = vec_edits(a, xs); - ix(0u, 1u, len(b)) {|i| log(error, vec_to_str(b[i])); } -} - -fn demo_edits() { - let xs = ~[7, 8]; - show_edits(~[], xs); - show_edits(~[1], xs); - show_edits(~[1, 2], xs); - show_edits(~[1, 2, 3], xs); - show_edits(~[1, 2, 3, 4], xs); -} - -fn main() { demo_edits(); } diff --git a/src/libfuzzer/rand_util.rs b/src/libfuzzer/rand_util.rs deleted file mode 100644 index abc6b1cfc0af..000000000000 --- a/src/libfuzzer/rand_util.rs +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::prelude::*; -use extra::rand; - -// random uint less than n -fn under(r : rand::rng, n : uint) -> uint { - assert!(n != 0u); r.next() as uint % n -} - -// random choice from a vec -fn choice(r : rand::rng, v : ~[T]) -> T { - assert!(v.len() != 0u); v[under(r, v.len())] -} - -// 1 in n chance of being true -fn unlikely(r : rand::rng, n : uint) -> bool { under(r, n) == 0u } - -// shuffle a vec in place -fn shuffle(r : rand::rng, &v : ~[T]) { - let i = v.len(); - while i >= 2u { - // Loop invariant: elements with index >= i have been locked in place. - i -= 1u; - vec::swap(v, i, under(r, i + 1u)); // Lock element i in place. - } -} - -// create a shuffled copy of a vec -fn shuffled(r : rand::rng, v : ~[T]) -> ~[T] { - let w = vec::to_mut(v); - shuffle(r, w); - vec::from_mut(w) // Shouldn't this happen automatically? -} - -// sample from a population without replacement -//fn sample(r : rand::rng, pop : ~[T], k : uint) -> ~[T] { fail!() } - -// Two ways to make a weighted choice. -// * weighted_choice is O(number of choices) time -// * weighted_vec is O(total weight) space -type weighted = { weight: uint, item: T }; -fn weighted_choice(r : rand::rng, v : ~[weighted]) -> T { - assert!(v.len() != 0u); - let total = 0u; - for {weight: weight, item: _} in v { - total += weight; - } - assert!(total >= 0u); - let chosen = under(r, total); - let so_far = 0u; - for {weight: weight, item: item} in v { - so_far += weight; - if so_far > chosen { - return item; - } - } - std::unreachable(); -} - -fn weighted_vec(v : ~[weighted]) -> ~[T] { - let r = ~[]; - for {weight: weight, item: item} in v { - let i = 0u; - while i < weight { - r.push(item); - i += 1u; - } - } - r -} - -fn main() -{ - let r = rand::mk_rng(); - - log(error, under(r, 5u)); - log(error, choice(r, ~[10, 20, 30])); - log(error, if unlikely(r, 5u) { "unlikely" } else { "likely" }); - - let mut a = ~[1, 2, 3]; - shuffle(r, a); - log(error, a); - - let i = 0u; - let v = ~[ - {weight:1u, item:"low"}, - {weight:8u, item:"middle"}, - {weight:1u, item:"high"} - ]; - let w = weighted_vec(v); - - while i < 1000u { - log(error, "Immed: " + weighted_choice(r, v)); - log(error, "Fast: " + choice(r, w)); - i += 1u; - } -} diff --git a/src/librustc/back/passes.rs b/src/librustc/back/passes.rs index 315bb5d63177..987c76dccb42 100644 --- a/src/librustc/back/passes.rs +++ b/src/librustc/back/passes.rs @@ -221,7 +221,7 @@ pub static analysis_passes : &'static [(&'static str, &'static str)] = &'static /** Transformation Passes */ pub static transform_passes : &'static [(&'static str, &'static str)] = &'static [ ("adce", "Aggressive Dead Code Elimination"), - ("always-inline", "Inliner for #[inline(always)] functions"), + ("always-inline", "Inliner for #[inline] functions"), ("argpromotion", "Promote 'by reference' arguments to scalars"), ("bb-vectorize", "Basic-Block Vectorization"), ("block-placement", "Profile Guided Basic Block Placement"), @@ -299,18 +299,27 @@ fn passes_exist() { let mut failed = ~[]; unsafe { llvm::LLVMInitializePasses(); } for analysis_passes.each() |&(name,_)| { - if !create_pass(name).is_some() { + let pass = create_pass(name); + if !pass.is_some() { failed.push(name); + } else { + unsafe { llvm::LLVMDestroyPass(pass.get()) } } } for transform_passes.each() |&(name,_)| { - if !create_pass(name).is_some() { + let pass = create_pass(name); + if !pass.is_some() { failed.push(name); + } else { + unsafe { llvm::LLVMDestroyPass(pass.get()) } } } for utility_passes.each() |&(name,_)| { - if !create_pass(name).is_some() { + let pass = create_pass(name); + if !pass.is_some() { failed.push(name); + } else { + unsafe { llvm::LLVMDestroyPass(pass.get()) } } } diff --git a/src/librustc/back/rpath.rs b/src/librustc/back/rpath.rs index 85fc0575170b..fd22a7e79c6e 100644 --- a/src/librustc/back/rpath.rs +++ b/src/librustc/back/rpath.rs @@ -77,6 +77,10 @@ fn get_rpaths(os: session::os, // crates they depend on. let rel_rpaths = get_rpaths_relative_to_output(os, output, libs); + // Make backup absolute paths to the libraries. Binaries can + // be moved as long as the crates they link against don't move. + let abs_rpaths = get_absolute_rpaths(libs); + // And a final backup rpath to the global library location. let fallback_rpaths = ~[get_install_prefix_rpath(target_triple)]; @@ -88,9 +92,11 @@ fn get_rpaths(os: session::os, } log_rpaths("relative", rel_rpaths); + log_rpaths("absolute", abs_rpaths); log_rpaths("fallback", fallback_rpaths); let mut rpaths = rel_rpaths; + rpaths.push_all(abs_rpaths); rpaths.push_all(fallback_rpaths); // Remove duplicates @@ -160,19 +166,14 @@ pub fn get_relative_to(abs1: &Path, abs2: &Path) -> Path { } } -#[cfg(stage0)] -pub fn get_install_prefix_rpath(target_triple: &str) -> Path { - let install_prefix = env!("CFG_PREFIX"); - - if install_prefix.is_empty() { - fail!("rustc compiled without CFG_PREFIX environment variable"); - } - - let tlib = filesearch::relative_target_lib_path(target_triple); - os::make_absolute(&Path(install_prefix).push_rel(&tlib)) +fn get_absolute_rpaths(libs: &[Path]) -> ~[Path] { + vec::map(libs, |a| get_absolute_rpath(a) ) +} + +pub fn get_absolute_rpath(lib: &Path) -> Path { + os::make_absolute(lib).dir_path() } -#[cfg(not(stage0))] pub fn get_install_prefix_rpath(target_triple: &str) -> Path { let install_prefix = env!("CFG_PREFIX"); @@ -198,15 +199,13 @@ pub fn minimize_rpaths(rpaths: &[Path]) -> ~[Path] { #[cfg(unix, test)] mod test { use core::prelude::*; - use core::os; - use core::str; // FIXME(#2119): the outer attribute should be #[cfg(unix, test)], then // these redundant #[cfg(test)] blocks can be removed #[cfg(test)] #[cfg(test)] - use back::rpath::{get_install_prefix_rpath}; + use back::rpath::{get_absolute_rpath, get_install_prefix_rpath}; use back::rpath::{get_relative_to, get_rpath_relative_to_output}; use back::rpath::{minimize_rpaths, rpaths_to_flags}; use driver::session; @@ -350,4 +349,14 @@ mod test { &Path("lib/libstd.so")); assert_eq!(res.to_str(), ~"@executable_path/../lib"); } + + #[test] + fn test_get_absolute_rpath() { + let res = get_absolute_rpath(&Path("lib/libstd.so")); + debug!("test_get_absolute_rpath: %s vs. %s", + res.to_str(), + os::make_absolute(&Path("lib")).to_str()); + + assert_eq!(res, os::make_absolute(&Path("lib"))); + } } diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index 73347f2b91d6..43b3397094b5 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -65,34 +65,24 @@ pub fn source_name(input: &input) -> @str { pub fn default_configuration(sess: Session, argv0: @str, input: &input) -> ast::crate_cfg { - let libc = match sess.targ_cfg.os { - session::os_win32 => @"msvcrt.dll", - session::os_macos => @"libc.dylib", - session::os_linux => @"libc.so.6", - session::os_android => @"libc.so", - session::os_freebsd => @"libc.so.7" - // _ { "libc.so" } + let (libc, tos) = match sess.targ_cfg.os { + session::os_win32 => (@"msvcrt.dll", @"win32"), + session::os_macos => (@"libc.dylib", @"macos"), + session::os_linux => (@"libc.so.6", @"linux"), + session::os_android => (@"libc.so", @"android"), + session::os_freebsd => (@"libc.so.7", @"freebsd") }; - let tos = match sess.targ_cfg.os { - session::os_win32 => @"win32", - session::os_macos => @"macos", - session::os_linux => @"linux", - session::os_android => @"android", - session::os_freebsd => @"freebsd" - // _ { "libc.so" } - }; - - let mk = attr::mk_name_value_item_str; // ARM is bi-endian, however using NDK seems to default // to little-endian unless a flag is provided. let (end,arch,wordsz) = match sess.targ_cfg.arch { - abi::X86 => (@"little",@"x86",@"32"), - abi::X86_64 => (@"little",@"x86_64",@"64"), - abi::Arm => (@"little",@"arm",@"32"), - abi::Mips => (@"big",@"mips",@"32") + abi::X86 => (@"little", @"x86", @"32"), + abi::X86_64 => (@"little", @"x86_64", @"64"), + abi::Arm => (@"little", @"arm", @"32"), + abi::Mips => (@"big", @"mips", @"32") }; + let mk = attr::mk_name_value_item_str; return ~[ // Target bindings. attr::mk_word_item(os::FAMILY.to_managed()), mk(@"target_os", tos), @@ -463,36 +453,38 @@ pub fn pretty_print_input(sess: Session, cfg: ast::crate_cfg, input: &input, } pub fn get_os(triple: &str) -> Option { - if triple.contains("win32") || - triple.contains("mingw32") { - Some(session::os_win32) - } else if triple.contains("darwin") { - Some(session::os_macos) - } else if triple.contains("android") { - Some(session::os_android) - } else if triple.contains("linux") { - Some(session::os_linux) - } else if triple.contains("freebsd") { - Some(session::os_freebsd) - } else { None } + for os_names.each |&(name, os)| { + if triple.contains(name) { return Some(os) } + } + None } +static os_names : &'static [(&'static str, session::os)] = &'static [ + ("mingw32", session::os_win32), + ("win32", session::os_win32), + ("darwin", session::os_macos), + ("android", session::os_android), + ("linux", session::os_linux), + ("freebsd", session::os_freebsd)]; pub fn get_arch(triple: &str) -> Option { - if triple.contains("i386") || - triple.contains("i486") || - triple.contains("i586") || - triple.contains("i686") || - triple.contains("i786") { - Some(abi::X86) - } else if triple.contains("x86_64") { - Some(abi::X86_64) - } else if triple.contains("arm") || - triple.contains("xscale") { - Some(abi::Arm) - } else if triple.contains("mips") { - Some(abi::Mips) - } else { None } + for architecture_abis.each |&(arch, abi)| { + if triple.contains(arch) { return Some(abi) } + } + None } +static architecture_abis : &'static [(&'static str, abi::Architecture)] = &'static [ + ("i386", abi::X86), + ("i486", abi::X86), + ("i586", abi::X86), + ("i686", abi::X86), + ("i786", abi::X86), + + ("x86_64", abi::X86_64), + + ("arm", abi::Arm), + ("xscale", abi::Arm), + + ("mips", abi::Mips)]; pub fn build_target_config(sopts: @session::options, demitter: diagnostic::Emitter) @@ -529,25 +521,6 @@ pub fn build_target_config(sopts: @session::options, return target_cfg; } -#[cfg(stage0)] -pub fn host_triple() -> ~str { - // Get the host triple out of the build environment. This ensures that our - // idea of the host triple is the same as for the set of libraries we've - // actually built. We can't just take LLVM's host triple because they - // normalize all ix86 architectures to i386. - // - // Instead of grabbing the host triple (for the current host), we grab (at - // compile time) the target triple that this rustc is built with and - // calling that (at runtime) the host triple. - let ht = env!("CFG_COMPILER_TRIPLE"); - return if ht != ~"" { - ht - } else { - fail!("rustc built without CFG_COMPILER_TRIPLE") - }; -} - -#[cfg(not(stage0))] pub fn host_triple() -> ~str { // Get the host triple out of the build environment. This ensures that our // idea of the host triple is the same as for the set of libraries we've diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs index 289bb4f63f59..5d5a5e736bce 100644 --- a/src/librustc/lib/llvm.rs +++ b/src/librustc/lib/llvm.rs @@ -224,13 +224,50 @@ pub type SectionIteratorRef = *SectionIterator_opaque; pub enum Pass_opaque {} pub type PassRef = *Pass_opaque; +pub mod debuginfo { + use super::{ValueRef}; + + pub enum DIBuilder_opaque {} + pub type DIBuilderRef = *DIBuilder_opaque; + + pub type DIDescriptor = ValueRef; + pub type DIScope = DIDescriptor; + pub type DILocation = DIDescriptor; + pub type DIFile = DIScope; + pub type DILexicalBlock = DIScope; + pub type DISubprogram = DIScope; + pub type DIType = DIDescriptor; + pub type DIBasicType = DIType; + pub type DIDerivedType = DIType; + pub type DICompositeType = DIDerivedType; + pub type DIVariable = DIDescriptor; + pub type DIArray = DIDescriptor; + pub type DISubrange = DIDescriptor; + + pub enum DIDescriptorFlags { + FlagPrivate = 1 << 0, + FlagProtected = 1 << 1, + FlagFwdDecl = 1 << 2, + FlagAppleBlock = 1 << 3, + FlagBlockByrefStruct = 1 << 4, + FlagVirtual = 1 << 5, + FlagArtificial = 1 << 6, + FlagExplicit = 1 << 7, + FlagPrototyped = 1 << 8, + FlagObjcClassComplete = 1 << 9, + FlagObjectPointer = 1 << 10, + FlagVector = 1 << 11, + FlagStaticMember = 1 << 12 + } +} + pub mod llvm { use super::{AtomicBinOp, AtomicOrdering, BasicBlockRef, ExecutionEngineRef}; use super::{Bool, BuilderRef, ContextRef, MemoryBufferRef, ModuleRef}; use super::{ObjectFileRef, Opcode, PassManagerRef, PassManagerBuilderRef}; use super::{SectionIteratorRef, TargetDataRef, TypeKind, TypeRef, UseRef}; - use super::{ValueRef,PassRef}; - + use super::{ValueRef, PassRef}; + use super::debuginfo::*; use core::libc::{c_char, c_int, c_longlong, c_ushort, c_uint, c_ulonglong}; #[link_args = "-Lrustllvm -lrustllvm"] @@ -929,6 +966,12 @@ pub mod llvm { #[fast_ffi] pub unsafe fn LLVMDeleteBasicBlock(BB: BasicBlockRef); + #[fast_ffi] + pub unsafe fn LLVMMoveBasicBlockAfter(BB: BasicBlockRef, MoveAfter: BasicBlockRef); + + #[fast_ffi] + pub unsafe fn LLVMMoveBasicBlockBefore(BB: BasicBlockRef, MoveBefore: BasicBlockRef); + /* Operations on instructions */ #[fast_ffi] pub unsafe fn LLVMGetInstructionParent(Inst: ValueRef) @@ -1641,6 +1684,9 @@ pub mod llvm { #[fast_ffi] pub unsafe fn LLVMCreatePass(PassName:*c_char) -> PassRef; + #[fast_ffi] + pub unsafe fn LLVMDestroyPass(P: PassRef); + /** Adds a verification pass. */ #[fast_ffi] pub unsafe fn LLVMAddVerifierPass(PM: PassManagerRef); @@ -1885,6 +1931,164 @@ pub mod llvm { AlignStack: Bool, Dialect: c_uint) -> ValueRef; + + #[fast_ffi] + pub unsafe fn LLVMDIBuilderCreate(M: ModuleRef) -> DIBuilderRef; + + #[fast_ffi] + pub unsafe fn LLVMDIBuilderDispose(Builder: DIBuilderRef); + + #[fast_ffi] + pub unsafe fn LLVMDIBuilderFinalize(Builder: DIBuilderRef); + + #[fast_ffi] + pub unsafe fn LLVMDIBuilderCreateCompileUnit( + Builder: DIBuilderRef, + Lang: c_uint, + File: *c_char, + Dir: *c_char, + Producer: *c_char, + isOptimized: bool, + Flags: *c_char, + RuntimeVer: c_uint, + SplitName: *c_char); + + #[fast_ffi] + pub unsafe fn LLVMDIBuilderCreateFile( + Builder: DIBuilderRef, + Filename: *c_char, + Directory: *c_char) -> DIFile; + + #[fast_ffi] + pub unsafe fn LLVMDIBuilderCreateSubroutineType( + Builder: DIBuilderRef, + File: DIFile, + ParameterTypes: DIArray) -> DICompositeType; + + #[fast_ffi] + pub unsafe fn LLVMDIBuilderCreateFunction( + Builder: DIBuilderRef, + Scope: DIDescriptor, + Name: *c_char, + LinkageName: *c_char, + File: DIFile, + LineNo: c_uint, + Ty: DIType, + isLocalToUnit: bool, + isDefinition: bool, + ScopeLine: c_uint, + Flags: c_uint, + isOptimized: bool, + Fn: ValueRef, + TParam: ValueRef, + Decl: ValueRef) -> DISubprogram; + + #[fast_ffi] + pub unsafe fn LLVMDIBuilderCreateBasicType( + Builder: DIBuilderRef, + Name: *c_char, + SizeInBits: c_ulonglong, + AlignInBits: c_ulonglong, + Encoding: c_uint) -> DIBasicType; + + #[fast_ffi] + pub unsafe fn LLVMDIBuilderCreatePointerType( + Builder: DIBuilderRef, + PointeeTy: DIType, + SizeInBits: c_ulonglong, + AlignInBits: c_ulonglong, + Name: *c_char) -> DIDerivedType; + + #[fast_ffi] + pub unsafe fn LLVMDIBuilderCreateStructType( + Builder: DIBuilderRef, + Scope: DIDescriptor, + Name: *c_char, + File: DIFile, + LineNumber: c_uint, + SizeInBits: c_ulonglong, + AlignInBits: c_ulonglong, + Flags: c_uint, + DerivedFrom: DIType, + Elements: DIArray, + RunTimeLang: c_uint, + VTableHolder: ValueRef) -> DICompositeType; + + #[fast_ffi] + pub unsafe fn LLVMDIBuilderCreateMemberType( + Builder: DIBuilderRef, + Scope: DIDescriptor, + Name: *c_char, + File: DIFile, + LineNo: c_uint, + SizeInBits: c_ulonglong, + AlignInBits: c_ulonglong, + OffsetInBits: c_ulonglong, + Flags: c_uint, + Ty: DIType) -> DIDerivedType; + + #[fast_ffi] + pub unsafe fn LLVMDIBuilderCreateLexicalBlock( + Builder: DIBuilderRef, + Scope: DIDescriptor, + File: DIFile, + Line: c_uint, + Col: c_uint) -> DILexicalBlock; + + #[fast_ffi] + pub unsafe fn LLVMDIBuilderCreateLocalVariable( + Builder: DIBuilderRef, + Tag: c_uint, + Scope: DIDescriptor, + Name: *c_char, + File: DIFile, + LineNo: c_uint, + Ty: DIType, + AlwaysPreserve: bool, + Flags: c_uint, + ArgNo: c_uint) -> DIVariable; + + #[fast_ffi] + pub unsafe fn LLVMDIBuilderCreateArrayType( + Builder: DIBuilderRef, + Size: c_ulonglong, + AlignInBits: c_ulonglong, + Ty: DIType, + Subscripts: DIArray) -> DIType; + + #[fast_ffi] + pub unsafe fn LLVMDIBuilderCreateVectorType( + Builder: DIBuilderRef, + Size: c_ulonglong, + AlignInBits: c_ulonglong, + Ty: DIType, + Subscripts: DIArray) -> DIType; + + #[fast_ffi] + pub unsafe fn LLVMDIBuilderGetOrCreateSubrange( + Builder: DIBuilderRef, + Lo: c_longlong, + Count: c_longlong) -> DISubrange; + + #[fast_ffi] + pub unsafe fn LLVMDIBuilderGetOrCreateArray( + Builder: DIBuilderRef, + Ptr: *DIDescriptor, + Count: c_uint) -> DIArray; + + #[fast_ffi] + pub unsafe fn LLVMDIBuilderInsertDeclareAtEnd( + Builder: DIBuilderRef, + Val: ValueRef, + VarInfo: DIVariable, + InsertAtEnd: BasicBlockRef) -> ValueRef; + + #[fast_ffi] + pub unsafe fn LLVMDIBuilderInsertDeclareBefore( + Builder: DIBuilderRef, + Val: ValueRef, + VarInfo: DIVariable, + InsertBefore: ValueRef) -> ValueRef; } } @@ -1988,9 +2192,7 @@ pub fn type_to_str_inner(names: @TypeNames, outer0: &[TypeRef], ty: TypeRef) let out_ty: TypeRef = llvm::LLVMGetReturnType(ty); let n_args = llvm::LLVMCountParamTypes(ty) as uint; let args = vec::from_elem(n_args, 0 as TypeRef); - unsafe { - llvm::LLVMGetParamTypes(ty, vec::raw::to_ptr(args)); - } + llvm::LLVMGetParamTypes(ty, vec::raw::to_ptr(args)); // See [Note at-str] return fmt!("fn(%s) -> %s", tys_str(names, outer, args), diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 110f686e5a66..5d5d7582b5f3 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -1184,7 +1184,7 @@ fn create_index(index: ~[entry]) -> for uint::range(0u, 256u) |_i| { buckets.push(@mut ~[]); }; for index.each |elt| { let h = elt.val.hash() as uint; - buckets[h % 256].push(*elt); + buckets[h % 256].push(copy *elt); } let mut buckets_frozen = ~[]; diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs index 5d9355053de9..585704381b69 100644 --- a/src/librustc/metadata/loader.rs +++ b/src/librustc/metadata/loader.rs @@ -204,35 +204,33 @@ fn get_metadata_section(os: os, let si = mk_section_iter(of.llof); while llvm::LLVMIsSectionIteratorAtEnd(of.llof, si.llsi) == False { let name_buf = llvm::LLVMGetSectionName(si.llsi); - let name = unsafe { str::raw::from_c_str(name_buf) }; + let name = str::raw::from_c_str(name_buf); debug!("get_metadata_section: name %s", name); if name == read_meta_section_name(os) { let cbuf = llvm::LLVMGetSectionContents(si.llsi); let csz = llvm::LLVMGetSectionSize(si.llsi) as uint; let mut found = None; - unsafe { - let cvbuf: *u8 = cast::transmute(cbuf); - let vlen = encoder::metadata_encoding_version.len(); - debug!("checking %u bytes of metadata-version stamp", - vlen); - let minsz = uint::min(vlen, csz); - let mut version_ok = false; - do vec::raw::buf_as_slice(cvbuf, minsz) |buf0| { - version_ok = (buf0 == - encoder::metadata_encoding_version); - } - if !version_ok { return None; } + let cvbuf: *u8 = cast::transmute(cbuf); + let vlen = encoder::metadata_encoding_version.len(); + debug!("checking %u bytes of metadata-version stamp", + vlen); + let minsz = uint::min(vlen, csz); + let mut version_ok = false; + do vec::raw::buf_as_slice(cvbuf, minsz) |buf0| { + version_ok = (buf0 == + encoder::metadata_encoding_version); + } + if !version_ok { return None; } - let cvbuf1 = ptr::offset(cvbuf, vlen); - debug!("inflating %u bytes of compressed metadata", - csz - vlen); - do vec::raw::buf_as_slice(cvbuf1, csz-vlen) |bytes| { - let inflated = flate::inflate_bytes(bytes); - found = Some(@(inflated)); - } - if found != None { - return found; - } + let cvbuf1 = ptr::offset(cvbuf, vlen); + debug!("inflating %u bytes of compressed metadata", + csz - vlen); + do vec::raw::buf_as_slice(cvbuf1, csz-vlen) |bytes| { + let inflated = flate::inflate_bytes(bytes); + found = Some(@(inflated)); + } + if found != None { + return found; } } llvm::LLVMMoveToNextSection(si.llsi); diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index e11367a7a7da..925b1f506d75 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -15,7 +15,6 @@ use cstore = metadata::cstore; use driver::session::Session; use e = metadata::encoder; use metadata::decoder; -use metadata::encoder; use metadata::tydecode; use metadata::tydecode::{DefIdSource, NominalType, TypeWithId, TypeParameter}; use metadata::tyencode; diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs index e384d35373e6..be87beba7784 100644 --- a/src/librustc/middle/borrowck/check_loans.rs +++ b/src/librustc/middle/borrowck/check_loans.rs @@ -82,7 +82,7 @@ impl<'self> CheckLoanCtxt<'self> { //! are issued for future scopes and thus they may have been //! *issued* but not yet be in effect. - for self.dfcx_loans.each_bit_on_entry(scope_id) |loan_index| { + for self.dfcx_loans.each_bit_on_entry_frozen(scope_id) |loan_index| { let loan = &self.all_loans[loan_index]; if !op(loan) { return false; @@ -134,7 +134,7 @@ impl<'self> CheckLoanCtxt<'self> { //! we encounter `scope_id`. let mut result = ~[]; - for self.dfcx_loans.each_gen_bit(scope_id) |loan_index| { + for self.dfcx_loans.each_gen_bit_frozen(scope_id) |loan_index| { result.push(loan_index); } return result; diff --git a/src/librustc/middle/borrowck/gather_loans/gather_moves.rs b/src/librustc/middle/borrowck/gather_loans/gather_moves.rs index ef911c9a808e..5431a0a29980 100644 --- a/src/librustc/middle/borrowck/gather_loans/gather_moves.rs +++ b/src/librustc/middle/borrowck/gather_loans/gather_moves.rs @@ -105,7 +105,8 @@ fn check_is_legal_to_move_from(bccx: @BorrowckCtxt, mc::cat_implicit_self(*) | mc::cat_copied_upvar(*) | mc::cat_deref(_, _, mc::region_ptr(*)) | - mc::cat_deref(_, _, mc::gc_ptr(*)) => { + mc::cat_deref(_, _, mc::gc_ptr(*)) | + mc::cat_deref(_, _, mc::unsafe_ptr(*)) => { bccx.span_err( cmt0.span, fmt!("cannot move out of %s", @@ -129,8 +130,7 @@ fn check_is_legal_to_move_from(bccx: @BorrowckCtxt, mc::cat_rvalue(*) | mc::cat_local(*) | mc::cat_arg(*) | - mc::cat_self(*) | - mc::cat_deref(_, _, mc::unsafe_ptr(*)) => { + mc::cat_self(*) => { true } diff --git a/src/librustc/middle/borrowck/mod.rs b/src/librustc/middle/borrowck/mod.rs index 95e26e9e42fa..d7186ad93335 100644 --- a/src/librustc/middle/borrowck/mod.rs +++ b/src/librustc/middle/borrowck/mod.rs @@ -775,17 +775,17 @@ impl BorrowckCtxt { } impl DataFlowOperator for LoanDataFlowOperator { - #[inline(always)] + #[inline] fn initial_value(&self) -> bool { false // no loans in scope by default } - #[inline(always)] + #[inline] fn join(&self, succ: uint, pred: uint) -> uint { succ | pred // loans from both preds are in scope } - #[inline(always)] + #[inline] fn walk_closures(&self) -> bool { true } diff --git a/src/librustc/middle/borrowck/move_data.rs b/src/librustc/middle/borrowck/move_data.rs index bd560fca9854..3b1c451d0a6e 100644 --- a/src/librustc/middle/borrowck/move_data.rs +++ b/src/librustc/middle/borrowck/move_data.rs @@ -504,7 +504,7 @@ impl FlowedMoveData { let opt_loan_path_index = self.move_data.existing_move_path(loan_path); - for self.dfcx_moves.each_bit_on_entry(id) |index| { + for self.dfcx_moves.each_bit_on_entry_frozen(id) |index| { let move = &self.move_data.moves[index]; let moved_path = move.path; if base_indices.contains(&moved_path) { @@ -560,7 +560,7 @@ impl FlowedMoveData { } }; - for self.dfcx_assign.each_bit_on_entry(id) |index| { + for self.dfcx_assign.each_bit_on_entry_frozen(id) |index| { let assignment = &self.move_data.var_assignments[index]; if assignment.path == loan_path_index && !f(assignment) { return false; @@ -571,34 +571,34 @@ impl FlowedMoveData { } impl DataFlowOperator for MoveDataFlowOperator { - #[inline(always)] + #[inline] fn initial_value(&self) -> bool { false // no loans in scope by default } - #[inline(always)] + #[inline] fn join(&self, succ: uint, pred: uint) -> uint { succ | pred // moves from both preds are in scope } - #[inline(always)] + #[inline] fn walk_closures(&self) -> bool { true } } impl DataFlowOperator for AssignDataFlowOperator { - #[inline(always)] + #[inline] fn initial_value(&self) -> bool { false // no assignments in scope by default } - #[inline(always)] + #[inline] fn join(&self, succ: uint, pred: uint) -> uint { succ | pred // moves from both preds are in scope } - #[inline(always)] + #[inline] fn walk_closures(&self) -> bool { true } diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs index 8037bacd3e72..b4942fba05da 100644 --- a/src/librustc/middle/dataflow.rs +++ b/src/librustc/middle/dataflow.rs @@ -22,6 +22,7 @@ use core::cast; use core::io; use core::uint; use core::vec; +use core::hashmap::HashMap; use syntax::ast; use syntax::ast_util; use syntax::ast_util::id_range; @@ -37,9 +38,6 @@ pub struct DataFlowContext { /// the data flow operator priv oper: O, - /// range of ids that appear within the item in question - priv id_range: id_range, - /// number of bits to propagate per id priv bits_per_id: uint, @@ -47,6 +45,9 @@ pub struct DataFlowContext { /// equal to bits_per_id/uint::bits rounded up. priv words_per_id: uint, + // mapping from node to bitset index. + priv nodeid_to_bitset: HashMap, + // Bit sets per id. The following three fields (`gens`, `kills`, // and `on_entry`) all have the same structure. For each id in // `id_range`, there is a range of words equal to `words_per_id`. @@ -108,19 +109,17 @@ impl DataFlowContext { debug!("DataFlowContext::new(id_range=%?, bits_per_id=%?, words_per_id=%?)", id_range, bits_per_id, words_per_id); - let len = (id_range.max - id_range.min) as uint * words_per_id; - let gens = vec::from_elem(len, 0); - let kills = vec::from_elem(len, 0); - let elem = if oper.initial_value() {uint::max_value} else {0}; - let on_entry = vec::from_elem(len, elem); + let gens = ~[]; + let kills = ~[]; + let on_entry = ~[]; DataFlowContext { tcx: tcx, method_map: method_map, words_per_id: words_per_id, + nodeid_to_bitset: HashMap::new(), bits_per_id: bits_per_id, oper: oper, - id_range: id_range, gens: gens, kills: kills, on_entry: on_entry @@ -149,7 +148,7 @@ impl DataFlowContext { } } - fn apply_gen_kill(&self, id: ast::node_id, bits: &mut [uint]) { + fn apply_gen_kill(&mut self, id: ast::node_id, bits: &mut [uint]) { //! Applies the gen and kill sets for `id` to `bits` debug!("apply_gen_kill(id=%?, bits=%s) [before]", @@ -164,7 +163,7 @@ impl DataFlowContext { id, mut_bits_to_str(bits)); } - fn apply_kill(&self, id: ast::node_id, bits: &mut [uint]) { + fn apply_kill(&mut self, id: ast::node_id, bits: &mut [uint]) { debug!("apply_kill(id=%?, bits=%s) [before]", id, mut_bits_to_str(bits)); let (start, end) = self.compute_id_range(id); @@ -174,18 +173,56 @@ impl DataFlowContext { id, mut_bits_to_str(bits)); } - fn compute_id_range(&self, absolute_id: ast::node_id) -> (uint, uint) { - assert!(absolute_id >= self.id_range.min); - assert!(absolute_id < self.id_range.max); - - let relative_id = absolute_id - self.id_range.min; - let start = (relative_id as uint) * self.words_per_id; + fn compute_id_range_frozen(&self, id: ast::node_id) -> (uint, uint) { + let n = *self.nodeid_to_bitset.get(&id); + let start = n * self.words_per_id; let end = start + self.words_per_id; (start, end) } + fn compute_id_range(&mut self, id: ast::node_id) -> (uint, uint) { + let mut expanded = false; + let len = self.nodeid_to_bitset.len(); + let n = do self.nodeid_to_bitset.find_or_insert_with(id) |_| { + expanded = true; + len + }; + if expanded { + let entry = if self.oper.initial_value() { uint::max_value } else {0}; + for self.words_per_id.times { + self.gens.push(0); + self.kills.push(0); + self.on_entry.push(entry); + } + } + let start = *n * self.words_per_id; + let end = start + self.words_per_id; - pub fn each_bit_on_entry(&self, + assert!(start < self.gens.len()); + assert!(end <= self.gens.len()); + assert!(self.gens.len() == self.kills.len()); + assert!(self.gens.len() == self.on_entry.len()); + + (start, end) + } + + + pub fn each_bit_on_entry_frozen(&self, + id: ast::node_id, + f: &fn(uint) -> bool) -> bool { + //! Iterates through each bit that is set on entry to `id`. + //! Only useful after `propagate()` has been called. + if !self.nodeid_to_bitset.contains_key(&id) { + return true; + } + let (start, end) = self.compute_id_range_frozen(id); + let on_entry = vec::slice(self.on_entry, start, end); + debug!("each_bit_on_entry_frozen(id=%?, on_entry=%s)", + id, bits_to_str(on_entry)); + self.each_bit(on_entry, f) + } + + pub fn each_bit_on_entry(&mut self, id: ast::node_id, f: &fn(uint) -> bool) -> bool { //! Iterates through each bit that is set on entry to `id`. @@ -198,7 +235,7 @@ impl DataFlowContext { self.each_bit(on_entry, f) } - pub fn each_gen_bit(&self, + pub fn each_gen_bit(&mut self, id: ast::node_id, f: &fn(uint) -> bool) -> bool { //! Iterates through each bit in the gen set for `id`. @@ -210,6 +247,20 @@ impl DataFlowContext { self.each_bit(gens, f) } + pub fn each_gen_bit_frozen(&self, + id: ast::node_id, + f: &fn(uint) -> bool) -> bool { + //! Iterates through each bit in the gen set for `id`. + if !self.nodeid_to_bitset.contains_key(&id) { + return true; + } + let (start, end) = self.compute_id_range_frozen(id); + let gens = vec::slice(self.gens, start, end); + debug!("each_gen_bit(id=%?, gens=%s)", + id, bits_to_str(gens)); + self.each_bit(gens, f) + } + fn each_bit(&self, words: &[uint], f: &fn(uint) -> bool) -> bool { @@ -285,8 +336,8 @@ impl DataFlowContext { pprust::node_pat(ps, pat) => (ps, pat.id) }; - if id >= self.id_range.min || id < self.id_range.max { - let (start, end) = self.compute_id_range(id); + if self.nodeid_to_bitset.contains_key(&id) { + let (start, end) = self.compute_id_range_frozen(id); let on_entry = vec::slice(self.on_entry, start, end); let entry_str = bits_to_str(on_entry); @@ -965,7 +1016,7 @@ fn join_bits(oper: &O, bitwise(out_vec, in_vec, |a, b| oper.join(a, b)) } -#[inline(always)] +#[inline] fn bitwise(out_vec: &mut [uint], in_vec: &[uint], op: &fn(uint, uint) -> uint) -> bool { diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 1c335ee40842..08cba4d51cd3 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -749,11 +749,7 @@ impl Liveness { None => { // Vanilla 'break' or 'loop', so use the enclosing // loop scope - let len = { // FIXME(#5074) stage0 - let loop_scope = &mut *self.loop_scope; - loop_scope.len() - }; - if len == 0 { + if self.loop_scope.len() == 0 { self.tcx.sess.span_bug(sp, "break outside loop"); } else { // FIXME(#5275): this shouldn't have to be a method... diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 2803608567d2..3e656b3e5940 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -4845,7 +4845,7 @@ impl Resolver { let mut smallest = 0; for maybes.eachi |i, &other| { - values[i] = str::levdistance(name, other); + values[i] = name.lev_distance(other); if values[i] <= values[smallest] { smallest = i; diff --git a/src/librustc/middle/trans/adt.rs b/src/librustc/middle/trans/adt.rs index ad07f41f8c30..0976407b0bd0 100644 --- a/src/librustc/middle/trans/adt.rs +++ b/src/librustc/middle/trans/adt.rs @@ -47,7 +47,6 @@ use core::container::Map; use core::libc::c_ulonglong; use core::option::{Option, Some, None}; -use core::str; use core::vec; use lib::llvm::{ValueRef, TypeRef, True, IntEQ, IntNE}; @@ -165,7 +164,7 @@ fn represent_type_uncached(cx: &mut CrateContext, t: ty::t) -> Repr { if cases.all(|c| c.tys.len() == 0) { // All bodies empty -> intlike let discrs = cases.map(|c| c.discr); - return CEnum(discrs.min(), discrs.max()); + return CEnum(*discrs.iter().min().unwrap(), *discrs.iter().max().unwrap()); } if cases.len() == 1 { @@ -509,7 +508,7 @@ pub fn trans_const(ccx: &mut CrateContext, r: &Repr, discr: int, } General(ref cases) => { let case = &cases[discr as uint]; - let max_sz = cases.map(|s| s.size).max(); + let max_sz = cases.iter().transform(|x| x.size).max().unwrap(); let discr_ty = C_int(ccx, discr); let contents = build_const_struct(ccx, case, ~[discr_ty] + vals); @@ -577,7 +576,7 @@ fn padding(size: u64) -> ValueRef { } // XXX this utility routine should be somewhere more general -#[inline(always)] +#[inline] fn roundup(x: u64, a: u64) -> u64 { ((x + (a - 1)) / a) * a } /// Get the discriminant of a constant value. (Not currently used.) diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index e2073d21fe39..d7d21707f40f 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -71,7 +71,6 @@ use core::libc::c_uint; use core::str; use core::uint; use core::vec; -use core::local_data; use extra::time; use syntax::ast::ident; use syntax::ast_map::{path, path_elt_to_str, path_name}; @@ -1318,26 +1317,38 @@ pub fn cleanup_and_leave(bcx: block, match cur.kind { block_scope(inf) if !inf.empty_cleanups() => { - let (sub_cx, inf_cleanups) = { - let inf = &mut *inf; // FIXME(#5074) workaround stage0 + let (sub_cx, dest, inf_cleanups) = { + let inf = &mut *inf; + let mut skip = 0; + let mut dest = None; { - let r = vec::find((*inf).cleanup_paths, |cp| cp.target == leave); + let r = vec::rfind((*inf).cleanup_paths, |cp| cp.target == leave); for r.iter().advance |cp| { - Br(bcx, cp.dest); - return; + if cp.size == inf.cleanups.len() { + Br(bcx, cp.dest); + return; + } + + skip = cp.size; + dest = Some(cp.dest); } } let sub_cx = sub_block(bcx, "cleanup"); Br(bcx, sub_cx.llbb); inf.cleanup_paths.push(cleanup_path { target: leave, + size: inf.cleanups.len(), dest: sub_cx.llbb }); - (sub_cx, copy inf.cleanups) + (sub_cx, dest, inf.cleanups.tailn(skip).to_owned()) }; bcx = trans_block_cleanups_(sub_cx, inf_cleanups, is_lpad); + for dest.iter().advance |&dest| { + Br(bcx, dest); + return; + } } _ => () } @@ -1897,6 +1908,12 @@ pub fn trans_closure(ccx: @mut CrateContext, finish(bcx); cleanup_and_Br(bcx, bcx_top, fcx.llreturn); + // Put return block after all other blocks. + // This somewhat improves single-stepping experience in debugger. + unsafe { + llvm::LLVMMoveBasicBlockAfter(fcx.llreturn, bcx.llbb); + } + // Insert the mandatory first few basic blocks before lltop. finish_fn(fcx, lltop); } @@ -3033,7 +3050,7 @@ pub fn write_metadata(cx: &mut CrateContext, crate: &ast::crate) { // Writes the current ABI version into the crate. pub fn write_abi_version(ccx: &mut CrateContext) { - mk_global(ccx, ~"rust_abi_version", C_uint(ccx, abi::abi_version), + mk_global(ccx, "rust_abi_version", C_uint(ccx, abi::abi_version), false); } @@ -3091,6 +3108,9 @@ pub fn trans_crate(sess: session::Session, fill_crate_map(ccx, ccx.crate_map); glue::emit_tydescs(ccx); write_abi_version(ccx); + if ccx.sess.opts.debuginfo { + debuginfo::finalize(ccx); + } // Translate the metadata. write_metadata(ccx, crate); @@ -3120,4 +3140,3 @@ pub fn trans_crate(sess: session::Session, return (llcx, llmod, link_meta); } - diff --git a/src/librustc/middle/trans/build.rs b/src/librustc/middle/trans/build.rs index 604cd3d2ba66..a55e89747f5b 100644 --- a/src/librustc/middle/trans/build.rs +++ b/src/librustc/middle/trans/build.rs @@ -618,13 +618,11 @@ pub fn InBoundsGEP(cx: block, Pointer: ValueRef, Indices: &[ValueRef]) -> ValueRef { unsafe { if cx.unreachable { return llvm::LLVMGetUndef(T_ptr(T_nil())); } - unsafe { - count_insn(cx, "inboundsgep"); + count_insn(cx, "inboundsgep"); return llvm::LLVMBuildInBoundsGEP(B(cx), Pointer, vec::raw::to_ptr(Indices), Indices.len() as c_uint, noname()); - } } } @@ -1072,11 +1070,9 @@ pub fn Trap(cx: block) { }); assert!((T as int != 0)); let Args: ~[ValueRef] = ~[]; - unsafe { - count_insn(cx, "trap"); - llvm::LLVMBuildCall(b, T, vec::raw::to_ptr(Args), - Args.len() as c_uint, noname()); - } + count_insn(cx, "trap"); + llvm::LLVMBuildCall(b, T, vec::raw::to_ptr(Args), + Args.len() as c_uint, noname()); } } diff --git a/src/librustc/middle/trans/closure.rs b/src/librustc/middle/trans/closure.rs index 1440d3856f09..c368ab5c9bdf 100644 --- a/src/librustc/middle/trans/closure.rs +++ b/src/librustc/middle/trans/closure.rs @@ -553,7 +553,7 @@ pub fn make_opaque_cbox_drop_glue( ast::BorrowedSigil => bcx, ast::ManagedSigil => { glue::decr_refcnt_maybe_free( - bcx, Load(bcx, cboxptr), + bcx, Load(bcx, cboxptr), Some(cboxptr), ty::mk_opaque_closure_ptr(bcx.tcx(), sigil)) } ast::OwnedSigil => { diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index f5919ca2586f..ff98e5a177f2 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -325,11 +325,17 @@ pub enum cleanup { // target: none means the path ends in an resume instruction pub struct cleanup_path { target: Option, + size: uint, dest: BasicBlockRef } -pub fn scope_clean_changed(scope_info: &mut scope_info) { - if scope_info.cleanup_paths.len() > 0u { scope_info.cleanup_paths = ~[]; } +pub fn shrink_scope_clean(scope_info: &mut scope_info, size: uint) { + scope_info.landing_pad = None; + scope_info.cleanup_paths = scope_info.cleanup_paths.iter() + .take_while(|&cu| cu.size <= size).transform(|&x|x).collect(); +} + +pub fn grow_scope_clean(scope_info: &mut scope_info) { scope_info.landing_pad = None; } @@ -374,7 +380,7 @@ pub fn add_clean(bcx: block, val: ValueRef, t: ty::t) { scope_info.cleanups.push( clean(|a| glue::drop_ty_root(a, root, rooted, t), cleanup_type)); - scope_clean_changed(scope_info); + grow_scope_clean(scope_info); } } @@ -388,7 +394,7 @@ pub fn add_clean_temp_immediate(cx: block, val: ValueRef, ty: ty::t) { scope_info.cleanups.push( clean_temp(val, |a| glue::drop_ty_immediate(a, val, ty), cleanup_type)); - scope_clean_changed(scope_info); + grow_scope_clean(scope_info); } } pub fn add_clean_temp_mem(bcx: block, val: ValueRef, t: ty::t) { @@ -402,7 +408,7 @@ pub fn add_clean_temp_mem(bcx: block, val: ValueRef, t: ty::t) { scope_info.cleanups.push( clean_temp(val, |a| glue::drop_ty_root(a, root, rooted, t), cleanup_type)); - scope_clean_changed(scope_info); + grow_scope_clean(scope_info); } } pub fn add_clean_return_to_mut(bcx: block, @@ -434,7 +440,7 @@ pub fn add_clean_return_to_mut(bcx: block, filename_val, line_val), normal_exit_only)); - scope_clean_changed(scope_info); + grow_scope_clean(scope_info); } } pub fn add_clean_free(cx: block, ptr: ValueRef, heap: heap) { @@ -451,7 +457,7 @@ pub fn add_clean_free(cx: block, ptr: ValueRef, heap: heap) { do in_scope_cx(cx) |scope_info| { scope_info.cleanups.push(clean_temp(ptr, free_fn, normal_exit_and_unwind)); - scope_clean_changed(scope_info); + grow_scope_clean(scope_info); } } @@ -474,7 +480,7 @@ pub fn revoke_clean(cx: block, val: ValueRef) { vec::slice(scope_info.cleanups, *i + 1u, scope_info.cleanups.len())); - scope_clean_changed(scope_info); + shrink_scope_clean(scope_info, *i); } } } diff --git a/src/librustc/middle/trans/context.rs b/src/librustc/middle/trans/context.rs index 75d7aaa88a6d..d6c7472424f7 100644 --- a/src/librustc/middle/trans/context.rs +++ b/src/librustc/middle/trans/context.rs @@ -148,7 +148,7 @@ impl CrateContext { lib::llvm::associate_type(tn, @"tydesc", tydesc_type); let crate_map = decl_crate_map(sess, link_meta, llmod); let dbg_cx = if sess.opts.debuginfo { - Some(debuginfo::mk_ctxt(name.to_owned())) + Some(debuginfo::DebugContext::new(llmod, name.to_owned())) } else { None }; @@ -211,9 +211,7 @@ impl CrateContext { int_type: int_type, float_type: float_type, opaque_vec_type: T_opaque_vec(targ_cfg), - builder: BuilderRef_res(unsafe { - llvm::LLVMCreateBuilderInContext(llcx) - }), + builder: BuilderRef_res(llvm::LLVMCreateBuilderInContext(llcx)), shape_cx: mk_ctxt(llmod), crate_map: crate_map, uses_gc: false, diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index 7a8ebb4abfdd..269451b13070 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -11,9 +11,9 @@ use core::prelude::*; use driver::session; -use lib::llvm::ValueRef; use lib::llvm::llvm; -use middle::trans::context::task_llcx; +use lib::llvm::{ValueRef, ModuleRef, ContextRef}; +use lib::llvm::debuginfo::*; use middle::trans::common::*; use middle::trans::machine; use middle::trans::type_of; @@ -21,21 +21,18 @@ use middle::trans; use middle::ty; use util::ppaux::ty_to_str; -use core::cast; use core::hashmap::HashMap; use core::libc; -use core::option; +use core::libc::c_uint; +use core::cmp; use core::ptr; -use core::str; +use core::str::as_c_str; use core::sys; use core::vec; use syntax::codemap::span; use syntax::{ast, codemap, ast_util, ast_map}; -static LLVMDebugVersion: int = (9 << 16); - static DW_LANG_RUST: int = 0x9000; -static DW_VIRTUALITY_none: int = 0; static CompileUnitTag: int = 17; static FileDescriptorTag: int = 41; @@ -59,302 +56,169 @@ static DW_ATE_signed_char: int = 0x06; static DW_ATE_unsigned: int = 0x07; static DW_ATE_unsigned_char: int = 0x08; -fn llstr(s: &str) -> ValueRef { - do str::as_c_str(s) |sbuf| { - unsafe { - llvm::LLVMMDStringInContext(task_llcx(), - sbuf, - s.len() as libc::c_uint) - } - } -} -fn lltag(lltag: int) -> ValueRef { - lli32(LLVMDebugVersion | lltag) -} -fn lli32(val: int) -> ValueRef { - C_i32(val as i32) -} -fn lli64(val: int) -> ValueRef { - C_i64(val as i64) -} -fn lli1(bval: bool) -> ValueRef { - C_i1(bval) -} -fn llmdnode(elems: &[ValueRef]) -> ValueRef { - unsafe { - llvm::LLVMMDNodeInContext(task_llcx(), - vec::raw::to_ptr(elems), - elems.len() as libc::c_uint) - } -} -fn llunused() -> ValueRef { - lli32(0x0) -} -fn llnull() -> ValueRef { - unsafe { - cast::transmute(ptr::null::()) - } -} - -fn add_named_metadata(cx: &CrateContext, name: ~str, val: ValueRef) { - str::as_c_str(name, |sbuf| { - unsafe { - llvm::LLVMAddNamedMetadataOperand(cx.llmod, sbuf, val) - } - }) -} - //////////////// pub struct DebugContext { - llmetadata: metadata_cache, names: namegen, - crate_file: ~str + crate_file: ~str, + llcontext: ContextRef, + builder: DIBuilderRef, + curr_loc: (uint, uint), + created_files: HashMap<~str, DIFile>, + created_functions: HashMap, + created_blocks: HashMap, + created_types: HashMap } -pub fn mk_ctxt(crate: ~str) -> DebugContext { - DebugContext { - llmetadata: @mut HashMap::new(), - names: new_namegen(), - crate_file: crate +impl DebugContext { + pub fn new(llmod: ModuleRef, crate: ~str) -> DebugContext { + debug!("DebugContext::new"); + let builder = unsafe { llvm::LLVMDIBuilderCreate(llmod) }; + // DIBuilder inherits context from the module, so we'd better use the same one + let llcontext = unsafe { llvm::LLVMGetModuleContext(llmod) }; + return DebugContext { + names: new_namegen(), + crate_file: crate, + llcontext: llcontext, + builder: builder, + curr_loc: (0, 0), + created_files: HashMap::new(), + created_functions: HashMap::new(), + created_blocks: HashMap::new(), + created_types: HashMap::new(), + }; } } -fn update_cache(cache: metadata_cache, mdtag: int, val: debug_metadata) { - let mut existing = match cache.pop(&mdtag) { - Some(arr) => arr, None => ~[] - }; - existing.push(val); - cache.insert(mdtag, existing); +#[inline] +fn dbg_cx<'a>(cx: &'a mut CrateContext) -> &'a mut DebugContext { + cx.dbg_cx.get_mut_ref() } -struct Metadata { - node: ValueRef, - data: T +#[inline] +fn DIB(cx: &CrateContext) -> DIBuilderRef { + cx.dbg_cx.get_ref().builder } -struct FileMetadata { - path: ~str -} -struct CompileUnitMetadata { - name: ~str -} -struct SubProgramMetadata { - id: ast::node_id -} -struct LocalVarMetadata { - id: ast::node_id -} -struct TyDescMetadata { - hash: uint -} -struct BlockMetadata { - start: codemap::Loc, - end: codemap::Loc -} -struct ArgumentMetadata { - id: ast::node_id -} -struct RetvalMetadata { - id: ast::node_id -} - -type metadata_cache = @mut HashMap; - -enum debug_metadata { - file_metadata(@Metadata), - compile_unit_metadata(@Metadata), - subprogram_metadata(@Metadata), - local_var_metadata(@Metadata), - tydesc_metadata(@Metadata), - block_metadata(@Metadata), - argument_metadata(@Metadata), - retval_metadata(@Metadata), -} - -fn cast_safely(val: T) -> U { +/// Create any deferred debug metadata nodes +pub fn finalize(cx: @mut CrateContext) { + debug!("finalize"); + create_compile_unit(cx); unsafe { - let val2 = val; - return cast::transmute(val2); - } -} - -fn md_from_metadata(val: debug_metadata) -> T { - match val { - file_metadata(md) => cast_safely(md), - compile_unit_metadata(md) => cast_safely(md), - subprogram_metadata(md) => cast_safely(md), - local_var_metadata(md) => cast_safely(md), - tydesc_metadata(md) => cast_safely(md), - block_metadata(md) => cast_safely(md), - argument_metadata(md) => cast_safely(md), - retval_metadata(md) => cast_safely(md) - } -} - -fn cached_metadata(cache: metadata_cache, - mdtag: int, - eq_fn: &fn(md: T) -> bool) - -> Option { - if cache.contains_key(&mdtag) { - let items = cache.get(&mdtag); - for items.each |item| { - let md: T = md_from_metadata::(*item); - if eq_fn(md) { - return option::Some(md); - } - } - } - return option::None; -} - -fn create_compile_unit(cx: &mut CrateContext) -> @Metadata { - let cache = get_cache(cx); - let crate_name = /*bad*/copy (/*bad*/copy cx.dbg_cx).get().crate_file; - let tg = CompileUnitTag; - match cached_metadata::<@Metadata>(cache, tg, - |md| md.data.name == crate_name) { - option::Some(md) => return md, - option::None => () - } - - let (_, work_dir) = get_file_path_and_dir( - cx.sess.working_dir.to_str(), crate_name); - let unit_metadata = ~[lltag(tg), - llunused(), - lli32(DW_LANG_RUST), - llstr(crate_name), - llstr(work_dir), - llstr(env!("CFG_VERSION")), - lli1(true), // deprecated: main compile unit - lli1(cx.sess.opts.optimize != session::No), - llstr(""), // flags (???) - lli32(0) // runtime version (???) - ]; - let unit_node = llmdnode(unit_metadata); - add_named_metadata(cx, ~"llvm.dbg.cu", unit_node); - let mdval = @Metadata { - node: unit_node, - data: CompileUnitMetadata { - name: crate_name - } + llvm::LLVMDIBuilderFinalize(DIB(cx)); + llvm::LLVMDIBuilderDispose(DIB(cx)); }; - update_cache(cache, tg, compile_unit_metadata(mdval)); - - return mdval; } -fn get_cache(cx: &CrateContext) -> metadata_cache { - cx.dbg_cx.get_ref().llmetadata +fn create_DIArray(builder: DIBuilderRef, arr: &[DIDescriptor]) -> DIArray { + return unsafe { + llvm::LLVMDIBuilderGetOrCreateArray(builder, vec::raw::to_ptr(arr), arr.len() as u32) + }; } -fn get_file_path_and_dir(work_dir: &str, full_path: &str) -> (~str, ~str) { - (if full_path.starts_with(work_dir) { - full_path.slice(work_dir.len() + 1u, - full_path.len()).to_owned() - } else { - full_path.to_owned() - }, work_dir.to_owned()) +fn create_compile_unit(cx: @mut CrateContext) { + let dcx = dbg_cx(cx); + let crate_name: &str = dcx.crate_file; + let work_dir = cx.sess.working_dir.to_str(); + let producer = fmt!("rustc version %s", env!("CFG_VERSION")); + + do as_c_str(crate_name) |crate_name| { + do as_c_str(work_dir) |work_dir| { + do as_c_str(producer) |producer| { + do as_c_str("") |flags| { + do as_c_str("") |split_name| { unsafe { + llvm::LLVMDIBuilderCreateCompileUnit(dcx.builder, + DW_LANG_RUST as c_uint, crate_name, work_dir, producer, + cx.sess.opts.optimize != session::No, + flags, 0, split_name); + }}}}}}; } -fn create_file(cx: &mut CrateContext, full_path: ~str) - -> @Metadata { - let cache = get_cache(cx);; - let tg = FileDescriptorTag; - match cached_metadata::<@Metadata>( - cache, tg, |md| md.data.path == full_path) { - option::Some(md) => return md, - option::None => () +fn create_file(cx: @mut CrateContext, full_path: &str) -> DIFile { + match dbg_cx(cx).created_files.find_equiv(&full_path) { + Some(file_md) => return *file_md, + None => () } - let (file_path, work_dir) = - get_file_path_and_dir(cx.sess.working_dir.to_str(), - full_path); - let unit_node = create_compile_unit(cx).node; - let file_md = ~[lltag(tg), - llstr(file_path), - llstr(work_dir), - unit_node]; - let val = llmdnode(file_md); - let mdval = @Metadata { - node: val, - data: FileMetadata { - path: full_path - } - }; - update_cache(cache, tg, file_metadata(mdval)); - return mdval; + debug!("create_file: %s", full_path); + + let work_dir = cx.sess.working_dir.to_str(); + let file_name = + if full_path.starts_with(work_dir) { + full_path.slice(work_dir.len() + 1u, full_path.len()) + } else { + full_path + }; + + let file_md = + do as_c_str(file_name) |file_name| { + do as_c_str(work_dir) |work_dir| { unsafe { + llvm::LLVMDIBuilderCreateFile(DIB(cx), file_name, work_dir) + }}}; + + dbg_cx(cx).created_files.insert(full_path.to_owned(), file_md); + return file_md; } -fn line_from_span(cm: @codemap::CodeMap, sp: span) -> uint { - cm.lookup_char_pos(sp.lo).line +/// Return codemap::Loc corresponding to the beginning of the span +fn span_start(cx: &CrateContext, span: span) -> codemap::Loc { + return cx.sess.codemap.lookup_char_pos(span.lo); } -fn create_block(mut cx: block) -> @Metadata { - let cache = get_cache(cx.ccx()); - while cx.node_info.is_none() { - match cx.parent { - Some(b) => cx = b, +fn create_block(bcx: block) -> DILexicalBlock { + let mut bcx = bcx; + let cx = bcx.ccx(); + + while bcx.node_info.is_none() { + match bcx.parent { + Some(b) => bcx = b, None => fail!() } } - let sp = cx.node_info.get().span; + let span = bcx.node_info.get().span; + let id = bcx.node_info.get().id; - let start = cx.sess().codemap.lookup_char_pos(sp.lo); - let fname = /*bad*/copy start.file.name; - let end = cx.sess().codemap.lookup_char_pos(sp.hi); - let tg = LexicalBlockTag; - /*match cached_metadata::<@Metadata>( - cache, tg, - {|md| start == md.data.start && end == md.data.end}) { - option::Some(md) { return md; } - option::None {} - }*/ - - let parent = match cx.parent { - None => create_function(cx.fcx).node, - Some(bcx) => create_block(bcx).node - }; - let file_node = create_file(cx.ccx(), /* bad */ fname.to_owned()); - let unique_id = match cache.find(&LexicalBlockTag) { - option::Some(v) => v.len() as int, - option::None => 0 - }; - let lldata = ~[lltag(tg), - parent, - lli32(start.line.to_int()), - lli32(start.col.to_int()), - file_node.node, - lli32(unique_id) - ]; - let val = llmdnode(lldata); - let mdval = @Metadata { - node: val, - data: BlockMetadata { - start: start, - end: end - } - }; - //update_cache(cache, tg, block_metadata(mdval)); - return mdval; -} - -fn size_and_align_of(cx: &mut CrateContext, t: ty::t) -> (int, int) { - let llty = type_of::type_of(cx, t); - (machine::llsize_of_real(cx, llty) as int, - machine::llalign_of_pref(cx, llty) as int) -} - -fn create_basic_type(cx: &mut CrateContext, t: ty::t, span: span) - -> @Metadata { - let cache = get_cache(cx); - let tg = BasicTypeDescriptorTag; - match cached_metadata::<@Metadata>( - cache, tg, |md| ty::type_id(t) == md.data.hash) { - option::Some(md) => return md, - option::None => () + match dbg_cx(cx).created_blocks.find(&id) { + Some(block) => return *block, + None => () } + debug!("create_block: %s", bcx.sess().codemap.span_to_str(span)); + + let parent = match bcx.parent { + None => create_function(bcx.fcx), + Some(b) => create_block(b) + }; + let cx = bcx.ccx(); + let loc = span_start(cx, span); + let file_md = create_file(cx, loc.file.name); + + let block_md = unsafe { + llvm::LLVMDIBuilderCreateLexicalBlock( + DIB(cx), + parent, file_md, + loc.line as c_uint, loc.col.to_uint() as c_uint) + }; + + dbg_cx(cx).created_blocks.insert(id, block_md); + + return block_md; +} + +fn size_and_align_of(cx: @mut CrateContext, t: ty::t) -> (uint, uint) { + let llty = type_of::type_of(cx, t); + (machine::llsize_of_real(cx, llty), machine::llalign_of_min(cx, llty)) +} + +fn create_basic_type(cx: @mut CrateContext, t: ty::t, _span: span) -> DIType { + let ty_id = ty::type_id(t); + match dbg_cx(cx).created_types.find(&ty_id) { + Some(ty_md) => return *ty_md, + None => () + } + + debug!("create_basic_type: %?", ty::get(t)); + let (name, encoding) = match ty::get(t).sty { ty::ty_nil | ty::ty_bot => (~"uint", DW_ATE_unsigned), ty::ty_bool => (~"bool", DW_ATE_boolean), @@ -381,380 +245,272 @@ fn create_basic_type(cx: &mut CrateContext, t: ty::t, span: span) _ => cx.sess.bug("debuginfo::create_basic_type - t is invalid type") }; - let fname = filename_from_span(cx, span); - let file_node = create_file(cx, fname.to_owned()); - let cu_node = create_compile_unit(cx); let (size, align) = size_and_align_of(cx, t); - let lldata = ~[lltag(tg), - cu_node.node, - llstr(name), - file_node.node, - lli32(0), //XXX source line - lli64(size * 8), // size in bits - lli64(align * 8), // alignment in bits - lli64(0), //XXX offset? - lli32(0), //XXX flags? - lli32(encoding)]; - let llnode = llmdnode(lldata); - let mdval = @Metadata { - node: llnode, - data: TyDescMetadata { - hash: ty::type_id(t) - } - }; - update_cache(cache, tg, tydesc_metadata(mdval)); - add_named_metadata(cx, ~"llvm.dbg.ty", llnode); - return mdval; + let ty_md = do as_c_str(name) |name| { unsafe { + llvm::LLVMDIBuilderCreateBasicType( + DIB(cx), name, + size * 8 as u64, align * 8 as u64, encoding as c_uint) + }}; + + dbg_cx(cx).created_types.insert(ty_id, ty_md); + return ty_md; } -fn create_pointer_type(cx: &mut CrateContext, t: ty::t, span: span, - pointee: @Metadata) - -> @Metadata { - let tg = PointerTypeTag; - /*let cache = cx.llmetadata; - match cached_metadata::<@Metadata>( - cache, tg, {|md| ty::hash_ty(t) == ty::hash_ty(md.data.hash)}) { - option::Some(md) { return md; } - option::None {} - }*/ +fn create_pointer_type(cx: @mut CrateContext, t: ty::t, _span: span, pointee: DIType) -> DIType { let (size, align) = size_and_align_of(cx, t); - let fname = filename_from_span(cx, span); - let file_node = create_file(cx, fname.to_owned()); - //let cu_node = create_compile_unit(cx, fname); let name = ty_to_str(cx.tcx, t); - let llnode = create_derived_type(tg, file_node.node, name, 0, size * 8, - align * 8, 0, pointee.node); - let mdval = @Metadata { - node: llnode, - data: TyDescMetadata { - hash: ty::type_id(t) - } - }; - //update_cache(cache, tg, tydesc_metadata(mdval)); - add_named_metadata(cx, ~"llvm.dbg.ty", llnode); - return mdval; + let ptr_md = do as_c_str(name) |name| { unsafe { + llvm::LLVMDIBuilderCreatePointerType(DIB(cx), + pointee, size * 8 as u64, align * 8 as u64, name) + }}; + return ptr_md; } -struct StructCtxt { - file: ValueRef, - name: @str, - line: int, - members: ~[ValueRef], - total_size: int, - align: int +struct StructContext { + builder: DIBuilderRef, + file: DIFile, + name: ~str, + line: uint, + members: ~[DIDerivedType], + total_size: uint, + align: uint } -fn finish_structure(cx: @mut StructCtxt) -> ValueRef { - return create_composite_type(StructureTypeTag, - cx.name, - cx.file, - cx.line, - cx.total_size, - cx.align, - 0, - None, - Some(/*bad*/copy cx.members)); +impl StructContext { + fn new(cx: &CrateContext, name: ~str, file: DIFile, line: uint) -> ~StructContext { + debug!("StructContext::create: %s", name); + let scx = ~StructContext { + builder: DIB(cx), + file: file, + name: name, + line: line, + members: ~[], + total_size: 0, + align: 1 + }; + return scx; + } + + fn add_member(&mut self, name: &str, line: uint, size: uint, align: uint, ty: DIType) { + debug!("StructContext(%s)::add_member: %s, size=%u, align=%u", + self.name, name, size, align); + let offset = roundup(self.total_size, align); + let mem_t = do as_c_str(name) |name| { unsafe { + llvm::LLVMDIBuilderCreateMemberType( + self.builder, ptr::null(), name, self.file, line as c_uint, + size * 8 as u64, align * 8 as u64, offset * 8 as u64, + 0, ty) + }}; + self.members.push(mem_t); + self.total_size = offset + size; + // struct alignment is the max alignment of its' members + self.align = cmp::max(self.align, align); + } + + fn finalize(&self) -> DICompositeType { + debug!("StructContext(%s)::finalize: total_size=%u, align=%u", + self.name, self.total_size, self.align); + let members_md = create_DIArray(self.builder, self.members); + + let struct_md = + do as_c_str(self.name) |name| { unsafe { + llvm::LLVMDIBuilderCreateStructType( + self.builder, self.file, name, + self.file, self.line as c_uint, + self.total_size * 8 as u64, self.align * 8 as u64, 0, ptr::null(), + members_md, 0, ptr::null()) + }}; + return struct_md; + } } -fn create_structure(file: @Metadata, name: @str, line: int) - -> @mut StructCtxt { - let cx = @mut StructCtxt { - file: file.node, - name: name, - line: line, - members: ~[], - total_size: 0, - align: 64 //XXX different alignment per arch? - }; - return cx; +#[inline] +fn roundup(x: uint, a: uint) -> uint { + ((x + (a - 1)) / a) * a } -fn create_derived_type(type_tag: int, file: ValueRef, name: &str, line: int, - size: int, align: int, offset: int, ty: ValueRef) - -> ValueRef { - let lldata = ~[lltag(type_tag), - file, - llstr(name), - file, - lli32(line), - lli64(size), - lli64(align), - lli64(offset), - lli32(0), - ty]; - return llmdnode(lldata); -} +fn create_struct(cx: @mut CrateContext, t: ty::t, fields: ~[ty::field], span: span) + -> DICompositeType { + let loc = span_start(cx, span); + let file_md = create_file(cx, loc.file.name); -fn add_member(cx: @mut StructCtxt, - name: &str, - line: int, - size: int, - align: int, - ty: ValueRef) { - cx.members.push(create_derived_type(MemberTag, cx.file, name, line, - size * 8, align * 8, cx.total_size, - ty)); - cx.total_size += size * 8; -} - -fn create_struct(cx: &mut CrateContext, t: ty::t, fields: ~[ty::field], - span: span) -> @Metadata { - let fname = filename_from_span(cx, span); - let file_node = create_file(cx, fname.to_owned()); - let scx = create_structure(file_node, (ty_to_str(cx.tcx, t)).to_managed(), - line_from_span(cx.sess.codemap, span) as int); + let mut scx = StructContext::new(cx, ty_to_str(cx.tcx, t), file_md, loc.line); for fields.each |field| { let field_t = field.mt.ty; let ty_md = create_ty(cx, field_t, span); let (size, align) = size_and_align_of(cx, field_t); - add_member(scx, cx.sess.str_of(field.ident), - line_from_span(cx.sess.codemap, span) as int, - size as int, align as int, ty_md.node); + scx.add_member(cx.sess.str_of(field.ident), loc.line, size, align, ty_md); } - let mdval = @Metadata { - node: finish_structure(scx), - data: TyDescMetadata { - hash: ty::type_id(t) - } - }; - return mdval; -} - -fn create_tuple(cx: &mut CrateContext, t: ty::t, elements: &[ty::t], span: span) - -> @Metadata { - let fname = filename_from_span(cx, span); - let file_node = create_file(cx, fname.to_owned()); - let scx = create_structure(file_node, - cx.sess.str_of( - ((/*bad*/copy cx.dbg_cx).get().names) - ("tuple")), - line_from_span(cx.sess.codemap, span) as int); - for elements.each |element| { - let ty_md = create_ty(cx, *element, span); - let (size, align) = size_and_align_of(cx, *element); - add_member(scx, "", line_from_span(cx.sess.codemap, span) as int, - size as int, align as int, ty_md.node); - } - let mdval = @Metadata { - node: finish_structure(scx), - data: TyDescMetadata { - hash: ty::type_id(t) - } - }; - return mdval; + return scx.finalize(); } // returns (void* type as a ValueRef, size in bytes, align in bytes) -fn voidptr() -> (ValueRef, int, int) { - let null = ptr::null(); - let size = sys::size_of::() as int; - let align = sys::min_align_of::() as int; - let vp = create_derived_type(PointerTypeTag, null, "", 0, - size, align, 0, null); +fn voidptr(cx: @mut CrateContext) -> (DIDerivedType, uint, uint) { + let size = sys::size_of::(); + let align = sys::min_align_of::(); + let vp = do as_c_str("*void") |name| { unsafe { + llvm::LLVMDIBuilderCreatePointerType(DIB(cx), ptr::null(), + size*8 as u64, align*8 as u64, name) + }}; return (vp, size, align); } -fn create_boxed_type(cx: &mut CrateContext, contents: ty::t, - span: span, boxed: @Metadata) - -> @Metadata { - //let tg = StructureTypeTag; - /*let cache = cx.llmetadata; - match cached_metadata::<@Metadata>( - cache, tg, {|md| ty::hash_ty(contents) == ty::hash_ty(md.data.hash)}) { - option::Some(md) { return md; } - option::None {} - }*/ - let fname = filename_from_span(cx, span); - let file_node = create_file(cx, fname.to_owned()); - //let cu_node = create_compile_unit_metadata(cx, fname); +fn create_tuple(cx: @mut CrateContext, _t: ty::t, elements: &[ty::t], span: span) + -> DICompositeType { + let loc = span_start(cx, span); + let file_md = create_file(cx, loc.file.name); + + let name = (cx.sess.str_of((dbg_cx(cx).names)("tuple"))).to_owned(); + let mut scx = StructContext::new(cx, name, file_md, loc.line); + for elements.each |element| { + let ty_md = create_ty(cx, *element, span); + let (size, align) = size_and_align_of(cx, *element); + scx.add_member("", loc.line, size, align, ty_md); + } + return scx.finalize(); +} + +fn create_boxed_type(cx: @mut CrateContext, contents: ty::t, + span: span, boxed: DIType) -> DICompositeType { + let loc = span_start(cx, span); + let file_md = create_file(cx, loc.file.name); let int_t = ty::mk_int(); let refcount_type = create_basic_type(cx, int_t, span); let name = ty_to_str(cx.tcx, contents); - let scx = create_structure(file_node, (fmt!("box<%s>", name)).to_managed(), 0); - add_member(scx, "refcnt", 0, sys::size_of::() as int, - sys::min_align_of::() as int, refcount_type.node); + + let mut scx = StructContext::new(cx, fmt!("box<%s>", name), file_md, 0); + scx.add_member("refcnt", 0, sys::size_of::(), + sys::min_align_of::(), refcount_type); // the tydesc and other pointers should be irrelevant to the // debugger, so treat them as void* types - let (vp, vpsize, vpalign) = voidptr(); - add_member(scx, "tydesc", 0, vpsize, vpalign, vp); - add_member(scx, "prev", 0, vpsize, vpalign, vp); - add_member(scx, "next", 0, vpsize, vpalign, vp); + let (vp, vpsize, vpalign) = voidptr(cx); + scx.add_member("tydesc", 0, vpsize, vpalign, vp); + scx.add_member("prev", 0, vpsize, vpalign, vp); + scx.add_member("next", 0, vpsize, vpalign, vp); let (size, align) = size_and_align_of(cx, contents); - add_member(scx, "boxed", 0, size, align, boxed.node); - let llnode = finish_structure(scx); - let mdval = @Metadata { - node: llnode, - data: TyDescMetadata { - hash: ty::type_id(contents) - } - }; - //update_cache(cache, tg, tydesc_metadata(mdval)); - add_named_metadata(cx, ~"llvm.dbg.ty", llnode); - return mdval; + scx.add_member("boxed", 0, size, align, boxed); + return scx.finalize(); } -fn create_composite_type(type_tag: int, name: &str, file: ValueRef, - line: int, size: int, align: int, offset: int, - derived: Option, - members: Option<~[ValueRef]>) - -> ValueRef { - let lldata = ~[lltag(type_tag), - file, - llstr(name), // type name - file, // source file definition - lli32(line), // source line definition - lli64(size), // size of members - lli64(align), // align - lli32/*64*/(offset), // offset - lli32(0), // flags - if derived.is_none() { - llnull() - } else { // derived from - derived.get() - }, - if members.is_none() { - llnull() - } else { //members - llmdnode(members.get()) - }, - lli32(0), // runtime language - llnull() - ]; - return llmdnode(lldata); -} - -fn create_fixed_vec(cx: &mut CrateContext, vec_t: ty::t, elem_t: ty::t, - len: int, span: span) -> @Metadata { - let t_md = create_ty(cx, elem_t, span); - let fname = filename_from_span(cx, span); - let file_node = create_file(cx, fname.to_owned()); +fn create_fixed_vec(cx: @mut CrateContext, _vec_t: ty::t, elem_t: ty::t, + len: uint, span: span) -> DIType { + let elem_ty_md = create_ty(cx, elem_t, span); let (size, align) = size_and_align_of(cx, elem_t); - let subrange = llmdnode([lltag(SubrangeTag), lli64(0), lli64(len - 1)]); - let name = fmt!("[%s]", ty_to_str(cx.tcx, elem_t)); - let array = create_composite_type(ArrayTypeTag, name, file_node.node, 0, - size * len, align, 0, Some(t_md.node), - Some(~[subrange])); - @Metadata { - node: array, - data: TyDescMetadata { - hash: ty::type_id(vec_t) - } - } + + let subrange = unsafe { + llvm::LLVMDIBuilderGetOrCreateSubrange(DIB(cx), 0_i64, len as i64) + }; + + let subscripts = create_DIArray(DIB(cx), [subrange]); + return unsafe { + llvm::LLVMDIBuilderCreateArrayType(DIB(cx), + size * len * 8 as u64, align * 8 as u64, elem_ty_md, subscripts) + }; } -fn create_boxed_vec(cx: &mut CrateContext, vec_t: ty::t, elem_t: ty::t, - vec_ty_span: codemap::span) - -> @Metadata { - let fname = filename_from_span(cx, vec_ty_span); - let file_node = create_file(cx, fname.to_owned()); +fn create_boxed_vec(cx: @mut CrateContext, vec_t: ty::t, elem_t: ty::t, + vec_ty_span: span) -> DICompositeType { + let loc = span_start(cx, vec_ty_span); + let file_md = create_file(cx, loc.file.name); let elem_ty_md = create_ty(cx, elem_t, vec_ty_span); - let vec_scx = create_structure(file_node, - ty_to_str(cx.tcx, vec_t).to_managed(), 0); + + let mut vec_scx = StructContext::new(cx, ty_to_str(cx.tcx, vec_t), file_md, 0); let size_t_type = create_basic_type(cx, ty::mk_uint(), vec_ty_span); - add_member(vec_scx, "fill", 0, sys::size_of::() as int, - sys::min_align_of::() as int, size_t_type.node); - add_member(vec_scx, "alloc", 0, sys::size_of::() as int, - sys::min_align_of::() as int, size_t_type.node); - let subrange = llmdnode([lltag(SubrangeTag), lli64(0), lli64(0)]); + vec_scx.add_member("fill", 0, sys::size_of::(), + sys::min_align_of::(), size_t_type); + vec_scx.add_member("alloc", 0, sys::size_of::(), + sys::min_align_of::(), size_t_type); + let subrange = unsafe { + llvm::LLVMDIBuilderGetOrCreateSubrange(DIB(cx), 0_i64, 0_i64) + }; let (arr_size, arr_align) = size_and_align_of(cx, elem_t); let name = fmt!("[%s]", ty_to_str(cx.tcx, elem_t)); - let data_ptr = create_composite_type(ArrayTypeTag, name, file_node.node, 0, - arr_size, arr_align, 0, - Some(elem_ty_md.node), - Some(~[subrange])); - add_member(vec_scx, "data", 0, 0, // clang says the size should be 0 - sys::min_align_of::() as int, data_ptr); - let llnode = finish_structure(vec_scx); - let vec_md = @Metadata { - node: llnode, - data: TyDescMetadata { - hash: ty::type_id(vec_t) - } - }; - let box_scx = create_structure(file_node, (fmt!("box<%s>", name)).to_managed(), 0); + let subscripts = create_DIArray(DIB(cx), [subrange]); + let data_ptr = unsafe { + llvm::LLVMDIBuilderCreateArrayType(DIB(cx), + arr_size * 8 as u64, arr_align * 8 as u64, elem_ty_md, subscripts) + }; + vec_scx.add_member("data", 0, 0, // clang says the size should be 0 + sys::min_align_of::(), data_ptr); + let vec_md = vec_scx.finalize(); + + let mut box_scx = StructContext::new(cx, fmt!("box<%s>", name), file_md, 0); let int_t = ty::mk_int(); let refcount_type = create_basic_type(cx, int_t, vec_ty_span); - add_member(box_scx, "refcnt", 0, sys::size_of::() as int, - sys::min_align_of::() as int, refcount_type.node); - let (vp, vpsize, vpalign) = voidptr(); - add_member(box_scx, "tydesc", 0, vpsize, vpalign, vp); - add_member(box_scx, "prev", 0, vpsize, vpalign, vp); - add_member(box_scx, "next", 0, vpsize, vpalign, vp); - let size = 2 * sys::size_of::() as int; - let align = sys::min_align_of::() as int; - add_member(box_scx, "boxed", 0, size, align, vec_md.node); - let llnode = finish_structure(box_scx); - let mdval = @Metadata { - node: llnode, - data: TyDescMetadata { - hash: ty::type_id(elem_t) - } - }; + box_scx.add_member("refcnt", 0, sys::size_of::(), + sys::min_align_of::(), refcount_type); + let (vp, vpsize, vpalign) = voidptr(cx); + box_scx.add_member("tydesc", 0, vpsize, vpalign, vp); + box_scx.add_member("prev", 0, vpsize, vpalign, vp); + box_scx.add_member("next", 0, vpsize, vpalign, vp); + let size = 2 * sys::size_of::(); + let align = sys::min_align_of::(); + box_scx.add_member("boxed", 0, size, align, vec_md); + let mdval = box_scx.finalize(); return mdval; } -fn create_vec_slice(cx: &mut CrateContext, vec_t: ty::t, elem_t: ty::t, span: span) - -> @Metadata { - let fname = filename_from_span(cx, span); - let file_node = create_file(cx, fname.to_owned()); +fn create_vec_slice(cx: @mut CrateContext, vec_t: ty::t, elem_t: ty::t, span: span) + -> DICompositeType { + let loc = span_start(cx, span); + let file_md = create_file(cx, loc.file.name); let elem_ty_md = create_ty(cx, elem_t, span); let uint_type = create_basic_type(cx, ty::mk_uint(), span); let elem_ptr = create_pointer_type(cx, elem_t, span, elem_ty_md); - let scx = create_structure(file_node, ty_to_str(cx.tcx, vec_t).to_managed(), 0); - let (_, ptr_size, ptr_align) = voidptr(); - add_member(scx, "vec", 0, ptr_size, ptr_align, elem_ptr.node); - add_member(scx, "length", 0, sys::size_of::() as int, - sys::min_align_of::() as int, uint_type.node); - let llnode = finish_structure(scx); - let mdval = @Metadata { - node: llnode, - data: TyDescMetadata { - hash: ty::type_id(vec_t) - } - }; - return mdval; + + let mut scx = StructContext::new(cx, ty_to_str(cx.tcx, vec_t), file_md, 0); + let (_, ptr_size, ptr_align) = voidptr(cx); + scx.add_member("vec", 0, ptr_size, ptr_align, elem_ptr); + scx.add_member("length", 0, sys::size_of::(), + sys::min_align_of::(), uint_type); + return scx.finalize(); } -fn create_fn_ty(cx: &mut CrateContext, fn_ty: ty::t, inputs: ~[ty::t], output: ty::t, - span: span) -> @Metadata { - let fname = filename_from_span(cx, span); - let file_node = create_file(cx, fname.to_owned()); - let (vp, _, _) = voidptr(); +fn create_fn_ty(cx: @mut CrateContext, _fn_ty: ty::t, inputs: ~[ty::t], output: ty::t, + span: span) -> DICompositeType { + let loc = span_start(cx, span); + let file_md = create_file(cx, loc.file.name); + let (vp, _, _) = voidptr(cx); let output_md = create_ty(cx, output, span); let output_ptr_md = create_pointer_type(cx, output, span, output_md); - let inputs_vals = do inputs.map |arg| { create_ty(cx, *arg, span).node }; - let members = ~[output_ptr_md.node, vp] + inputs_vals; - let llnode = create_composite_type(SubroutineTag, "", file_node.node, - 0, 0, 0, 0, None, Some(members)); - let mdval = @Metadata { - node: llnode, - data: TyDescMetadata { - hash: ty::type_id(fn_ty) - } + let inputs_vals = do inputs.map |arg| { create_ty(cx, *arg, span) }; + let members = ~[output_ptr_md, vp] + inputs_vals; + + return unsafe { + llvm::LLVMDIBuilderCreateSubroutineType(DIB(cx), file_md, + create_DIArray(DIB(cx), members)) }; - return mdval; } -fn create_ty(cx: &mut CrateContext, t: ty::t, span: span) - -> @Metadata { +fn create_unimpl_ty(cx: @mut CrateContext, t: ty::t) -> DIType { + let name = ty_to_str(cx.tcx, t); + let md = do as_c_str(fmt!("NYI<%s>", name)) |name| { unsafe { + llvm::LLVMDIBuilderCreateBasicType( + DIB(cx), name, + 0_u64, 8_u64, DW_ATE_unsigned as c_uint) + }}; + return md; +} + +fn create_ty(cx: @mut CrateContext, t: ty::t, span: span) -> DIType { + let ty_id = ty::type_id(t); + match dbg_cx(cx).created_types.find(&ty_id) { + Some(ty_md) => return *ty_md, + None => () + } + debug!("create_ty: %?", ty::get(t)); - /*let cache = get_cache(cx); - match cached_metadata::<@Metadata>( - cache, tg, {|md| t == md.data.hash}) { - option::Some(md) { return md; } - option::None {} - }*/ let sty = copy ty::get(t).sty; - match sty { + let ty_md = match sty { ty::ty_nil | ty::ty_bot | ty::ty_bool | ty::ty_int(_) | ty::ty_uint(_) | ty::ty_float(_) => create_basic_type(cx, t, span), ty::ty_estr(ref vstore) => { let i8_t = ty::mk_i8(); match *vstore { ty::vstore_fixed(len) => { - create_fixed_vec(cx, t, i8_t, len as int + 1, span) + create_fixed_vec(cx, t, i8_t, len + 1, span) }, ty::vstore_uniq | ty::vstore_box => { let box_md = create_boxed_vec(cx, t, i8_t, span); @@ -766,7 +522,8 @@ fn create_ty(cx: &mut CrateContext, t: ty::t, span: span) } }, ty::ty_enum(_did, ref _substs) => { - cx.sess.span_bug(span, "debuginfo for enum NYI") + cx.sess.span_note(span, "debuginfo for enum NYI"); + create_unimpl_ty(cx, t) } ty::ty_box(ref mt) | ty::ty_uniq(ref mt) => { let boxed = create_ty(cx, mt.ty, span); @@ -776,7 +533,7 @@ fn create_ty(cx: &mut CrateContext, t: ty::t, span: span) ty::ty_evec(ref mt, ref vstore) => { match *vstore { ty::vstore_fixed(len) => { - create_fixed_vec(cx, t, mt.ty, len as int, span) + create_fixed_vec(cx, t, mt.ty, len, span) }, ty::vstore_uniq | ty::vstore_box => { let box_md = create_boxed_vec(cx, t, mt.ty, span); @@ -792,7 +549,8 @@ fn create_ty(cx: &mut CrateContext, t: ty::t, span: span) create_pointer_type(cx, t, span, pointee) }, ty::ty_rptr(ref _region, ref _mt) => { - cx.sess.span_bug(span, "debuginfo for rptr NYI") + cx.sess.span_note(span, "debuginfo for rptr NYI"); + create_unimpl_ty(cx, t) }, ty::ty_bare_fn(ref barefnty) => { let inputs = barefnty.sig.inputs.map(|a| *a); @@ -800,10 +558,12 @@ fn create_ty(cx: &mut CrateContext, t: ty::t, span: span) create_fn_ty(cx, t, inputs, output, span) }, ty::ty_closure(ref _closurety) => { - cx.sess.span_bug(span, "debuginfo for closure NYI") + cx.sess.span_note(span, "debuginfo for closure NYI"); + create_unimpl_ty(cx, t) }, ty::ty_trait(_did, ref _substs, ref _vstore, _) => { - cx.sess.span_bug(span, "debuginfo for trait NYI") + cx.sess.span_note(span, "debuginfo for trait NYI"); + create_unimpl_ty(cx, t) }, ty::ty_struct(did, ref substs) => { let fields = ty::struct_fields(cx.tcx, did, substs); @@ -813,59 +573,41 @@ fn create_ty(cx: &mut CrateContext, t: ty::t, span: span) create_tuple(cx, t, *elements, span) }, _ => cx.sess.bug("debuginfo: unexpected type in create_ty") - } + }; + + dbg_cx(cx).created_types.insert(ty_id, ty_md); + return ty_md; } -fn filename_from_span(cx: &CrateContext, sp: codemap::span) -> @str { - cx.sess.codemap.lookup_char_pos(sp.lo).file.name -} - -fn create_var(type_tag: int, context: ValueRef, name: &str, file: ValueRef, - line: int, ret_ty: ValueRef) -> ValueRef { - let lldata = ~[lltag(type_tag), - context, - llstr(name), - file, - lli32(line), - ret_ty, - lli32(0) - ]; - return llmdnode(lldata); -} - -pub fn create_local_var(bcx: block, local: @ast::local) - -> @Metadata { +pub fn create_local_var(bcx: block, local: @ast::local) -> DIVariable { let cx = bcx.ccx(); - let cache = get_cache(cx); - let tg = AutoVariableTag; - match cached_metadata::<@Metadata>( - cache, tg, |md| md.data.id == local.node.id) { - option::Some(md) => return md, - option::None => () - } - let name = match local.node.pat.node { + let ident = match local.node.pat.node { ast::pat_ident(_, pth, _) => ast_util::path_to_ident(pth), // FIXME this should be handled (#2533) - _ => fail!("no single variable name for local") + _ => { + bcx.sess().span_note(local.span, "debuginfo for pattern bindings NYI"); + return ptr::null(); + } }; - let loc = cx.sess.codemap.lookup_char_pos(local.span.lo); + let name: &str = cx.sess.str_of(ident); + debug!("create_local_var: %s", name); + + let loc = span_start(cx, local.span); let ty = node_id_type(bcx, local.node.id); let tymd = create_ty(cx, ty, local.node.ty.span); - let filemd = create_file(cx, /*bad*/ loc.file.name.to_owned()); + let filemd = create_file(cx, loc.file.name); let context = match bcx.parent { - None => create_function(bcx.fcx).node, - Some(_) => create_block(bcx).node + None => create_function(bcx.fcx), + Some(_) => create_block(bcx) }; - let mdnode = create_var(tg, context, cx.sess.str_of(name), - filemd.node, loc.line as int, tymd.node); - let mdval = @Metadata { - node: mdnode, - data: LocalVarMetadata { - id: local.node.id - } - }; - update_cache(cache, AutoVariableTag, local_var_metadata(mdval)); + + let var_md = do as_c_str(name) |name| { unsafe { + llvm::LLVMDIBuilderCreateLocalVariable( + DIB(cx), AutoVariableTag as u32, + context, name, filemd, + loc.line as c_uint, tymd, false, 0, 0) + }}; // FIXME(#6814) Should use `pat_util::pat_bindings` for pats like (a, b) etc let llptr = match bcx.fcx.lllocals.find_copy(&local.node.pat.id) { @@ -876,59 +618,57 @@ pub fn create_local_var(bcx: block, local: @ast::local) fmt!("No entry in lllocals table for %?", local.node.id)); } }; - let declargs = ~[llmdnode([llptr]), mdnode]; - trans::build::Call(bcx, cx.intrinsics.get_copy(&("llvm.dbg.declare")), - declargs); - return mdval; -} -pub fn create_arg(bcx: block, arg: ast::arg, sp: span) - -> Option<@Metadata> { - let fcx = bcx.fcx; - let cx = fcx.ccx; - let cache = get_cache(cx); - let tg = ArgVariableTag; - match cached_metadata::<@Metadata>( - cache, ArgVariableTag, |md| md.data.id == arg.id) { - option::Some(md) => return Some(md), - option::None => () + set_debug_location(cx, create_block(bcx), loc.line, loc.col.to_uint()); + unsafe { + let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd(DIB(cx), llptr, var_md, bcx.llbb); + llvm::LLVMSetInstDebugLocation(trans::build::B(bcx), instr); } - let loc = cx.sess.codemap.lookup_char_pos(sp.lo); + return var_md; +} + +pub fn create_arg(bcx: block, arg: ast::arg, span: span) -> Option { + debug!("create_arg"); + if true { + // XXX create_arg disabled for now because "node_id_type(bcx, arg.id)" below blows + // up: "error: internal compiler error: node_id_to_type: no type for node `arg (id=10)`" + return None; + } + + let fcx = bcx.fcx; + let cx = fcx.ccx; + + let loc = span_start(cx, span); if "" == loc.file.name { return None; } + let ty = node_id_type(bcx, arg.id); let tymd = create_ty(cx, ty, arg.ty.span); - let filemd = create_file(cx, /* bad */ loc.file.name.to_owned()); - let context = create_function(bcx.fcx); + let filemd = create_file(cx, loc.file.name); + let context = create_function(fcx); match arg.pat.node { ast::pat_ident(_, path, _) => { // XXX: This is wrong; it should work for multiple bindings. - let mdnode = create_var( - tg, - context.node, - cx.sess.str_of(*path.idents.last()), - filemd.node, - loc.line as int, - tymd.node - ); - - let mdval = @Metadata { - node: mdnode, - data: ArgumentMetadata { - id: arg.id - } - }; - update_cache(cache, tg, argument_metadata(mdval)); + let ident = path.idents.last(); + let name: &str = cx.sess.str_of(*ident); + let mdnode = do as_c_str(name) |name| { unsafe { + llvm::LLVMDIBuilderCreateLocalVariable(DIB(cx), + ArgVariableTag as u32, context, name, + filemd, loc.line as c_uint, tymd, false, 0, 0) + // XXX need to pass in a real argument number + }}; let llptr = fcx.llargs.get_copy(&arg.id); - let declargs = ~[llmdnode([llptr]), mdnode]; - trans::build::Call(bcx, - cx.intrinsics.get_copy(&("llvm.dbg.declare")), - declargs); - return Some(mdval); + set_debug_location(cx, create_block(bcx), loc.line, loc.col.to_uint()); + unsafe { + let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd( + DIB(cx), llptr, mdnode, bcx.llbb); + llvm::LLVMSetInstDebugLocation(trans::build::B(bcx), instr); + } + return Some(mdnode); } _ => { return None; @@ -936,32 +676,36 @@ pub fn create_arg(bcx: block, arg: ast::arg, sp: span) } } -pub fn update_source_pos(cx: block, s: span) { - if !cx.sess().opts.debuginfo || (*s.lo == 0 && *s.hi == 0) { +fn set_debug_location(cx: @mut CrateContext, scope: DIScope, line: uint, col: uint) { + if dbg_cx(cx).curr_loc == (line, col) { return; } - let cm = cx.sess().codemap; - let blockmd = create_block(cx); - let loc = cm.lookup_char_pos(s.lo); - let scopedata = ~[lli32(loc.line.to_int()), - lli32(loc.col.to_int()), - blockmd.node, - llnull()]; - let dbgscope = llmdnode(scopedata); + debug!("setting debug location to %u %u", line, col); + dbg_cx(cx).curr_loc = (line, col); + + let elems = ~[C_i32(line as i32), C_i32(col as i32), scope, ptr::null()]; unsafe { - llvm::LLVMSetCurrentDebugLocation(trans::build::B(cx), dbgscope); + let dbg_loc = llvm::LLVMMDNodeInContext( + dbg_cx(cx).llcontext, vec::raw::to_ptr(elems), + elems.len() as libc::c_uint); + llvm::LLVMSetCurrentDebugLocation(cx.builder.B, dbg_loc); } } -pub fn create_function(fcx: fn_ctxt) -> @Metadata { - let mut cx = fcx.ccx; - - debug!("~~"); +/// Set current debug location at the beginning of the span +pub fn update_source_pos(bcx: block, span: span) { + if !bcx.sess().opts.debuginfo || (*span.lo == 0 && *span.hi == 0) { + return; + } + debug!("update_source_pos: %s", bcx.sess().codemap.span_to_str(span)); + let loc = span_start(bcx.ccx(), span); + set_debug_location(bcx.ccx(), create_block(bcx), loc.line, loc.col.to_uint()) +} +pub fn create_function(fcx: fn_ctxt) -> DISubprogram { + let cx = fcx.ccx; let fcx = &mut *fcx; - - let sp = fcx.span.get(); - debug!("%s", cx.sess.codemap.span_to_str(sp)); + let span = fcx.span.get(); let (ident, ret_ty, id) = match cx.tcx.items.get_copy(&fcx.id) { ast_map::node_item(item, _) => { @@ -978,8 +722,7 @@ pub fn create_function(fcx: fn_ctxt) -> @Metadata { ast_map::node_expr(expr) => { match expr.node { ast::expr_fn_block(ref decl, _) => { - let dbg_cx = cx.dbg_cx.get_ref(); - ((dbg_cx.names)("fn"), decl.output, expr.id) + ((dbg_cx(cx).names)("fn"), decl.output, expr.id) } _ => fcx.ccx.sess.span_bug(expr.span, "create_function: expected an expr_fn_block here") @@ -988,62 +731,46 @@ pub fn create_function(fcx: fn_ctxt) -> @Metadata { _ => fcx.ccx.sess.bug("create_function: unexpected sort of node") }; - debug!("%?", ident); - debug!("%?", id); - - let cache = get_cache(cx); - match cached_metadata::<@Metadata>( - cache, SubprogramTag, |md| md.data.id == id) { - option::Some(md) => return md, - option::None => () + match dbg_cx(cx).created_functions.find(&id) { + Some(fn_md) => return *fn_md, + None => () } - let loc = cx.sess.codemap.lookup_char_pos(sp.lo); - let file_node = create_file(cx, loc.file.name.to_owned()).node; - let ty_node = if cx.sess.opts.extra_debuginfo { + debug!("create_function: %s, %s", cx.sess.str_of(ident), cx.sess.codemap.span_to_str(span)); + + let loc = span_start(cx, span); + let file_md = create_file(cx, loc.file.name); + + let ret_ty_md = if cx.sess.opts.extra_debuginfo { match ret_ty.node { - ast::ty_nil => llnull(), + ast::ty_nil => ptr::null(), _ => create_ty(cx, ty::node_id_to_type(cx.tcx, id), - ret_ty.span).node + ret_ty.span) } } else { - llnull() + ptr::null() }; - let sub_node = create_composite_type(SubroutineTag, "", file_node, 0, 0, - 0, 0, option::None, - option::Some(~[ty_node])); - let fn_metadata = ~[lltag(SubprogramTag), - llunused(), - file_node, - llstr(cx.sess.str_of(ident)), - //XXX fully-qualified C++ name: - llstr(cx.sess.str_of(ident)), - llstr(""), //XXX MIPS name????? - file_node, - lli32(loc.line as int), - sub_node, - lli1(false), //XXX static (check export) - lli1(true), // defined in compilation unit - lli32(DW_VIRTUALITY_none), // virtual-ness - lli32(0i), //index into virt func - /*llnull()*/ lli32(0), // base type with vtbl - lli32(256), // flags - lli1(cx.sess.opts.optimize != session::No), - fcx.llfn - //list of template params - //func decl descriptor - //list of func vars - ]; - let val = llmdnode(fn_metadata); - add_named_metadata(cx, ~"llvm.dbg.sp", val); - let mdval = @Metadata { - node: val, - data: SubProgramMetadata { - id: id - } + let fn_ty = unsafe { + llvm::LLVMDIBuilderCreateSubroutineType(DIB(cx), + file_md, create_DIArray(DIB(cx), [ret_ty_md])) }; - update_cache(cache, SubprogramTag, subprogram_metadata(mdval)); - return mdval; + let fn_md = + do as_c_str(cx.sess.str_of(ident)) |name| { + do as_c_str(cx.sess.str_of(ident)) |linkage| { unsafe { + llvm::LLVMDIBuilderCreateFunction( + DIB(cx), + file_md, + name, linkage, + file_md, loc.line as c_uint, + fn_ty, false, true, + loc.line as c_uint, + FlagPrototyped as c_uint, + cx.sess.opts.optimize != session::No, + fcx.llfn, ptr::null(), ptr::null()) + }}}; + + dbg_cx(cx).created_functions.insert(id, fn_md); + return fn_md; } diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs index 3c43e8535f42..05461c936318 100644 --- a/src/librustc/middle/trans/glue.rs +++ b/src/librustc/middle/trans/glue.rs @@ -103,7 +103,7 @@ pub fn drop_ty_immediate(bcx: block, v: ValueRef, t: ty::t) -> block { ty::ty_box(_) | ty::ty_opaque_box | ty::ty_evec(_, ty::vstore_box) | ty::ty_estr(ty::vstore_box) => { - decr_refcnt_maybe_free(bcx, v, t) + decr_refcnt_maybe_free(bcx, v, None, t) } _ => bcx.tcx().sess.bug("drop_ty_immediate: non-box ty") } @@ -419,15 +419,6 @@ pub fn make_free_glue(bcx: block, v: ValueRef, t: ty::t) { ty::ty_opaque_closure_ptr(ck) => { closure::make_opaque_cbox_free_glue(bcx, ck, v) } - ty::ty_struct(did, ref substs) => { - // Call the dtor if there is one - match ty::ty_dtor(bcx.tcx(), did) { - ty::NoDtor => bcx, - ty::TraitDtor(ref dt_id) => { - trans_struct_drop(bcx, t, v, *dt_id, did, substs) - } - } - } _ => bcx }; build_return(bcx); @@ -489,7 +480,7 @@ pub fn make_drop_glue(bcx: block, v0: ValueRef, t: ty::t) { let bcx = match ty::get(t).sty { ty::ty_box(_) | ty::ty_opaque_box | ty::ty_estr(ty::vstore_box) | ty::ty_evec(_, ty::vstore_box) => { - decr_refcnt_maybe_free(bcx, Load(bcx, v0), t) + decr_refcnt_maybe_free(bcx, Load(bcx, v0), Some(v0), t) } ty::ty_uniq(_) | ty::ty_evec(_, ty::vstore_uniq) | ty::ty_estr(ty::vstore_uniq) => { @@ -514,8 +505,10 @@ pub fn make_drop_glue(bcx: block, v0: ValueRef, t: ty::t) { closure::make_closure_glue(bcx, v0, t, drop_ty) } ty::ty_trait(_, _, ty::BoxTraitStore, _) => { - let llbox = Load(bcx, GEPi(bcx, v0, [0u, abi::trt_field_box])); - decr_refcnt_maybe_free(bcx, llbox, ty::mk_opaque_box(ccx.tcx)) + let llbox_ptr = GEPi(bcx, v0, [0u, abi::trt_field_box]); + let llbox = Load(bcx, llbox_ptr); + decr_refcnt_maybe_free(bcx, llbox, Some(llbox_ptr), + ty::mk_opaque_box(ccx.tcx)) } ty::ty_trait(_, _, ty::UniqTraitStore, _) => { let lluniquevalue = GEPi(bcx, v0, [0, abi::trt_field_box]); @@ -549,7 +542,10 @@ pub fn make_drop_glue(bcx: block, v0: ValueRef, t: ty::t) { build_return(bcx); } -pub fn decr_refcnt_maybe_free(bcx: block, box_ptr: ValueRef, t: ty::t) +// box_ptr_ptr is optional, it is constructed if not supplied. +pub fn decr_refcnt_maybe_free(bcx: block, box_ptr: ValueRef, + box_ptr_ptr: Option, + t: ty::t) -> block { let _icx = bcx.insn_ctxt("decr_refcnt_maybe_free"); let ccx = bcx.ccx(); @@ -559,7 +555,12 @@ pub fn decr_refcnt_maybe_free(bcx: block, box_ptr: ValueRef, t: ty::t) let rc = Sub(bcx, Load(bcx, rc_ptr), C_int(ccx, 1)); Store(bcx, rc, rc_ptr); let zero_test = ICmp(bcx, lib::llvm::IntEQ, C_int(ccx, 0), rc); - with_cond(bcx, zero_test, |bcx| free_ty_immediate(bcx, box_ptr, t)) + do with_cond(bcx, zero_test) |bcx| { + match box_ptr_ptr { + Some(p) => free_ty(bcx, p, t), + None => free_ty_immediate(bcx, box_ptr, t) + } + } } } diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index b54f362c7d2d..4fc431e0a54c 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -1094,62 +1094,62 @@ fn mk_t(cx: ctxt, st: sty) -> t { } } -#[inline(always)] +#[inline] pub fn mk_prim_t(primitive: &'static t_box_) -> t { unsafe { cast::transmute::<&'static t_box_, t>(primitive) } } -#[inline(always)] +#[inline] pub fn mk_nil() -> t { mk_prim_t(&primitives::TY_NIL) } -#[inline(always)] +#[inline] pub fn mk_err() -> t { mk_prim_t(&primitives::TY_ERR) } -#[inline(always)] +#[inline] pub fn mk_bot() -> t { mk_prim_t(&primitives::TY_BOT) } -#[inline(always)] +#[inline] pub fn mk_bool() -> t { mk_prim_t(&primitives::TY_BOOL) } -#[inline(always)] +#[inline] pub fn mk_int() -> t { mk_prim_t(&primitives::TY_INT) } -#[inline(always)] +#[inline] pub fn mk_i8() -> t { mk_prim_t(&primitives::TY_I8) } -#[inline(always)] +#[inline] pub fn mk_i16() -> t { mk_prim_t(&primitives::TY_I16) } -#[inline(always)] +#[inline] pub fn mk_i32() -> t { mk_prim_t(&primitives::TY_I32) } -#[inline(always)] +#[inline] pub fn mk_i64() -> t { mk_prim_t(&primitives::TY_I64) } -#[inline(always)] +#[inline] pub fn mk_float() -> t { mk_prim_t(&primitives::TY_FLOAT) } -#[inline(always)] +#[inline] pub fn mk_f32() -> t { mk_prim_t(&primitives::TY_F32) } -#[inline(always)] +#[inline] pub fn mk_f64() -> t { mk_prim_t(&primitives::TY_F64) } -#[inline(always)] +#[inline] pub fn mk_uint() -> t { mk_prim_t(&primitives::TY_UINT) } -#[inline(always)] +#[inline] pub fn mk_u8() -> t { mk_prim_t(&primitives::TY_U8) } -#[inline(always)] +#[inline] pub fn mk_u16() -> t { mk_prim_t(&primitives::TY_U16) } -#[inline(always)] +#[inline] pub fn mk_u32() -> t { mk_prim_t(&primitives::TY_U32) } -#[inline(always)] +#[inline] pub fn mk_u64() -> t { mk_prim_t(&primitives::TY_U64) } pub fn mk_mach_int(tm: ast::int_ty) -> t { @@ -1181,7 +1181,7 @@ pub fn mk_mach_float(tm: ast::float_ty) -> t { } } -#[inline(always)] +#[inline] pub fn mk_char() -> t { mk_prim_t(&primitives::TY_CHAR) } pub fn mk_estr(cx: ctxt, t: vstore) -> t { @@ -2273,7 +2273,7 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents { for type_param_def.bounds.builtin_bounds.each |bound| { debug!("tc = %s, bound = %?", tc.to_str(), bound); tc = tc - match bound { - BoundCopy => TypeContents::nonimplicitly_copyable(cx), + BoundCopy => TypeContents::noncopyable(cx), BoundStatic => TypeContents::nonstatic(cx), BoundOwned => TypeContents::nonowned(cx), BoundConst => TypeContents::nonconst(cx), @@ -3694,7 +3694,7 @@ fn lookup_locally_or_in_crate_store( */ match map.find(&def_id) { - Some(&v) => { return v; } + Some(&ref v) => { return copy *v; } None => { } } @@ -3702,8 +3702,8 @@ fn lookup_locally_or_in_crate_store( fail!("No def'n found for %? in tcx.%s", def_id, descr); } let v = load_external(); - map.insert(def_id, v); - return v; + map.insert(def_id, copy v); + return copy v; } pub fn trait_method(cx: ctxt, trait_did: ast::def_id, idx: uint) -> @Method { diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index ea41dff99b89..12b413bc5af9 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -725,7 +725,7 @@ impl FnCtxt { ty::re_scope(self.region_lb) } - #[inline(always)] + #[inline] pub fn write_ty(&self, node_id: ast::node_id, ty: ty::t) { debug!("write_ty(%d, %s) in fcx %s", node_id, ppaux::ty_to_str(self.tcx(), ty), self.tag()); diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs index 99e68e3330bf..197bf5d82cce 100644 --- a/src/librustc/middle/typeck/check/vtable.rs +++ b/src/librustc/middle/typeck/check/vtable.rs @@ -10,7 +10,6 @@ use core::prelude::*; -use middle::resolve::Impl; use middle::ty::param_ty; use middle::ty; use middle::typeck::check::{FnCtxt, impl_self_ty}; @@ -27,7 +26,6 @@ use util::ppaux; use core::hashmap::HashSet; use core::result; -use core::uint; use syntax::ast; use syntax::ast_util; use syntax::codemap::span; @@ -248,16 +246,9 @@ fn lookup_vtable(vcx: &VtableContext, // Nothing found. Continue. } Some(implementations) => { - let len = { // FIXME(#5074): stage0 requires it - let implementations: &mut ~[@Impl] = *implementations; - implementations.len() - }; - // implementations is the list of all impls in scope for // trait_ref. (Usually, there's just one.) - for uint::range(0, len) |i| { - let im = implementations[i]; - + for implementations.iter().advance |im| { // im is one specific impl of trait_ref. // First, ensure we haven't processed this impl yet. diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs index 9528c825fbed..d71820a67b35 100644 --- a/src/librustc/middle/typeck/coherence.rs +++ b/src/librustc/middle/typeck/coherence.rs @@ -520,12 +520,8 @@ impl CoherenceChecker { match extension_methods.find(&trait_def_id) { Some(impls) => { - let len = { // FIXME(#5074) stage0 requires this - let impls: &mut ~[@Impl] = *impls; - impls.len() - }; - for uint::range(0, len) |i| { - f(impls[i]); + for impls.iter().advance |&im| { + f(im); } } None => { /* no impls? */ } diff --git a/src/librustc/middle/typeck/infer/lattice.rs b/src/librustc/middle/typeck/infer/lattice.rs index 820bb2f86b04..7a3230079ee3 100644 --- a/src/librustc/middle/typeck/infer/lattice.rs +++ b/src/librustc/middle/typeck/infer/lattice.rs @@ -89,10 +89,10 @@ impl CombineFields { // Need to make sub_id a subtype of sup_id. let node_a = self.infcx.get(a_id); let node_b = self.infcx.get(b_id); - let a_id = node_a.root; - let b_id = node_b.root; - let a_bounds = node_a.possible_types; - let b_bounds = node_b.possible_types; + let a_id = copy node_a.root; + let b_id = copy node_b.root; + let a_bounds = copy node_a.possible_types; + let b_bounds = copy node_b.possible_types; debug!("vars(%s=%s <: %s=%s)", a_id.to_str(), a_bounds.inf_str(self.infcx), @@ -102,8 +102,8 @@ impl CombineFields { // If both A's UB and B's LB have already been bound to types, // see if we can make those types subtypes. - match (a_bounds.ub, b_bounds.lb) { - (Some(ref a_ub), Some(ref b_lb)) => { + match (&a_bounds.ub, &b_bounds.lb) { + (&Some(ref a_ub), &Some(ref b_lb)) => { let r = self.infcx.try( || LatticeValue::sub(self, a_ub, b_lb)); match r { @@ -138,9 +138,9 @@ impl CombineFields { * Make a variable (`a_id`) a subtype of the concrete type `b` */ let node_a = self.infcx.get(a_id); - let a_id = node_a.root; + let a_id = copy node_a.root; let a_bounds = &node_a.possible_types; - let b_bounds = &Bounds { lb: None, ub: Some(b) }; + let b_bounds = &Bounds { lb: None, ub: Some(copy b) }; debug!("var_sub_t(%s=%s <: %s)", a_id.to_str(), @@ -161,9 +161,9 @@ impl CombineFields { * * Make a concrete type (`a`) a subtype of the variable `b_id` */ - let a_bounds = &Bounds { lb: Some(a), ub: None }; + let a_bounds = &Bounds { lb: Some(copy a), ub: None }; let node_b = self.infcx.get(b_id); - let b_id = node_b.root; + let b_id = copy node_b.root; let b_bounds = &node_b.possible_types; debug!("t_sub_var(%s <: %s=%s)", @@ -190,11 +190,11 @@ impl CombineFields { b.inf_str(self.infcx)); let _r = indenter(); - match (*a, *b) { - (None, None) => Ok(None), - (Some(_), None) => Ok(*a), - (None, Some(_)) => Ok(*b), - (Some(ref v_a), Some(ref v_b)) => { + match (a, b) { + (&None, &None) => Ok(None), + (&Some(_), &None) => Ok(copy *a), + (&None, &Some(_)) => Ok(copy *b), + (&Some(ref v_a), &Some(ref v_b)) => { do lattice_op(self, v_a, v_b).chain |v| { Ok(Some(v)) } @@ -272,13 +272,13 @@ impl CombineFields { b.inf_str(self.infcx)); let _r = indenter(); - match (*a, *b) { - (None, None) | - (Some(_), None) | - (None, Some(_)) => { + match (a, b) { + (&None, &None) | + (&Some(_), &None) | + (&None, &Some(_)) => { uok() } - (Some(ref t_a), Some(ref t_b)) => { + (&Some(ref t_a), &Some(ref t_b)) => { LatticeValue::sub(self, t_a, t_b) } } @@ -303,9 +303,9 @@ pub trait TyLatticeDir { impl LatticeDir for Lub { fn combine_fields(&self) -> CombineFields { **self } - fn bnd(&self, b: &Bounds) -> Option { b.ub } + fn bnd(&self, b: &Bounds) -> Option { copy b.ub } fn with_bnd(&self, b: &Bounds, t: T) -> Bounds { - Bounds { ub: Some(t), ..*b } + Bounds { ub: Some(t), ..copy *b } } } @@ -317,9 +317,9 @@ impl TyLatticeDir for Lub { impl LatticeDir for Glb { fn combine_fields(&self) -> CombineFields { **self } - fn bnd(&self, b: &Bounds) -> Option { b.lb } + fn bnd(&self, b: &Bounds) -> Option { copy b.lb } fn with_bnd(&self, b: &Bounds, t: T) -> Bounds { - Bounds { lb: Some(t), ..*b } + Bounds { lb: Some(t), ..copy *b } } } @@ -405,8 +405,8 @@ pub fn lattice_vars cres> { let nde_a = this.infcx().get(a_vid); let nde_b = this.infcx().get(b_vid); - let a_vid = nde_a.root; - let b_vid = nde_b.root; + let a_vid = copy nde_a.root; + let b_vid = copy nde_b.root; let a_bounds = &nde_a.possible_types; let b_bounds = &nde_b.possible_types; @@ -436,8 +436,8 @@ pub fn lattice_vars) -> cres { let nde_a = this.infcx().get(a_id); - let a_id = nde_a.root; + let a_id = copy nde_a.root; let a_bounds = &nde_a.possible_types; // The comments in this function are written for LUB, but they @@ -472,10 +472,11 @@ pub fn lattice_var_and_t { impl CresCompare for cres { fn compare(&self, t: T, f: &fn() -> ty::type_err) -> cres { - do self.chain |s| { + do (copy *self).chain |s| { if s == t { - *self + copy *self } else { Err(f()) } diff --git a/src/librustc/middle/typeck/infer/unify.rs b/src/librustc/middle/typeck/infer/unify.rs index c6e4b485d29b..371d389f712c 100644 --- a/src/librustc/middle/typeck/infer/unify.rs +++ b/src/librustc/middle/typeck/infer/unify.rs @@ -61,7 +61,7 @@ impl InferCtxt { { let vid_u = vid.to_uint(); let var_val = match vb.vals.find(&vid_u) { - Some(&var_val) => var_val, + Some(&ref var_val) => copy *var_val, None => { tcx.sess.bug(fmt!( "failed lookup of vid `%u`", vid_u)); @@ -69,11 +69,11 @@ impl InferCtxt { }; match var_val { Redirect(vid) => { - let node: Node = helper(tcx, vb, vid); + let node: Node = helper(tcx, vb, copy vid); if node.root != vid { // Path compression vb.vals.insert(vid.to_uint(), - Redirect(node.root)); + Redirect(copy node.root)); } node } @@ -96,12 +96,10 @@ impl InferCtxt { debug!("Updating variable %s to %s", vid.to_str(), new_v.inf_str(self)); - { // FIXME(#4903)---borrow checker is not flow sensitive - let vb = UnifyVid::appropriate_vals_and_bindings(self); - let old_v = { *vb.vals.get(&vid.to_uint()) }; // FIXME(#4903) - vb.bindings.push((vid, old_v)); - vb.vals.insert(vid.to_uint(), new_v); - } + let vb = UnifyVid::appropriate_vals_and_bindings(self); + let old_v = copy *vb.vals.get(&vid.to_uint()); + vb.bindings.push((copy vid, old_v)); + vb.vals.insert(vid.to_uint(), new_v); } pub fn unify node_b.rank { // a has greater rank, so a should become b's parent, // i.e., b should redirect to a. - self.set(node_b.root, Redirect(node_a.root)); - (node_a.root, node_a.rank) + self.set(copy node_b.root, Redirect(copy node_a.root)); + (copy node_a.root, node_a.rank) } else if node_a.rank < node_b.rank { // b has greater rank, so a should redirect to b. - self.set(node_a.root, Redirect(node_b.root)); - (node_b.root, node_b.rank) + self.set(copy node_a.root, Redirect(copy node_b.root)); + (copy node_b.root, node_b.rank) } else { // If equal, redirect one to the other and increment the // other's rank. assert_eq!(node_a.rank, node_b.rank); - self.set(node_b.root, Redirect(node_a.root)); - (node_a.root, node_a.rank + 1) + self.set(copy node_b.root, Redirect(copy node_a.root)); + (copy node_a.root, node_a.rank + 1) } } @@ -174,20 +172,20 @@ impl InferCtxt { let node_a = self.get(a_id); let node_b = self.get(b_id); - let a_id = node_a.root; - let b_id = node_b.root; + let a_id = copy node_a.root; + let b_id = copy node_b.root; if a_id == b_id { return uok(); } let combined = match (&node_a.possible_types, &node_b.possible_types) { (&None, &None) => None, - (&Some(ref v), &None) | (&None, &Some(ref v)) => Some(*v), + (&Some(ref v), &None) | (&None, &Some(ref v)) => Some(copy *v), (&Some(ref v1), &Some(ref v2)) => { if *v1 != *v2 { - return mk_err(a_is_expected, *v1, *v2); + return mk_err(a_is_expected, copy *v1, copy *v2); } - Some(*v1) + Some(copy *v1) } }; @@ -211,7 +209,7 @@ impl InferCtxt { * `b`. */ let node_a = self.get(a_id); - let a_id = node_a.root; + let a_id = copy node_a.root; match node_a.possible_types { None => { @@ -223,7 +221,7 @@ impl InferCtxt { if *a_t == b { return uok(); } else { - return mk_err(a_is_expected, *a_t, b); + return mk_err(a_is_expected, copy *a_t, b); } } } diff --git a/src/librustc/rustc.rc b/src/librustc/rustc.rc index 1197693d1b6d..021dd6648cbf 100644 --- a/src/librustc/rustc.rc +++ b/src/librustc/rustc.rc @@ -28,16 +28,8 @@ extern mod core(name = "std"); extern mod extra(name = "extra"); extern mod syntax; -// For deriving(Encodable) purposes... -#[cfg(stage0)] -extern mod std(name = "extra", vers = "0.7-pre"); -#[cfg(not(stage0))] extern mod std(name = "std", vers = "0.7-pre"); -// For bootstrapping purposes. -#[cfg(stage0)] -pub use core::unstable; - use core::prelude::*; use driver::driver::{host_triple, optgroups, early_error}; diff --git a/src/librustdoc/astsrv.rs b/src/librustdoc/astsrv.rs index 9d8f750a3500..3775aafb5696 100644 --- a/src/librustdoc/astsrv.rs +++ b/src/librustdoc/astsrv.rs @@ -32,8 +32,6 @@ use syntax::ast; use syntax::ast_map; use syntax; -#[cfg(test)] use core::vec; - pub struct Ctxt { ast: @ast::crate, ast_map: ast_map::map diff --git a/src/librustdoc/attr_parser.rs b/src/librustdoc/attr_parser.rs index a86a7f38a8cd..1abdae113c59 100644 --- a/src/librustdoc/attr_parser.rs +++ b/src/librustdoc/attr_parser.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -152,6 +152,6 @@ mod test { fn should_concatenate_multiple_doc_comments() { let source = @"/// foo\n/// bar"; let desc = parse_desc(parse_attributes(source)); - assert!(desc == Some(~"foo\nbar")); + assert!(desc == Some(~" foo\n bar")); } } diff --git a/src/librustdoc/desc_to_brief_pass.rs b/src/librustdoc/desc_to_brief_pass.rs index 51fea9b46b3c..dbaa5e8532cb 100644 --- a/src/librustdoc/desc_to_brief_pass.rs +++ b/src/librustdoc/desc_to_brief_pass.rs @@ -24,7 +24,6 @@ use fold::Fold; use fold; use pass::Pass; -use core::str; use core::util; pub fn mk_pass() -> Pass { @@ -129,25 +128,21 @@ fn first_sentence_(s: &str) -> ~str { } }); match idx { - Some(idx) if idx > 2u => { - str::to_owned(s.slice(0, idx - 1)) - } + Some(idx) if idx > 2u => s.slice(0, idx - 1).to_owned(), _ => { if s.ends_with(".") { - str::to_owned(s) + s.to_owned() } else { - str::to_owned(s) + s.to_owned() } } } } pub fn paragraphs(s: &str) -> ~[~str] { - let mut lines = ~[]; - for str::each_line_any(s) |line| { lines.push(line.to_owned()); } let mut whitespace_lines = 0; let mut accum = ~""; - let paras = do lines.iter().fold(~[]) |paras, line| { + let paras = do s.any_line_iter().fold(~[]) |paras, line| { let mut res = paras; if line.is_whitespace() { @@ -163,9 +158,9 @@ pub fn paragraphs(s: &str) -> ~[~str] { whitespace_lines = 0; accum = if accum.is_empty() { - copy *line + line.to_owned() } else { - accum + "\n" + *line + fmt!("%s\n%s", accum, line) } } diff --git a/src/librustdoc/extract.rs b/src/librustdoc/extract.rs index f4b6ae8fb32a..f8c49f544bc2 100644 --- a/src/librustdoc/extract.rs +++ b/src/librustdoc/extract.rs @@ -285,8 +285,6 @@ mod test { use extract::{extract, from_srv}; use parse; - use core::vec; - fn mk_doc(source: @str) -> doc::Doc { let ast = parse::from_str(source); extract(ast, ~"") diff --git a/src/librustdoc/markdown_pass.rs b/src/librustdoc/markdown_pass.rs index 17db7c24a7c8..075b64a674cb 100644 --- a/src/librustdoc/markdown_pass.rs +++ b/src/librustdoc/markdown_pass.rs @@ -466,10 +466,7 @@ fn write_variant(ctxt: &Ctxt, doc: doc::VariantDoc) { } fn list_item_indent(item: &str) -> ~str { - let mut indented = ~[]; - for str::each_line_any(item) |line| { - indented.push(line); - } + let indented = item.any_line_iter().collect::<~[&str]>(); // separate markdown elements within `*` lists must be indented by four // spaces, or they will escape the list context. indenting everything @@ -539,8 +536,6 @@ mod test { use tystr_pass; use unindent_pass; - use core::str; - fn render(source: ~str) -> ~str { let (srv, doc) = create_doc_srv(source); let markdown = write_markdown_str_srv(srv, doc); diff --git a/src/librustdoc/page_pass.rs b/src/librustdoc/page_pass.rs index bb5d71e8db16..584e6ccc8873 100644 --- a/src/librustdoc/page_pass.rs +++ b/src/librustdoc/page_pass.rs @@ -157,7 +157,6 @@ mod test { use doc; use extract; use page_pass::run; - use core::vec; fn mk_doc_( output_style: config::OutputStyle, diff --git a/src/librustdoc/prune_hidden_pass.rs b/src/librustdoc/prune_hidden_pass.rs index 8a90d3f74d39..484eb8c7980d 100644 --- a/src/librustdoc/prune_hidden_pass.rs +++ b/src/librustdoc/prune_hidden_pass.rs @@ -77,8 +77,6 @@ mod test { #[test] fn should_prune_hidden_items() { - use core::vec; - let doc = mk_doc(~"#[doc(hidden)] mod a { }"); assert!(doc.cratemod().mods().is_empty()) } diff --git a/src/librustdoc/prune_private_pass.rs b/src/librustdoc/prune_private_pass.rs index e861939c2dde..741da3e265ee 100644 --- a/src/librustdoc/prune_private_pass.rs +++ b/src/librustdoc/prune_private_pass.rs @@ -162,7 +162,6 @@ mod test { use extract; use tystr_pass; use prune_private_pass::run; - use core::vec; fn mk_doc(source: ~str) -> doc::Doc { do astsrv::from_str(copy source) |srv| { diff --git a/src/librustdoc/sectionalize_pass.rs b/src/librustdoc/sectionalize_pass.rs index 8716f823848e..ba433bf479d2 100644 --- a/src/librustdoc/sectionalize_pass.rs +++ b/src/librustdoc/sectionalize_pass.rs @@ -19,7 +19,7 @@ use fold::Fold; use fold; use pass::Pass; -use core::str; +use core::iterator::IteratorUtil; pub fn mk_pass() -> Pass { Pass { @@ -104,21 +104,19 @@ fn sectionalize(desc: Option<~str>) -> (Option<~str>, ~[doc::Section]) { if desc.is_none() { return (None, ~[]); } - let mut lines = ~[]; - for str::each_line_any(*desc.get_ref()) |line| { lines.push(line.to_owned()); } let mut new_desc = None::<~str>; let mut current_section = None; let mut sections = ~[]; - for lines.each |line| { - match parse_header(copy *line) { + for desc.get_ref().any_line_iter().advance |line| { + match parse_header(line) { Some(header) => { if current_section.is_some() { - sections += [copy *current_section.get_ref()]; + sections.push(copy *current_section.get_ref()); } current_section = Some(doc::Section { - header: header, + header: header.to_owned(), body: ~"" }); } @@ -126,17 +124,17 @@ fn sectionalize(desc: Option<~str>) -> (Option<~str>, ~[doc::Section]) { match copy current_section { Some(section) => { current_section = Some(doc::Section { - body: section.body + "\n" + *line, + body: fmt!("%s\n%s", section.body, line), .. section }); } None => { new_desc = match copy new_desc { Some(desc) => { - Some(desc + "\n" + *line) + Some(fmt!("%s\n%s", desc, line)) } None => { - Some(copy *line) + Some(line.to_owned()) } }; } @@ -146,15 +144,15 @@ fn sectionalize(desc: Option<~str>) -> (Option<~str>, ~[doc::Section]) { } if current_section.is_some() { - sections += [current_section.get()]; + sections.push(current_section.unwrap()); } (new_desc, sections) } -fn parse_header(line: ~str) -> Option<~str> { +fn parse_header<'a>(line: &'a str) -> Option<&'a str> { if line.starts_with("# ") { - Some(line.slice(2u, line.len()).to_owned()) + Some(line.slice_from(2)) } else { None } @@ -172,9 +170,6 @@ mod test { use extract; use sectionalize_pass::run; - use core::str; - use core::vec; - fn mk_doc(source: ~str) -> doc::Doc { do astsrv::from_str(copy source) |srv| { let doc = extract::from_srv(srv.clone(), ~""); diff --git a/src/librustdoc/text_pass.rs b/src/librustdoc/text_pass.rs index 1f7a71e0fd89..6db582a60e98 100644 --- a/src/librustdoc/text_pass.rs +++ b/src/librustdoc/text_pass.rs @@ -149,8 +149,6 @@ mod test { use sectionalize_pass; use text_pass::mk_pass; - use core::str; - fn mk_doc(source: ~str) -> doc::Doc { do astsrv::from_str(copy source) |srv| { let doc = extract::from_srv(srv.clone(), ~""); diff --git a/src/librustdoc/unindent_pass.rs b/src/librustdoc/unindent_pass.rs index caf0e5376d12..2bcf04c0262e 100644 --- a/src/librustdoc/unindent_pass.rs +++ b/src/librustdoc/unindent_pass.rs @@ -21,7 +21,6 @@ middle of a line, and each of the following lines is indented. use core::prelude::*; -use core::str; use core::uint; use pass::Pass; use text_pass; @@ -31,8 +30,7 @@ pub fn mk_pass() -> Pass { } fn unindent(s: &str) -> ~str { - let mut lines = ~[]; - for str::each_line_any(s) |line| { lines.push(line.to_owned()); } + let lines = s.any_line_iter().collect::<~[&str]>(); let mut saw_first_line = false; let mut saw_second_line = false; let min_indent = do lines.iter().fold(uint::max_value) @@ -76,19 +74,20 @@ fn unindent(s: &str) -> ~str { } }; - if !lines.is_empty() { - let unindented = ~[lines.head().trim().to_owned()] - + do lines.tail().map |line| { - if line.is_whitespace() { - copy *line - } else { - assert!(line.len() >= min_indent); - line.slice(min_indent, line.len()).to_owned() - } - }; - unindented.connect("\n") - } else { - s.to_str() + match lines { + [head, .. tail] => { + let mut unindented = ~[ head.trim() ]; + unindented.push_all(do tail.map |&line| { + if line.is_whitespace() { + line + } else { + assert!(line.len() >= min_indent); + line.slice_from(min_indent) + } + }); + unindented.connect("\n") + } + [] => s.to_owned() } } diff --git a/src/librusti/rusti.rc b/src/librusti/rusti.rc index 06ec6769385c..c618623a2cb7 100644 --- a/src/librusti/rusti.rc +++ b/src/librusti/rusti.rc @@ -370,7 +370,7 @@ fn run_cmd(repl: &mut Repl, _in: @io::Reader, _out: @io::Writer, if arg.ends_with(".rs") || arg.ends_with(".rc") { (arg.slice_to(arg.len() - 3).to_owned(), copy *arg) } else { - (copy *arg, arg + ".rs") + (copy *arg, *arg + ".rs") }; match compile_crate(filename, copy repl.binary) { Some(_) => loaded_crates.push(crate), @@ -537,6 +537,9 @@ mod tests { } #[test] + // FIXME: #7220 rusti on 32bit mac doesn't work. + #[cfg(not(target_word_size="32", + target_os="macos"))] fn run_all() { // FIXME(#7071): // By default, unit tests are run in parallel. Rusti, on the other hand, @@ -648,6 +651,9 @@ mod tests { } #[test] + // FIXME: #7220 rusti on 32bit mac doesn't work. + #[cfg(not(target_word_size="32", + target_os="macos"))] fn exit_quits() { let mut r = repl(); assert!(r.running); diff --git a/src/librustpkg/tests.rs b/src/librustpkg/tests.rs index 6ec14e2aecf6..8b9158732696 100644 --- a/src/librustpkg/tests.rs +++ b/src/librustpkg/tests.rs @@ -309,7 +309,7 @@ fn frob_source_file(workspace: &Path, pkgid: &PkgId) { } } -#[test] +#[test] #[ignore] //FIXME(#7249) fn test_all() { // FIXME(#7071): these tests use rustc, so they can't be run in parallel // until this issue is resolved diff --git a/src/libstd/at_vec.rs b/src/libstd/at_vec.rs index a118e445fe20..18dfbd82c5ae 100644 --- a/src/libstd/at_vec.rs +++ b/src/libstd/at_vec.rs @@ -23,22 +23,8 @@ use vec; /// Code for dealing with @-vectors. This is pretty incomplete, and /// contains a bunch of duplication from the code for ~-vectors. -pub mod rustrt { - use libc; - use sys; - use vec; - - #[abi = "cdecl"] - #[link_name = "rustrt"] - pub extern { - pub unsafe fn vec_reserve_shared_actual(t: *sys::TypeDesc, - v: **vec::raw::VecRepr, - n: libc::size_t); - } -} - /// Returns the number of elements the vector can hold without reallocating -#[inline(always)] +#[inline] pub fn capacity(v: @[T]) -> uint { unsafe { let repr: **raw::VecRepr = transmute(&v); @@ -58,7 +44,7 @@ pub fn capacity(v: @[T]) -> uint { * as an argument a function that will push an element * onto the vector being constructed. */ -#[inline(always)] +#[inline] pub fn build_sized(size: uint, builder: &fn(push: &fn(v: A))) -> @[A] { let mut vec: @[A] = @[]; unsafe { raw::reserve(&mut vec, size); } @@ -76,7 +62,7 @@ pub fn build_sized(size: uint, builder: &fn(push: &fn(v: A))) -> @[A] { * as an argument a function that will push an element * onto the vector being constructed. */ -#[inline(always)] +#[inline] pub fn build(builder: &fn(push: &fn(v: A))) -> @[A] { build_sized(4, builder) } @@ -93,7 +79,7 @@ pub fn build(builder: &fn(push: &fn(v: A))) -> @[A] { * as an argument a function that will push an element * onto the vector being constructed. */ -#[inline(always)] +#[inline] pub fn build_sized_opt(size: Option, builder: &fn(push: &fn(v: A))) -> @[A] { @@ -104,11 +90,11 @@ pub fn build_sized_opt(size: Option, /// Iterates over the `rhs` vector, copying each element and appending it to the /// `lhs`. Afterwards, the `lhs` is then returned for use again. -#[inline(always)] +#[inline] pub fn append(lhs: @[T], rhs: &const [T]) -> @[T] { do build_sized(lhs.len() + rhs.len()) |push| { - for lhs.each |x| { push(*x); } - for uint::range(0, rhs.len()) |i| { push(rhs[i]); } + for lhs.each |x| { push(copy *x); } + for uint::range(0, rhs.len()) |i| { push(copy rhs[i]); } } } @@ -168,7 +154,7 @@ pub fn to_managed_consume(v: ~[T]) -> @[T] { * elements of a slice. */ pub fn to_managed(v: &[T]) -> @[T] { - from_fn(v.len(), |i| v[i]) + from_fn(v.len(), |i| copy v[i]) } #[cfg(not(test))] @@ -178,7 +164,7 @@ pub mod traits { use ops::Add; impl<'self,T:Copy> Add<&'self const [T],@[T]> for @[T] { - #[inline(always)] + #[inline] fn add(&self, rhs: & &'self const [T]) -> @[T] { append(*self, (*rhs)) } @@ -189,7 +175,7 @@ pub mod traits { pub mod traits {} pub mod raw { - use at_vec::{capacity, rustrt}; + use at_vec::capacity; use cast::{transmute, transmute_copy}; use libc; use ptr; @@ -197,6 +183,8 @@ pub mod raw { use uint; use unstable::intrinsics::{move_val_init}; use vec; + use vec::UnboxedVecRepr; + use sys::TypeDesc; pub type VecRepr = vec::raw::VecRepr; pub type SliceRepr = vec::raw::SliceRepr; @@ -208,7 +196,7 @@ pub mod raw { * modifing its buffers, so it is up to the caller to ensure that * the vector is actually the specified size. */ - #[inline(always)] + #[inline] pub unsafe fn set_len(v: @[T], new_len: uint) { let repr: **mut VecRepr = transmute(&v); (**repr).unboxed.fill = new_len * sys::size_of::(); @@ -217,7 +205,7 @@ pub mod raw { /** * Pushes a new value onto this vector. */ - #[inline(always)] + #[inline] pub unsafe fn push(v: &mut @[T], initval: T) { let repr: **VecRepr = transmute_copy(&v); let fill = (**repr).unboxed.fill; @@ -228,7 +216,7 @@ pub mod raw { } } - #[inline(always)] // really pretty please + #[inline] // really pretty please unsafe fn push_fast(v: &mut @[T], initval: T) { let repr: **mut VecRepr = ::cast::transmute(v); let fill = (**repr).unboxed.fill; @@ -257,9 +245,47 @@ pub mod raw { pub unsafe fn reserve(v: &mut @[T], n: uint) { // Only make the (slow) call into the runtime if we have to if capacity(*v) < n { - let ptr: **VecRepr = transmute(v); - rustrt::vec_reserve_shared_actual(sys::get_type_desc::(), - ptr, n as libc::size_t); + let ptr: *mut *mut VecRepr = transmute(v); + let ty = sys::get_type_desc::(); + return reserve_raw(ty, ptr, n); + } + } + + // Implementation detail. Shouldn't be public + #[allow(missing_doc)] + pub fn reserve_raw(ty: *TypeDesc, ptr: *mut *mut VecRepr, n: uint) { + + unsafe { + let size_in_bytes = n * (*ty).size; + if size_in_bytes > (**ptr).unboxed.alloc { + let total_size = size_in_bytes + sys::size_of::(); + // XXX: UnboxedVecRepr has an extra u8 at the end + let total_size = total_size - sys::size_of::(); + (*ptr) = local_realloc(*ptr as *(), total_size) as *mut VecRepr; + (**ptr).unboxed.alloc = size_in_bytes; + } + } + + fn local_realloc(ptr: *(), size: uint) -> *() { + use rt; + use rt::OldTaskContext; + use rt::local::Local; + use rt::task::Task; + + if rt::context() == OldTaskContext { + unsafe { + return rust_local_realloc(ptr, size as libc::size_t); + } + + extern { + #[fast_ffi] + fn rust_local_realloc(ptr: *(), size: libc::size_t) -> *(); + } + } else { + do Local::borrow:: |task| { + task.heap.realloc(ptr as *libc::c_void, size) as *() + } + } } } diff --git a/src/libstd/bool.rs b/src/libstd/bool.rs index 66a5bfa944f1..e6be164099bf 100644 --- a/src/libstd/bool.rs +++ b/src/libstd/bool.rs @@ -212,7 +212,7 @@ impl FromStr for bool { * ~~~ */ impl ToStr for bool { - #[inline(always)] + #[inline] fn to_str(&self) -> ~str { if *self { ~"true" } else { ~"false" } } @@ -250,24 +250,24 @@ pub fn all_values(blk: &fn(v: bool)) { * 0 * ~~~ */ -#[inline(always)] +#[inline] pub fn to_bit(v: bool) -> u8 { if v { 1u8 } else { 0u8 } } #[cfg(not(test))] impl Ord for bool { - #[inline(always)] + #[inline] fn lt(&self, other: &bool) -> bool { to_bit(*self) < to_bit(*other) } - #[inline(always)] + #[inline] fn le(&self, other: &bool) -> bool { to_bit(*self) <= to_bit(*other) } - #[inline(always)] + #[inline] fn gt(&self, other: &bool) -> bool { to_bit(*self) > to_bit(*other) } - #[inline(always)] + #[inline] fn ge(&self, other: &bool) -> bool { to_bit(*self) >= to_bit(*other) } } #[cfg(not(test))] impl TotalOrd for bool { - #[inline(always)] + #[inline] fn cmp(&self, other: &bool) -> Ordering { to_bit(*self).cmp(&to_bit(*other)) } } @@ -298,9 +298,9 @@ impl TotalOrd for bool { */ #[cfg(not(test))] impl Eq for bool { - #[inline(always)] + #[inline] fn eq(&self, other: &bool) -> bool { (*self) == (*other) } - #[inline(always)] + #[inline] fn ne(&self, other: &bool) -> bool { (*self) != (*other) } } diff --git a/src/libstd/borrow.rs b/src/libstd/borrow.rs index 703011aea7f8..9e3a3a28fe8c 100644 --- a/src/libstd/borrow.rs +++ b/src/libstd/borrow.rs @@ -14,13 +14,13 @@ use prelude::*; /// Cast a region pointer - &T - to a uint. -#[inline(always)] +#[inline] pub fn to_uint(thing: &T) -> uint { thing as *T as uint } /// Determine if two borrowed pointers point to the same thing. -#[inline(always)] +#[inline] pub fn ref_eq<'a, 'b, T>(thing: &'a T, other: &'b T) -> bool { to_uint(thing) == to_uint(other) } @@ -28,11 +28,11 @@ pub fn ref_eq<'a, 'b, T>(thing: &'a T, other: &'b T) -> bool { // Equality for region pointers #[cfg(not(test))] impl<'self, T: Eq> Eq for &'self T { - #[inline(always)] + #[inline] fn eq(&self, other: & &'self T) -> bool { *(*self) == *(*other) } - #[inline(always)] + #[inline] fn ne(&self, other: & &'self T) -> bool { *(*self) != *(*other) } @@ -41,19 +41,19 @@ impl<'self, T: Eq> Eq for &'self T { // Comparison for region pointers #[cfg(not(test))] impl<'self, T: Ord> Ord for &'self T { - #[inline(always)] + #[inline] fn lt(&self, other: & &'self T) -> bool { *(*self) < *(*other) } - #[inline(always)] + #[inline] fn le(&self, other: & &'self T) -> bool { *(*self) <= *(*other) } - #[inline(always)] + #[inline] fn ge(&self, other: & &'self T) -> bool { *(*self) >= *(*other) } - #[inline(always)] + #[inline] fn gt(&self, other: & &'self T) -> bool { *(*self) > *(*other) } diff --git a/src/libstd/cast.rs b/src/libstd/cast.rs index 2109568a0a4e..30b6b030dba2 100644 --- a/src/libstd/cast.rs +++ b/src/libstd/cast.rs @@ -14,22 +14,9 @@ use sys; use unstable::intrinsics; /// Casts the value at `src` to U. The two types must have the same length. -#[cfg(stage0)] -pub unsafe fn transmute_copy(src: &T) -> U { - let mut dest: U = intrinsics::uninit(); - { - let dest_ptr: *mut u8 = transmute(&mut dest); - let src_ptr: *u8 = transmute(src); - intrinsics::memmove64(dest_ptr, - src_ptr, - sys::size_of::() as u64); - } - dest -} - /// Casts the value at `src` to U. The two types must have the same length. -#[cfg(target_word_size = "32", not(stage0))] -#[inline(always)] +#[cfg(target_word_size = "32")] +#[inline] pub unsafe fn transmute_copy(src: &T) -> U { let mut dest: U = intrinsics::uninit(); let dest_ptr: *mut u8 = transmute(&mut dest); @@ -39,8 +26,8 @@ pub unsafe fn transmute_copy(src: &T) -> U { } /// Casts the value at `src` to U. The two types must have the same length. -#[cfg(target_word_size = "64", not(stage0))] -#[inline(always)] +#[cfg(target_word_size = "64")] +#[inline] pub unsafe fn transmute_copy(src: &T) -> U { let mut dest: U = intrinsics::uninit(); let dest_ptr: *mut u8 = transmute(&mut dest); @@ -54,19 +41,16 @@ pub unsafe fn transmute_copy(src: &T) -> U { * * The forget function will take ownership of the provided value but neglect * to run any required cleanup or memory-management operations on it. This - * can be used for various acts of magick, particularly when using - * reinterpret_cast on pointer types. + * can be used for various acts of magick. */ -#[inline(always)] +#[inline] pub unsafe fn forget(thing: T) { intrinsics::forget(thing); } /** * Force-increment the reference count on a shared box. If used - * carelessly, this can leak the box. Use this in conjunction with transmute - * and/or reinterpret_cast when such calls would otherwise scramble a box's - * reference count + * carelessly, this can leak the box. */ -#[inline(always)] +#[inline] pub unsafe fn bump_box_refcount(t: @T) { forget(t); } /** @@ -77,59 +61,59 @@ pub unsafe fn bump_box_refcount(t: @T) { forget(t); } * * assert!(transmute("L") == ~[76u8, 0u8]); */ -#[inline(always)] +#[inline] pub unsafe fn transmute(thing: L) -> G { intrinsics::transmute(thing) } /// Coerce an immutable reference to be mutable. -#[inline(always)] +#[inline] pub unsafe fn transmute_mut<'a,T>(ptr: &'a T) -> &'a mut T { transmute(ptr) } /// Coerce a mutable reference to be immutable. -#[inline(always)] +#[inline] pub unsafe fn transmute_immut<'a,T>(ptr: &'a mut T) -> &'a T { transmute(ptr) } /// Coerce a borrowed pointer to have an arbitrary associated region. -#[inline(always)] +#[inline] pub unsafe fn transmute_region<'a,'b,T>(ptr: &'a T) -> &'b T { transmute(ptr) } /// Coerce an immutable reference to be mutable. -#[inline(always)] +#[inline] pub unsafe fn transmute_mut_unsafe(ptr: *const T) -> *mut T { transmute(ptr) } /// Coerce an immutable reference to be mutable. -#[inline(always)] +#[inline] pub unsafe fn transmute_immut_unsafe(ptr: *const T) -> *T { transmute(ptr) } /// Coerce a borrowed mutable pointer to have an arbitrary associated region. -#[inline(always)] +#[inline] pub unsafe fn transmute_mut_region<'a,'b,T>(ptr: &'a mut T) -> &'b mut T { transmute(ptr) } /// Transforms lifetime of the second pointer to match the first. -#[inline(always)] +#[inline] pub unsafe fn copy_lifetime<'a,S,T>(_ptr: &'a S, ptr: &T) -> &'a T { transmute_region(ptr) } /// Transforms lifetime of the second pointer to match the first. -#[inline(always)] +#[inline] pub unsafe fn copy_mut_lifetime<'a,S,T>(_ptr: &'a mut S, ptr: &mut T) -> &'a mut T { transmute_mut_region(ptr) } /// Transforms lifetime of the second pointer to match the first. -#[inline(always)] +#[inline] pub unsafe fn copy_lifetime_vec<'a,S,T>(_ptr: &'a [S], ptr: &T) -> &'a T { transmute_region(ptr) } diff --git a/src/libstd/char.rs b/src/libstd/char.rs index 073ced8988ad..797fd9e8c020 100644 --- a/src/libstd/char.rs +++ b/src/libstd/char.rs @@ -17,8 +17,8 @@ use u32; use uint; use unicode::{derived_property, general_category}; -#[cfg(not(test))] -use cmp::{Eq, Ord}; +#[cfg(not(test))] use cmp::{Eq, Ord}; +#[cfg(not(test))] use num::Zero; /* Lu Uppercase_Letter an uppercase letter @@ -65,14 +65,14 @@ pub fn is_XID_continue(c: char) -> bool { derived_property::XID_Continue(c) } /// Indicates whether a character is in lower case, defined /// in terms of the Unicode General Category 'Ll' /// -#[inline(always)] +#[inline] pub fn is_lowercase(c: char) -> bool { general_category::Ll(c) } /// /// Indicates whether a character is in upper case, defined /// in terms of the Unicode General Category 'Lu'. /// -#[inline(always)] +#[inline] pub fn is_uppercase(c: char) -> bool { general_category::Lu(c) } /// @@ -80,7 +80,7 @@ pub fn is_uppercase(c: char) -> bool { general_category::Lu(c) } /// terms of the Unicode General Categories 'Zs', 'Zl', 'Zp' /// additional 'Cc'-category control codes in the range [0x09, 0x0d] /// -#[inline(always)] +#[inline] pub fn is_whitespace(c: char) -> bool { ('\x09' <= c && c <= '\x0d') || general_category::Zs(c) @@ -93,7 +93,7 @@ pub fn is_whitespace(c: char) -> bool { /// defined in terms of the Unicode General Categories 'Nd', 'Nl', 'No' /// and the Derived Core Property 'Alphabetic'. /// -#[inline(always)] +#[inline] pub fn is_alphanumeric(c: char) -> bool { derived_property::Alphabetic(c) || general_category::Nd(c) @@ -102,7 +102,7 @@ pub fn is_alphanumeric(c: char) -> bool { } /// Indicates whether the character is numeric (Nd, Nl, or No) -#[inline(always)] +#[inline] pub fn is_digit(c: char) -> bool { general_category::Nd(c) || general_category::Nl(c) @@ -127,7 +127,7 @@ pub fn is_digit(c: char) -> bool { /// /// This just wraps `to_digit()`. /// -#[inline(always)] +#[inline] pub fn is_digit_radix(c: char, radix: uint) -> bool { match to_digit(c, radix) { Some(_) => true, @@ -310,24 +310,30 @@ impl Char for char { #[cfg(not(test))] impl Eq for char { - #[inline(always)] + #[inline] fn eq(&self, other: &char) -> bool { (*self) == (*other) } - #[inline(always)] + #[inline] fn ne(&self, other: &char) -> bool { (*self) != (*other) } } #[cfg(not(test))] impl Ord for char { - #[inline(always)] + #[inline] fn lt(&self, other: &char) -> bool { *self < *other } - #[inline(always)] + #[inline] fn le(&self, other: &char) -> bool { *self <= *other } - #[inline(always)] + #[inline] fn gt(&self, other: &char) -> bool { *self > *other } - #[inline(always)] + #[inline] fn ge(&self, other: &char) -> bool { *self >= *other } } +#[cfg(not(test))] +impl Zero for char { + fn zero() -> char { 0 as char } + fn is_zero(&self) -> bool { *self == 0 as char } +} + #[test] fn test_is_lowercase() { assert!('a'.is_lowercase()); diff --git a/src/libstd/cleanup.rs b/src/libstd/cleanup.rs index d1460b7a3c96..36c1fdf781b2 100644 --- a/src/libstd/cleanup.rs +++ b/src/libstd/cleanup.rs @@ -13,107 +13,14 @@ use libc::{c_char, c_void, intptr_t, uintptr_t}; use ptr::mut_null; use repr::BoxRepr; +use rt; +use rt::OldTaskContext; use sys::TypeDesc; use cast::transmute; -#[cfg(not(test))] use unstable::lang::clear_task_borrow_list; #[cfg(not(test))] use ptr::to_unsafe_ptr; -/** - * Runtime structures - * - * NB: These must match the representation in the C++ runtime. - */ - type DropGlue<'self> = &'self fn(**TypeDesc, *c_void); -type FreeGlue<'self> = &'self fn(**TypeDesc, *c_void); - -type TaskID = uintptr_t; - -struct StackSegment { priv opaque: () } -struct Scheduler { priv opaque: () } -struct SchedulerLoop { priv opaque: () } -struct Kernel { priv opaque: () } -struct Env { priv opaque: () } -struct AllocHeader { priv opaque: () } -struct MemoryRegion { priv opaque: () } - -#[cfg(target_arch="x86")] -struct Registers { - data: [u32, ..16] -} - -#[cfg(target_arch="arm")] -#[cfg(target_arch="mips")] -struct Registers { - data: [u32, ..32] -} - -#[cfg(target_arch="x86")] -#[cfg(target_arch="arm")] -#[cfg(target_arch="mips")] -struct Context { - regs: Registers, - next: *Context, - pad: [u32, ..3] -} - -#[cfg(target_arch="x86_64")] -struct Registers { - data: [u64, ..22] -} - -#[cfg(target_arch="x86_64")] -struct Context { - regs: Registers, - next: *Context, - pad: uintptr_t -} - -struct BoxedRegion { - env: *Env, - backing_region: *MemoryRegion, - live_allocs: *BoxRepr -} - -#[cfg(target_arch="x86")] -#[cfg(target_arch="arm")] -#[cfg(target_arch="mips")] -struct Task { - // Public fields - refcount: intptr_t, // 0 - id: TaskID, // 4 - pad: [u32, ..2], // 8 - ctx: Context, // 16 - stack_segment: *StackSegment, // 96 - runtime_sp: uintptr_t, // 100 - scheduler: *Scheduler, // 104 - scheduler_loop: *SchedulerLoop, // 108 - - // Fields known only to the runtime - kernel: *Kernel, // 112 - name: *c_char, // 116 - list_index: i32, // 120 - boxed_region: BoxedRegion // 128 -} - -#[cfg(target_arch="x86_64")] -struct Task { - // Public fields - refcount: intptr_t, - id: TaskID, - ctx: Context, - stack_segment: *StackSegment, - runtime_sp: uintptr_t, - scheduler: *Scheduler, - scheduler_loop: *SchedulerLoop, - - // Fields known only to the runtime - kernel: *Kernel, - name: *c_char, - list_index: i32, - boxed_region: BoxedRegion -} /* * Box annihilation @@ -132,9 +39,9 @@ unsafe fn each_live_alloc(read_next_before: bool, //! Walks the internal list of allocations use managed; + use rt::local_heap; - let task: *Task = transmute(rustrt::rust_get_task()); - let box = (*task).boxed_region.live_allocs; + let box = local_heap::live_allocs(); let mut box: *mut BoxRepr = transmute(copy box); while box != mut_null() { let next_before = transmute(copy (*box).header.next); @@ -156,7 +63,11 @@ unsafe fn each_live_alloc(read_next_before: bool, #[cfg(unix)] fn debug_mem() -> bool { - ::rt::env::get().debug_mem + // XXX: Need to port the environment struct to newsched + match rt::context() { + OldTaskContext => ::rt::env::get().debug_mem, + _ => false + } } #[cfg(windows)] @@ -165,13 +76,12 @@ fn debug_mem() -> bool { } /// Destroys all managed memory (i.e. @ boxes) held by the current task. -#[cfg(not(test))] -#[lang="annihilate"] pub unsafe fn annihilate() { - use unstable::lang::local_free; + use rt::local_heap::local_free; use io::WriterUtil; use io; use libc; + use rt::borrowck; use sys; use managed; @@ -183,7 +93,7 @@ pub unsafe fn annihilate() { // Quick hack: we need to free this list upon task exit, and this // is a convenient place to do it. - clear_task_borrow_list(); + borrowck::clear_task_borrow_list(); // Pass 1: Make all boxes immortal. // @@ -207,7 +117,7 @@ pub unsafe fn annihilate() { if !uniq { let tydesc: *TypeDesc = transmute(copy (*box).header.type_desc); let drop_glue: DropGlue = transmute(((*tydesc).drop_glue, 0)); - drop_glue(to_unsafe_ptr(&tydesc), transmute(&(*box).data)); + drop_glue(&tydesc, transmute(&(*box).data)); } } diff --git a/src/libstd/clone.rs b/src/libstd/clone.rs index 266dd1a35e32..5ec594cef7ee 100644 --- a/src/libstd/clone.rs +++ b/src/libstd/clone.rs @@ -34,25 +34,25 @@ pub trait Clone { impl Clone for ~T { /// Return a deep copy of the owned box. - #[inline(always)] + #[inline] fn clone(&self) -> ~T { ~(**self).clone() } } impl Clone for @T { /// Return a shallow copy of the managed box. - #[inline(always)] + #[inline] fn clone(&self) -> @T { *self } } impl Clone for @mut T { /// Return a shallow copy of the managed box. - #[inline(always)] + #[inline] fn clone(&self) -> @mut T { *self } } impl<'self, T> Clone for &'self T { /// Return a shallow copy of the borrowed pointer. - #[inline(always)] + #[inline] fn clone(&self) -> &'self T { *self } } @@ -60,7 +60,7 @@ macro_rules! clone_impl( ($t:ty) => { impl Clone for $t { /// Return a deep copy of the value. - #[inline(always)] + #[inline] fn clone(&self) -> $t { *self } } } @@ -96,7 +96,7 @@ pub trait DeepClone { impl DeepClone for ~T { /// Return a deep copy of the owned box. - #[inline(always)] + #[inline] fn deep_clone(&self) -> ~T { ~(**self).deep_clone() } } @@ -104,7 +104,7 @@ impl DeepClone for ~T { impl DeepClone for @T { /// Return a deep copy of the managed box. The `Const` trait is required to prevent performing /// a deep clone of a potentially cyclical type. - #[inline(always)] + #[inline] fn deep_clone(&self) -> @T { @(**self).deep_clone() } } @@ -112,7 +112,7 @@ impl DeepClone for @T { impl DeepClone for @mut T { /// Return a deep copy of the managed box. The `Const` trait is required to prevent performing /// a deep clone of a potentially cyclical type. - #[inline(always)] + #[inline] fn deep_clone(&self) -> @mut T { @mut (**self).deep_clone() } } @@ -120,7 +120,7 @@ macro_rules! deep_clone_impl( ($t:ty) => { impl DeepClone for $t { /// Return a deep copy of the value. - #[inline(always)] + #[inline] fn deep_clone(&self) -> $t { *self } } } diff --git a/src/libstd/cmp.rs b/src/libstd/cmp.rs index ce6a04c3688b..2c4bb46b23b8 100644 --- a/src/libstd/cmp.rs +++ b/src/libstd/cmp.rs @@ -45,7 +45,7 @@ pub trait TotalEq { macro_rules! totaleq_impl( ($t:ty) => { impl TotalEq for $t { - #[inline(always)] + #[inline] fn equals(&self, other: &$t) -> bool { *self == *other } } } @@ -84,27 +84,27 @@ pub trait TotalOrd: TotalEq { } impl TotalOrd for Ordering { - #[inline(always)] + #[inline] fn cmp(&self, other: &Ordering) -> Ordering { (*self as int).cmp(&(*other as int)) } } impl Ord for Ordering { - #[inline(always)] + #[inline] fn lt(&self, other: &Ordering) -> bool { (*self as int) < (*other as int) } - #[inline(always)] + #[inline] fn le(&self, other: &Ordering) -> bool { (*self as int) <= (*other as int) } - #[inline(always)] + #[inline] fn gt(&self, other: &Ordering) -> bool { (*self as int) > (*other as int) } - #[inline(always)] + #[inline] fn ge(&self, other: &Ordering) -> bool { (*self as int) >= (*other as int) } } macro_rules! totalord_impl( ($t:ty) => { impl TotalOrd for $t { - #[inline(always)] + #[inline] fn cmp(&self, other: &$t) -> Ordering { if *self < *other { Less } else if *self > *other { Greater } @@ -146,7 +146,7 @@ Return `o1` if it is not `Equal`, otherwise `o2`. Simulates the lexical ordering on a type `(int, int)`. */ // used in deriving code in libsyntax -#[inline(always)] +#[inline] pub fn lexical_ordering(o1: Ordering, o2: Ordering) -> Ordering { match o1 { Equal => o2, @@ -180,12 +180,12 @@ pub trait Equiv { fn equiv(&self, other: &T) -> bool; } -#[inline(always)] +#[inline] pub fn min(v1: T, v2: T) -> T { if v1 < v2 { v1 } else { v2 } } -#[inline(always)] +#[inline] pub fn max(v1: T, v2: T) -> T { if v1 > v2 { v1 } else { v2 } } diff --git a/src/libstd/comm.rs b/src/libstd/comm.rs index f0c353c8d62b..00c33c8ab325 100644 --- a/src/libstd/comm.rs +++ b/src/libstd/comm.rs @@ -20,7 +20,6 @@ use either::{Either, Left, Right}; use kinds::Owned; use option::{Option, Some, None}; use uint; -use vec; use vec::OwnedVector; use util::replace; use unstable::sync::{Exclusive, exclusive}; @@ -209,7 +208,7 @@ impl Peekable for PortSet { fn peek(&self) -> bool { // It'd be nice to use self.port.each, but that version isn't // pure. - for uint::range(0, vec::uniq_len(&const self.ports)) |i| { + for uint::range(0, self.ports.len()) |i| { let port: &pipesy::Port = &self.ports[i]; if port.peek() { return true; @@ -221,7 +220,7 @@ impl Peekable for PortSet { /// A channel that can be shared between many senders. pub struct SharedChan { - ch: Exclusive> + inner: Either>, rtcomm::SharedChan> } impl SharedChan { @@ -229,40 +228,50 @@ impl SharedChan { pub fn new(c: Chan) -> SharedChan { let Chan { inner } = c; let c = match inner { - Left(c) => c, - Right(_) => fail!("SharedChan not implemented") + Left(c) => Left(exclusive(c)), + Right(c) => Right(rtcomm::SharedChan::new(c)) }; - SharedChan { ch: exclusive(c) } + SharedChan { inner: c } } } impl GenericChan for SharedChan { fn send(&self, x: T) { - unsafe { - let mut xx = Some(x); - do self.ch.with_imm |chan| { - let x = replace(&mut xx, None); - chan.send(x.unwrap()) + match self.inner { + Left(ref chan) => { + unsafe { + let mut xx = Some(x); + do chan.with_imm |chan| { + let x = replace(&mut xx, None); + chan.send(x.unwrap()) + } + } } + Right(ref chan) => chan.send(x) } } } impl GenericSmartChan for SharedChan { fn try_send(&self, x: T) -> bool { - unsafe { - let mut xx = Some(x); - do self.ch.with_imm |chan| { - let x = replace(&mut xx, None); - chan.try_send(x.unwrap()) + match self.inner { + Left(ref chan) => { + unsafe { + let mut xx = Some(x); + do chan.with_imm |chan| { + let x = replace(&mut xx, None); + chan.try_send(x.unwrap()) + } + } } + Right(ref chan) => chan.try_send(x) } } } impl ::clone::Clone for SharedChan { fn clone(&self) -> SharedChan { - SharedChan { ch: self.ch.clone() } + SharedChan { inner: self.inner.clone() } } } @@ -625,7 +634,7 @@ mod pipesy { } impl GenericChan for Chan { - #[inline(always)] + #[inline] fn send(&self, x: T) { unsafe { let self_endp = transmute_mut(&self.endp); @@ -636,7 +645,7 @@ mod pipesy { } impl GenericSmartChan for Chan { - #[inline(always)] + #[inline] fn try_send(&self, x: T) -> bool { unsafe { let self_endp = transmute_mut(&self.endp); @@ -653,7 +662,7 @@ mod pipesy { } impl GenericPort for Port { - #[inline(always)] + #[inline] fn recv(&self) -> T { unsafe { let self_endp = transmute_mut(&self.endp); @@ -664,7 +673,7 @@ mod pipesy { } } - #[inline(always)] + #[inline] fn try_recv(&self) -> Option { unsafe { let self_endp = transmute_mut(&self.endp); @@ -681,7 +690,7 @@ mod pipesy { } impl Peekable for Port { - #[inline(always)] + #[inline] fn peek(&self) -> bool { unsafe { let self_endp = transmute_mut(&self.endp); diff --git a/src/libstd/container.rs b/src/libstd/container.rs index 065582e2e0d2..c1b656f1cd9e 100644 --- a/src/libstd/container.rs +++ b/src/libstd/container.rs @@ -16,10 +16,10 @@ use option::Option; /// knowledge known is the number of elements contained within. pub trait Container { /// Return the number of elements in the container - fn len(&const self) -> uint; + fn len(&self) -> uint; /// Return true if the container contains no elements - fn is_empty(&const self) -> bool; + fn is_empty(&self) -> bool; } /// A trait to represent mutable containers diff --git a/src/libstd/core.rc b/src/libstd/core.rc index 8e09a9b17fdb..6911c00e55ba 100644 --- a/src/libstd/core.rc +++ b/src/libstd/core.rc @@ -12,19 +12,20 @@ # The Rust standard library -The Rust standard library provides runtime features required by the language, -including the task scheduler and memory allocators, as well as library -support for Rust built-in types, platform abstractions, and other commonly -used features. +The Rust standard library is a group of interrelated modules defining +the core language traits, operations on built-in data types, collections, +platform abstractions, the task scheduler, runtime support for language +features and other common functionality. -`std` includes modules corresponding to each of the integer types, each of -the floating point types, the `bool` type, tuples, characters, strings -(`str`), vectors (`vec`), managed boxes (`managed`), owned boxes (`owned`), -and unsafe and borrowed pointers (`ptr`). Additionally, `std` provides -pervasive types (`option` and `result`), task creation and communication -primitives (`task`, `comm`), platform abstractions (`os` and `path`), basic -I/O abstractions (`io`), common traits (`kinds`, `ops`, `cmp`, `num`, -`to_str`), and complete bindings to the C standard library (`libc`). +`std` includes modules corresponding to each of the integer types, +each of the floating point types, the `bool` type, tuples, characters, +strings (`str`), vectors (`vec`), managed boxes (`managed`), owned +boxes (`owned`), and unsafe and borrowed pointers (`ptr`, `borrowed`). +Additionally, `std` provides pervasive types (`option` and `result`), +task creation and communication primitives (`task`, `comm`), platform +abstractions (`os` and `path`), basic I/O abstractions (`io`), common +traits (`kinds`, `ops`, `cmp`, `num`, `to_str`), and complete bindings +to the C standard library (`libc`). # Standard library injection and the Rust prelude @@ -38,7 +39,7 @@ with the `std::` path prefix, as in `use std::vec`, `use std::task::spawn`, etc. Additionally, `std` contains a `prelude` module that reexports many of the -most common std modules, types and traits. The contents of the prelude are +most common types, traits and functions. The contents of the prelude are imported into every *module* by default. Implicitly, all modules behave as if they contained the following prologue: @@ -56,17 +57,13 @@ they contained the following prologue: #[license = "MIT/ASL2"]; #[crate_type = "lib"]; -// NOTE: remove these two attributes after the next snapshot -#[no_core]; // for stage0 -#[allow(unrecognized_lint)]; // otherwise stage0 is seriously ugly - // Don't link to std. We are std. #[no_std]; #[deny(non_camel_case_types)]; #[deny(missing_doc)]; -// Make core testable by not duplicating lang items. See #2912 +// Make std testable by not duplicating lang items. See #2912 #[cfg(test)] extern mod realstd(name = "std"); #[cfg(test)] pub use kinds = realstd::kinds; #[cfg(test)] pub use ops = realstd::ops; diff --git a/src/libstd/either.rs b/src/libstd/either.rs index fac0866f17e7..681a7fbc821f 100644 --- a/src/libstd/either.rs +++ b/src/libstd/either.rs @@ -33,7 +33,7 @@ pub enum Either { /// If `value` is left(T) then `f_left` is applied to its contents, if /// `value` is right(U) then `f_right` is applied to its contents, and the /// result is returned. -#[inline(always)] +#[inline] pub fn either(f_left: &fn(&T) -> V, f_right: &fn(&U) -> V, value: &Either) -> V { match *value { @@ -47,7 +47,7 @@ pub fn lefts(eithers: &[Either]) -> ~[T] { do vec::build_sized(eithers.len()) |push| { for eithers.each |elt| { match *elt { - Left(ref l) => { push(*l); } + Left(ref l) => { push(copy *l); } _ => { /* fallthrough */ } } } @@ -59,7 +59,7 @@ pub fn rights(eithers: &[Either]) -> ~[U] { do vec::build_sized(eithers.len()) |push| { for eithers.each |elt| { match *elt { - Right(ref r) => { push(*r); } + Right(ref r) => { push(copy *r); } _ => { /* fallthrough */ } } } @@ -83,7 +83,7 @@ pub fn partition(eithers: ~[Either]) -> (~[T], ~[U]) { } /// Flips between left and right of a given either -#[inline(always)] +#[inline] pub fn flip(eith: Either) -> Either { match eith { Right(r) => Left(r), @@ -95,7 +95,7 @@ pub fn flip(eith: Either) -> Either { /// /// Converts an `either` type to a `result` type, making the "right" choice /// an ok result, and the "left" choice a fail -#[inline(always)] +#[inline] pub fn to_result(eith: Either) -> Result { match eith { Right(r) => result::Ok(r), @@ -104,7 +104,7 @@ pub fn to_result(eith: Either) -> Result { } /// Checks whether the given value is a left -#[inline(always)] +#[inline] pub fn is_left(eith: &Either) -> bool { match *eith { Left(_) => true, @@ -113,7 +113,7 @@ pub fn is_left(eith: &Either) -> bool { } /// Checks whether the given value is a right -#[inline(always)] +#[inline] pub fn is_right(eith: &Either) -> bool { match *eith { Right(_) => true, @@ -122,7 +122,7 @@ pub fn is_right(eith: &Either) -> bool { } /// Retrieves the value in the left branch. Fails if the either is Right. -#[inline(always)] +#[inline] pub fn unwrap_left(eith: Either) -> T { match eith { Left(x) => x, @@ -131,7 +131,7 @@ pub fn unwrap_left(eith: Either) -> T { } /// Retrieves the value in the right branch. Fails if the either is Left. -#[inline(always)] +#[inline] pub fn unwrap_right(eith: Either) -> U { match eith { Right(x) => x, @@ -140,27 +140,27 @@ pub fn unwrap_right(eith: Either) -> U { } impl Either { - #[inline(always)] + #[inline] pub fn either(&self, f_left: &fn(&T) -> V, f_right: &fn(&U) -> V) -> V { either(f_left, f_right, self) } - #[inline(always)] + #[inline] pub fn flip(self) -> Either { flip(self) } - #[inline(always)] + #[inline] pub fn to_result(self) -> Result { to_result(self) } - #[inline(always)] + #[inline] pub fn is_left(&self) -> bool { is_left(self) } - #[inline(always)] + #[inline] pub fn is_right(&self) -> bool { is_right(self) } - #[inline(always)] + #[inline] pub fn unwrap_left(self) -> T { unwrap_left(self) } - #[inline(always)] + #[inline] pub fn unwrap_right(self) -> U { unwrap_right(self) } } diff --git a/src/libstd/hash.rs b/src/libstd/hash.rs index e90224457863..1967a57e867f 100644 --- a/src/libstd/hash.rs +++ b/src/libstd/hash.rs @@ -64,7 +64,7 @@ pub trait HashUtil { } impl HashUtil for A { - #[inline(always)] + #[inline] fn hash(&self) -> u64 { self.hash_keyed(0,0) } } @@ -79,7 +79,7 @@ pub trait Streaming { } impl Hash for A { - #[inline(always)] + #[inline] fn hash_keyed(&self, k0: u64, k1: u64) -> u64 { let mut s = State::new(k0, k1); for self.iter_bytes(true) |bytes| { @@ -176,7 +176,7 @@ fn hash_keyed_5 State { State::new(0, 0) } @@ -194,7 +194,7 @@ struct SipState { } impl SipState { - #[inline(always)] + #[inline] fn new(key0: u64, key1: u64) -> SipState { let mut state = SipState { k0: key0, @@ -248,7 +248,7 @@ macro_rules! compress ( impl Writer for SipState { // Methods for io::writer - #[inline(always)] + #[inline] fn write(&mut self, msg: &[u8]) { let length = msg.len(); self.length += length; @@ -315,12 +315,12 @@ impl Writer for SipState { } impl Streaming for SipState { - #[inline(always)] + #[inline] fn input(&mut self, buf: &[u8]) { self.write(buf); } - #[inline(always)] + #[inline] fn result_u64(&mut self) -> u64 { let mut v0 = self.v0; let mut v1 = self.v1; @@ -373,7 +373,7 @@ impl Streaming for SipState { s } - #[inline(always)] + #[inline] fn reset(&mut self) { self.length = 0; self.v0 = self.k0 ^ 0x736f6d6570736575; @@ -558,4 +558,15 @@ mod tests { val & !(0xff << (byte * 8)) } } + + #[test] + fn test_float_hashes_differ() { + assert!(0.0.hash() != 1.0.hash()); + assert!(1.0.hash() != (-1.0).hash()); + } + + #[test] + fn test_float_hashes_of_zero() { + assert_eq!(0.0.hash(), (-0.0).hash()); + } } diff --git a/src/libstd/hashmap.rs b/src/libstd/hashmap.rs index 85156d6996d9..d05fa63a6f9b 100644 --- a/src/libstd/hashmap.rs +++ b/src/libstd/hashmap.rs @@ -59,7 +59,7 @@ enum SearchResult { FoundEntry(uint), FoundHole(uint), TableFull } -#[inline(always)] +#[inline] fn resize_at(capacity: uint) -> uint { ((capacity as float) * 3. / 4.) as uint } @@ -85,19 +85,19 @@ fn linear_map_with_capacity_and_keys( } impl HashMap { - #[inline(always)] + #[inline] fn to_bucket(&self, h: uint) -> uint { // A good hash function with entropy spread over all of the // bits is assumed. SipHash is more than good enough. h % self.buckets.len() } - #[inline(always)] + #[inline] fn next_bucket(&self, idx: uint, len_buckets: uint) -> uint { (idx + 1) % len_buckets } - #[inline(always)] + #[inline] fn bucket_sequence(&self, hash: uint, op: &fn(uint) -> bool) -> bool { let start_idx = self.to_bucket(hash); @@ -112,20 +112,20 @@ impl HashMap { } } - #[inline(always)] + #[inline] fn bucket_for_key(&self, k: &K) -> SearchResult { let hash = k.hash_keyed(self.k0, self.k1) as uint; self.bucket_for_key_with_hash(hash, k) } - #[inline(always)] + #[inline] fn bucket_for_key_equiv>(&self, k: &Q) -> SearchResult { let hash = k.hash_keyed(self.k0, self.k1) as uint; self.bucket_for_key_with_hash_equiv(hash, k) } - #[inline(always)] + #[inline] fn bucket_for_key_with_hash(&self, hash: uint, k: &K) @@ -141,7 +141,7 @@ impl HashMap { TableFull } - #[inline(always)] + #[inline] fn bucket_for_key_with_hash_equiv>(&self, hash: uint, k: &Q) @@ -161,7 +161,7 @@ impl HashMap { /// Expand the capacity of the array to the next power of two /// and re-insert each of the existing buckets. - #[inline(always)] + #[inline] fn expand(&mut self) { let new_capacity = self.buckets.len() * 2; self.resize(new_capacity); @@ -190,7 +190,7 @@ impl HashMap { } } - #[inline(always)] + #[inline] fn value_for_bucket<'a>(&'a self, idx: uint) -> &'a V { match self.buckets[idx] { Some(ref bkt) => &bkt.value, @@ -198,7 +198,7 @@ impl HashMap { } } - #[inline(always)] + #[inline] fn mut_value_for_bucket<'a>(&'a mut self, idx: uint) -> &'a mut V { match self.buckets[idx] { Some(ref mut bkt) => &mut bkt.value, diff --git a/src/libstd/io.rs b/src/libstd/io.rs index 6f065d74fa2e..e5e8a4cb6018 100644 --- a/src/libstd/io.rs +++ b/src/libstd/io.rs @@ -1654,9 +1654,7 @@ impl Writer for BytesWriter { vec::reserve(bytes, count); unsafe { - // Silly stage0 borrow check workaround... - let casted: &mut ~[u8] = cast::transmute_copy(&bytes); - vec::raw::set_len(casted, count); + vec::raw::set_len(bytes, count); let view = vec::mut_slice(*bytes, *self.pos, count); vec::bytes::copy_memory(view, v, v_len); @@ -1667,7 +1665,7 @@ impl Writer for BytesWriter { fn seek(&self, offset: int, whence: SeekStyle) { let pos = *self.pos; - let len = vec::uniq_len(&const *self.bytes); + let len = self.bytes.len(); *self.pos = seek_in_buf(offset, pos, len, whence); } @@ -1779,7 +1777,7 @@ pub mod fsync { None => (), Some(level) => { // fail hard if not succesful - assert!(((self.arg.fsync_fn)(self.arg.val, level) + assert!(((self.arg.fsync_fn)(copy self.arg.val, level) != -1)); } } diff --git a/src/libstd/iter.rs b/src/libstd/iter.rs index 2197feea4523..7053cbe0df5a 100644 --- a/src/libstd/iter.rs +++ b/src/libstd/iter.rs @@ -73,7 +73,7 @@ pub trait FromIter { * assert!(!any(|&x: &uint| x > 5, |f| xs.each(f))); * ~~~ */ -#[inline(always)] +#[inline] pub fn any(predicate: &fn(T) -> bool, iter: &fn(f: &fn(T) -> bool) -> bool) -> bool { for iter |x| { @@ -94,7 +94,7 @@ pub fn any(predicate: &fn(T) -> bool, * assert!(!all(|&x: &uint| x < 5, |f| uint::range(1, 6, f))); * ~~~ */ -#[inline(always)] +#[inline] pub fn all(predicate: &fn(T) -> bool, iter: &fn(f: &fn(T) -> bool) -> bool) -> bool { // If we ever break, iter will return false, so this will only return true @@ -112,7 +112,7 @@ pub fn all(predicate: &fn(T) -> bool, * assert_eq!(*find(|& &x: & &uint| x > 3, |f| xs.each(f)).unwrap(), 4); * ~~~ */ -#[inline(always)] +#[inline] pub fn find(predicate: &fn(&T) -> bool, iter: &fn(f: &fn(T) -> bool) -> bool) -> Option { for iter |x| { @@ -226,7 +226,7 @@ pub fn fold_ref(start: T, iter: &fn(f: &fn(&U) -> bool) -> bool, f: &fn(&m * assert_eq!(do sum |f| { xs.each(f) }, 10); * ~~~ */ -#[inline(always)] +#[inline] pub fn sum>(iter: &fn(f: &fn(&T) -> bool) -> bool) -> T { fold_ref(Zero::zero::(), iter, |a, x| *a = a.add(x)) } @@ -241,7 +241,7 @@ pub fn sum>(iter: &fn(f: &fn(&T) -> bool) -> bool) -> T { * assert_eq!(do product |f| { xs.each(f) }, 24); * ~~~ */ -#[inline(always)] +#[inline] pub fn product>(iter: &fn(f: &fn(&T) -> bool) -> bool) -> T { fold_ref(One::one::(), iter, |a, x| *a = a.mul(x)) } diff --git a/src/libstd/iterator.rs b/src/libstd/iterator.rs index e65904a68992..eefad1a03dcb 100644 --- a/src/libstd/iterator.rs +++ b/src/libstd/iterator.rs @@ -308,6 +308,12 @@ pub trait IteratorUtil { /// assert!(!it.any_(|&x| *x == 3)); /// ~~~ fn any_(&mut self, f: &fn(A) -> bool) -> bool; + + /// Return the first element satisfying the specified predicate + fn find_(&mut self, predicate: &fn(&A) -> bool) -> Option; + + /// Return the index of the first element satisfying the specified predicate + fn position_(&mut self, predicate: &fn(A) -> bool) -> Option; } /// Iterator adaptors provided for every `Iterator` implementation. The adaptor objects are also @@ -315,59 +321,59 @@ pub trait IteratorUtil { /// /// In the future these will be default methods instead of a utility trait. impl> IteratorUtil for T { - #[inline(always)] + #[inline] fn chain_>(self, other: U) -> ChainIterator { ChainIterator{a: self, b: other, flag: false} } - #[inline(always)] + #[inline] fn zip>(self, other: U) -> ZipIterator { ZipIterator{a: self, b: other} } // FIXME: #5898: should be called map - #[inline(always)] + #[inline] fn transform<'r, B>(self, f: &'r fn(A) -> B) -> MapIterator<'r, A, B, T> { MapIterator{iter: self, f: f} } - #[inline(always)] + #[inline] fn filter<'r>(self, predicate: &'r fn(&A) -> bool) -> FilterIterator<'r, A, T> { FilterIterator{iter: self, predicate: predicate} } - #[inline(always)] + #[inline] fn filter_map<'r, B>(self, f: &'r fn(A) -> Option) -> FilterMapIterator<'r, A, B, T> { FilterMapIterator { iter: self, f: f } } - #[inline(always)] + #[inline] fn enumerate(self) -> EnumerateIterator { EnumerateIterator{iter: self, count: 0} } - #[inline(always)] + #[inline] fn skip_while<'r>(self, predicate: &'r fn(&A) -> bool) -> SkipWhileIterator<'r, A, T> { SkipWhileIterator{iter: self, flag: false, predicate: predicate} } - #[inline(always)] + #[inline] fn take_while<'r>(self, predicate: &'r fn(&A) -> bool) -> TakeWhileIterator<'r, A, T> { TakeWhileIterator{iter: self, flag: false, predicate: predicate} } - #[inline(always)] + #[inline] fn skip(self, n: uint) -> SkipIterator { SkipIterator{iter: self, n: n} } // FIXME: #5898: should be called take - #[inline(always)] + #[inline] fn take_(self, n: uint) -> TakeIterator { TakeIterator{iter: self, n: n} } - #[inline(always)] + #[inline] fn scan<'r, St, B>(self, initial_state: St, f: &'r fn(&mut St, A) -> Option) -> ScanIterator<'r, A, B, T, St> { ScanIterator{iter: self, f: f, state: initial_state} @@ -386,13 +392,13 @@ impl> IteratorUtil for T { } } - #[inline(always)] + #[inline] fn collect>(&mut self) -> B { FromIter::from_iter::(|f| self.advance(f)) } /// Return the `n`th item yielded by an iterator. - #[inline(always)] + #[inline] fn nth(&mut self, mut n: uint) -> Option { loop { match self.next() { @@ -404,7 +410,7 @@ impl> IteratorUtil for T { } /// Return the last item yielded by an iterator. - #[inline(always)] + #[inline] fn last_(&mut self) -> Option { let mut last = None; for self.advance |x| { last = Some(x); } @@ -421,23 +427,45 @@ impl> IteratorUtil for T { None => { break; } } } - return accum; + accum } /// Count the number of items yielded by an iterator - #[inline(always)] + #[inline] fn count(&mut self) -> uint { self.fold(0, |cnt, _x| cnt + 1) } - #[inline(always)] + #[inline] fn all(&mut self, f: &fn(A) -> bool) -> bool { for self.advance |x| { if !f(x) { return false; } } - return true; + true } - #[inline(always)] + #[inline] fn any_(&mut self, f: &fn(A) -> bool) -> bool { for self.advance |x| { if f(x) { return true; } } - return false; + false + } + + /// Return the first element satisfying the specified predicate + #[inline] + fn find_(&mut self, predicate: &fn(&A) -> bool) -> Option { + for self.advance |x| { + if predicate(&x) { return Some(x) } + } + None + } + + /// Return the index of the first element satisfying the specified predicate + #[inline] + fn position_(&mut self, predicate: &fn(A) -> bool) -> Option { + let mut i = 0; + for self.advance |x| { + if predicate(x) { + return Some(i); + } + i += 1; + } + None } } @@ -456,7 +484,7 @@ pub trait AdditiveIterator { } impl + Zero, T: Iterator> AdditiveIterator for T { - #[inline(always)] + #[inline] fn sum(&mut self) -> A { self.fold(Zero::zero::(), |s, x| s + x) } } @@ -481,7 +509,7 @@ pub trait MultiplicativeIterator { } impl + One, T: Iterator> MultiplicativeIterator for T { - #[inline(always)] + #[inline] fn product(&mut self) -> A { self.fold(One::one::(), |p, x| p * x) } } @@ -510,7 +538,7 @@ pub trait OrdIterator { } impl> OrdIterator for T { - #[inline(always)] + #[inline] fn max(&mut self) -> Option { self.fold(None, |max, x| { match max { @@ -520,7 +548,7 @@ impl> OrdIterator for T { }) } - #[inline(always)] + #[inline] fn min(&mut self) -> Option { self.fold(None, |min, x| { match min { @@ -788,8 +816,8 @@ impl<'self, A, St> UnfoldrIterator<'self, A, St> { /// Creates a new iterator with the specified closure as the "iterator /// function" and an initial state to eventually pass to the iterator #[inline] - pub fn new(f: &'self fn(&mut St) -> Option, initial_state: St) - -> UnfoldrIterator<'self, A, St> { + pub fn new<'a>(f: &'a fn(&mut St) -> Option, initial_state: St) + -> UnfoldrIterator<'a, A, St> { UnfoldrIterator { f: f, state: initial_state @@ -815,14 +843,14 @@ pub struct Counter { impl Counter { /// Creates a new counter with the specified start/step - #[inline(always)] + #[inline] pub fn new(start: A, step: A) -> Counter { Counter{state: start, step: step} } } impl + Clone> Iterator for Counter { - #[inline(always)] + #[inline] fn next(&mut self) -> Option { let result = self.state.clone(); self.state = self.state.add(&self.step); // FIXME: #6050 @@ -1055,4 +1083,20 @@ mod tests { assert!(!v.iter().any_(|&x| x > 100)); assert!(!v.slice(0, 0).iter().any_(|_| fail!())); } + + #[test] + fn test_find() { + let v = &[1, 3, 9, 27, 103, 14, 11]; + assert_eq!(*v.iter().find_(|x| *x & 1 == 0).unwrap(), 14); + assert_eq!(*v.iter().find_(|x| *x % 3 == 0).unwrap(), 3); + assert!(v.iter().find_(|x| *x % 12 == 0).is_none()); + } + + #[test] + fn test_position() { + let v = &[1, 3, 9, 27, 103, 14, 11]; + assert_eq!(v.iter().position_(|x| *x & 1 == 0).unwrap(), 5); + assert_eq!(v.iter().position_(|x| *x % 3 == 0).unwrap(), 1); + assert!(v.iter().position_(|x| *x % 12 == 0).is_none()); + } } diff --git a/src/libstd/libc.rs b/src/libstd/libc.rs index 26205c930f0c..07b2ac6ed01b 100644 --- a/src/libstd/libc.rs +++ b/src/libstd/libc.rs @@ -14,8 +14,8 @@ * This module contains bindings to the C standard library, * organized into modules by their defining standard. * Additionally, it contains some assorted platform-specific definitions. -* For convenience, most functions and types are reexported from `core::libc`, -* so `pub use core::libc::*` will import the available +* For convenience, most functions and types are reexported from `std::libc`, +* so `pub use std::libc::*` will import the available * C bindings as appropriate for the target platform. The exact * set of functions available are platform specific. * @@ -1457,11 +1457,11 @@ pub mod funcs { // These are fine to execute on the Rust stack. They must be, // in fact, because LLVM generates calls to them! #[rust_stack] - #[inline(always)] + #[inline] unsafe fn memcmp(cx: *c_void, ct: *c_void, n: size_t) -> c_int; #[rust_stack] - #[inline(always)] + #[inline] unsafe fn memchr(cx: *c_void, c: c_int, n: size_t) -> *c_void; } } diff --git a/src/libstd/logging.rs b/src/libstd/logging.rs index c2f854179b8d..743b71e33ea8 100644 --- a/src/libstd/logging.rs +++ b/src/libstd/logging.rs @@ -11,13 +11,20 @@ //! Logging use option::*; +use os; use either::*; +use rt; +use rt::OldTaskContext; use rt::logging::{Logger, StdErrLogger}; /// Turns on logging to stdout globally pub fn console_on() { - unsafe { - rustrt::rust_log_console_on(); + if rt::context() == OldTaskContext { + unsafe { + rustrt::rust_log_console_on(); + } + } else { + rt::logging::console_on(); } } @@ -29,8 +36,17 @@ pub fn console_on() { * the RUST_LOG environment variable */ pub fn console_off() { - unsafe { - rustrt::rust_log_console_off(); + // If RUST_LOG is set then the console can't be turned off + if os::getenv("RUST_LOG").is_some() { + return; + } + + if rt::context() == OldTaskContext { + unsafe { + rustrt::rust_log_console_off(); + } + } else { + rt::logging::console_off(); } } diff --git a/src/libstd/managed.rs b/src/libstd/managed.rs index 7d0defea05ac..d514612b5afd 100644 --- a/src/libstd/managed.rs +++ b/src/libstd/managed.rs @@ -38,14 +38,14 @@ pub mod raw { } /// Determine if two shared boxes point to the same object -#[inline(always)] +#[inline] pub fn ptr_eq(a: @T, b: @T) -> bool { let (a_ptr, b_ptr): (*T, *T) = (to_unsafe_ptr(&*a), to_unsafe_ptr(&*b)); a_ptr == b_ptr } /// Determine if two mutable shared boxes point to the same object -#[inline(always)] +#[inline] pub fn mut_ptr_eq(a: @mut T, b: @mut T) -> bool { let (a_ptr, b_ptr): (*T, *T) = (to_unsafe_ptr(&*a), to_unsafe_ptr(&*b)); a_ptr == b_ptr @@ -53,41 +53,41 @@ pub fn mut_ptr_eq(a: @mut T, b: @mut T) -> bool { #[cfg(not(test))] impl Eq for @T { - #[inline(always)] + #[inline] fn eq(&self, other: &@T) -> bool { *(*self) == *(*other) } - #[inline(always)] + #[inline] fn ne(&self, other: &@T) -> bool { *(*self) != *(*other) } } #[cfg(not(test))] impl Eq for @mut T { - #[inline(always)] + #[inline] fn eq(&self, other: &@mut T) -> bool { *(*self) == *(*other) } - #[inline(always)] + #[inline] fn ne(&self, other: &@mut T) -> bool { *(*self) != *(*other) } } #[cfg(not(test))] impl Ord for @T { - #[inline(always)] + #[inline] fn lt(&self, other: &@T) -> bool { *(*self) < *(*other) } - #[inline(always)] + #[inline] fn le(&self, other: &@T) -> bool { *(*self) <= *(*other) } - #[inline(always)] + #[inline] fn ge(&self, other: &@T) -> bool { *(*self) >= *(*other) } - #[inline(always)] + #[inline] fn gt(&self, other: &@T) -> bool { *(*self) > *(*other) } } #[cfg(not(test))] impl Ord for @mut T { - #[inline(always)] + #[inline] fn lt(&self, other: &@mut T) -> bool { *(*self) < *(*other) } - #[inline(always)] + #[inline] fn le(&self, other: &@mut T) -> bool { *(*self) <= *(*other) } - #[inline(always)] + #[inline] fn ge(&self, other: &@mut T) -> bool { *(*self) >= *(*other) } - #[inline(always)] + #[inline] fn gt(&self, other: &@mut T) -> bool { *(*self) > *(*other) } } diff --git a/src/libstd/nil.rs b/src/libstd/nil.rs index 833bd3459ceb..40f6d53ed22f 100644 --- a/src/libstd/nil.rs +++ b/src/libstd/nil.rs @@ -19,32 +19,32 @@ use prelude::*; #[cfg(not(test))] impl Eq for () { - #[inline(always)] + #[inline] fn eq(&self, _other: &()) -> bool { true } - #[inline(always)] + #[inline] fn ne(&self, _other: &()) -> bool { false } } #[cfg(not(test))] impl Ord for () { - #[inline(always)] + #[inline] fn lt(&self, _other: &()) -> bool { false } - #[inline(always)] + #[inline] fn le(&self, _other: &()) -> bool { true } - #[inline(always)] + #[inline] fn ge(&self, _other: &()) -> bool { true } - #[inline(always)] + #[inline] fn gt(&self, _other: &()) -> bool { false } } #[cfg(not(test))] impl TotalOrd for () { - #[inline(always)] + #[inline] fn cmp(&self, _other: &()) -> Ordering { Equal } } #[cfg(not(test))] impl TotalEq for () { - #[inline(always)] + #[inline] fn equals(&self, _other: &()) -> bool { true } } diff --git a/src/libstd/num/f32.rs b/src/libstd/num/f32.rs index 7f9811873003..117a474ffd7d 100644 --- a/src/libstd/num/f32.rs +++ b/src/libstd/num/f32.rs @@ -20,7 +20,7 @@ use to_str; pub use cmath::c_float_targ_consts::*; -// An inner module is required to get the #[inline(always)] attribute on the +// An inner module is required to get the #[inline] attribute on the // functions. pub use self::delegated::*; @@ -40,7 +40,7 @@ macro_rules! delegate( use unstable::intrinsics; $( - #[inline(always)] + #[inline] pub fn $name($( $arg : $arg_ty ),*) -> $rv { unsafe { $bound_name($( $arg ),*) @@ -115,45 +115,45 @@ pub static infinity: f32 = 1.0_f32/0.0_f32; pub static neg_infinity: f32 = -1.0_f32/0.0_f32; -#[inline(always)] +#[inline] pub fn add(x: f32, y: f32) -> f32 { return x + y; } -#[inline(always)] +#[inline] pub fn sub(x: f32, y: f32) -> f32 { return x - y; } -#[inline(always)] +#[inline] pub fn mul(x: f32, y: f32) -> f32 { return x * y; } -#[inline(always)] +#[inline] pub fn div(x: f32, y: f32) -> f32 { return x / y; } -#[inline(always)] +#[inline] pub fn rem(x: f32, y: f32) -> f32 { return x % y; } -#[inline(always)] +#[inline] pub fn lt(x: f32, y: f32) -> bool { return x < y; } -#[inline(always)] +#[inline] pub fn le(x: f32, y: f32) -> bool { return x <= y; } -#[inline(always)] +#[inline] pub fn eq(x: f32, y: f32) -> bool { return x == y; } -#[inline(always)] +#[inline] pub fn ne(x: f32, y: f32) -> bool { return x != y; } -#[inline(always)] +#[inline] pub fn ge(x: f32, y: f32) -> bool { return x >= y; } -#[inline(always)] +#[inline] pub fn gt(x: f32, y: f32) -> bool { return x > y; } -#[inline(always)] +#[inline] pub fn fmax(x: f32, y: f32) -> f32 { if x >= y || y.is_NaN() { x } else { y } } -#[inline(always)] +#[inline] pub fn fmin(x: f32, y: f32) -> f32 { if x <= y || y.is_NaN() { x } else { y } } @@ -212,23 +212,23 @@ impl Num for f32 {} #[cfg(not(test))] impl Eq for f32 { - #[inline(always)] + #[inline] fn eq(&self, other: &f32) -> bool { (*self) == (*other) } - #[inline(always)] + #[inline] fn ne(&self, other: &f32) -> bool { (*self) != (*other) } } #[cfg(not(test))] impl ApproxEq for f32 { - #[inline(always)] + #[inline] fn approx_epsilon() -> f32 { 1.0e-6 } - #[inline(always)] + #[inline] fn approx_eq(&self, other: &f32) -> bool { self.approx_eq_eps(other, &ApproxEq::approx_epsilon::()) } - #[inline(always)] + #[inline] fn approx_eq_eps(&self, other: &f32, approx_epsilon: &f32) -> bool { (*self - *other).abs() < *approx_epsilon } @@ -236,32 +236,32 @@ impl ApproxEq for f32 { #[cfg(not(test))] impl Ord for f32 { - #[inline(always)] + #[inline] fn lt(&self, other: &f32) -> bool { (*self) < (*other) } - #[inline(always)] + #[inline] fn le(&self, other: &f32) -> bool { (*self) <= (*other) } - #[inline(always)] + #[inline] fn ge(&self, other: &f32) -> bool { (*self) >= (*other) } - #[inline(always)] + #[inline] fn gt(&self, other: &f32) -> bool { (*self) > (*other) } } impl Orderable for f32 { /// Returns `NaN` if either of the numbers are `NaN`. - #[inline(always)] + #[inline] fn min(&self, other: &f32) -> f32 { if self.is_NaN() || other.is_NaN() { Float::NaN() } else { fmin(*self, *other) } } /// Returns `NaN` if either of the numbers are `NaN`. - #[inline(always)] + #[inline] fn max(&self, other: &f32) -> f32 { if self.is_NaN() || other.is_NaN() { Float::NaN() } else { fmax(*self, *other) } } /// Returns the number constrained within the range `mn <= self <= mx`. /// If any of the numbers are `NaN` then `NaN` is returned. - #[inline(always)] + #[inline] fn clamp(&self, mn: &f32, mx: &f32) -> f32 { cond!( (self.is_NaN()) { *self } @@ -273,65 +273,65 @@ impl Orderable for f32 { } impl Zero for f32 { - #[inline(always)] + #[inline] fn zero() -> f32 { 0.0 } /// Returns true if the number is equal to either `0.0` or `-0.0` - #[inline(always)] + #[inline] fn is_zero(&self) -> bool { *self == 0.0 || *self == -0.0 } } impl One for f32 { - #[inline(always)] + #[inline] fn one() -> f32 { 1.0 } } #[cfg(not(test))] impl Add for f32 { - #[inline(always)] + #[inline] fn add(&self, other: &f32) -> f32 { *self + *other } } #[cfg(not(test))] impl Sub for f32 { - #[inline(always)] + #[inline] fn sub(&self, other: &f32) -> f32 { *self - *other } } #[cfg(not(test))] impl Mul for f32 { - #[inline(always)] + #[inline] fn mul(&self, other: &f32) -> f32 { *self * *other } } #[cfg(not(test))] impl Div for f32 { - #[inline(always)] + #[inline] fn div(&self, other: &f32) -> f32 { *self / *other } } #[cfg(not(test))] impl Rem for f32 { - #[inline(always)] + #[inline] fn rem(&self, other: &f32) -> f32 { *self % *other } } #[cfg(not(test))] impl Neg for f32 { - #[inline(always)] + #[inline] fn neg(&self) -> f32 { -*self } } impl Signed for f32 { /// Computes the absolute value. Returns `NaN` if the number is `NaN`. - #[inline(always)] + #[inline] fn abs(&self) -> f32 { abs(*self) } /// /// The positive difference of two numbers. Returns `0.0` if the number is less than or /// equal to `other`, otherwise the difference between`self` and `other` is returned. /// - #[inline(always)] + #[inline] fn abs_sub(&self, other: &f32) -> f32 { abs_sub(*self, *other) } /// @@ -341,35 +341,35 @@ impl Signed for f32 { /// - `-1.0` if the number is negative, `-0.0` or `neg_infinity` /// - `NaN` if the number is NaN /// - #[inline(always)] + #[inline] fn signum(&self) -> f32 { if self.is_NaN() { NaN } else { copysign(1.0, *self) } } /// Returns `true` if the number is positive, including `+0.0` and `infinity` - #[inline(always)] + #[inline] fn is_positive(&self) -> bool { *self > 0.0 || (1.0 / *self) == infinity } /// Returns `true` if the number is negative, including `-0.0` and `neg_infinity` - #[inline(always)] + #[inline] fn is_negative(&self) -> bool { *self < 0.0 || (1.0 / *self) == neg_infinity } } impl Round for f32 { /// Round half-way cases toward `neg_infinity` - #[inline(always)] + #[inline] fn floor(&self) -> f32 { floor(*self) } /// Round half-way cases toward `infinity` - #[inline(always)] + #[inline] fn ceil(&self) -> f32 { ceil(*self) } /// Round half-way cases away from `0.0` - #[inline(always)] + #[inline] fn round(&self) -> f32 { round(*self) } /// The integer part of the number (rounds towards `0.0`) - #[inline(always)] + #[inline] fn trunc(&self) -> f32 { trunc(*self) } /// @@ -379,57 +379,57 @@ impl Round for f32 { /// assert!(x == trunc(x) + fract(x)) /// ~~~ /// - #[inline(always)] + #[inline] fn fract(&self) -> f32 { *self - self.trunc() } } impl Fractional for f32 { /// The reciprocal (multiplicative inverse) of the number - #[inline(always)] + #[inline] fn recip(&self) -> f32 { 1.0 / *self } } impl Algebraic for f32 { - #[inline(always)] + #[inline] fn pow(&self, n: &f32) -> f32 { pow(*self, *n) } - #[inline(always)] + #[inline] fn sqrt(&self) -> f32 { sqrt(*self) } - #[inline(always)] + #[inline] fn rsqrt(&self) -> f32 { self.sqrt().recip() } - #[inline(always)] + #[inline] fn cbrt(&self) -> f32 { cbrt(*self) } - #[inline(always)] + #[inline] fn hypot(&self, other: &f32) -> f32 { hypot(*self, *other) } } impl Trigonometric for f32 { - #[inline(always)] + #[inline] fn sin(&self) -> f32 { sin(*self) } - #[inline(always)] + #[inline] fn cos(&self) -> f32 { cos(*self) } - #[inline(always)] + #[inline] fn tan(&self) -> f32 { tan(*self) } - #[inline(always)] + #[inline] fn asin(&self) -> f32 { asin(*self) } - #[inline(always)] + #[inline] fn acos(&self) -> f32 { acos(*self) } - #[inline(always)] + #[inline] fn atan(&self) -> f32 { atan(*self) } - #[inline(always)] + #[inline] fn atan2(&self, other: &f32) -> f32 { atan2(*self, *other) } /// Simultaneously computes the sine and cosine of the number - #[inline(always)] + #[inline] fn sin_cos(&self) -> (f32, f32) { (self.sin(), self.cos()) } @@ -437,38 +437,38 @@ impl Trigonometric for f32 { impl Exponential for f32 { /// Returns the exponential of the number - #[inline(always)] + #[inline] fn exp(&self) -> f32 { exp(*self) } /// Returns 2 raised to the power of the number - #[inline(always)] + #[inline] fn exp2(&self) -> f32 { exp2(*self) } /// Returns the natural logarithm of the number - #[inline(always)] + #[inline] fn ln(&self) -> f32 { ln(*self) } /// Returns the logarithm of the number with respect to an arbitrary base - #[inline(always)] + #[inline] fn log(&self, base: &f32) -> f32 { self.ln() / base.ln() } /// Returns the base 2 logarithm of the number - #[inline(always)] + #[inline] fn log2(&self) -> f32 { log2(*self) } /// Returns the base 10 logarithm of the number - #[inline(always)] + #[inline] fn log10(&self) -> f32 { log10(*self) } } impl Hyperbolic for f32 { - #[inline(always)] + #[inline] fn sinh(&self) -> f32 { sinh(*self) } - #[inline(always)] + #[inline] fn cosh(&self) -> f32 { cosh(*self) } - #[inline(always)] + #[inline] fn tanh(&self) -> f32 { tanh(*self) } /// @@ -480,7 +480,7 @@ impl Hyperbolic for f32 { /// - `self` if `self` is `0.0`, `-0.0`, `infinity`, or `neg_infinity` /// - `NaN` if `self` is `NaN` /// - #[inline(always)] + #[inline] fn asinh(&self) -> f32 { match *self { neg_infinity => neg_infinity, @@ -497,7 +497,7 @@ impl Hyperbolic for f32 { /// - `infinity` if `self` is `infinity` /// - `NaN` if `self` is `NaN` or `self < 1.0` (including `neg_infinity`) /// - #[inline(always)] + #[inline] fn acosh(&self) -> f32 { match *self { x if x < 1.0 => Float::NaN(), @@ -517,7 +517,7 @@ impl Hyperbolic for f32 { /// - `NaN` if the `self` is `NaN` or outside the domain of `-1.0 <= self <= 1.0` /// (including `infinity` and `neg_infinity`) /// - #[inline(always)] + #[inline] fn atanh(&self) -> f32 { 0.5 * ((2.0 * *self) / (1.0 - *self)).ln_1p() } @@ -525,129 +525,129 @@ impl Hyperbolic for f32 { impl Real for f32 { /// Archimedes' constant - #[inline(always)] + #[inline] fn pi() -> f32 { 3.14159265358979323846264338327950288 } /// 2.0 * pi - #[inline(always)] + #[inline] fn two_pi() -> f32 { 6.28318530717958647692528676655900576 } /// pi / 2.0 - #[inline(always)] + #[inline] fn frac_pi_2() -> f32 { 1.57079632679489661923132169163975144 } /// pi / 3.0 - #[inline(always)] + #[inline] fn frac_pi_3() -> f32 { 1.04719755119659774615421446109316763 } /// pi / 4.0 - #[inline(always)] + #[inline] fn frac_pi_4() -> f32 { 0.785398163397448309615660845819875721 } /// pi / 6.0 - #[inline(always)] + #[inline] fn frac_pi_6() -> f32 { 0.52359877559829887307710723054658381 } /// pi / 8.0 - #[inline(always)] + #[inline] fn frac_pi_8() -> f32 { 0.39269908169872415480783042290993786 } /// 1 .0/ pi - #[inline(always)] + #[inline] fn frac_1_pi() -> f32 { 0.318309886183790671537767526745028724 } /// 2.0 / pi - #[inline(always)] + #[inline] fn frac_2_pi() -> f32 { 0.636619772367581343075535053490057448 } /// 2.0 / sqrt(pi) - #[inline(always)] + #[inline] fn frac_2_sqrtpi() -> f32 { 1.12837916709551257389615890312154517 } /// sqrt(2.0) - #[inline(always)] + #[inline] fn sqrt2() -> f32 { 1.41421356237309504880168872420969808 } /// 1.0 / sqrt(2.0) - #[inline(always)] + #[inline] fn frac_1_sqrt2() -> f32 { 0.707106781186547524400844362104849039 } /// Euler's number - #[inline(always)] + #[inline] fn e() -> f32 { 2.71828182845904523536028747135266250 } /// log2(e) - #[inline(always)] + #[inline] fn log2_e() -> f32 { 1.44269504088896340735992468100189214 } /// log10(e) - #[inline(always)] + #[inline] fn log10_e() -> f32 { 0.434294481903251827651128918916605082 } /// ln(2.0) - #[inline(always)] + #[inline] fn ln_2() -> f32 { 0.693147180559945309417232121458176568 } /// ln(10.0) - #[inline(always)] + #[inline] fn ln_10() -> f32 { 2.30258509299404568401799145468436421 } /// Converts to degrees, assuming the number is in radians - #[inline(always)] + #[inline] fn to_degrees(&self) -> f32 { *self * (180.0 / Real::pi::()) } /// Converts to radians, assuming the number is in degrees - #[inline(always)] + #[inline] fn to_radians(&self) -> f32 { *self * (Real::pi::() / 180.0) } } impl Bounded for f32 { - #[inline(always)] + #[inline] fn min_value() -> f32 { 1.17549435e-38 } - #[inline(always)] + #[inline] fn max_value() -> f32 { 3.40282347e+38 } } impl Primitive for f32 { - #[inline(always)] + #[inline] fn bits() -> uint { 32 } - #[inline(always)] + #[inline] fn bytes() -> uint { Primitive::bits::() / 8 } } impl Float for f32 { - #[inline(always)] + #[inline] fn NaN() -> f32 { 0.0 / 0.0 } - #[inline(always)] + #[inline] fn infinity() -> f32 { 1.0 / 0.0 } - #[inline(always)] + #[inline] fn neg_infinity() -> f32 { -1.0 / 0.0 } - #[inline(always)] + #[inline] fn neg_zero() -> f32 { -0.0 } /// Returns `true` if the number is NaN - #[inline(always)] + #[inline] fn is_NaN(&self) -> bool { *self != *self } /// Returns `true` if the number is infinite - #[inline(always)] + #[inline] fn is_infinite(&self) -> bool { *self == Float::infinity() || *self == Float::neg_infinity() } /// Returns `true` if the number is neither infinite or NaN - #[inline(always)] + #[inline] fn is_finite(&self) -> bool { !(self.is_NaN() || self.is_infinite()) } /// Returns `true` if the number is neither zero, infinite, subnormal or NaN - #[inline(always)] + #[inline] fn is_normal(&self) -> bool { self.classify() == FPNormal } @@ -670,29 +670,29 @@ impl Float for f32 { } } - #[inline(always)] + #[inline] fn mantissa_digits() -> uint { 24 } - #[inline(always)] + #[inline] fn digits() -> uint { 6 } - #[inline(always)] + #[inline] fn epsilon() -> f32 { 1.19209290e-07 } - #[inline(always)] + #[inline] fn min_exp() -> int { -125 } - #[inline(always)] + #[inline] fn max_exp() -> int { 128 } - #[inline(always)] + #[inline] fn min_10_exp() -> int { -37 } - #[inline(always)] + #[inline] fn max_10_exp() -> int { 38 } /// Constructs a floating point number by multiplying `x` by 2 raised to the power of `exp` - #[inline(always)] + #[inline] fn ldexp(x: f32, exp: int) -> f32 { ldexp(x, exp as c_int) } @@ -703,7 +703,7 @@ impl Float for f32 { /// - `self = x * pow(2, exp)` /// - `0.5 <= abs(x) < 1.0` /// - #[inline(always)] + #[inline] fn frexp(&self) -> (f32, int) { let mut exp = 0; let x = frexp(*self, &mut exp); @@ -714,14 +714,14 @@ impl Float for f32 { /// Returns the exponential of the number, minus `1`, in a way that is accurate /// even if the number is close to zero /// - #[inline(always)] + #[inline] fn exp_m1(&self) -> f32 { exp_m1(*self) } /// /// Returns the natural logarithm of the number plus `1` (`ln(1+n)`) more accurately /// than if the operations were performed separately /// - #[inline(always)] + #[inline] fn ln_1p(&self) -> f32 { ln_1p(*self) } /// @@ -729,13 +729,13 @@ impl Float for f32 { /// produces a more accurate result with better performance than a separate multiplication /// operation followed by an add. /// - #[inline(always)] + #[inline] fn mul_add(&self, a: f32, b: f32) -> f32 { mul_add(*self, a, b) } /// Returns the next representable floating-point value in the direction of `other` - #[inline(always)] + #[inline] fn next_after(&self, other: f32) -> f32 { next_after(*self, other) } @@ -752,7 +752,7 @@ impl Float for f32 { /// /// * num - The float value /// -#[inline(always)] +#[inline] pub fn to_str(num: f32) -> ~str { let (r, _) = strconv::to_str_common( &num, 10u, true, strconv::SignNeg, strconv::DigAll); @@ -766,7 +766,7 @@ pub fn to_str(num: f32) -> ~str { /// /// * num - The float value /// -#[inline(always)] +#[inline] pub fn to_str_hex(num: f32) -> ~str { let (r, _) = strconv::to_str_common( &num, 16u, true, strconv::SignNeg, strconv::DigAll); @@ -787,7 +787,7 @@ pub fn to_str_hex(num: f32) -> ~str { /// possible misinterpretation of the result at higher bases. If those values /// are expected, use `to_str_radix_special()` instead. /// -#[inline(always)] +#[inline] pub fn to_str_radix(num: f32, rdx: uint) -> ~str { let (r, special) = strconv::to_str_common( &num, rdx, true, strconv::SignNeg, strconv::DigAll); @@ -805,7 +805,7 @@ pub fn to_str_radix(num: f32, rdx: uint) -> ~str { /// * num - The float value /// * radix - The base to use /// -#[inline(always)] +#[inline] pub fn to_str_radix_special(num: f32, rdx: uint) -> (~str, bool) { strconv::to_str_common(&num, rdx, true, strconv::SignNeg, strconv::DigAll) @@ -820,7 +820,7 @@ pub fn to_str_radix_special(num: f32, rdx: uint) -> (~str, bool) { /// * num - The float value /// * digits - The number of significant digits /// -#[inline(always)] +#[inline] pub fn to_str_exact(num: f32, dig: uint) -> ~str { let (r, _) = strconv::to_str_common( &num, 10u, true, strconv::SignNeg, strconv::DigExact(dig)); @@ -836,7 +836,7 @@ pub fn to_str_exact(num: f32, dig: uint) -> ~str { /// * num - The float value /// * digits - The number of significant digits /// -#[inline(always)] +#[inline] pub fn to_str_digits(num: f32, dig: uint) -> ~str { let (r, _) = strconv::to_str_common( &num, 10u, true, strconv::SignNeg, strconv::DigMax(dig)); @@ -844,12 +844,12 @@ pub fn to_str_digits(num: f32, dig: uint) -> ~str { } impl to_str::ToStr for f32 { - #[inline(always)] + #[inline] fn to_str(&self) -> ~str { to_str_digits(*self, 8) } } impl num::ToStrRadix for f32 { - #[inline(always)] + #[inline] fn to_str_radix(&self, rdx: uint) -> ~str { to_str_radix(*self, rdx) } @@ -882,7 +882,7 @@ impl num::ToStrRadix for f32 { /// `none` if the string did not represent a valid number. Otherwise, /// `Some(n)` where `n` is the floating-point number represented by `num`. /// -#[inline(always)] +#[inline] pub fn from_str(num: &str) -> Option { strconv::from_str_common(num, 10u, true, true, true, strconv::ExpDec, false, false) @@ -915,7 +915,7 @@ pub fn from_str(num: &str) -> Option { /// `none` if the string did not represent a valid number. Otherwise, /// `Some(n)` where `n` is the floating-point number represented by `[num]`. /// -#[inline(always)] +#[inline] pub fn from_str_hex(num: &str) -> Option { strconv::from_str_common(num, 16u, true, true, true, strconv::ExpBin, false, false) @@ -940,19 +940,19 @@ pub fn from_str_hex(num: &str) -> Option { /// `none` if the string did not represent a valid number. Otherwise, /// `Some(n)` where `n` is the floating-point number represented by `num`. /// -#[inline(always)] +#[inline] pub fn from_str_radix(num: &str, rdx: uint) -> Option { strconv::from_str_common(num, rdx, true, true, false, strconv::ExpNone, false, false) } impl FromStr for f32 { - #[inline(always)] + #[inline] fn from_str(val: &str) -> Option { from_str(val) } } impl num::FromStrRadix for f32 { - #[inline(always)] + #[inline] fn from_str_radix(val: &str, rdx: uint) -> Option { from_str_radix(val, rdx) } diff --git a/src/libstd/num/f64.rs b/src/libstd/num/f64.rs index 6303e3045764..e13dff1e6235 100644 --- a/src/libstd/num/f64.rs +++ b/src/libstd/num/f64.rs @@ -22,7 +22,7 @@ use to_str; pub use cmath::c_double_targ_consts::*; pub use cmp::{min, max}; -// An inner module is required to get the #[inline(always)] attribute on the +// An inner module is required to get the #[inline] attribute on the // functions. pub use self::delegated::*; @@ -42,7 +42,7 @@ macro_rules! delegate( use unstable::intrinsics; $( - #[inline(always)] + #[inline] pub fn $name($( $arg : $arg_ty ),*) -> $rv { unsafe { $bound_name($( $arg ),*) @@ -141,45 +141,45 @@ pub static infinity: f64 = 1.0_f64/0.0_f64; pub static neg_infinity: f64 = -1.0_f64/0.0_f64; -#[inline(always)] +#[inline] pub fn add(x: f64, y: f64) -> f64 { return x + y; } -#[inline(always)] +#[inline] pub fn sub(x: f64, y: f64) -> f64 { return x - y; } -#[inline(always)] +#[inline] pub fn mul(x: f64, y: f64) -> f64 { return x * y; } -#[inline(always)] +#[inline] pub fn div(x: f64, y: f64) -> f64 { return x / y; } -#[inline(always)] +#[inline] pub fn rem(x: f64, y: f64) -> f64 { return x % y; } -#[inline(always)] +#[inline] pub fn lt(x: f64, y: f64) -> bool { return x < y; } -#[inline(always)] +#[inline] pub fn le(x: f64, y: f64) -> bool { return x <= y; } -#[inline(always)] +#[inline] pub fn eq(x: f64, y: f64) -> bool { return x == y; } -#[inline(always)] +#[inline] pub fn ne(x: f64, y: f64) -> bool { return x != y; } -#[inline(always)] +#[inline] pub fn ge(x: f64, y: f64) -> bool { return x >= y; } -#[inline(always)] +#[inline] pub fn gt(x: f64, y: f64) -> bool { return x > y; } -#[inline(always)] +#[inline] pub fn fmax(x: f64, y: f64) -> f64 { if x >= y || y.is_NaN() { x } else { y } } -#[inline(always)] +#[inline] pub fn fmin(x: f64, y: f64) -> f64 { if x <= y || y.is_NaN() { x } else { y } } @@ -234,23 +234,23 @@ impl Num for f64 {} #[cfg(not(test))] impl Eq for f64 { - #[inline(always)] + #[inline] fn eq(&self, other: &f64) -> bool { (*self) == (*other) } - #[inline(always)] + #[inline] fn ne(&self, other: &f64) -> bool { (*self) != (*other) } } #[cfg(not(test))] impl ApproxEq for f64 { - #[inline(always)] + #[inline] fn approx_epsilon() -> f64 { 1.0e-6 } - #[inline(always)] + #[inline] fn approx_eq(&self, other: &f64) -> bool { self.approx_eq_eps(other, &ApproxEq::approx_epsilon::()) } - #[inline(always)] + #[inline] fn approx_eq_eps(&self, other: &f64, approx_epsilon: &f64) -> bool { (*self - *other).abs() < *approx_epsilon } @@ -258,32 +258,32 @@ impl ApproxEq for f64 { #[cfg(not(test))] impl Ord for f64 { - #[inline(always)] + #[inline] fn lt(&self, other: &f64) -> bool { (*self) < (*other) } - #[inline(always)] + #[inline] fn le(&self, other: &f64) -> bool { (*self) <= (*other) } - #[inline(always)] + #[inline] fn ge(&self, other: &f64) -> bool { (*self) >= (*other) } - #[inline(always)] + #[inline] fn gt(&self, other: &f64) -> bool { (*self) > (*other) } } impl Orderable for f64 { /// Returns `NaN` if either of the numbers are `NaN`. - #[inline(always)] + #[inline] fn min(&self, other: &f64) -> f64 { if self.is_NaN() || other.is_NaN() { Float::NaN() } else { fmin(*self, *other) } } /// Returns `NaN` if either of the numbers are `NaN`. - #[inline(always)] + #[inline] fn max(&self, other: &f64) -> f64 { if self.is_NaN() || other.is_NaN() { Float::NaN() } else { fmax(*self, *other) } } /// Returns the number constrained within the range `mn <= self <= mx`. /// If any of the numbers are `NaN` then `NaN` is returned. - #[inline(always)] + #[inline] fn clamp(&self, mn: &f64, mx: &f64) -> f64 { cond!( (self.is_NaN()) { *self } @@ -295,16 +295,16 @@ impl Orderable for f64 { } impl Zero for f64 { - #[inline(always)] + #[inline] fn zero() -> f64 { 0.0 } /// Returns true if the number is equal to either `0.0` or `-0.0` - #[inline(always)] + #[inline] fn is_zero(&self) -> bool { *self == 0.0 || *self == -0.0 } } impl One for f64 { - #[inline(always)] + #[inline] fn one() -> f64 { 1.0 } } @@ -326,7 +326,7 @@ impl Div for f64 { } #[cfg(not(test))] impl Rem for f64 { - #[inline(always)] + #[inline] fn rem(&self, other: &f64) -> f64 { *self % *other } } #[cfg(not(test))] @@ -336,14 +336,14 @@ impl Neg for f64 { impl Signed for f64 { /// Computes the absolute value. Returns `NaN` if the number is `NaN`. - #[inline(always)] + #[inline] fn abs(&self) -> f64 { abs(*self) } /// /// The positive difference of two numbers. Returns `0.0` if the number is less than or /// equal to `other`, otherwise the difference between`self` and `other` is returned. /// - #[inline(always)] + #[inline] fn abs_sub(&self, other: &f64) -> f64 { abs_sub(*self, *other) } /// @@ -353,35 +353,35 @@ impl Signed for f64 { /// - `-1.0` if the number is negative, `-0.0` or `neg_infinity` /// - `NaN` if the number is NaN /// - #[inline(always)] + #[inline] fn signum(&self) -> f64 { if self.is_NaN() { NaN } else { copysign(1.0, *self) } } /// Returns `true` if the number is positive, including `+0.0` and `infinity` - #[inline(always)] + #[inline] fn is_positive(&self) -> bool { *self > 0.0 || (1.0 / *self) == infinity } /// Returns `true` if the number is negative, including `-0.0` and `neg_infinity` - #[inline(always)] + #[inline] fn is_negative(&self) -> bool { *self < 0.0 || (1.0 / *self) == neg_infinity } } impl Round for f64 { /// Round half-way cases toward `neg_infinity` - #[inline(always)] + #[inline] fn floor(&self) -> f64 { floor(*self) } /// Round half-way cases toward `infinity` - #[inline(always)] + #[inline] fn ceil(&self) -> f64 { ceil(*self) } /// Round half-way cases away from `0.0` - #[inline(always)] + #[inline] fn round(&self) -> f64 { round(*self) } /// The integer part of the number (rounds towards `0.0`) - #[inline(always)] + #[inline] fn trunc(&self) -> f64 { trunc(*self) } /// @@ -391,57 +391,57 @@ impl Round for f64 { /// assert!(x == trunc(x) + fract(x)) /// ~~~ /// - #[inline(always)] + #[inline] fn fract(&self) -> f64 { *self - self.trunc() } } impl Fractional for f64 { /// The reciprocal (multiplicative inverse) of the number - #[inline(always)] + #[inline] fn recip(&self) -> f64 { 1.0 / *self } } impl Algebraic for f64 { - #[inline(always)] + #[inline] fn pow(&self, n: &f64) -> f64 { pow(*self, *n) } - #[inline(always)] + #[inline] fn sqrt(&self) -> f64 { sqrt(*self) } - #[inline(always)] + #[inline] fn rsqrt(&self) -> f64 { self.sqrt().recip() } - #[inline(always)] + #[inline] fn cbrt(&self) -> f64 { cbrt(*self) } - #[inline(always)] + #[inline] fn hypot(&self, other: &f64) -> f64 { hypot(*self, *other) } } impl Trigonometric for f64 { - #[inline(always)] + #[inline] fn sin(&self) -> f64 { sin(*self) } - #[inline(always)] + #[inline] fn cos(&self) -> f64 { cos(*self) } - #[inline(always)] + #[inline] fn tan(&self) -> f64 { tan(*self) } - #[inline(always)] + #[inline] fn asin(&self) -> f64 { asin(*self) } - #[inline(always)] + #[inline] fn acos(&self) -> f64 { acos(*self) } - #[inline(always)] + #[inline] fn atan(&self) -> f64 { atan(*self) } - #[inline(always)] + #[inline] fn atan2(&self, other: &f64) -> f64 { atan2(*self, *other) } /// Simultaneously computes the sine and cosine of the number - #[inline(always)] + #[inline] fn sin_cos(&self) -> (f64, f64) { (self.sin(), self.cos()) } @@ -449,38 +449,38 @@ impl Trigonometric for f64 { impl Exponential for f64 { /// Returns the exponential of the number - #[inline(always)] + #[inline] fn exp(&self) -> f64 { exp(*self) } /// Returns 2 raised to the power of the number - #[inline(always)] + #[inline] fn exp2(&self) -> f64 { exp2(*self) } /// Returns the natural logarithm of the number - #[inline(always)] + #[inline] fn ln(&self) -> f64 { ln(*self) } /// Returns the logarithm of the number with respect to an arbitrary base - #[inline(always)] + #[inline] fn log(&self, base: &f64) -> f64 { self.ln() / base.ln() } /// Returns the base 2 logarithm of the number - #[inline(always)] + #[inline] fn log2(&self) -> f64 { log2(*self) } /// Returns the base 10 logarithm of the number - #[inline(always)] + #[inline] fn log10(&self) -> f64 { log10(*self) } } impl Hyperbolic for f64 { - #[inline(always)] + #[inline] fn sinh(&self) -> f64 { sinh(*self) } - #[inline(always)] + #[inline] fn cosh(&self) -> f64 { cosh(*self) } - #[inline(always)] + #[inline] fn tanh(&self) -> f64 { tanh(*self) } /// @@ -492,7 +492,7 @@ impl Hyperbolic for f64 { /// - `self` if `self` is `0.0`, `-0.0`, `infinity`, or `neg_infinity` /// - `NaN` if `self` is `NaN` /// - #[inline(always)] + #[inline] fn asinh(&self) -> f64 { match *self { neg_infinity => neg_infinity, @@ -509,7 +509,7 @@ impl Hyperbolic for f64 { /// - `infinity` if `self` is `infinity` /// - `NaN` if `self` is `NaN` or `self < 1.0` (including `neg_infinity`) /// - #[inline(always)] + #[inline] fn acosh(&self) -> f64 { match *self { x if x < 1.0 => Float::NaN(), @@ -529,7 +529,7 @@ impl Hyperbolic for f64 { /// - `NaN` if the `self` is `NaN` or outside the domain of `-1.0 <= self <= 1.0` /// (including `infinity` and `neg_infinity`) /// - #[inline(always)] + #[inline] fn atanh(&self) -> f64 { 0.5 * ((2.0 * *self) / (1.0 - *self)).ln_1p() } @@ -537,159 +537,159 @@ impl Hyperbolic for f64 { impl Real for f64 { /// Archimedes' constant - #[inline(always)] + #[inline] fn pi() -> f64 { 3.14159265358979323846264338327950288 } /// 2.0 * pi - #[inline(always)] + #[inline] fn two_pi() -> f64 { 6.28318530717958647692528676655900576 } /// pi / 2.0 - #[inline(always)] + #[inline] fn frac_pi_2() -> f64 { 1.57079632679489661923132169163975144 } /// pi / 3.0 - #[inline(always)] + #[inline] fn frac_pi_3() -> f64 { 1.04719755119659774615421446109316763 } /// pi / 4.0 - #[inline(always)] + #[inline] fn frac_pi_4() -> f64 { 0.785398163397448309615660845819875721 } /// pi / 6.0 - #[inline(always)] + #[inline] fn frac_pi_6() -> f64 { 0.52359877559829887307710723054658381 } /// pi / 8.0 - #[inline(always)] + #[inline] fn frac_pi_8() -> f64 { 0.39269908169872415480783042290993786 } /// 1.0 / pi - #[inline(always)] + #[inline] fn frac_1_pi() -> f64 { 0.318309886183790671537767526745028724 } /// 2.0 / pi - #[inline(always)] + #[inline] fn frac_2_pi() -> f64 { 0.636619772367581343075535053490057448 } /// 2.0 / sqrt(pi) - #[inline(always)] + #[inline] fn frac_2_sqrtpi() -> f64 { 1.12837916709551257389615890312154517 } /// sqrt(2.0) - #[inline(always)] + #[inline] fn sqrt2() -> f64 { 1.41421356237309504880168872420969808 } /// 1.0 / sqrt(2.0) - #[inline(always)] + #[inline] fn frac_1_sqrt2() -> f64 { 0.707106781186547524400844362104849039 } /// Euler's number - #[inline(always)] + #[inline] fn e() -> f64 { 2.71828182845904523536028747135266250 } /// log2(e) - #[inline(always)] + #[inline] fn log2_e() -> f64 { 1.44269504088896340735992468100189214 } /// log10(e) - #[inline(always)] + #[inline] fn log10_e() -> f64 { 0.434294481903251827651128918916605082 } /// ln(2.0) - #[inline(always)] + #[inline] fn ln_2() -> f64 { 0.693147180559945309417232121458176568 } /// ln(10.0) - #[inline(always)] + #[inline] fn ln_10() -> f64 { 2.30258509299404568401799145468436421 } /// Converts to degrees, assuming the number is in radians - #[inline(always)] + #[inline] fn to_degrees(&self) -> f64 { *self * (180.0 / Real::pi::()) } /// Converts to radians, assuming the number is in degrees - #[inline(always)] + #[inline] fn to_radians(&self) -> f64 { *self * (Real::pi::() / 180.0) } } impl RealExt for f64 { - #[inline(always)] + #[inline] fn lgamma(&self) -> (int, f64) { let mut sign = 0; let result = lgamma(*self, &mut sign); (sign as int, result) } - #[inline(always)] + #[inline] fn tgamma(&self) -> f64 { tgamma(*self) } - #[inline(always)] + #[inline] fn j0(&self) -> f64 { j0(*self) } - #[inline(always)] + #[inline] fn j1(&self) -> f64 { j1(*self) } - #[inline(always)] + #[inline] fn jn(&self, n: int) -> f64 { jn(n as c_int, *self) } - #[inline(always)] + #[inline] fn y0(&self) -> f64 { y0(*self) } - #[inline(always)] + #[inline] fn y1(&self) -> f64 { y1(*self) } - #[inline(always)] + #[inline] fn yn(&self, n: int) -> f64 { yn(n as c_int, *self) } } impl Bounded for f64 { - #[inline(always)] + #[inline] fn min_value() -> f64 { 2.2250738585072014e-308 } - #[inline(always)] + #[inline] fn max_value() -> f64 { 1.7976931348623157e+308 } } impl Primitive for f64 { - #[inline(always)] + #[inline] fn bits() -> uint { 64 } - #[inline(always)] + #[inline] fn bytes() -> uint { Primitive::bits::() / 8 } } impl Float for f64 { - #[inline(always)] + #[inline] fn NaN() -> f64 { 0.0 / 0.0 } - #[inline(always)] + #[inline] fn infinity() -> f64 { 1.0 / 0.0 } - #[inline(always)] + #[inline] fn neg_infinity() -> f64 { -1.0 / 0.0 } - #[inline(always)] + #[inline] fn neg_zero() -> f64 { -0.0 } /// Returns `true` if the number is NaN - #[inline(always)] + #[inline] fn is_NaN(&self) -> bool { *self != *self } /// Returns `true` if the number is infinite - #[inline(always)] + #[inline] fn is_infinite(&self) -> bool { *self == Float::infinity() || *self == Float::neg_infinity() } /// Returns `true` if the number is neither infinite or NaN - #[inline(always)] + #[inline] fn is_finite(&self) -> bool { !(self.is_NaN() || self.is_infinite()) } /// Returns `true` if the number is neither zero, infinite, subnormal or NaN - #[inline(always)] + #[inline] fn is_normal(&self) -> bool { self.classify() == FPNormal } @@ -712,29 +712,29 @@ impl Float for f64 { } } - #[inline(always)] + #[inline] fn mantissa_digits() -> uint { 53 } - #[inline(always)] + #[inline] fn digits() -> uint { 15 } - #[inline(always)] + #[inline] fn epsilon() -> f64 { 2.2204460492503131e-16 } - #[inline(always)] + #[inline] fn min_exp() -> int { -1021 } - #[inline(always)] + #[inline] fn max_exp() -> int { 1024 } - #[inline(always)] + #[inline] fn min_10_exp() -> int { -307 } - #[inline(always)] + #[inline] fn max_10_exp() -> int { 308 } /// Constructs a floating point number by multiplying `x` by 2 raised to the power of `exp` - #[inline(always)] + #[inline] fn ldexp(x: f64, exp: int) -> f64 { ldexp(x, exp as c_int) } @@ -745,7 +745,7 @@ impl Float for f64 { /// - `self = x * pow(2, exp)` /// - `0.5 <= abs(x) < 1.0` /// - #[inline(always)] + #[inline] fn frexp(&self) -> (f64, int) { let mut exp = 0; let x = frexp(*self, &mut exp); @@ -756,14 +756,14 @@ impl Float for f64 { /// Returns the exponential of the number, minus `1`, in a way that is accurate /// even if the number is close to zero /// - #[inline(always)] + #[inline] fn exp_m1(&self) -> f64 { exp_m1(*self) } /// /// Returns the natural logarithm of the number plus `1` (`ln(1+n)`) more accurately /// than if the operations were performed separately /// - #[inline(always)] + #[inline] fn ln_1p(&self) -> f64 { ln_1p(*self) } /// @@ -771,13 +771,13 @@ impl Float for f64 { /// produces a more accurate result with better performance than a separate multiplication /// operation followed by an add. /// - #[inline(always)] + #[inline] fn mul_add(&self, a: f64, b: f64) -> f64 { mul_add(*self, a, b) } /// Returns the next representable floating-point value in the direction of `other` - #[inline(always)] + #[inline] fn next_after(&self, other: f64) -> f64 { next_after(*self, other) } @@ -794,7 +794,7 @@ impl Float for f64 { /// /// * num - The float value /// -#[inline(always)] +#[inline] pub fn to_str(num: f64) -> ~str { let (r, _) = strconv::to_str_common( &num, 10u, true, strconv::SignNeg, strconv::DigAll); @@ -808,7 +808,7 @@ pub fn to_str(num: f64) -> ~str { /// /// * num - The float value /// -#[inline(always)] +#[inline] pub fn to_str_hex(num: f64) -> ~str { let (r, _) = strconv::to_str_common( &num, 16u, true, strconv::SignNeg, strconv::DigAll); @@ -829,7 +829,7 @@ pub fn to_str_hex(num: f64) -> ~str { /// possible misinterpretation of the result at higher bases. If those values /// are expected, use `to_str_radix_special()` instead. /// -#[inline(always)] +#[inline] pub fn to_str_radix(num: f64, rdx: uint) -> ~str { let (r, special) = strconv::to_str_common( &num, rdx, true, strconv::SignNeg, strconv::DigAll); @@ -847,7 +847,7 @@ pub fn to_str_radix(num: f64, rdx: uint) -> ~str { /// * num - The float value /// * radix - The base to use /// -#[inline(always)] +#[inline] pub fn to_str_radix_special(num: f64, rdx: uint) -> (~str, bool) { strconv::to_str_common(&num, rdx, true, strconv::SignNeg, strconv::DigAll) @@ -862,7 +862,7 @@ pub fn to_str_radix_special(num: f64, rdx: uint) -> (~str, bool) { /// * num - The float value /// * digits - The number of significant digits /// -#[inline(always)] +#[inline] pub fn to_str_exact(num: f64, dig: uint) -> ~str { let (r, _) = strconv::to_str_common( &num, 10u, true, strconv::SignNeg, strconv::DigExact(dig)); @@ -878,7 +878,7 @@ pub fn to_str_exact(num: f64, dig: uint) -> ~str { /// * num - The float value /// * digits - The number of significant digits /// -#[inline(always)] +#[inline] pub fn to_str_digits(num: f64, dig: uint) -> ~str { let (r, _) = strconv::to_str_common( &num, 10u, true, strconv::SignNeg, strconv::DigMax(dig)); @@ -886,12 +886,12 @@ pub fn to_str_digits(num: f64, dig: uint) -> ~str { } impl to_str::ToStr for f64 { - #[inline(always)] + #[inline] fn to_str(&self) -> ~str { to_str_digits(*self, 8) } } impl num::ToStrRadix for f64 { - #[inline(always)] + #[inline] fn to_str_radix(&self, rdx: uint) -> ~str { to_str_radix(*self, rdx) } @@ -924,7 +924,7 @@ impl num::ToStrRadix for f64 { /// `none` if the string did not represent a valid number. Otherwise, /// `Some(n)` where `n` is the floating-point number represented by `num`. /// -#[inline(always)] +#[inline] pub fn from_str(num: &str) -> Option { strconv::from_str_common(num, 10u, true, true, true, strconv::ExpDec, false, false) @@ -957,7 +957,7 @@ pub fn from_str(num: &str) -> Option { /// `none` if the string did not represent a valid number. Otherwise, /// `Some(n)` where `n` is the floating-point number represented by `[num]`. /// -#[inline(always)] +#[inline] pub fn from_str_hex(num: &str) -> Option { strconv::from_str_common(num, 16u, true, true, true, strconv::ExpBin, false, false) @@ -982,19 +982,19 @@ pub fn from_str_hex(num: &str) -> Option { /// `none` if the string did not represent a valid number. Otherwise, /// `Some(n)` where `n` is the floating-point number represented by `num`. /// -#[inline(always)] +#[inline] pub fn from_str_radix(num: &str, rdx: uint) -> Option { strconv::from_str_common(num, rdx, true, true, false, strconv::ExpNone, false, false) } impl FromStr for f64 { - #[inline(always)] + #[inline] fn from_str(val: &str) -> Option { from_str(val) } } impl num::FromStrRadix for f64 { - #[inline(always)] + #[inline] fn from_str_radix(val: &str, rdx: uint) -> Option { from_str_radix(val, rdx) } diff --git a/src/libstd/num/float.rs b/src/libstd/num/float.rs index 267a8890e826..c583aeacf162 100644 --- a/src/libstd/num/float.rs +++ b/src/libstd/num/float.rs @@ -99,7 +99,7 @@ pub mod consts { /// /// * num - The float value /// -#[inline(always)] +#[inline] pub fn to_str(num: float) -> ~str { let (r, _) = strconv::to_str_common( &num, 10u, true, strconv::SignNeg, strconv::DigAll); @@ -113,7 +113,7 @@ pub fn to_str(num: float) -> ~str { /// /// * num - The float value /// -#[inline(always)] +#[inline] pub fn to_str_hex(num: float) -> ~str { let (r, _) = strconv::to_str_common( &num, 16u, true, strconv::SignNeg, strconv::DigAll); @@ -134,7 +134,7 @@ pub fn to_str_hex(num: float) -> ~str { /// possible misinterpretation of the result at higher bases. If those values /// are expected, use `to_str_radix_special()` instead. /// -#[inline(always)] +#[inline] pub fn to_str_radix(num: float, radix: uint) -> ~str { let (r, special) = strconv::to_str_common( &num, radix, true, strconv::SignNeg, strconv::DigAll); @@ -152,7 +152,7 @@ pub fn to_str_radix(num: float, radix: uint) -> ~str { /// * num - The float value /// * radix - The base to use /// -#[inline(always)] +#[inline] pub fn to_str_radix_special(num: float, radix: uint) -> (~str, bool) { strconv::to_str_common(&num, radix, true, strconv::SignNeg, strconv::DigAll) @@ -167,7 +167,7 @@ pub fn to_str_radix_special(num: float, radix: uint) -> (~str, bool) { /// * num - The float value /// * digits - The number of significant digits /// -#[inline(always)] +#[inline] pub fn to_str_exact(num: float, digits: uint) -> ~str { let (r, _) = strconv::to_str_common( &num, 10u, true, strconv::SignNeg, strconv::DigExact(digits)); @@ -183,7 +183,7 @@ pub fn to_str_exact(num: float, digits: uint) -> ~str { /// * num - The float value /// * digits - The number of significant digits /// -#[inline(always)] +#[inline] pub fn to_str_digits(num: float, digits: uint) -> ~str { let (r, _) = strconv::to_str_common( &num, 10u, true, strconv::SignNeg, strconv::DigMax(digits)); @@ -191,12 +191,12 @@ pub fn to_str_digits(num: float, digits: uint) -> ~str { } impl to_str::ToStr for float { - #[inline(always)] + #[inline] fn to_str(&self) -> ~str { to_str_digits(*self, 8) } } impl num::ToStrRadix for float { - #[inline(always)] + #[inline] fn to_str_radix(&self, radix: uint) -> ~str { to_str_radix(*self, radix) } @@ -229,7 +229,7 @@ impl num::ToStrRadix for float { /// `none` if the string did not represent a valid number. Otherwise, /// `Some(n)` where `n` is the floating-point number represented by `num`. /// -#[inline(always)] +#[inline] pub fn from_str(num: &str) -> Option { strconv::from_str_common(num, 10u, true, true, true, strconv::ExpDec, false, false) @@ -262,7 +262,7 @@ pub fn from_str(num: &str) -> Option { /// `none` if the string did not represent a valid number. Otherwise, /// `Some(n)` where `n` is the floating-point number represented by `[num]`. /// -#[inline(always)] +#[inline] pub fn from_str_hex(num: &str) -> Option { strconv::from_str_common(num, 16u, true, true, true, strconv::ExpBin, false, false) @@ -287,19 +287,19 @@ pub fn from_str_hex(num: &str) -> Option { /// `none` if the string did not represent a valid number. Otherwise, /// `Some(n)` where `n` is the floating-point number represented by `num`. /// -#[inline(always)] +#[inline] pub fn from_str_radix(num: &str, radix: uint) -> Option { strconv::from_str_common(num, radix, true, true, false, strconv::ExpNone, false, false) } impl FromStr for float { - #[inline(always)] + #[inline] fn from_str(val: &str) -> Option { from_str(val) } } impl num::FromStrRadix for float { - #[inline(always)] + #[inline] fn from_str_radix(val: &str, radix: uint) -> Option { from_str_radix(val, radix) } @@ -341,27 +341,27 @@ pub fn pow_with_uint(base: uint, pow: uint) -> float { return total; } -#[inline(always)] +#[inline] pub fn abs(x: float) -> float { f64::abs(x as f64) as float } -#[inline(always)] +#[inline] pub fn sqrt(x: float) -> float { f64::sqrt(x as f64) as float } -#[inline(always)] +#[inline] pub fn atan(x: float) -> float { f64::atan(x as f64) as float } -#[inline(always)] +#[inline] pub fn sin(x: float) -> float { f64::sin(x as f64) as float } -#[inline(always)] +#[inline] pub fn cos(x: float) -> float { f64::cos(x as f64) as float } -#[inline(always)] +#[inline] pub fn tan(x: float) -> float { f64::tan(x as f64) as float } @@ -370,23 +370,23 @@ impl Num for float {} #[cfg(not(test))] impl Eq for float { - #[inline(always)] + #[inline] fn eq(&self, other: &float) -> bool { (*self) == (*other) } - #[inline(always)] + #[inline] fn ne(&self, other: &float) -> bool { (*self) != (*other) } } #[cfg(not(test))] impl ApproxEq for float { - #[inline(always)] + #[inline] fn approx_epsilon() -> float { 1.0e-6 } - #[inline(always)] + #[inline] fn approx_eq(&self, other: &float) -> bool { self.approx_eq_eps(other, &ApproxEq::approx_epsilon::()) } - #[inline(always)] + #[inline] fn approx_eq_eps(&self, other: &float, approx_epsilon: &float) -> bool { (*self - *other).abs() < *approx_epsilon } @@ -394,66 +394,66 @@ impl ApproxEq for float { #[cfg(not(test))] impl Ord for float { - #[inline(always)] + #[inline] fn lt(&self, other: &float) -> bool { (*self) < (*other) } - #[inline(always)] + #[inline] fn le(&self, other: &float) -> bool { (*self) <= (*other) } - #[inline(always)] + #[inline] fn ge(&self, other: &float) -> bool { (*self) >= (*other) } - #[inline(always)] + #[inline] fn gt(&self, other: &float) -> bool { (*self) > (*other) } } impl Orderable for float { /// Returns `NaN` if either of the numbers are `NaN`. - #[inline(always)] + #[inline] fn min(&self, other: &float) -> float { (*self as f64).min(&(*other as f64)) as float } /// Returns `NaN` if either of the numbers are `NaN`. - #[inline(always)] + #[inline] fn max(&self, other: &float) -> float { (*self as f64).max(&(*other as f64)) as float } /// Returns the number constrained within the range `mn <= self <= mx`. /// If any of the numbers are `NaN` then `NaN` is returned. - #[inline(always)] + #[inline] fn clamp(&self, mn: &float, mx: &float) -> float { (*self as f64).clamp(&(*mn as f64), &(*mx as f64)) as float } } impl Zero for float { - #[inline(always)] + #[inline] fn zero() -> float { 0.0 } /// Returns true if the number is equal to either `0.0` or `-0.0` - #[inline(always)] + #[inline] fn is_zero(&self) -> bool { *self == 0.0 || *self == -0.0 } } impl One for float { - #[inline(always)] + #[inline] fn one() -> float { 1.0 } } impl Round for float { /// Round half-way cases toward `neg_infinity` - #[inline(always)] + #[inline] fn floor(&self) -> float { floor(*self as f64) as float } /// Round half-way cases toward `infinity` - #[inline(always)] + #[inline] fn ceil(&self) -> float { ceil(*self as f64) as float } /// Round half-way cases away from `0.0` - #[inline(always)] + #[inline] fn round(&self) -> float { round(*self as f64) as float } /// The integer part of the number (rounds towards `0.0`) - #[inline(always)] + #[inline] fn trunc(&self) -> float { trunc(*self as f64) as float } /// @@ -463,81 +463,81 @@ impl Round for float { /// assert!(x == trunc(x) + fract(x)) /// ~~~ /// - #[inline(always)] + #[inline] fn fract(&self) -> float { *self - self.trunc() } } impl Fractional for float { /// The reciprocal (multiplicative inverse) of the number - #[inline(always)] + #[inline] fn recip(&self) -> float { 1.0 / *self } } impl Algebraic for float { - #[inline(always)] + #[inline] fn pow(&self, n: &float) -> float { (*self as f64).pow(&(*n as f64)) as float } - #[inline(always)] + #[inline] fn sqrt(&self) -> float { (*self as f64).sqrt() as float } - #[inline(always)] + #[inline] fn rsqrt(&self) -> float { (*self as f64).rsqrt() as float } - #[inline(always)] + #[inline] fn cbrt(&self) -> float { (*self as f64).cbrt() as float } - #[inline(always)] + #[inline] fn hypot(&self, other: &float) -> float { (*self as f64).hypot(&(*other as f64)) as float } } impl Trigonometric for float { - #[inline(always)] + #[inline] fn sin(&self) -> float { (*self as f64).sin() as float } - #[inline(always)] + #[inline] fn cos(&self) -> float { (*self as f64).cos() as float } - #[inline(always)] + #[inline] fn tan(&self) -> float { (*self as f64).tan() as float } - #[inline(always)] + #[inline] fn asin(&self) -> float { (*self as f64).asin() as float } - #[inline(always)] + #[inline] fn acos(&self) -> float { (*self as f64).acos() as float } - #[inline(always)] + #[inline] fn atan(&self) -> float { (*self as f64).atan() as float } - #[inline(always)] + #[inline] fn atan2(&self, other: &float) -> float { (*self as f64).atan2(&(*other as f64)) as float } /// Simultaneously computes the sine and cosine of the number - #[inline(always)] + #[inline] fn sin_cos(&self) -> (float, float) { match (*self as f64).sin_cos() { (s, c) => (s as float, c as float) @@ -547,54 +547,54 @@ impl Trigonometric for float { impl Exponential for float { /// Returns the exponential of the number - #[inline(always)] + #[inline] fn exp(&self) -> float { (*self as f64).exp() as float } /// Returns 2 raised to the power of the number - #[inline(always)] + #[inline] fn exp2(&self) -> float { (*self as f64).exp2() as float } /// Returns the natural logarithm of the number - #[inline(always)] + #[inline] fn ln(&self) -> float { (*self as f64).ln() as float } /// Returns the logarithm of the number with respect to an arbitrary base - #[inline(always)] + #[inline] fn log(&self, base: &float) -> float { (*self as f64).log(&(*base as f64)) as float } /// Returns the base 2 logarithm of the number - #[inline(always)] + #[inline] fn log2(&self) -> float { (*self as f64).log2() as float } /// Returns the base 10 logarithm of the number - #[inline(always)] + #[inline] fn log10(&self) -> float { (*self as f64).log10() as float } } impl Hyperbolic for float { - #[inline(always)] + #[inline] fn sinh(&self) -> float { (*self as f64).sinh() as float } - #[inline(always)] + #[inline] fn cosh(&self) -> float { (*self as f64).cosh() as float } - #[inline(always)] + #[inline] fn tanh(&self) -> float { (*self as f64).tanh() as float } @@ -608,7 +608,7 @@ impl Hyperbolic for float { /// - `self` if `self` is `0.0`, `-0.0`, `infinity`, or `neg_infinity` /// - `NaN` if `self` is `NaN` /// - #[inline(always)] + #[inline] fn asinh(&self) -> float { (*self as f64).asinh() as float } @@ -622,7 +622,7 @@ impl Hyperbolic for float { /// - `infinity` if `self` is `infinity` /// - `NaN` if `self` is `NaN` or `self < 1.0` (including `neg_infinity`) /// - #[inline(always)] + #[inline] fn acosh(&self) -> float { (*self as f64).acosh() as float } @@ -639,7 +639,7 @@ impl Hyperbolic for float { /// - `NaN` if the `self` is `NaN` or outside the domain of `-1.0 <= self <= 1.0` /// (including `infinity` and `neg_infinity`) /// - #[inline(always)] + #[inline] fn atanh(&self) -> float { (*self as f64).atanh() as float } @@ -647,157 +647,157 @@ impl Hyperbolic for float { impl Real for float { /// Archimedes' constant - #[inline(always)] + #[inline] fn pi() -> float { 3.14159265358979323846264338327950288 } /// 2.0 * pi - #[inline(always)] + #[inline] fn two_pi() -> float { 6.28318530717958647692528676655900576 } /// pi / 2.0 - #[inline(always)] + #[inline] fn frac_pi_2() -> float { 1.57079632679489661923132169163975144 } /// pi / 3.0 - #[inline(always)] + #[inline] fn frac_pi_3() -> float { 1.04719755119659774615421446109316763 } /// pi / 4.0 - #[inline(always)] + #[inline] fn frac_pi_4() -> float { 0.785398163397448309615660845819875721 } /// pi / 6.0 - #[inline(always)] + #[inline] fn frac_pi_6() -> float { 0.52359877559829887307710723054658381 } /// pi / 8.0 - #[inline(always)] + #[inline] fn frac_pi_8() -> float { 0.39269908169872415480783042290993786 } /// 1.0 / pi - #[inline(always)] + #[inline] fn frac_1_pi() -> float { 0.318309886183790671537767526745028724 } /// 2.0 / pi - #[inline(always)] + #[inline] fn frac_2_pi() -> float { 0.636619772367581343075535053490057448 } /// 2 .0/ sqrt(pi) - #[inline(always)] + #[inline] fn frac_2_sqrtpi() -> float { 1.12837916709551257389615890312154517 } /// sqrt(2.0) - #[inline(always)] + #[inline] fn sqrt2() -> float { 1.41421356237309504880168872420969808 } /// 1.0 / sqrt(2.0) - #[inline(always)] + #[inline] fn frac_1_sqrt2() -> float { 0.707106781186547524400844362104849039 } /// Euler's number - #[inline(always)] + #[inline] fn e() -> float { 2.71828182845904523536028747135266250 } /// log2(e) - #[inline(always)] + #[inline] fn log2_e() -> float { 1.44269504088896340735992468100189214 } /// log10(e) - #[inline(always)] + #[inline] fn log10_e() -> float { 0.434294481903251827651128918916605082 } /// ln(2.0) - #[inline(always)] + #[inline] fn ln_2() -> float { 0.693147180559945309417232121458176568 } /// ln(10.0) - #[inline(always)] + #[inline] fn ln_10() -> float { 2.30258509299404568401799145468436421 } /// Converts to degrees, assuming the number is in radians - #[inline(always)] + #[inline] fn to_degrees(&self) -> float { (*self as f64).to_degrees() as float } /// Converts to radians, assuming the number is in degrees - #[inline(always)] + #[inline] fn to_radians(&self) -> float { (*self as f64).to_radians() as float } } impl RealExt for float { - #[inline(always)] + #[inline] fn lgamma(&self) -> (int, float) { let mut sign = 0; let result = lgamma(*self as f64, &mut sign); (sign as int, result as float) } - #[inline(always)] + #[inline] fn tgamma(&self) -> float { tgamma(*self as f64) as float } - #[inline(always)] + #[inline] fn j0(&self) -> float { j0(*self as f64) as float } - #[inline(always)] + #[inline] fn j1(&self) -> float { j1(*self as f64) as float } - #[inline(always)] + #[inline] fn jn(&self, n: int) -> float { jn(n as c_int, *self as f64) as float } - #[inline(always)] + #[inline] fn y0(&self) -> float { y0(*self as f64) as float } - #[inline(always)] + #[inline] fn y1(&self) -> float { y1(*self as f64) as float } - #[inline(always)] + #[inline] fn yn(&self, n: int) -> float { yn(n as c_int, *self as f64) as float } } #[cfg(not(test))] impl Add for float { - #[inline(always)] + #[inline] fn add(&self, other: &float) -> float { *self + *other } } #[cfg(not(test))] impl Sub for float { - #[inline(always)] + #[inline] fn sub(&self, other: &float) -> float { *self - *other } } #[cfg(not(test))] impl Mul for float { - #[inline(always)] + #[inline] fn mul(&self, other: &float) -> float { *self * *other } } #[cfg(not(test))] impl Div for float { - #[inline(always)] + #[inline] fn div(&self, other: &float) -> float { *self / *other } } #[cfg(not(test))] impl Rem for float { - #[inline(always)] + #[inline] fn rem(&self, other: &float) -> float { *self % *other } } #[cfg(not(test))] impl Neg for float { - #[inline(always)] + #[inline] fn neg(&self) -> float { -*self } } impl Signed for float { /// Computes the absolute value. Returns `NaN` if the number is `NaN`. - #[inline(always)] + #[inline] fn abs(&self) -> float { abs(*self) } /// /// The positive difference of two numbers. Returns `0.0` if the number is less than or /// equal to `other`, otherwise the difference between`self` and `other` is returned. /// - #[inline(always)] + #[inline] fn abs_sub(&self, other: &float) -> float { (*self as f64).abs_sub(&(*other as f64)) as float } @@ -809,93 +809,93 @@ impl Signed for float { /// - `-1.0` if the number is negative, `-0.0` or `neg_infinity` /// - `NaN` if the number is NaN /// - #[inline(always)] + #[inline] fn signum(&self) -> float { if self.is_NaN() { NaN } else { f64::copysign(1.0, *self as f64) as float } } /// Returns `true` if the number is positive, including `+0.0` and `infinity` - #[inline(always)] + #[inline] fn is_positive(&self) -> bool { *self > 0.0 || (1.0 / *self) == infinity } /// Returns `true` if the number is negative, including `-0.0` and `neg_infinity` - #[inline(always)] + #[inline] fn is_negative(&self) -> bool { *self < 0.0 || (1.0 / *self) == neg_infinity } } impl Bounded for float { - #[inline(always)] + #[inline] fn min_value() -> float { Bounded::min_value::() as float } - #[inline(always)] + #[inline] fn max_value() -> float { Bounded::max_value::() as float } } impl Primitive for float { - #[inline(always)] + #[inline] fn bits() -> uint { Primitive::bits::() } - #[inline(always)] + #[inline] fn bytes() -> uint { Primitive::bytes::() } } impl Float for float { - #[inline(always)] + #[inline] fn NaN() -> float { Float::NaN::() as float } - #[inline(always)] + #[inline] fn infinity() -> float { Float::infinity::() as float } - #[inline(always)] + #[inline] fn neg_infinity() -> float { Float::neg_infinity::() as float } - #[inline(always)] + #[inline] fn neg_zero() -> float { Float::neg_zero::() as float } /// Returns `true` if the number is NaN - #[inline(always)] + #[inline] fn is_NaN(&self) -> bool { (*self as f64).is_NaN() } /// Returns `true` if the number is infinite - #[inline(always)] + #[inline] fn is_infinite(&self) -> bool { (*self as f64).is_infinite() } /// Returns `true` if the number is neither infinite or NaN - #[inline(always)] + #[inline] fn is_finite(&self) -> bool { (*self as f64).is_finite() } /// Returns `true` if the number is neither zero, infinite, subnormal or NaN - #[inline(always)] + #[inline] fn is_normal(&self) -> bool { (*self as f64).is_normal() } /// Returns the floating point category of the number. If only one property is going to /// be tested, it is generally faster to use the specific predicate instead. - #[inline(always)] + #[inline] fn classify(&self) -> FPCategory { (*self as f64).classify() } - #[inline(always)] + #[inline] fn mantissa_digits() -> uint { Float::mantissa_digits::() } - #[inline(always)] + #[inline] fn digits() -> uint { Float::digits::() } - #[inline(always)] + #[inline] fn epsilon() -> float { Float::epsilon::() as float } - #[inline(always)] + #[inline] fn min_exp() -> int { Float::min_exp::() } - #[inline(always)] + #[inline] fn max_exp() -> int { Float::max_exp::() } - #[inline(always)] + #[inline] fn min_10_exp() -> int { Float::min_10_exp::() } - #[inline(always)] + #[inline] fn max_10_exp() -> int { Float::max_10_exp::() } /// Constructs a floating point number by multiplying `x` by 2 raised to the power of `exp` - #[inline(always)] + #[inline] fn ldexp(x: float, exp: int) -> float { Float::ldexp(x as f64, exp) as float } @@ -906,7 +906,7 @@ impl Float for float { /// - `self = x * pow(2, exp)` /// - `0.5 <= abs(x) < 1.0` /// - #[inline(always)] + #[inline] fn frexp(&self) -> (float, int) { match (*self as f64).frexp() { (x, exp) => (x as float, exp) @@ -917,7 +917,7 @@ impl Float for float { /// Returns the exponential of the number, minus `1`, in a way that is accurate /// even if the number is close to zero /// - #[inline(always)] + #[inline] fn exp_m1(&self) -> float { (*self as f64).exp_m1() as float } @@ -926,7 +926,7 @@ impl Float for float { /// Returns the natural logarithm of the number plus `1` (`ln(1+n)`) more accurately /// than if the operations were performed separately /// - #[inline(always)] + #[inline] fn ln_1p(&self) -> float { (*self as f64).ln_1p() as float } @@ -936,13 +936,13 @@ impl Float for float { /// produces a more accurate result with better performance than a separate multiplication /// operation followed by an add. /// - #[inline(always)] + #[inline] fn mul_add(&self, a: float, b: float) -> float { mul_add(*self as f64, a as f64, b as f64) as float } /// Returns the next representable floating-point value in the direction of `other` - #[inline(always)] + #[inline] fn next_after(&self, other: float) -> float { next_after(*self as f64, other as f64) as float } diff --git a/src/libstd/num/i16.rs b/src/libstd/num/i16.rs index 9977247b249b..eec20297a533 100644 --- a/src/libstd/num/i16.rs +++ b/src/libstd/num/i16.rs @@ -19,14 +19,14 @@ int_module!(i16, 16) impl BitCount for i16 { /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic. - #[inline(always)] + #[inline] fn population_count(&self) -> i16 { unsafe { intrinsics::ctpop16(*self) } } /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic. - #[inline(always)] + #[inline] fn leading_zeros(&self) -> i16 { unsafe { intrinsics::ctlz16(*self) } } /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic. - #[inline(always)] + #[inline] fn trailing_zeros(&self) -> i16 { unsafe { intrinsics::cttz16(*self) } } } diff --git a/src/libstd/num/i32.rs b/src/libstd/num/i32.rs index 0115f306e4e0..769187cc66d6 100644 --- a/src/libstd/num/i32.rs +++ b/src/libstd/num/i32.rs @@ -19,14 +19,14 @@ int_module!(i32, 32) impl BitCount for i32 { /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic. - #[inline(always)] + #[inline] fn population_count(&self) -> i32 { unsafe { intrinsics::ctpop32(*self) } } /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic. - #[inline(always)] + #[inline] fn leading_zeros(&self) -> i32 { unsafe { intrinsics::ctlz32(*self) } } /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic. - #[inline(always)] + #[inline] fn trailing_zeros(&self) -> i32 { unsafe { intrinsics::cttz32(*self) } } } diff --git a/src/libstd/num/i64.rs b/src/libstd/num/i64.rs index 4e280f01f272..ae0e59d16610 100644 --- a/src/libstd/num/i64.rs +++ b/src/libstd/num/i64.rs @@ -19,14 +19,14 @@ int_module!(i64, 64) impl BitCount for i64 { /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic. - #[inline(always)] + #[inline] fn population_count(&self) -> i64 { unsafe { intrinsics::ctpop64(*self) } } /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic. - #[inline(always)] + #[inline] fn leading_zeros(&self) -> i64 { unsafe { intrinsics::ctlz64(*self) } } /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic. - #[inline(always)] + #[inline] fn trailing_zeros(&self) -> i64 { unsafe { intrinsics::cttz64(*self) } } } diff --git a/src/libstd/num/i8.rs b/src/libstd/num/i8.rs index 939965b96918..31a1f4241f58 100644 --- a/src/libstd/num/i8.rs +++ b/src/libstd/num/i8.rs @@ -19,14 +19,14 @@ int_module!(i8, 8) impl BitCount for i8 { /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic. - #[inline(always)] + #[inline] fn population_count(&self) -> i8 { unsafe { intrinsics::ctpop8(*self) } } /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic. - #[inline(always)] + #[inline] fn leading_zeros(&self) -> i8 { unsafe { intrinsics::ctlz8(*self) } } /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic. - #[inline(always)] + #[inline] fn trailing_zeros(&self) -> i8 { unsafe { intrinsics::cttz8(*self) } } } diff --git a/src/libstd/num/int.rs b/src/libstd/num/int.rs index 96ef7e9e3412..d3c2733b47d5 100644 --- a/src/libstd/num/int.rs +++ b/src/libstd/num/int.rs @@ -22,30 +22,30 @@ int_module!(int, super::bits) #[cfg(target_word_size = "32")] impl BitCount for int { /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic. - #[inline(always)] + #[inline] fn population_count(&self) -> int { (*self as i32).population_count() as int } /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic. - #[inline(always)] + #[inline] fn leading_zeros(&self) -> int { (*self as i32).leading_zeros() as int } /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic. - #[inline(always)] + #[inline] fn trailing_zeros(&self) -> int { (*self as i32).trailing_zeros() as int } } #[cfg(target_word_size = "64")] impl BitCount for int { /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic. - #[inline(always)] + #[inline] fn population_count(&self) -> int { (*self as i64).population_count() as int } /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic. - #[inline(always)] + #[inline] fn leading_zeros(&self) -> int { (*self as i64).leading_zeros() as int } /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic. - #[inline(always)] + #[inline] fn trailing_zeros(&self) -> int { (*self as i64).trailing_zeros() as int } } diff --git a/src/libstd/num/int_macros.rs b/src/libstd/num/int_macros.rs index 74f74d11b730..74ec46ccfcd4 100644 --- a/src/libstd/num/int_macros.rs +++ b/src/libstd/num/int_macros.rs @@ -27,17 +27,17 @@ pub static min_value: $T = (-1 as $T) << (bits - 1); pub static max_value: $T = min_value - 1 as $T; /// Calculates the sum of two numbers -#[inline(always)] +#[inline] pub fn add(x: $T, y: $T) -> $T { x + y } /// Subtracts the second number from the first -#[inline(always)] +#[inline] pub fn sub(x: $T, y: $T) -> $T { x - y } /// Multiplies two numbers together -#[inline(always)] +#[inline] pub fn mul(x: $T, y: $T) -> $T { x * y } /// Divides the first argument by the second argument (using integer division) /// Divides the first argument by the second argument (using integer division) -#[inline(always)] +#[inline] pub fn div(x: $T, y: $T) -> $T { x / y } /// @@ -60,26 +60,26 @@ pub fn div(x: $T, y: $T) -> $T { x / y } /// ~~~ /// /// -#[inline(always)] +#[inline] pub fn rem(x: $T, y: $T) -> $T { x % y } /// Returns true iff `x < y` -#[inline(always)] +#[inline] pub fn lt(x: $T, y: $T) -> bool { x < y } /// Returns true iff `x <= y` -#[inline(always)] +#[inline] pub fn le(x: $T, y: $T) -> bool { x <= y } /// Returns true iff `x == y` -#[inline(always)] +#[inline] pub fn eq(x: $T, y: $T) -> bool { x == y } /// Returns true iff `x != y` -#[inline(always)] +#[inline] pub fn ne(x: $T, y: $T) -> bool { x != y } /// Returns true iff `x >= y` -#[inline(always)] +#[inline] pub fn ge(x: $T, y: $T) -> bool { x >= y } /// Returns true iff `x > y` -#[inline(always)] +#[inline] pub fn gt(x: $T, y: $T) -> bool { x > y } /// @@ -99,7 +99,7 @@ pub fn gt(x: $T, y: $T) -> bool { x > y } /// assert!(sum == 10); /// ~~~ /// -#[inline(always)] +#[inline] pub fn range_step(start: $T, stop: $T, step: $T, it: &fn($T) -> bool) -> bool { let mut i = start; if step == 0 { @@ -122,62 +122,62 @@ pub fn range_step(start: $T, stop: $T, step: $T, it: &fn($T) -> bool) -> bool { return true; } -#[inline(always)] +#[inline] /// Iterate over the range [`lo`..`hi`) pub fn range(lo: $T, hi: $T, it: &fn($T) -> bool) -> bool { range_step(lo, hi, 1 as $T, it) } -#[inline(always)] +#[inline] /// Iterate over the range [`hi`..`lo`) pub fn range_rev(hi: $T, lo: $T, it: &fn($T) -> bool) -> bool { range_step(hi, lo, -1 as $T, it) } /// Computes the bitwise complement -#[inline(always)] +#[inline] pub fn compl(i: $T) -> $T { -1 as $T ^ i } /// Computes the absolute value -#[inline(always)] +#[inline] pub fn abs(i: $T) -> $T { i.abs() } impl Num for $T {} #[cfg(not(test))] impl Ord for $T { - #[inline(always)] + #[inline] fn lt(&self, other: &$T) -> bool { return (*self) < (*other); } - #[inline(always)] + #[inline] fn le(&self, other: &$T) -> bool { return (*self) <= (*other); } - #[inline(always)] + #[inline] fn ge(&self, other: &$T) -> bool { return (*self) >= (*other); } - #[inline(always)] + #[inline] fn gt(&self, other: &$T) -> bool { return (*self) > (*other); } } #[cfg(not(test))] impl Eq for $T { - #[inline(always)] + #[inline] fn eq(&self, other: &$T) -> bool { return (*self) == (*other); } - #[inline(always)] + #[inline] fn ne(&self, other: &$T) -> bool { return (*self) != (*other); } } impl Orderable for $T { - #[inline(always)] + #[inline] fn min(&self, other: &$T) -> $T { if *self < *other { *self } else { *other } } - #[inline(always)] + #[inline] fn max(&self, other: &$T) -> $T { if *self > *other { *self } else { *other } } - #[inline(always)] + #[inline] fn clamp(&self, mn: &$T, mx: &$T) -> $T { if *self > *mx { *mx } else if *self < *mn { *mn } else { *self } @@ -185,33 +185,33 @@ impl Orderable for $T { } impl Zero for $T { - #[inline(always)] + #[inline] fn zero() -> $T { 0 } - #[inline(always)] + #[inline] fn is_zero(&self) -> bool { *self == 0 } } impl One for $T { - #[inline(always)] + #[inline] fn one() -> $T { 1 } } #[cfg(not(test))] impl Add<$T,$T> for $T { - #[inline(always)] + #[inline] fn add(&self, other: &$T) -> $T { *self + *other } } #[cfg(not(test))] impl Sub<$T,$T> for $T { - #[inline(always)] + #[inline] fn sub(&self, other: &$T) -> $T { *self - *other } } #[cfg(not(test))] impl Mul<$T,$T> for $T { - #[inline(always)] + #[inline] fn mul(&self, other: &$T) -> $T { *self * *other } } @@ -235,7 +235,7 @@ impl Div<$T,$T> for $T { /// assert!(-1 / -2 == 0); /// ~~~ /// - #[inline(always)] + #[inline] fn div(&self, other: &$T) -> $T { *self / *other } } @@ -262,19 +262,19 @@ impl Rem<$T,$T> for $T { /// assert!(-1 % -2 == -1); /// ~~~ /// - #[inline(always)] + #[inline] fn rem(&self, other: &$T) -> $T { *self % *other } } #[cfg(not(test))] impl Neg<$T> for $T { - #[inline(always)] + #[inline] fn neg(&self) -> $T { -*self } } impl Signed for $T { /// Computes the absolute value - #[inline(always)] + #[inline] fn abs(&self) -> $T { if self.is_negative() { -*self } else { *self } } @@ -283,7 +283,7 @@ impl Signed for $T { /// The positive difference of two numbers. Returns `0` if the number is less than or /// equal to `other`, otherwise the difference between`self` and `other` is returned. /// - #[inline(always)] + #[inline] fn abs_sub(&self, other: &$T) -> $T { if *self <= *other { 0 } else { *self - *other } } @@ -295,7 +295,7 @@ impl Signed for $T { /// - `1` if the number is positive /// - `-1` if the number is negative /// - #[inline(always)] + #[inline] fn signum(&self) -> $T { match *self { n if n > 0 => 1, @@ -305,11 +305,11 @@ impl Signed for $T { } /// Returns true if the number is positive - #[inline(always)] + #[inline] fn is_positive(&self) -> bool { *self > 0 } /// Returns true if the number is negative - #[inline(always)] + #[inline] fn is_negative(&self) -> bool { *self < 0 } } @@ -331,7 +331,7 @@ impl Integer for $T { /// assert!((-1).div_floor(-2) == 0); /// ~~~ /// - #[inline(always)] + #[inline] fn div_floor(&self, other: &$T) -> $T { // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_, // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf) @@ -363,7 +363,7 @@ impl Integer for $T { /// assert!((-1).mod_floor(-2) == -1); /// ~~~ /// - #[inline(always)] + #[inline] fn mod_floor(&self, other: &$T) -> $T { // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_, // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf) @@ -375,7 +375,7 @@ impl Integer for $T { } /// Calculates `div_floor` and `mod_floor` simultaneously - #[inline(always)] + #[inline] fn div_mod_floor(&self, other: &$T) -> ($T,$T) { // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_, // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf) @@ -387,7 +387,7 @@ impl Integer for $T { } /// Calculates `div` (`\`) and `rem` (`%`) simultaneously - #[inline(always)] + #[inline] fn div_rem(&self, other: &$T) -> ($T,$T) { (*self / *other, *self % *other) } @@ -397,7 +397,7 @@ impl Integer for $T { /// /// The result is always positive /// - #[inline(always)] + #[inline] fn gcd(&self, other: &$T) -> $T { // Use Euclid's algorithm let mut (m, n) = (*self, *other); @@ -412,21 +412,21 @@ impl Integer for $T { /// /// Calculates the Lowest Common Multiple (LCM) of the number and `other` /// - #[inline(always)] + #[inline] fn lcm(&self, other: &$T) -> $T { ((*self * *other) / self.gcd(other)).abs() // should not have to recaluculate abs } /// Returns `true` if the number can be divided by `other` without leaving a remainder - #[inline(always)] + #[inline] fn is_multiple_of(&self, other: &$T) -> bool { *self % *other == 0 } /// Returns `true` if the number is divisible by `2` - #[inline(always)] + #[inline] fn is_even(&self) -> bool { self.is_multiple_of(&2) } /// Returns `true` if the number is not divisible by `2` - #[inline(always)] + #[inline] fn is_odd(&self) -> bool { !self.is_even() } } @@ -434,90 +434,90 @@ impl Bitwise for $T {} #[cfg(not(test))] impl BitOr<$T,$T> for $T { - #[inline(always)] + #[inline] fn bitor(&self, other: &$T) -> $T { *self | *other } } #[cfg(not(test))] impl BitAnd<$T,$T> for $T { - #[inline(always)] + #[inline] fn bitand(&self, other: &$T) -> $T { *self & *other } } #[cfg(not(test))] impl BitXor<$T,$T> for $T { - #[inline(always)] + #[inline] fn bitxor(&self, other: &$T) -> $T { *self ^ *other } } #[cfg(not(test))] impl Shl<$T,$T> for $T { - #[inline(always)] + #[inline] fn shl(&self, other: &$T) -> $T { *self << *other } } #[cfg(not(test))] impl Shr<$T,$T> for $T { - #[inline(always)] + #[inline] fn shr(&self, other: &$T) -> $T { *self >> *other } } #[cfg(not(test))] impl Not<$T> for $T { - #[inline(always)] + #[inline] fn not(&self) -> $T { !*self } } impl Bounded for $T { - #[inline(always)] + #[inline] fn min_value() -> $T { min_value } - #[inline(always)] + #[inline] fn max_value() -> $T { max_value } } impl Int for $T {} impl Primitive for $T { - #[inline(always)] + #[inline] fn bits() -> uint { bits } - #[inline(always)] + #[inline] fn bytes() -> uint { bits / 8 } } // String conversion functions and impl str -> num /// Parse a string as a number in base 10. -#[inline(always)] +#[inline] pub fn from_str(s: &str) -> Option<$T> { strconv::from_str_common(s, 10u, true, false, false, strconv::ExpNone, false, false) } /// Parse a string as a number in the given base. -#[inline(always)] +#[inline] pub fn from_str_radix(s: &str, radix: uint) -> Option<$T> { strconv::from_str_common(s, radix, true, false, false, strconv::ExpNone, false, false) } /// Parse a byte slice as a number in the given base. -#[inline(always)] +#[inline] pub fn parse_bytes(buf: &[u8], radix: uint) -> Option<$T> { strconv::from_str_bytes_common(buf, radix, true, false, false, strconv::ExpNone, false, false) } impl FromStr for $T { - #[inline(always)] + #[inline] fn from_str(s: &str) -> Option<$T> { from_str(s) } } impl FromStrRadix for $T { - #[inline(always)] + #[inline] fn from_str_radix(s: &str, radix: uint) -> Option<$T> { from_str_radix(s, radix) } @@ -526,7 +526,7 @@ impl FromStrRadix for $T { // String conversion functions and impl num -> str /// Convert to a string as a byte slice in a given base. -#[inline(always)] +#[inline] pub fn to_str_bytes(n: $T, radix: uint, f: &fn(v: &[u8]) -> U) -> U { let (buf, _) = strconv::to_str_bytes_common(&n, radix, false, strconv::SignNeg, strconv::DigAll); @@ -534,7 +534,7 @@ pub fn to_str_bytes(n: $T, radix: uint, f: &fn(v: &[u8]) -> U) -> U { } /// Convert to a string in base 10. -#[inline(always)] +#[inline] pub fn to_str(num: $T) -> ~str { let (buf, _) = strconv::to_str_common(&num, 10u, false, strconv::SignNeg, strconv::DigAll); @@ -542,7 +542,7 @@ pub fn to_str(num: $T) -> ~str { } /// Convert to a string in a given base. -#[inline(always)] +#[inline] pub fn to_str_radix(num: $T, radix: uint) -> ~str { let (buf, _) = strconv::to_str_common(&num, radix, false, strconv::SignNeg, strconv::DigAll); @@ -550,14 +550,14 @@ pub fn to_str_radix(num: $T, radix: uint) -> ~str { } impl ToStr for $T { - #[inline(always)] + #[inline] fn to_str(&self) -> ~str { to_str(*self) } } impl ToStrRadix for $T { - #[inline(always)] + #[inline] fn to_str_radix(&self, radix: uint) -> ~str { to_str_radix(*self, radix) } diff --git a/src/libstd/num/num.rs b/src/libstd/num/num.rs index a9893579721c..30a18a0587bc 100644 --- a/src/libstd/num/num.rs +++ b/src/libstd/num/num.rs @@ -307,7 +307,7 @@ pub trait Float: Real /// assert_eq!(twenty, 20f32); /// ~~~ /// -#[inline(always)] +#[inline] pub fn cast(n: T) -> U { NumCast::from(n) } @@ -338,28 +338,28 @@ pub trait NumCast { macro_rules! impl_num_cast( ($T:ty, $conv:ident) => ( impl NumCast for $T { - #[inline(always)] + #[inline] fn from(n: N) -> $T { // `$conv` could be generated using `concat_idents!`, but that // macro seems to be broken at the moment n.$conv() } - #[inline(always)] fn to_u8(&self) -> u8 { *self as u8 } - #[inline(always)] fn to_u16(&self) -> u16 { *self as u16 } - #[inline(always)] fn to_u32(&self) -> u32 { *self as u32 } - #[inline(always)] fn to_u64(&self) -> u64 { *self as u64 } - #[inline(always)] fn to_uint(&self) -> uint { *self as uint } + #[inline] fn to_u8(&self) -> u8 { *self as u8 } + #[inline] fn to_u16(&self) -> u16 { *self as u16 } + #[inline] fn to_u32(&self) -> u32 { *self as u32 } + #[inline] fn to_u64(&self) -> u64 { *self as u64 } + #[inline] fn to_uint(&self) -> uint { *self as uint } - #[inline(always)] fn to_i8(&self) -> i8 { *self as i8 } - #[inline(always)] fn to_i16(&self) -> i16 { *self as i16 } - #[inline(always)] fn to_i32(&self) -> i32 { *self as i32 } - #[inline(always)] fn to_i64(&self) -> i64 { *self as i64 } - #[inline(always)] fn to_int(&self) -> int { *self as int } + #[inline] fn to_i8(&self) -> i8 { *self as i8 } + #[inline] fn to_i16(&self) -> i16 { *self as i16 } + #[inline] fn to_i32(&self) -> i32 { *self as i32 } + #[inline] fn to_i64(&self) -> i64 { *self as i64 } + #[inline] fn to_int(&self) -> int { *self as int } - #[inline(always)] fn to_f32(&self) -> f32 { *self as f32 } - #[inline(always)] fn to_f64(&self) -> f64 { *self as f64 } - #[inline(always)] fn to_float(&self) -> float { *self as float } + #[inline] fn to_f32(&self) -> f32 { *self as f32 } + #[inline] fn to_f64(&self) -> f64 { *self as f64 } + #[inline] fn to_float(&self) -> float { *self as float } } ) ) @@ -410,14 +410,29 @@ pub fn pow_with_uint+Mul>(radix: uint, pow let mut multiplier = cast(radix); while (my_pow > 0u) { if my_pow % 2u == 1u { - total *= multiplier; + total = total * multiplier; } - my_pow /= 2u; - multiplier *= multiplier; + my_pow = my_pow / 2u; + multiplier = multiplier * multiplier; } total } +impl Zero for @mut T { + fn zero() -> @mut T { @mut Zero::zero() } + fn is_zero(&self) -> bool { (**self).is_zero() } +} + +impl Zero for @T { + fn zero() -> @T { @Zero::zero() } + fn is_zero(&self) -> bool { (**self).is_zero() } +} + +impl Zero for ~T { + fn zero() -> ~T { ~Zero::zero() } + fn is_zero(&self) -> bool { (**self).is_zero() } +} + /// Helper function for testing numeric operations #[cfg(test)] pub fn test_num(ten: T, two: T) { diff --git a/src/libstd/num/strconv.rs b/src/libstd/num/strconv.rs index 3905d82cd0f5..a062838aacf0 100644 --- a/src/libstd/num/strconv.rs +++ b/src/libstd/num/strconv.rs @@ -42,12 +42,12 @@ pub enum SignFormat { SignAll } -#[inline(always)] +#[inline] fn is_NaN(num: &T) -> bool { *num != *num } -#[inline(always)] +#[inline] fn is_inf(num: &T) -> bool { match NumStrConv::inf() { None => false, @@ -55,7 +55,7 @@ fn is_inf(num: &T) -> bool { } } -#[inline(always)] +#[inline] fn is_neg_inf(num: &T) -> bool { match NumStrConv::neg_inf() { None => false, @@ -63,7 +63,7 @@ fn is_neg_inf(num: &T) -> bool { } } -#[inline(always)] +#[inline] fn is_neg_zero>(num: &T) -> bool { let _0: T = Zero::zero(); let _1: T = One::one(); @@ -83,23 +83,23 @@ pub trait NumStrConv { macro_rules! impl_NumStrConv_Floating (($t:ty) => ( impl NumStrConv for $t { - #[inline(always)] + #[inline] fn NaN() -> Option<$t> { Some( 0.0 / 0.0) } - #[inline(always)] + #[inline] fn inf() -> Option<$t> { Some( 1.0 / 0.0) } - #[inline(always)] + #[inline] fn neg_inf() -> Option<$t> { Some(-1.0 / 0.0) } - #[inline(always)] + #[inline] fn neg_zero() -> Option<$t> { Some(-0.0 ) } - #[inline(always)] + #[inline] fn round_to_zero(&self) -> $t { ( if *self < 0.0 { f64::ceil(*self as f64) } else { f64::floor(*self as f64) } ) as $t } - #[inline(always)] + #[inline] fn fractional_part(&self) -> $t { *self - self.round_to_zero() } @@ -108,13 +108,13 @@ macro_rules! impl_NumStrConv_Floating (($t:ty) => ( macro_rules! impl_NumStrConv_Integer (($t:ty) => ( impl NumStrConv for $t { - #[inline(always)] fn NaN() -> Option<$t> { None } - #[inline(always)] fn inf() -> Option<$t> { None } - #[inline(always)] fn neg_inf() -> Option<$t> { None } - #[inline(always)] fn neg_zero() -> Option<$t> { None } + #[inline] fn NaN() -> Option<$t> { None } + #[inline] fn inf() -> Option<$t> { None } + #[inline] fn neg_inf() -> Option<$t> { None } + #[inline] fn neg_zero() -> Option<$t> { None } - #[inline(always)] fn round_to_zero(&self) -> $t { *self } - #[inline(always)] fn fractional_part(&self) -> $t { 0 } + #[inline] fn round_to_zero(&self) -> $t { *self } + #[inline] fn fractional_part(&self) -> $t { 0 } } )) @@ -229,7 +229,7 @@ pub fn to_str_bytes_common+Neg+Rem+Mul>( num: &T, radix: uint, negative_zero: bool, @@ -499,8 +499,8 @@ pub fn from_str_bytes_common+ // Initialize accumulator with signed zero for floating point parsing to // work - let mut accum = if accum_positive { _0 } else { -_1 * _0}; - let mut last_accum = accum; // Necessary to detect overflow + let mut accum = if accum_positive { copy _0 } else { -_1 * _0}; + let mut last_accum = copy accum; // Necessary to detect overflow let mut i = start; let mut exp_found = false; @@ -511,13 +511,13 @@ pub fn from_str_bytes_common+ match char::to_digit(c, radix) { Some(digit) => { // shift accum one digit left - accum *= radix_gen; + accum = accum * copy radix_gen; // add/subtract current digit depending on sign if accum_positive { - accum += cast(digit as int); + accum = accum + cast(digit as int); } else { - accum -= cast(digit as int); + accum = accum - cast(digit as int); } // Detect overflow by comparing to last value, except @@ -526,7 +526,7 @@ pub fn from_str_bytes_common+ if accum_positive && accum <= last_accum { return None; } if !accum_positive && accum >= last_accum { return None; } } - last_accum = accum; + last_accum = copy accum; } None => match c { '_' if ignore_underscores => {} @@ -548,7 +548,7 @@ pub fn from_str_bytes_common+ // Parse fractional part of number // Skip if already reached start of exponent if !exp_found { - let mut power = _1; + let mut power = copy _1; while i < len { let c = buf[i] as char; @@ -556,21 +556,21 @@ pub fn from_str_bytes_common+ match char::to_digit(c, radix) { Some(digit) => { // Decrease power one order of magnitude - power /= radix_gen; + power = power / radix_gen; let digit_t: T = cast(digit); // add/subtract current digit depending on sign if accum_positive { - accum += digit_t * power; + accum = accum + digit_t * power; } else { - accum -= digit_t * power; + accum = accum - digit_t * power; } // Detect overflow by comparing to last value if accum_positive && accum < last_accum { return None; } if !accum_positive && accum > last_accum { return None; } - last_accum = accum; + last_accum = copy accum; } None => match c { '_' if ignore_underscores => {} @@ -596,7 +596,7 @@ pub fn from_str_bytes_common+ } } - let mut multiplier = _1; + let mut multiplier = copy _1; if exp_found { let c = buf[i] as char; @@ -632,7 +632,7 @@ pub fn from_str_bytes_common+ * Parses a string as a number. This is a wrapper for * `from_str_bytes_common()`, for details see there. */ -#[inline(always)] +#[inline] pub fn from_str_common+Mul+ Sub+Neg+Add+NumStrConv>( buf: &str, radix: uint, negative: bool, fractional: bool, diff --git a/src/libstd/num/uint.rs b/src/libstd/num/uint.rs index bcb97ff5a07f..126150c0f1bf 100644 --- a/src/libstd/num/uint.rs +++ b/src/libstd/num/uint.rs @@ -95,7 +95,7 @@ pub fn iterate(lo: uint, hi: uint, it: &fn(uint) -> bool) -> bool { } impl iter::Times for uint { - #[inline(always)] + #[inline] /// /// A convenience form for basic iteration. Given a uint `x`, /// `for x.times { ... }` executes the given block x times. @@ -117,7 +117,7 @@ impl iter::Times for uint { } /// Returns the smallest power of 2 greater than or equal to `n` -#[inline(always)] +#[inline] pub fn next_power_of_two(n: uint) -> uint { let halfbits: uint = sys::size_of::() * 4u; let mut tmp: uint = n - 1u; diff --git a/src/libstd/num/uint_macros.rs b/src/libstd/num/uint_macros.rs index 2bc1ca9c6733..52f620f97ce8 100644 --- a/src/libstd/num/uint_macros.rs +++ b/src/libstd/num/uint_macros.rs @@ -28,42 +28,42 @@ pub static min_value: $T = 0 as $T; pub static max_value: $T = 0 as $T - 1 as $T; /// Calculates the sum of two numbers -#[inline(always)] +#[inline] pub fn add(x: $T, y: $T) -> $T { x + y } /// Subtracts the second number from the first -#[inline(always)] +#[inline] pub fn sub(x: $T, y: $T) -> $T { x - y } /// Multiplies two numbers together -#[inline(always)] +#[inline] pub fn mul(x: $T, y: $T) -> $T { x * y } /// Divides the first argument by the second argument (using integer division) -#[inline(always)] +#[inline] pub fn div(x: $T, y: $T) -> $T { x / y } /// Calculates the integer remainder when x is divided by y (equivalent to the /// '%' operator) -#[inline(always)] +#[inline] pub fn rem(x: $T, y: $T) -> $T { x % y } /// Returns true iff `x < y` -#[inline(always)] +#[inline] pub fn lt(x: $T, y: $T) -> bool { x < y } /// Returns true iff `x <= y` -#[inline(always)] +#[inline] pub fn le(x: $T, y: $T) -> bool { x <= y } /// Returns true iff `x == y` -#[inline(always)] +#[inline] pub fn eq(x: $T, y: $T) -> bool { x == y } /// Returns true iff `x != y` -#[inline(always)] +#[inline] pub fn ne(x: $T, y: $T) -> bool { x != y } /// Returns true iff `x >= y` -#[inline(always)] +#[inline] pub fn ge(x: $T, y: $T) -> bool { x >= y } /// Returns true iff `x > y` -#[inline(always)] +#[inline] pub fn gt(x: $T, y: $T) -> bool { x > y } -#[inline(always)] +#[inline] /** * Iterate through a range with a given step value. * @@ -99,20 +99,20 @@ pub fn range_step(start: $T, stop: $T, step: $T_SIGNED, it: &fn($T) -> bool) -> return true; } -#[inline(always)] +#[inline] /// Iterate over the range [`lo`..`hi`) pub fn range(lo: $T, hi: $T, it: &fn($T) -> bool) -> bool { range_step(lo, hi, 1 as $T_SIGNED, it) } -#[inline(always)] +#[inline] /// Iterate over the range [`hi`..`lo`) pub fn range_rev(hi: $T, lo: $T, it: &fn($T) -> bool) -> bool { range_step(hi, lo, -1 as $T_SIGNED, it) } /// Computes the bitwise complement -#[inline(always)] +#[inline] pub fn compl(i: $T) -> $T { max_value ^ i } @@ -121,37 +121,37 @@ impl Num for $T {} #[cfg(not(test))] impl Ord for $T { - #[inline(always)] + #[inline] fn lt(&self, other: &$T) -> bool { (*self) < (*other) } - #[inline(always)] + #[inline] fn le(&self, other: &$T) -> bool { (*self) <= (*other) } - #[inline(always)] + #[inline] fn ge(&self, other: &$T) -> bool { (*self) >= (*other) } - #[inline(always)] + #[inline] fn gt(&self, other: &$T) -> bool { (*self) > (*other) } } #[cfg(not(test))] impl Eq for $T { - #[inline(always)] + #[inline] fn eq(&self, other: &$T) -> bool { return (*self) == (*other); } - #[inline(always)] + #[inline] fn ne(&self, other: &$T) -> bool { return (*self) != (*other); } } impl Orderable for $T { - #[inline(always)] + #[inline] fn min(&self, other: &$T) -> $T { if *self < *other { *self } else { *other } } - #[inline(always)] + #[inline] fn max(&self, other: &$T) -> $T { if *self > *other { *self } else { *other } } /// Returns the number constrained within the range `mn <= self <= mx`. - #[inline(always)] + #[inline] fn clamp(&self, mn: &$T, mx: &$T) -> $T { cond!( (*self > *mx) { *mx } @@ -162,51 +162,51 @@ impl Orderable for $T { } impl Zero for $T { - #[inline(always)] + #[inline] fn zero() -> $T { 0 } - #[inline(always)] + #[inline] fn is_zero(&self) -> bool { *self == 0 } } impl One for $T { - #[inline(always)] + #[inline] fn one() -> $T { 1 } } #[cfg(not(test))] impl Add<$T,$T> for $T { - #[inline(always)] + #[inline] fn add(&self, other: &$T) -> $T { *self + *other } } #[cfg(not(test))] impl Sub<$T,$T> for $T { - #[inline(always)] + #[inline] fn sub(&self, other: &$T) -> $T { *self - *other } } #[cfg(not(test))] impl Mul<$T,$T> for $T { - #[inline(always)] + #[inline] fn mul(&self, other: &$T) -> $T { *self * *other } } #[cfg(not(test))] impl Div<$T,$T> for $T { - #[inline(always)] + #[inline] fn div(&self, other: &$T) -> $T { *self / *other } } #[cfg(not(test))] impl Rem<$T,$T> for $T { - #[inline(always)] + #[inline] fn rem(&self, other: &$T) -> $T { *self % *other } } #[cfg(not(test))] impl Neg<$T> for $T { - #[inline(always)] + #[inline] fn neg(&self) -> $T { -*self } } @@ -214,27 +214,27 @@ impl Unsigned for $T {} impl Integer for $T { /// Calculates `div` (`\`) and `rem` (`%`) simultaneously - #[inline(always)] + #[inline] fn div_rem(&self, other: &$T) -> ($T,$T) { (*self / *other, *self % *other) } /// Unsigned integer division. Returns the same result as `div` (`/`). - #[inline(always)] + #[inline] fn div_floor(&self, other: &$T) -> $T { *self / *other } /// Unsigned integer modulo operation. Returns the same result as `rem` (`%`). - #[inline(always)] + #[inline] fn mod_floor(&self, other: &$T) -> $T { *self / *other } /// Calculates `div_floor` and `modulo_floor` simultaneously - #[inline(always)] + #[inline] fn div_mod_floor(&self, other: &$T) -> ($T,$T) { (*self / *other, *self % *other) } /// Calculates the Greatest Common Divisor (GCD) of the number and `other` - #[inline(always)] + #[inline] fn gcd(&self, other: &$T) -> $T { // Use Euclid's algorithm let mut (m, n) = (*self, *other); @@ -247,21 +247,21 @@ impl Integer for $T { } /// Calculates the Lowest Common Multiple (LCM) of the number and `other` - #[inline(always)] + #[inline] fn lcm(&self, other: &$T) -> $T { (*self * *other) / self.gcd(other) } /// Returns `true` if the number can be divided by `other` without leaving a remainder - #[inline(always)] + #[inline] fn is_multiple_of(&self, other: &$T) -> bool { *self % *other == 0 } /// Returns `true` if the number is divisible by `2` - #[inline(always)] + #[inline] fn is_even(&self) -> bool { self.is_multiple_of(&2) } /// Returns `true` if the number is not divisible by `2` - #[inline(always)] + #[inline] fn is_odd(&self) -> bool { !self.is_even() } } @@ -269,45 +269,45 @@ impl Bitwise for $T {} #[cfg(not(test))] impl BitOr<$T,$T> for $T { - #[inline(always)] + #[inline] fn bitor(&self, other: &$T) -> $T { *self | *other } } #[cfg(not(test))] impl BitAnd<$T,$T> for $T { - #[inline(always)] + #[inline] fn bitand(&self, other: &$T) -> $T { *self & *other } } #[cfg(not(test))] impl BitXor<$T,$T> for $T { - #[inline(always)] + #[inline] fn bitxor(&self, other: &$T) -> $T { *self ^ *other } } #[cfg(not(test))] impl Shl<$T,$T> for $T { - #[inline(always)] + #[inline] fn shl(&self, other: &$T) -> $T { *self << *other } } #[cfg(not(test))] impl Shr<$T,$T> for $T { - #[inline(always)] + #[inline] fn shr(&self, other: &$T) -> $T { *self >> *other } } #[cfg(not(test))] impl Not<$T> for $T { - #[inline(always)] + #[inline] fn not(&self) -> $T { !*self } } impl Bounded for $T { - #[inline(always)] + #[inline] fn min_value() -> $T { min_value } - #[inline(always)] + #[inline] fn max_value() -> $T { max_value } } @@ -316,35 +316,35 @@ impl Int for $T {} // String conversion functions and impl str -> num /// Parse a string as a number in base 10. -#[inline(always)] +#[inline] pub fn from_str(s: &str) -> Option<$T> { strconv::from_str_common(s, 10u, false, false, false, strconv::ExpNone, false, false) } /// Parse a string as a number in the given base. -#[inline(always)] +#[inline] pub fn from_str_radix(s: &str, radix: uint) -> Option<$T> { strconv::from_str_common(s, radix, false, false, false, strconv::ExpNone, false, false) } /// Parse a byte slice as a number in the given base. -#[inline(always)] +#[inline] pub fn parse_bytes(buf: &[u8], radix: uint) -> Option<$T> { strconv::from_str_bytes_common(buf, radix, false, false, false, strconv::ExpNone, false, false) } impl FromStr for $T { - #[inline(always)] + #[inline] fn from_str(s: &str) -> Option<$T> { from_str(s) } } impl FromStrRadix for $T { - #[inline(always)] + #[inline] fn from_str_radix(s: &str, radix: uint) -> Option<$T> { from_str_radix(s, radix) } @@ -353,7 +353,7 @@ impl FromStrRadix for $T { // String conversion functions and impl num -> str /// Convert to a string as a byte slice in a given base. -#[inline(always)] +#[inline] pub fn to_str_bytes(n: $T, radix: uint, f: &fn(v: &[u8]) -> U) -> U { let (buf, _) = strconv::to_str_bytes_common(&n, radix, false, strconv::SignNeg, strconv::DigAll); @@ -361,7 +361,7 @@ pub fn to_str_bytes(n: $T, radix: uint, f: &fn(v: &[u8]) -> U) -> U { } /// Convert to a string in base 10. -#[inline(always)] +#[inline] pub fn to_str(num: $T) -> ~str { let (buf, _) = strconv::to_str_common(&num, 10u, false, strconv::SignNeg, strconv::DigAll); @@ -369,7 +369,7 @@ pub fn to_str(num: $T) -> ~str { } /// Convert to a string in a given base. -#[inline(always)] +#[inline] pub fn to_str_radix(num: $T, radix: uint) -> ~str { let (buf, _) = strconv::to_str_common(&num, radix, false, strconv::SignNeg, strconv::DigAll); @@ -377,42 +377,42 @@ pub fn to_str_radix(num: $T, radix: uint) -> ~str { } impl ToStr for $T { - #[inline(always)] + #[inline] fn to_str(&self) -> ~str { to_str(*self) } } impl ToStrRadix for $T { - #[inline(always)] + #[inline] fn to_str_radix(&self, radix: uint) -> ~str { to_str_radix(*self, radix) } } impl Primitive for $T { - #[inline(always)] + #[inline] fn bits() -> uint { bits } - #[inline(always)] + #[inline] fn bytes() -> uint { bits / 8 } } impl BitCount for $T { /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic. - #[inline(always)] + #[inline] fn population_count(&self) -> $T { (*self as $T_SIGNED).population_count() as $T } /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic. - #[inline(always)] + #[inline] fn leading_zeros(&self) -> $T { (*self as $T_SIGNED).leading_zeros() as $T } /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic. - #[inline(always)] + #[inline] fn trailing_zeros(&self) -> $T { (*self as $T_SIGNED).trailing_zeros() as $T } diff --git a/src/libstd/old_iter.rs b/src/libstd/old_iter.rs index 9fea43768161..83bb9eb09088 100644 --- a/src/libstd/old_iter.rs +++ b/src/libstd/old_iter.rs @@ -16,7 +16,7 @@ #[allow(missing_doc)]; -use cmp::{Eq, Ord}; +use cmp::{Eq}; use kinds::Copy; use option::{None, Option, Some}; use vec; @@ -54,11 +54,6 @@ pub trait CopyableIter { fn find(&self, p: &fn(&A) -> bool) -> Option; } -pub trait CopyableOrderedIter { - fn min(&self) -> A; - fn max(&self) -> A; -} - // A trait for sequences that can be built by imperatively pushing elements // onto them. pub trait Buildable { @@ -78,7 +73,7 @@ pub trait Buildable { fn build_sized(size: uint, builder: &fn(push: &fn(A))) -> Self; } -#[inline(always)] +#[inline] pub fn _eachi>(this: &IA, blk: &fn(uint, &A) -> bool) -> bool { let mut i = 0; for this.each |a| { @@ -94,7 +89,7 @@ pub fn eachi>(this: &IA, blk: &fn(uint, &A) -> bool) -> bool { _eachi(this, blk) } -#[inline(always)] +#[inline] pub fn all>(this: &IA, blk: &fn(&A) -> bool) -> bool { for this.each |a| { if !blk(a) { @@ -104,7 +99,7 @@ pub fn all>(this: &IA, blk: &fn(&A) -> bool) -> bool { return true; } -#[inline(always)] +#[inline] pub fn any>(this: &IA, blk: &fn(&A) -> bool) -> bool { for this.each |a| { if blk(a) { @@ -114,18 +109,18 @@ pub fn any>(this: &IA, blk: &fn(&A) -> bool) -> bool { return false; } -#[inline(always)] +#[inline] pub fn filter_to_vec>(this: &IA, prd: &fn(&A) -> bool) -> ~[A] { do vec::build_sized_opt(this.size_hint()) |push| { for this.each |a| { - if prd(a) { push(*a); } + if prd(a) { push(copy *a); } } } } -#[inline(always)] +#[inline] pub fn map_to_vec>(this: &IA, op: &fn(&A) -> B) -> ~[B] { do vec::build_sized_opt(this.size_hint()) |push| { for this.each |a| { @@ -134,7 +129,7 @@ pub fn map_to_vec>(this: &IA, op: &fn(&A) -> B) -> ~[B] { } } -#[inline(always)] +#[inline] pub fn flat_map_to_vec,IB:BaseIter>(this: &IA, op: &fn(&A) -> IB) -> ~[B] { @@ -147,7 +142,7 @@ pub fn flat_map_to_vec,IB:BaseIter>(this: &IA, } } -#[inline(always)] +#[inline] pub fn foldl>(this: &IA, b0: B, blk: &fn(&B, &A) -> B) -> B { let mut b = b0; @@ -157,12 +152,12 @@ pub fn foldl>(this: &IA, b0: B, blk: &fn(&B, &A) -> B) b } -#[inline(always)] +#[inline] pub fn to_vec>(this: &IA) -> ~[A] { map_to_vec(this, |&x| x) } -#[inline(always)] +#[inline] pub fn contains>(this: &IA, x: &A) -> bool { for this.each |a| { if *a == *x { return true; } @@ -170,7 +165,7 @@ pub fn contains>(this: &IA, x: &A) -> bool { return false; } -#[inline(always)] +#[inline] pub fn count>(this: &IA, x: &A) -> uint { do foldl(this, 0) |count, value| { if *value == *x { @@ -181,7 +176,7 @@ pub fn count>(this: &IA, x: &A) -> uint { } } -#[inline(always)] +#[inline] pub fn position>(this: &IA, f: &fn(&A) -> bool) -> Option { let mut i = 0; @@ -192,45 +187,11 @@ pub fn position>(this: &IA, f: &fn(&A) -> bool) return None; } -// note: 'rposition' would only make sense to provide with a bidirectional -// iter interface, such as would provide "reach" in addition to "each". As is, -// it would have to be implemented with foldr, which is too inefficient. - -#[inline(always)] -pub fn min>(this: &IA) -> A { - match do foldl::,IA>(this, None) |a, b| { - match a { - &Some(ref a_) if *a_ < *b => { - *(a) - } - _ => Some(*b) - } - } { - Some(val) => val, - None => fail!("min called on empty iterator") - } -} - -#[inline(always)] -pub fn max>(this: &IA) -> A { - match do foldl::,IA>(this, None) |a, b| { - match a { - &Some(ref a_) if *a_ > *b => { - *(a) - } - _ => Some(*b) - } - } { - Some(val) => val, - None => fail!("max called on empty iterator") - } -} - -#[inline(always)] +#[inline] pub fn find>(this: &IA, f: &fn(&A) -> bool) -> Option { for this.each |i| { - if f(i) { return Some(*i) } + if f(i) { return Some(copy *i) } } return None; } @@ -247,7 +208,7 @@ pub fn find>(this: &IA, f: &fn(&A) -> bool) * as an argument a function that will push an element * onto the sequence being constructed. */ -#[inline(always)] +#[inline] pub fn build>(builder: &fn(push: &fn(A))) -> B { Buildable::build_sized(4, builder) } @@ -265,7 +226,7 @@ pub fn build>(builder: &fn(push: &fn(A))) -> B { * as an argument a function that will push an element * onto the sequence being constructed. */ -#[inline(always)] +#[inline] pub fn build_sized_opt>(size: Option, builder: &fn(push: &fn(A))) -> B { Buildable::build_sized(size.get_or_default(4), builder) @@ -275,7 +236,7 @@ pub fn build_sized_opt>(size: Option, /// Applies a function to each element of an iterable and returns the results /// in a sequence built via `BU`. See also `map_to_vec`. -#[inline(always)] +#[inline] pub fn map,U,BU: Buildable>(v: &IT, f: &fn(&T) -> U) -> BU { do build_sized_opt(v.size_hint()) |push| { @@ -291,7 +252,7 @@ pub fn map,U,BU: Buildable>(v: &IT, f: &fn(&T) -> U) * Creates a generic sequence of size `n_elts` and initializes the elements * to the value returned by the function `op`. */ -#[inline(always)] +#[inline] pub fn from_fn>(n_elts: uint, op: InitOp) -> BT { do Buildable::build_sized(n_elts) |push| { let mut i: uint = 0u; @@ -305,31 +266,31 @@ pub fn from_fn>(n_elts: uint, op: InitOp) -> BT { * Creates an immutable vector of size `n_elts` and initializes the elements * to the value `t`. */ -#[inline(always)] +#[inline] pub fn from_elem>(n_elts: uint, t: T) -> BT { do Buildable::build_sized(n_elts) |push| { let mut i: uint = 0; - while i < n_elts { push(t); i += 1; } + while i < n_elts { push(copy t); i += 1; } } } /// Appends two generic sequences. -#[inline(always)] +#[inline] pub fn append,BT:Buildable>(lhs: &IT, rhs: &IT) -> BT { let size_opt = lhs.size_hint().chain_ref( |sz1| rhs.size_hint().map(|sz2| *sz1+*sz2)); do build_sized_opt(size_opt) |push| { - for lhs.each |x| { push(*x); } - for rhs.each |x| { push(*x); } + for lhs.each |x| { push(copy *x); } + for rhs.each |x| { push(copy *x); } } } /// Copies a generic sequence, possibly converting it to a different /// type of sequence. -#[inline(always)] +#[inline] pub fn copy_seq,BT:Buildable>(v: &IT) -> BT { do build_sized_opt(v.size_hint()) |push| { - for v.each |x| { push(*x); } + for v.each |x| { push(copy *x); } } } diff --git a/src/libstd/option.rs b/src/libstd/option.rs index 80f4fb7643c8..7dc6b7fe4b16 100644 --- a/src/libstd/option.rs +++ b/src/libstd/option.rs @@ -88,14 +88,14 @@ impl Ord for Option { } } -impl> Add, Option> for Option { - #[inline(always)] +impl> Add, Option> for Option { + #[inline] fn add(&self, other: &Option) -> Option { - match (*self, *other) { - (None, None) => None, - (_, None) => *self, - (None, _) => *other, - (Some(ref lhs), Some(ref rhs)) => Some(*lhs + *rhs) + match (&*self, &*other) { + (&None, &None) => None, + (_, &None) => copy *self, + (&None, _) => copy *other, + (&Some(ref lhs), &Some(ref rhs)) => Some(*lhs + *rhs) } } } @@ -126,12 +126,12 @@ impl Option { } /// Returns true if the option contains some value - #[inline(always)] + #[inline] pub fn is_some(&const self) -> bool { !self.is_none() } /// Update an optional value by optionally running its content through a /// function that returns an option. - #[inline(always)] + #[inline] pub fn chain(self, f: &fn(t: T) -> Option) -> Option { match self { Some(t) => f(t), @@ -140,7 +140,7 @@ impl Option { } /// Returns the leftmost Some() value, or None if both are None. - #[inline(always)] + #[inline] pub fn or(self, optb: Option) -> Option { match self { Some(opta) => Some(opta), @@ -150,7 +150,7 @@ impl Option { /// Update an optional value by optionally running its content by reference /// through a function that returns an option. - #[inline(always)] + #[inline] pub fn chain_ref<'a, U>(&'a self, f: &fn(x: &'a T) -> Option) -> Option { match *self { @@ -160,27 +160,27 @@ impl Option { } /// Maps a `some` value from one type to another by reference - #[inline(always)] + #[inline] pub fn map<'a, U>(&self, f: &fn(&'a T) -> U) -> Option { match *self { Some(ref x) => Some(f(x)), None => None } } /// As `map`, but consumes the option and gives `f` ownership to avoid /// copying. - #[inline(always)] + #[inline] pub fn map_consume(self, f: &fn(v: T) -> U) -> Option { match self { None => None, Some(v) => Some(f(v)) } } /// Applies a function to the contained value or returns a default - #[inline(always)] + #[inline] pub fn map_default<'a, U>(&'a self, def: U, f: &fn(&'a T) -> U) -> U { match *self { None => def, Some(ref t) => f(t) } } /// As `map_default`, but consumes the option and gives `f` /// ownership to avoid copying. - #[inline(always)] + #[inline] pub fn map_consume_default(self, def: U, f: &fn(v: T) -> U) -> U { match self { None => def, Some(v) => f(v) } } @@ -215,7 +215,7 @@ impl Option { Instead, prefer to use pattern matching and handle the `None` case explicitly. */ - #[inline(always)] + #[inline] pub fn get_ref<'a>(&'a self) -> &'a T { match *self { Some(ref x) => x, @@ -237,7 +237,7 @@ impl Option { Instead, prefer to use pattern matching and handle the `None` case explicitly. */ - #[inline(always)] + #[inline] pub fn get_mut_ref<'a>(&'a mut self) -> &'a mut T { match *self { Some(ref mut x) => x, @@ -245,7 +245,7 @@ impl Option { } } - #[inline(always)] + #[inline] pub fn unwrap(self) -> T { /*! Moves a value out of an option type and returns it. @@ -277,7 +277,7 @@ impl Option { * * Fails if the value equals `None`. */ - #[inline(always)] + #[inline] pub fn swap_unwrap(&mut self) -> T { if self.is_none() { fail!("option::swap_unwrap none") } util::replace(self, None).unwrap() @@ -291,7 +291,7 @@ impl Option { * * Fails if the value equals `none` */ - #[inline(always)] + #[inline] pub fn expect(self, reason: &str) -> T { match self { Some(val) => val, @@ -315,7 +315,7 @@ impl Option { Instead, prefer to use pattern matching and handle the `None` case explicitly. */ - #[inline(always)] + #[inline] pub fn get(self) -> T { match self { Some(x) => return x, @@ -324,13 +324,13 @@ impl Option { } /// Returns the contained value or a default - #[inline(always)] + #[inline] pub fn get_or_default(self, def: T) -> T { match self { Some(x) => x, None => def } } /// Applies a function zero or more times until the result is none. - #[inline(always)] + #[inline] pub fn while_some(self, blk: &fn(v: T) -> Option) { let mut opt = self; while opt.is_some() { @@ -341,7 +341,7 @@ impl Option { impl Option { /// Returns the contained value or zero (for this type) - #[inline(always)] + #[inline] pub fn get_or_zero(self) -> T { match self { Some(x) => x, @@ -350,6 +350,11 @@ impl Option { } } +impl Zero for Option { + fn zero() -> Option { None } + fn is_zero(&self) -> bool { self.is_none() } +} + /// Immutable iterator over an `Option` pub struct OptionIterator<'self, A> { priv opt: Option<&'self A> diff --git a/src/libstd/os.rs b/src/libstd/os.rs index 044b305a0dd9..765dd30febcf 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -40,6 +40,8 @@ use option::{Some, None}; use os; use prelude::*; use ptr; +use rt; +use rt::TaskContext; use str; use uint; use unstable::finally::Finally; @@ -144,7 +146,7 @@ pub mod win32 { } pub fn as_utf16_p(s: &str, f: &fn(*u16) -> T) -> T { - let mut t = str::to_utf16(s); + let mut t = s.to_utf16(); // Null terminate before passing on. t += [0u16]; vec::as_imm_buf(t, |buf, _len| f(buf)) @@ -959,12 +961,10 @@ pub fn copy_file(from: &Path, to: &Path) -> bool { fclose(ostream); // Give the new file the old file's permissions - unsafe { - if do str::as_c_str(to.to_str()) |to_buf| { - libc::chmod(to_buf, from_mode as mode_t) - } != 0 { - return false; // should be a condition... - } + if do str::as_c_str(to.to_str()) |to_buf| { + libc::chmod(to_buf, from_mode as mode_t) + } != 0 { + return false; // should be a condition... } return ok; } @@ -1169,10 +1169,17 @@ pub fn real_args() -> ~[~str] { #[cfg(target_os = "android")] #[cfg(target_os = "freebsd")] pub fn real_args() -> ~[~str] { - unsafe { - let argc = rustrt::rust_get_argc(); - let argv = rustrt::rust_get_argv(); - load_argc_and_argv(argc, argv) + if rt::context() == TaskContext { + match rt::args::clone() { + Some(args) => args, + None => fail!("process arguments not initialized") + } + } else { + unsafe { + let argc = rustrt::rust_get_argc(); + let argv = rustrt::rust_get_argv(); + load_argc_and_argv(argc, argv) + } } } @@ -1685,10 +1692,11 @@ mod tests { assert!((ostream as uint != 0u)); let s = ~"hello"; let mut buf = s.as_bytes_with_null().to_owned(); + let len = buf.len(); do vec::as_mut_buf(buf) |b, _len| { - assert!((libc::fwrite(b as *c_void, 1u as size_t, - (s.len() + 1u) as size_t, ostream) - == buf.len() as size_t)) + assert_eq!(libc::fwrite(b as *c_void, 1u as size_t, + (s.len() + 1u) as size_t, ostream), + len as size_t) } assert_eq!(libc::fclose(ostream), (0u as c_int)); let in_mode = in.get_mode(); diff --git a/src/libstd/owned.rs b/src/libstd/owned.rs index 3262fb4afdcf..e7a6e38fdb08 100644 --- a/src/libstd/owned.rs +++ b/src/libstd/owned.rs @@ -14,20 +14,20 @@ #[cfg(not(test))] impl Eq for ~T { - #[inline(always)] + #[inline] fn eq(&self, other: &~T) -> bool { *(*self) == *(*other) } - #[inline(always)] + #[inline] fn ne(&self, other: &~T) -> bool { *(*self) != *(*other) } } #[cfg(not(test))] impl Ord for ~T { - #[inline(always)] + #[inline] fn lt(&self, other: &~T) -> bool { *(*self) < *(*other) } - #[inline(always)] + #[inline] fn le(&self, other: &~T) -> bool { *(*self) <= *(*other) } - #[inline(always)] + #[inline] fn ge(&self, other: &~T) -> bool { *(*self) >= *(*other) } - #[inline(always)] + #[inline] fn gt(&self, other: &~T) -> bool { *(*self) > *(*other) } } diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 400657d0c255..9c51526aa7f6 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -515,7 +515,7 @@ impl GenericPath for PosixPath { fn with_filestem(&self, s: &str) -> PosixPath { match self.filetype() { None => self.with_filename(s), - Some(ref t) => self.with_filename(str::to_owned(s) + *t), + Some(ref t) => self.with_filename(s.to_owned() + *t), } } @@ -657,7 +657,7 @@ impl GenericPath for WindowsPath { (None, None) => { host = None; device = None; - rest = str::to_owned(s); + rest = s.to_owned(); } } @@ -729,7 +729,7 @@ impl GenericPath for WindowsPath { fn with_filestem(&self, s: &str) -> WindowsPath { match self.filetype() { None => self.with_filename(s), - Some(ref t) => self.with_filename(str::to_owned(s) + *t), + Some(ref t) => self.with_filename(s.to_owned() + *t), } } @@ -904,7 +904,7 @@ pub mod windows { use libc; use option::{None, Option, Some}; - #[inline(always)] + #[inline] pub fn is_sep(u: char) -> bool { u == '/' || u == '\\' } @@ -947,7 +947,6 @@ pub mod windows { mod tests { use option::{None, Some}; use path::{PosixPath, WindowsPath, windows}; - use str; #[test] fn test_double_slash_collapsing() { @@ -984,7 +983,7 @@ mod tests { fn test_posix_paths() { fn t(wp: &PosixPath, s: &str) { let ss = wp.to_str(); - let sss = str::to_owned(s); + let sss = s.to_owned(); if (ss != sss) { debug!("got %s", ss); debug!("expected %s", sss); @@ -1042,7 +1041,7 @@ mod tests { fn test_normalize() { fn t(wp: &PosixPath, s: &str) { let ss = wp.to_str(); - let sss = str::to_owned(s); + let sss = s.to_owned(); if (ss != sss) { debug!("got %s", ss); debug!("expected %s", sss); @@ -1105,7 +1104,7 @@ mod tests { fn test_windows_paths() { fn t(wp: &WindowsPath, s: &str) { let ss = wp.to_str(); - let sss = str::to_owned(s); + let sss = s.to_owned(); if (ss != sss) { debug!("got %s", ss); debug!("expected %s", sss); diff --git a/src/libstd/pipes.rs b/src/libstd/pipes.rs index 012ad0ed80d2..26dd4af45d6c 100644 --- a/src/libstd/pipes.rs +++ b/src/libstd/pipes.rs @@ -85,7 +85,7 @@ bounded and unbounded protocols allows for less code duplication. #[allow(missing_doc)]; use container::Container; -use cast::{forget, transmute, transmute_copy}; +use cast::{forget, transmute, transmute_copy, transmute_mut}; use either::{Either, Left, Right}; use iterator::IteratorUtil; use kinds::Owned; @@ -102,10 +102,6 @@ use util::replace; static SPIN_COUNT: uint = 0; -macro_rules! move_it ( - { $x:expr } => ( unsafe { let y = *ptr::to_unsafe_ptr(&($x)); y } ) -) - #[deriving(Eq)] enum State { Empty, @@ -316,9 +312,11 @@ impl Drop for BufferResource { fn finalize(&self) { unsafe { // FIXME(#4330) Need self by value to get mutability. - let this: &mut BufferResource = transmute(self); + let this: &mut BufferResource = transmute_mut(self); + + let null_buffer: ~Buffer = transmute(ptr::null::>()); + let mut b = replace(&mut this.buffer, null_buffer); - let mut b = move_it!(this.buffer); //let p = ptr::to_unsafe_ptr(*b); //error!("drop %?", p); let old_count = intrinsics::atomic_xsub_rel( diff --git a/src/libstd/prelude.rs b/src/libstd/prelude.rs index 61b8d36266e2..309df27e151d 100644 --- a/src/libstd/prelude.rs +++ b/src/libstd/prelude.rs @@ -47,9 +47,9 @@ pub use char::Char; pub use container::{Container, Mutable, Map, Set}; pub use hash::Hash; pub use old_iter::{BaseIter, ReverseIter, ExtendedIter, EqIter}; -pub use old_iter::{CopyableIter, CopyableOrderedIter}; +pub use old_iter::CopyableIter; pub use iter::{Times, FromIter}; -pub use iterator::{Iterator, IteratorUtil}; +pub use iterator::{Iterator, IteratorUtil, OrdIterator}; pub use num::{Num, NumCast}; pub use num::{Orderable, Signed, Unsigned, Round}; pub use num::{Algebraic, Trigonometric, Exponential, Hyperbolic}; @@ -61,7 +61,7 @@ pub use path::Path; pub use path::PosixPath; pub use path::WindowsPath; pub use ptr::RawPtr; -pub use ascii::{Ascii, AsciiCast, OwnedAsciiCast, AsciiStr}; +pub use ascii::{Ascii, AsciiCast, OwnedAsciiCast, AsciiStr, ToBytesConsume}; pub use str::{Str, StrVector, StrSlice, OwnedStr, StrUtil, NullTerminatedStr}; pub use from_str::{FromStr}; pub use to_bytes::IterBytes; diff --git a/src/libstd/ptr.rs b/src/libstd/ptr.rs index cd5a3182f6b8..7f89d454be11 100644 --- a/src/libstd/ptr.rs +++ b/src/libstd/ptr.rs @@ -19,31 +19,31 @@ use unstable::intrinsics; use uint; /// Calculate the offset from a pointer -#[inline(always)] +#[inline] pub fn offset(ptr: *T, count: uint) -> *T { (ptr as uint + count * sys::size_of::()) as *T } /// Calculate the offset from a const pointer -#[inline(always)] +#[inline] pub fn const_offset(ptr: *const T, count: uint) -> *const T { (ptr as uint + count * sys::size_of::()) as *T } /// Calculate the offset from a mut pointer -#[inline(always)] +#[inline] pub fn mut_offset(ptr: *mut T, count: uint) -> *mut T { (ptr as uint + count * sys::size_of::()) as *mut T } /// Return the offset of the first null pointer in `buf`. -#[inline(always)] +#[inline] pub unsafe fn buf_len(buf: **T) -> uint { position(buf, |i| *i == null()) } /// Return the first offset `i` such that `f(buf[i]) == true`. -#[inline(always)] +#[inline] pub unsafe fn position(buf: *T, f: &fn(&T) -> bool) -> uint { let mut i = 0; loop { @@ -53,19 +53,19 @@ pub unsafe fn position(buf: *T, f: &fn(&T) -> bool) -> uint { } /// Create an unsafe null pointer -#[inline(always)] +#[inline] pub fn null() -> *T { 0 as *T } /// Create an unsafe mutable null pointer -#[inline(always)] +#[inline] pub fn mut_null() -> *mut T { 0 as *mut T } /// Returns true if the pointer is equal to the null pointer. -#[inline(always)] +#[inline] pub fn is_null(ptr: *const T) -> bool { ptr == null() } /// Returns true if the pointer is not equal to the null pointer. -#[inline(always)] +#[inline] pub fn is_not_null(ptr: *const T) -> bool { !is_null(ptr) } /** @@ -74,22 +74,8 @@ pub fn is_not_null(ptr: *const T) -> bool { !is_null(ptr) } * Copies `count` elements (not bytes) from `src` to `dst`. The source * and destination may overlap. */ -#[inline(always)] -#[cfg(target_word_size = "32", stage0)] -pub unsafe fn copy_memory(dst: *mut T, src: *const T, count: uint) { - use unstable::intrinsics::memmove32; - let n = count * sys::size_of::(); - memmove32(dst as *mut u8, src as *u8, n as u32); -} - -/** - * Copies data from one location to another. - * - * Copies `count` elements (not bytes) from `src` to `dst`. The source - * and destination may overlap. - */ -#[inline(always)] -#[cfg(target_word_size = "32", not(stage0))] +#[inline] +#[cfg(target_word_size = "32")] pub unsafe fn copy_memory(dst: *mut T, src: *const T, count: uint) { use unstable::intrinsics::memmove32; memmove32(dst, src as *T, count as u32); @@ -101,22 +87,8 @@ pub unsafe fn copy_memory(dst: *mut T, src: *const T, count: uint) { * Copies `count` elements (not bytes) from `src` to `dst`. The source * and destination may overlap. */ -#[inline(always)] -#[cfg(target_word_size = "64", stage0)] -pub unsafe fn copy_memory(dst: *mut T, src: *const T, count: uint) { - use unstable::intrinsics::memmove64; - let n = count * sys::size_of::(); - memmove64(dst as *mut u8, src as *u8, n as u64); -} - -/** - * Copies data from one location to another. - * - * Copies `count` elements (not bytes) from `src` to `dst`. The source - * and destination may overlap. - */ -#[inline(always)] -#[cfg(target_word_size = "64", not(stage0))] +#[inline] +#[cfg(target_word_size = "64")] pub unsafe fn copy_memory(dst: *mut T, src: *const T, count: uint) { use unstable::intrinsics::memmove64; memmove64(dst, src as *T, count as u64); @@ -128,22 +100,8 @@ pub unsafe fn copy_memory(dst: *mut T, src: *const T, count: uint) { * Copies `count` elements (not bytes) from `src` to `dst`. The source * and destination may *not* overlap. */ -#[inline(always)] -#[cfg(target_word_size = "32", stage0)] -pub unsafe fn copy_nonoverlapping_memory(dst: *mut T, src: *const T, count: uint) { - use unstable::intrinsics::memmove32; - let n = count * sys::size_of::(); - memmove32(dst as *mut u8, src as *u8, n as u32); -} - -/** - * Copies data from one location to another. - * - * Copies `count` elements (not bytes) from `src` to `dst`. The source - * and destination may *not* overlap. - */ -#[inline(always)] -#[cfg(target_word_size = "32", not(stage0))] +#[inline] +#[cfg(target_word_size = "32")] pub unsafe fn copy_nonoverlapping_memory(dst: *mut T, src: *const T, count: uint) { use unstable::intrinsics::memcpy32; memcpy32(dst, src as *T, count as u32); @@ -155,22 +113,8 @@ pub unsafe fn copy_nonoverlapping_memory(dst: *mut T, src: *const T, count: u * Copies `count` elements (not bytes) from `src` to `dst`. The source * and destination may *not* overlap. */ -#[inline(always)] -#[cfg(target_word_size = "64", stage0)] -pub unsafe fn copy_nonoverlapping_memory(dst: *mut T, src: *const T, count: uint) { - use unstable::intrinsics::memmove64; - let n = count * sys::size_of::(); - memmove64(dst as *mut u8, src as *u8, n as u64); -} - -/** - * Copies data from one location to another. - * - * Copies `count` elements (not bytes) from `src` to `dst`. The source - * and destination may *not* overlap. - */ -#[inline(always)] -#[cfg(target_word_size = "64", not(stage0))] +#[inline] +#[cfg(target_word_size = "64")] pub unsafe fn copy_nonoverlapping_memory(dst: *mut T, src: *const T, count: uint) { use unstable::intrinsics::memcpy64; memcpy64(dst, src as *T, count as u64); @@ -180,8 +124,8 @@ pub unsafe fn copy_nonoverlapping_memory(dst: *mut T, src: *const T, count: u * Invokes memset on the specified pointer, setting `count * size_of::()` * bytes of memory starting at `dst` to `c`. */ -#[inline(always)] -#[cfg(target_word_size = "32", not(stage0))] +#[inline] +#[cfg(target_word_size = "32")] pub unsafe fn set_memory(dst: *mut T, c: u8, count: uint) { use unstable::intrinsics::memset32; memset32(dst, c, count as u32); @@ -191,8 +135,8 @@ pub unsafe fn set_memory(dst: *mut T, c: u8, count: uint) { * Invokes memset on the specified pointer, setting `count * size_of::()` * bytes of memory starting at `dst` to `c`. */ -#[inline(always)] -#[cfg(target_word_size = "64", not(stage0))] +#[inline] +#[cfg(target_word_size = "64")] pub unsafe fn set_memory(dst: *mut T, c: u8, count: uint) { use unstable::intrinsics::memset64; memset64(dst, c, count as u64); @@ -222,26 +166,26 @@ pub unsafe fn swap_ptr(x: *mut T, y: *mut T) { * Replace the value at a mutable location with a new one, returning the old * value, without deinitialising or copying either one. */ -#[inline(always)] +#[inline] pub unsafe fn replace_ptr(dest: *mut T, mut src: T) -> T { swap_ptr(dest, &mut src); src } /// Transform a region pointer - &T - to an unsafe pointer - *T. -#[inline(always)] +#[inline] pub fn to_unsafe_ptr(thing: &T) -> *T { thing as *T } /// Transform a const region pointer - &const T - to a const unsafe pointer - *const T. -#[inline(always)] +#[inline] pub fn to_const_unsafe_ptr(thing: &const T) -> *const T { thing as *const T } /// Transform a mutable region pointer - &mut T - to a mutable unsafe pointer - *mut T. -#[inline(always)] +#[inline] pub fn to_mut_unsafe_ptr(thing: &mut T) -> *mut T { thing as *mut T } @@ -297,11 +241,11 @@ pub trait RawPtr { /// Extension methods for immutable pointers impl RawPtr for *T { /// Returns true if the pointer is equal to the null pointer. - #[inline(always)] + #[inline] fn is_null(&const self) -> bool { is_null(*self) } /// Returns true if the pointer is not equal to the null pointer. - #[inline(always)] + #[inline] fn is_not_null(&const self) -> bool { is_not_null(*self) } /// @@ -314,7 +258,7 @@ impl RawPtr for *T { /// that this is still an unsafe operation because the returned value could /// be pointing to invalid memory. /// - #[inline(always)] + #[inline] unsafe fn to_option(&const self) -> Option<&T> { if self.is_null() { None } else { Some(cast::transmute(*self)) @@ -322,18 +266,18 @@ impl RawPtr for *T { } /// Calculates the offset from a pointer. - #[inline(always)] + #[inline] fn offset(&self, count: uint) -> *T { offset(*self, count) } } /// Extension methods for mutable pointers impl RawPtr for *mut T { /// Returns true if the pointer is equal to the null pointer. - #[inline(always)] + #[inline] fn is_null(&const self) -> bool { is_null(*self) } /// Returns true if the pointer is not equal to the null pointer. - #[inline(always)] + #[inline] fn is_not_null(&const self) -> bool { is_not_null(*self) } /// @@ -346,7 +290,7 @@ impl RawPtr for *mut T { /// that this is still an unsafe operation because the returned value could /// be pointing to invalid memory. /// - #[inline(always)] + #[inline] unsafe fn to_option(&const self) -> Option<&T> { if self.is_null() { None } else { Some(cast::transmute(*self)) @@ -354,37 +298,37 @@ impl RawPtr for *mut T { } /// Calculates the offset from a mutable pointer. - #[inline(always)] + #[inline] fn offset(&self, count: uint) -> *mut T { mut_offset(*self, count) } } // Equality for pointers #[cfg(not(test))] impl Eq for *const T { - #[inline(always)] + #[inline] fn eq(&self, other: &*const T) -> bool { (*self as uint) == (*other as uint) } - #[inline(always)] + #[inline] fn ne(&self, other: &*const T) -> bool { !self.eq(other) } } // Comparison for pointers #[cfg(not(test))] impl Ord for *const T { - #[inline(always)] + #[inline] fn lt(&self, other: &*const T) -> bool { (*self as uint) < (*other as uint) } - #[inline(always)] + #[inline] fn le(&self, other: &*const T) -> bool { (*self as uint) <= (*other as uint) } - #[inline(always)] + #[inline] fn ge(&self, other: &*const T) -> bool { (*self as uint) >= (*other as uint) } - #[inline(always)] + #[inline] fn gt(&self, other: &*const T) -> bool { (*self as uint) > (*other as uint) } @@ -592,7 +536,6 @@ pub mod ptr_tests { } #[test] - #[cfg(not(stage0))] fn test_set_memory() { let mut xs = [0u8, ..20]; let ptr = vec::raw::to_mut_ptr(xs); diff --git a/src/libstd/rand.rs b/src/libstd/rand.rs index 7946f7e4f13f..739e3dfedc7f 100644 --- a/src/libstd/rand.rs +++ b/src/libstd/rand.rs @@ -451,7 +451,7 @@ pub trait RngUtil { /// Extension methods for random number generators impl RngUtil for R { /// Return a random value for a Rand type - #[inline(always)] + #[inline] fn gen(&mut self) -> T { Rand::rand(self) } @@ -526,7 +526,7 @@ impl RngUtil for R { if values.is_empty() { None } else { - Some(values[self.gen_uint_range(0u, values.len())]) + Some(copy values[self.gen_uint_range(0u, values.len())]) } } /** @@ -555,7 +555,7 @@ impl RngUtil for R { for v.each |item| { so_far += item.weight; if so_far > chosen { - return Some(item.item); + return Some(copy item.item); } } util::unreachable(); @@ -569,7 +569,7 @@ impl RngUtil for R { let mut r = ~[]; for v.each |item| { for uint::range(0u, item.weight) |_i| { - r.push(item.item); + r.push(copy item.item); } } r @@ -762,7 +762,7 @@ impl IsaacRng { } impl Rng for IsaacRng { - #[inline(always)] + #[inline] fn next(&mut self) -> u32 { if self.cnt == 0 { // make some more numbers @@ -862,7 +862,7 @@ pub fn task_rng() -> @@mut IsaacRng { // Allow direct chaining with `task_rng` impl Rng for @@mut R { - #[inline(always)] + #[inline] fn next(&mut self) -> u32 { match *self { @@ref mut r => r.next() diff --git a/src/libstd/rand/distributions.rs b/src/libstd/rand/distributions.rs index f08d967cbe02..6f4f1a34977e 100644 --- a/src/libstd/rand/distributions.rs +++ b/src/libstd/rand/distributions.rs @@ -26,7 +26,7 @@ use rand::{Rng,Rand}; mod ziggurat_tables; // inlining should mean there is no performance penalty for this -#[inline(always)] +#[inline] fn ziggurat(rng: &mut R, center_u: bool, X: ziggurat_tables::ZigTable, @@ -77,11 +77,11 @@ pub struct StandardNormal(f64); impl Rand for StandardNormal { fn rand(rng: &mut R) -> StandardNormal { - #[inline(always)] + #[inline] fn pdf(x: f64) -> f64 { f64::exp((-x*x/2.0) as f64) as f64 } - #[inline(always)] + #[inline] fn zero_case(rng: &mut R, u: f64) -> f64 { // compute a random number in the tail by hand @@ -131,11 +131,11 @@ pub struct Exp1(f64); impl Rand for Exp1 { #[inline] fn rand(rng: &mut R) -> Exp1 { - #[inline(always)] + #[inline] fn pdf(x: f64) -> f64 { f64::exp(-x) } - #[inline(always)] + #[inline] fn zero_case(rng: &mut R, _u: f64) -> f64 { ziggurat_tables::ZIG_EXP_R - f64::ln(rng.gen()) } diff --git a/src/libstd/reflect.rs b/src/libstd/reflect.rs index 1eb3d3a0daaa..d276abf0c8b3 100644 --- a/src/libstd/reflect.rs +++ b/src/libstd/reflect.rs @@ -35,7 +35,7 @@ pub trait MovePtr { } /// Helper function for alignment calculation. -#[inline(always)] +#[inline] pub fn align(size: uint, align: uint) -> uint { ((size + align) - 1u) & !(align - 1u) } @@ -49,26 +49,26 @@ pub fn MovePtrAdaptor(v: V) -> MovePtrAdaptor { } impl MovePtrAdaptor { - #[inline(always)] + #[inline] pub fn bump(&self, sz: uint) { do self.inner.move_ptr() |p| { ((p as uint) + sz) as *c_void }; } - #[inline(always)] + #[inline] pub fn align(&self, a: uint) { do self.inner.move_ptr() |p| { align(p as uint, a) as *c_void }; } - #[inline(always)] + #[inline] pub fn align_to(&self) { self.align(sys::min_align_of::()); } - #[inline(always)] + #[inline] pub fn bump_past(&self) { self.bump(sys::size_of::()); } diff --git a/src/libstd/repr.rs b/src/libstd/repr.rs index 46f69d020d1e..ab3f83d34d59 100644 --- a/src/libstd/repr.rs +++ b/src/libstd/repr.rs @@ -18,6 +18,7 @@ More runtime type reflection use cast::transmute; use char; +use container::Container; use intrinsic; use intrinsic::{TyDesc, TyVisitor, visit_tydesc}; use intrinsic::Opaque; @@ -163,7 +164,7 @@ pub fn ReprVisitor(ptr: *c_void, writer: @Writer) -> ReprVisitor { } impl MovePtr for ReprVisitor { - #[inline(always)] + #[inline] fn move_ptr(&self, adjustment: &fn(*c_void) -> *c_void) { *self.ptr = adjustment(*self.ptr); } @@ -178,7 +179,7 @@ impl MovePtr for ReprVisitor { impl ReprVisitor { // Various helpers for the TyVisitor impl - #[inline(always)] + #[inline] pub fn get(&self, f: &fn(&T)) -> bool { unsafe { f(transmute::<*c_void,&T>(*self.ptr)); @@ -186,12 +187,12 @@ impl ReprVisitor { true } - #[inline(always)] + #[inline] pub fn visit_inner(&self, inner: *TyDesc) -> bool { self.visit_ptr_inner(*self.ptr, inner) } - #[inline(always)] + #[inline] pub fn visit_ptr_inner(&self, ptr: *c_void, inner: *TyDesc) -> bool { unsafe { let u = ReprVisitor(ptr, self.writer); @@ -201,7 +202,7 @@ impl ReprVisitor { } } - #[inline(always)] + #[inline] pub fn write(&self) -> bool { do self.get |v:&T| { v.write_repr(self.writer); @@ -502,7 +503,7 @@ impl TyVisitor for ReprVisitor { _offset: uint, inner: *TyDesc) -> bool { - match self.var_stk[vec::uniq_len(&const *self.var_stk) - 1] { + match self.var_stk[self.var_stk.len() - 1] { Matched => { if i != 0 { self.writer.write_str(", "); @@ -520,7 +521,7 @@ impl TyVisitor for ReprVisitor { _disr_val: int, n_fields: uint, _name: &str) -> bool { - match self.var_stk[vec::uniq_len(&const *self.var_stk) - 1] { + match self.var_stk[self.var_stk.len() - 1] { Matched => { if n_fields > 0 { self.writer.write_char(')'); diff --git a/src/libstd/result.rs b/src/libstd/result.rs index 24751b66925e..6cef5c33de06 100644 --- a/src/libstd/result.rs +++ b/src/libstd/result.rs @@ -38,7 +38,7 @@ pub enum Result { * * If the result is an error */ -#[inline(always)] +#[inline] pub fn get(res: &Result) -> T { match *res { Ok(ref t) => copy *t, @@ -54,7 +54,7 @@ pub fn get(res: &Result) -> T { * * If the result is an error */ -#[inline(always)] +#[inline] pub fn get_ref<'a, T, U>(res: &'a Result) -> &'a T { match *res { Ok(ref t) => t, @@ -70,7 +70,7 @@ pub fn get_ref<'a, T, U>(res: &'a Result) -> &'a T { * * If the result is not an error */ -#[inline(always)] +#[inline] pub fn get_err(res: &Result) -> U { match *res { Err(ref u) => copy *u, @@ -79,7 +79,7 @@ pub fn get_err(res: &Result) -> U { } /// Returns true if the result is `ok` -#[inline(always)] +#[inline] pub fn is_ok(res: &Result) -> bool { match *res { Ok(_) => true, @@ -88,7 +88,7 @@ pub fn is_ok(res: &Result) -> bool { } /// Returns true if the result is `err` -#[inline(always)] +#[inline] pub fn is_err(res: &Result) -> bool { !is_ok(res) } @@ -99,7 +99,7 @@ pub fn is_err(res: &Result) -> bool { * `ok` result variants are converted to `either::right` variants, `err` * result variants are converted to `either::left`. */ -#[inline(always)] +#[inline] pub fn to_either(res: &Result) -> Either { match *res { @@ -122,7 +122,7 @@ pub fn to_either(res: &Result) * ok(parse_bytes(buf)) * } */ -#[inline(always)] +#[inline] pub fn chain(res: Result, op: &fn(T) -> Result) -> Result { match res { @@ -139,7 +139,7 @@ pub fn chain(res: Result, op: &fn(T) * immediately returned. This function can be used to pass through a * successful result while handling an error. */ -#[inline(always)] +#[inline] pub fn chain_err( res: Result, op: &fn(t: V) -> Result) @@ -164,7 +164,7 @@ pub fn chain_err( * print_buf(buf) * } */ -#[inline(always)] +#[inline] pub fn iter(res: &Result, f: &fn(&T)) { match *res { Ok(ref t) => f(t), @@ -180,7 +180,7 @@ pub fn iter(res: &Result, f: &fn(&T)) { * This function can be used to pass through a successful result while * handling an error. */ -#[inline(always)] +#[inline] pub fn iter_err(res: &Result, f: &fn(&E)) { match *res { Ok(_) => (), @@ -202,7 +202,7 @@ pub fn iter_err(res: &Result, f: &fn(&E)) { * parse_bytes(buf) * } */ -#[inline(always)] +#[inline] pub fn map(res: &Result, op: &fn(&T) -> U) -> Result { match *res { @@ -219,7 +219,7 @@ pub fn map(res: &Result, op: &fn(&T) -> U) * is immediately returned. This function can be used to pass through a * successful result while handling an error. */ -#[inline(always)] +#[inline] pub fn map_err(res: &Result, op: &fn(&E) -> F) -> Result { match *res { @@ -229,53 +229,53 @@ pub fn map_err(res: &Result, op: &fn(&E) -> F) } impl Result { - #[inline(always)] + #[inline] pub fn get_ref<'a>(&'a self) -> &'a T { get_ref(self) } - #[inline(always)] + #[inline] pub fn is_ok(&self) -> bool { is_ok(self) } - #[inline(always)] + #[inline] pub fn is_err(&self) -> bool { is_err(self) } - #[inline(always)] + #[inline] pub fn iter(&self, f: &fn(&T)) { iter(self, f) } - #[inline(always)] + #[inline] pub fn iter_err(&self, f: &fn(&E)) { iter_err(self, f) } - #[inline(always)] + #[inline] pub fn unwrap(self) -> T { unwrap(self) } - #[inline(always)] + #[inline] pub fn unwrap_err(self) -> E { unwrap_err(self) } - #[inline(always)] + #[inline] pub fn chain(self, op: &fn(T) -> Result) -> Result { chain(self, op) } - #[inline(always)] + #[inline] pub fn chain_err(self, op: &fn(E) -> Result) -> Result { chain_err(self, op) } } impl Result { - #[inline(always)] + #[inline] pub fn get(&self) -> T { get(self) } - #[inline(always)] + #[inline] pub fn map_err(&self, op: &fn(&E) -> F) -> Result { map_err(self, op) } } impl Result { - #[inline(always)] + #[inline] pub fn get_err(&self) -> E { get_err(self) } - #[inline(always)] + #[inline] pub fn map(&self, op: &fn(&T) -> U) -> Result { map(self, op) } @@ -298,7 +298,7 @@ impl Result { * assert!(incd == ~[2u, 3u, 4u]); * } */ -#[inline(always)] +#[inline] pub fn map_vec( ts: &[T], op: &fn(&T) -> Result) -> Result<~[V],U> { @@ -312,7 +312,7 @@ pub fn map_vec( return Ok(vs); } -#[inline(always)] +#[inline] #[allow(missing_doc)] pub fn map_opt( o_t: &Option, op: &fn(&T) -> Result) -> Result,U> { @@ -335,7 +335,7 @@ pub fn map_opt( * used in 'careful' code contexts where it is both appropriate and easy * to accommodate an error like the vectors being of different lengths. */ -#[inline(always)] +#[inline] pub fn map_vec2(ss: &[S], ts: &[T], op: &fn(&S,&T) -> Result) -> Result<~[V],U> { @@ -358,7 +358,7 @@ pub fn map_vec2(ss: &[S], ts: &[T], * error. This could be implemented using `map_zip()` but it is more efficient * on its own as no result vector is built. */ -#[inline(always)] +#[inline] pub fn iter_vec2(ss: &[S], ts: &[T], op: &fn(&S,&T) -> Result<(),U>) -> Result<(),U> { @@ -376,7 +376,7 @@ pub fn iter_vec2(ss: &[S], ts: &[T], } /// Unwraps a result, assuming it is an `ok(T)` -#[inline(always)] +#[inline] pub fn unwrap(res: Result) -> T { match res { Ok(t) => t, @@ -385,7 +385,7 @@ pub fn unwrap(res: Result) -> T { } /// Unwraps a result, assuming it is an `err(U)` -#[inline(always)] +#[inline] pub fn unwrap_err(res: Result) -> U { match res { Err(u) => u, diff --git a/src/libstd/rt/args.rs b/src/libstd/rt/args.rs new file mode 100644 index 000000000000..75ee4f381f6e --- /dev/null +++ b/src/libstd/rt/args.rs @@ -0,0 +1,125 @@ +// Copyright 2012-2013 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. + +//! Global storage for command line arguments +//! +//! The current incarnation of the Rust runtime expects for +//! the processes `argc` and `argv` arguments to be stored +//! in a globally-accessible location for use by the `os` module. +//! +//! XXX: Would be nice for this to not exist. +//! XXX: This has a lot of C glue for lack of globals. + +use libc; +use option::{Option, Some, None}; +use str; +use uint; +use unstable::finally::Finally; +use util; + +/// One-time global initialization. +pub unsafe fn init(argc: int, argv: **u8) { + let args = load_argc_and_argv(argc, argv); + put(args); +} + +/// One-time global cleanup. +pub fn cleanup() { + rtassert!(take().is_some()); +} + +/// Take the global arguments from global storage. +pub fn take() -> Option<~[~str]> { + with_lock(|| unsafe { + let ptr = get_global_ptr(); + let val = util::replace(&mut *ptr, None); + val.map(|s: &~~[~str]| (**s).clone()) + }) +} + +/// Give the global arguments to global storage. +/// +/// It is an error if the arguments already exist. +pub fn put(args: ~[~str]) { + with_lock(|| unsafe { + let ptr = get_global_ptr(); + rtassert!((*ptr).is_none()); + (*ptr) = Some(~args.clone()); + }) +} + +/// Make a clone of the global arguments. +pub fn clone() -> Option<~[~str]> { + with_lock(|| unsafe { + let ptr = get_global_ptr(); + (*ptr).map(|s: &~~[~str]| (**s).clone()) + }) +} + +fn with_lock(f: &fn() -> T) -> T { + do (|| { + unsafe { + rust_take_global_args_lock(); + f() + } + }).finally { + unsafe { + rust_drop_global_args_lock(); + } + } +} + +fn get_global_ptr() -> *mut Option<~~[~str]> { + unsafe { rust_get_global_args_ptr() } +} + +// Copied from `os`. +unsafe fn load_argc_and_argv(argc: int, argv: **u8) -> ~[~str] { + let mut args = ~[]; + for uint::range(0, argc as uint) |i| { + args.push(str::raw::from_c_str(*(argv as **libc::c_char).offset(i))); + } + return args; +} + +extern { + fn rust_take_global_args_lock(); + fn rust_drop_global_args_lock(); + fn rust_get_global_args_ptr() -> *mut Option<~~[~str]>; +} + +#[cfg(test)] +mod tests { + use option::{Some, None}; + use super::*; + use unstable::finally::Finally; + + #[test] + fn smoke_test() { + // Preserve the actual global state. + let saved_value = take(); + + let expected = ~[~"happy", ~"today?"]; + + put(expected.clone()); + assert!(clone() == Some(expected.clone())); + assert!(take() == Some(expected.clone())); + assert!(take() == None); + + do (|| { + }).finally { + // Restore the actual global state. + match saved_value { + Some(ref args) => put(args.clone()), + None => () + } + } + } +} diff --git a/src/libstd/rt/borrowck.rs b/src/libstd/rt/borrowck.rs new file mode 100644 index 000000000000..e057f6e96371 --- /dev/null +++ b/src/libstd/rt/borrowck.rs @@ -0,0 +1,283 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use cast::transmute; +use libc::{c_char, c_void, size_t, STDERR_FILENO}; +use io; +use io::{Writer, WriterUtil}; +use managed::raw::BoxRepr; +use option::{Option, None, Some}; +use uint; +use str; +use str::OwnedStr; +use sys; +use vec::ImmutableVector; + +#[allow(non_camel_case_types)] +type rust_task = c_void; + +pub static FROZEN_BIT: uint = 1 << (uint::bits - 1); +pub static MUT_BIT: uint = 1 << (uint::bits - 2); +static ALL_BITS: uint = FROZEN_BIT | MUT_BIT; + +#[deriving(Eq)] +struct BorrowRecord { + box: *mut BoxRepr, + file: *c_char, + line: size_t +} + +fn try_take_task_borrow_list() -> Option<~[BorrowRecord]> { + unsafe { + let cur_task: *rust_task = rust_try_get_task(); + if cur_task.is_not_null() { + let ptr = rust_take_task_borrow_list(cur_task); + if ptr.is_null() { + None + } else { + let v: ~[BorrowRecord] = transmute(ptr); + Some(v) + } + } else { + None + } + } +} + +fn swap_task_borrow_list(f: &fn(~[BorrowRecord]) -> ~[BorrowRecord]) { + unsafe { + let cur_task: *rust_task = rust_try_get_task(); + if cur_task.is_not_null() { + let mut borrow_list: ~[BorrowRecord] = { + let ptr = rust_take_task_borrow_list(cur_task); + if ptr.is_null() { ~[] } else { transmute(ptr) } + }; + borrow_list = f(borrow_list); + rust_set_task_borrow_list(cur_task, transmute(borrow_list)); + } + } +} + +pub unsafe fn clear_task_borrow_list() { + // pub because it is used by the box annihilator. + let _ = try_take_task_borrow_list(); +} + +unsafe fn fail_borrowed(box: *mut BoxRepr, file: *c_char, line: size_t) { + debug_borrow("fail_borrowed: ", box, 0, 0, file, line); + + match try_take_task_borrow_list() { + None => { // not recording borrows + let msg = "borrowed"; + do str::as_buf(msg) |msg_p, _| { + sys::begin_unwind_(msg_p as *c_char, file, line); + } + } + Some(borrow_list) => { // recording borrows + let mut msg = ~"borrowed"; + let mut sep = " at "; + for borrow_list.rev_iter().advance |entry| { + if entry.box == box { + msg.push_str(sep); + let filename = str::raw::from_c_str(entry.file); + msg.push_str(filename); + msg.push_str(fmt!(":%u", entry.line as uint)); + sep = " and at "; + } + } + do str::as_buf(msg) |msg_p, _| { + sys::begin_unwind_(msg_p as *c_char, file, line) + } + } + } +} + +/// Because this code is so perf. sensitive, use a static constant so that +/// debug printouts are compiled out most of the time. +static ENABLE_DEBUG: bool = false; + +#[inline] +unsafe fn debug_borrow(tag: &'static str, + p: *const T, + old_bits: uint, + new_bits: uint, + filename: *c_char, + line: size_t) { + //! A useful debugging function that prints a pointer + tag + newline + //! without allocating memory. + + if ENABLE_DEBUG && ::rt::env::get().debug_borrow { + debug_borrow_slow(tag, p, old_bits, new_bits, filename, line); + } + + unsafe fn debug_borrow_slow(tag: &'static str, + p: *const T, + old_bits: uint, + new_bits: uint, + filename: *c_char, + line: size_t) { + let dbg = STDERR_FILENO as io::fd_t; + dbg.write_str(tag); + dbg.write_hex(p as uint); + dbg.write_str(" "); + dbg.write_hex(old_bits); + dbg.write_str(" "); + dbg.write_hex(new_bits); + dbg.write_str(" "); + dbg.write_cstr(filename); + dbg.write_str(":"); + dbg.write_hex(line as uint); + dbg.write_str("\n"); + } +} + +trait DebugPrints { + fn write_hex(&self, val: uint); + unsafe fn write_cstr(&self, str: *c_char); +} + +impl DebugPrints for io::fd_t { + fn write_hex(&self, mut i: uint) { + let letters = ['0', '1', '2', '3', '4', '5', '6', '7', '8', + '9', 'a', 'b', 'c', 'd', 'e', 'f']; + static uint_nibbles: uint = ::uint::bytes << 1; + let mut buffer = [0_u8, ..uint_nibbles+1]; + let mut c = uint_nibbles; + while c > 0 { + c -= 1; + buffer[c] = letters[i & 0xF] as u8; + i >>= 4; + } + self.write(buffer.slice(0, uint_nibbles)); + } + + unsafe fn write_cstr(&self, p: *c_char) { + use libc::strlen; + use vec; + + let len = strlen(p); + let p: *u8 = transmute(p); + do vec::raw::buf_as_slice(p, len as uint) |s| { + self.write(s); + } + } +} + +#[inline] +pub unsafe fn borrow_as_imm(a: *u8, file: *c_char, line: size_t) -> uint { + let a: *mut BoxRepr = transmute(a); + let old_ref_count = (*a).header.ref_count; + let new_ref_count = old_ref_count | FROZEN_BIT; + + debug_borrow("borrow_as_imm:", a, old_ref_count, new_ref_count, file, line); + + if (old_ref_count & MUT_BIT) != 0 { + fail_borrowed(a, file, line); + } + + (*a).header.ref_count = new_ref_count; + + old_ref_count +} + +#[inline] +pub unsafe fn borrow_as_mut(a: *u8, file: *c_char, line: size_t) -> uint { + let a: *mut BoxRepr = transmute(a); + let old_ref_count = (*a).header.ref_count; + let new_ref_count = old_ref_count | MUT_BIT | FROZEN_BIT; + + debug_borrow("borrow_as_mut:", a, old_ref_count, new_ref_count, file, line); + + if (old_ref_count & (MUT_BIT|FROZEN_BIT)) != 0 { + fail_borrowed(a, file, line); + } + + (*a).header.ref_count = new_ref_count; + + old_ref_count +} + +pub unsafe fn record_borrow(a: *u8, old_ref_count: uint, + file: *c_char, line: size_t) { + if (old_ref_count & ALL_BITS) == 0 { + // was not borrowed before + let a: *mut BoxRepr = transmute(a); + debug_borrow("record_borrow:", a, old_ref_count, 0, file, line); + do swap_task_borrow_list |borrow_list| { + let mut borrow_list = borrow_list; + borrow_list.push(BorrowRecord {box: a, file: file, line: line}); + borrow_list + } + } +} + +pub unsafe fn unrecord_borrow(a: *u8, old_ref_count: uint, + file: *c_char, line: size_t) { + if (old_ref_count & ALL_BITS) == 0 { + // was not borrowed before, so we should find the record at + // the end of the list + let a: *mut BoxRepr = transmute(a); + debug_borrow("unrecord_borrow:", a, old_ref_count, 0, file, line); + do swap_task_borrow_list |borrow_list| { + let mut borrow_list = borrow_list; + assert!(!borrow_list.is_empty()); + let br = borrow_list.pop(); + if br.box != a || br.file != file || br.line != line { + let err = fmt!("wrong borrow found, br=%?", br); + do str::as_buf(err) |msg_p, _| { + sys::begin_unwind_(msg_p as *c_char, file, line) + } + } + borrow_list + } + } +} + +#[inline] +pub unsafe fn return_to_mut(a: *u8, orig_ref_count: uint, + file: *c_char, line: size_t) { + // Sometimes the box is null, if it is conditionally frozen. + // See e.g. #4904. + if !a.is_null() { + let a: *mut BoxRepr = transmute(a); + let old_ref_count = (*a).header.ref_count; + let new_ref_count = + (old_ref_count & !ALL_BITS) | (orig_ref_count & ALL_BITS); + + debug_borrow("return_to_mut:", + a, old_ref_count, new_ref_count, file, line); + + (*a).header.ref_count = new_ref_count; + } +} + +#[inline] +pub unsafe fn check_not_borrowed(a: *u8, + file: *c_char, + line: size_t) { + let a: *mut BoxRepr = transmute(a); + let ref_count = (*a).header.ref_count; + debug_borrow("check_not_borrowed:", a, ref_count, 0, file, line); + if (ref_count & FROZEN_BIT) != 0 { + fail_borrowed(a, file, line); + } +} + + +extern { + #[rust_stack] + pub fn rust_take_task_borrow_list(task: *rust_task) -> *c_void; + + #[rust_stack] + pub fn rust_set_task_borrow_list(task: *rust_task, map: *c_void); + + #[rust_stack] + pub fn rust_try_get_task() -> *rust_task; +} diff --git a/src/libstd/rt/comm.rs b/src/libstd/rt/comm.rs index 82e6d44fe625..dd27c03ff516 100644 --- a/src/libstd/rt/comm.rs +++ b/src/libstd/rt/comm.rs @@ -399,12 +399,6 @@ impl GenericChan for SharedChan { } impl GenericSmartChan for SharedChan { - #[cfg(stage0)] // odd type checking errors - fn try_send(&self, _val: T) -> bool { - fail!() - } - - #[cfg(not(stage0))] fn try_send(&self, val: T) -> bool { unsafe { let (next_pone, next_cone) = oneshot(); @@ -448,12 +442,6 @@ impl GenericPort for SharedPort { } } - #[cfg(stage0)] // odd type checking errors - fn try_recv(&self) -> Option { - fail!() - } - - #[cfg(not(stage0))] fn try_recv(&self) -> Option { unsafe { let (next_link_port, next_link_chan) = oneshot(); diff --git a/src/libstd/rt/context.rs b/src/libstd/rt/context.rs index d5ca8473ceea..09ba869549fd 100644 --- a/src/libstd/rt/context.rs +++ b/src/libstd/rt/context.rs @@ -207,7 +207,7 @@ fn align_down(sp: *mut uint) -> *mut uint { } // XXX: ptr::offset is positive ints only -#[inline(always)] +#[inline] pub fn mut_offset(ptr: *mut T, count: int) -> *mut T { use core::sys::size_of; (ptr as int + count * (size_of::() as int)) as *mut T diff --git a/src/libstd/rt/io/extensions.rs b/src/libstd/rt/io/extensions.rs index c7c3eadbe219..55861f127bb4 100644 --- a/src/libstd/rt/io/extensions.rs +++ b/src/libstd/rt/io/extensions.rs @@ -297,7 +297,8 @@ impl ReaderUtil for T { do (|| { while total_read < len { - let slice = vec::mut_slice(*buf, start_len + total_read, buf.len()); + let len = buf.len(); + let slice = vec::mut_slice(*buf, start_len + total_read, len); match self.read(slice) { Some(nread) => { total_read += nread; diff --git a/src/libstd/rt/local_heap.rs b/src/libstd/rt/local_heap.rs index 6bf228a1b220..f62c9fb2c660 100644 --- a/src/libstd/rt/local_heap.rs +++ b/src/libstd/rt/local_heap.rs @@ -10,11 +10,24 @@ //! The local, garbage collected heap +use libc; use libc::{c_void, uintptr_t, size_t}; use ops::Drop; +use repr::BoxRepr; +use rt; +use rt::OldTaskContext; +use rt::local::Local; +use rt::task::Task; type MemoryRegion = c_void; -type BoxedRegion = c_void; + +struct Env { priv opaque: () } + +struct BoxedRegion { + env: *Env, + backing_region: *MemoryRegion, + live_allocs: *BoxRepr +} pub type OpaqueBox = c_void; pub type TypeDesc = c_void; @@ -49,6 +62,12 @@ impl LocalHeap { } } + pub fn realloc(&mut self, ptr: *OpaqueBox, size: uint) -> *OpaqueBox { + unsafe { + return rust_boxed_region_realloc(self.boxed_region, ptr, size as size_t); + } + } + pub fn free(&mut self, box: *OpaqueBox) { unsafe { return rust_boxed_region_free(self.boxed_region, box); @@ -65,6 +84,40 @@ impl Drop for LocalHeap { } } +// A little compatibility function +pub unsafe fn local_free(ptr: *libc::c_char) { + match rt::context() { + OldTaskContext => { + rust_upcall_free_noswitch(ptr); + + extern { + #[fast_ffi] + unsafe fn rust_upcall_free_noswitch(ptr: *libc::c_char); + } + } + _ => { + do Local::borrow:: |task| { + task.heap.free(ptr as *libc::c_void); + } + } + } +} + +pub fn live_allocs() -> *BoxRepr { + let region = match rt::context() { + OldTaskContext => { + unsafe { rust_current_boxed_region() } + } + _ => { + do Local::borrow:: |task| { + task.heap.boxed_region + } + } + }; + + return unsafe { (*region).live_allocs }; +} + extern { fn rust_new_memory_region(synchronized: uintptr_t, detailed_leaks: uintptr_t, @@ -76,5 +129,9 @@ extern { fn rust_boxed_region_malloc(region: *BoxedRegion, td: *TypeDesc, size: size_t) -> *OpaqueBox; + fn rust_boxed_region_realloc(region: *BoxedRegion, + ptr: *OpaqueBox, + size: size_t) -> *OpaqueBox; fn rust_boxed_region_free(region: *BoxedRegion, box: *OpaqueBox); + fn rust_current_boxed_region() -> *BoxedRegion; } diff --git a/src/libstd/rt/logging.rs b/src/libstd/rt/logging.rs index a0d053976891..84186180aa65 100644 --- a/src/libstd/rt/logging.rs +++ b/src/libstd/rt/logging.rs @@ -9,6 +9,7 @@ // except according to those terms. use either::*; +use libc; pub trait Logger { fn log(&mut self, msg: Either<~str, &'static str>); @@ -20,6 +21,10 @@ impl Logger for StdErrLogger { fn log(&mut self, msg: Either<~str, &'static str>) { use io::{Writer, WriterUtil}; + if !should_log_console() { + return; + } + let s: &str = match msg { Left(ref s) => { let s: &str = *s; @@ -44,7 +49,6 @@ pub fn init(crate_map: *u8) { use str; use ptr; use option::{Some, None}; - use libc::c_char; let log_spec = os::getenv("RUST_LOG"); match log_spec { @@ -61,8 +65,16 @@ pub fn init(crate_map: *u8) { } } } - - extern { - fn rust_update_log_settings(crate_map: *u8, settings: *c_char); - } } + +pub fn console_on() { unsafe { rust_log_console_on() } } +pub fn console_off() { unsafe { rust_log_console_off() } } +fn should_log_console() -> bool { unsafe { rust_should_log_console() != 0 } } + +extern { + fn rust_update_log_settings(crate_map: *u8, settings: *libc::c_char); + fn rust_log_console_on(); + fn rust_log_console_off(); + fn rust_should_log_console() -> libc::uintptr_t; +} + diff --git a/src/libstd/rt/mod.rs b/src/libstd/rt/mod.rs index 581e3addff0f..bbf1cf0d9b79 100644 --- a/src/libstd/rt/mod.rs +++ b/src/libstd/rt/mod.rs @@ -58,22 +58,23 @@ Several modules in `core` are clients of `rt`: #[deny(unused_imports)]; #[deny(unused_mut)]; #[deny(unused_variable)]; +#[deny(unused_unsafe)]; use cell::Cell; use clone::Clone; use container::Container; -use from_str::FromStr; +use iter::Times; use iterator::IteratorUtil; -use option::{Some, None}; -use os; +use option::Some; use ptr::RawPtr; -use uint; use rt::sched::{Scheduler, Coroutine, Shutdown}; use rt::sleeper_list::SleeperList; use rt::task::Task; use rt::thread::Thread; use rt::work_queue::WorkQueue; use rt::uv::uvio::UvEventLoop; +use unstable::atomics::{AtomicInt, SeqCst}; +use unstable::sync::UnsafeAtomicRcBox; use vec::{OwnedVector, MutableVector}; /// The global (exchange) heap. @@ -122,7 +123,7 @@ mod thread; pub mod env; /// The local, managed heap -mod local_heap; +pub mod local_heap; /// The Logger trait and implementations pub mod logging; @@ -148,7 +149,7 @@ pub mod local_ptr; /// Bindings to pthread/windows thread-local storage. pub mod thread_local_storage; -/// A concurrent data structure with which parent tasks wait on child tasks. +/// For waiting on child tasks. pub mod join_latch; pub mod metrics; @@ -157,6 +158,12 @@ pub mod metrics; /// Just stuff pub mod util; +// Global command line argument storage +pub mod args; + +// Support for dynamic borrowck +pub mod borrowck; + /// Set up a default runtime configuration, given compiler-supplied arguments. /// /// This is invoked by the `start` _language item_ (unstable::lang) to @@ -171,71 +178,104 @@ pub mod util; /// # Return value /// /// The return value is used as the process return code. 0 on success, 101 on error. -pub fn start(_argc: int, _argv: **u8, crate_map: *u8, main: ~fn()) -> int { +pub fn start(argc: int, argv: **u8, crate_map: *u8, main: ~fn()) -> int { - init(crate_map); - run(main); + init(argc, argv, crate_map); + let exit_code = run(main); cleanup(); - return 0; + return exit_code; } -/// One-time runtime initialization. Currently all this does is set up logging -/// based on the RUST_LOG environment variable. -pub fn init(crate_map: *u8) { - logging::init(crate_map); +/// One-time runtime initialization. +/// +/// Initializes global state, including frobbing +/// the crate's logging flags, registering GC +/// metadata, and storing the process arguments. +pub fn init(argc: int, argv: **u8, crate_map: *u8) { + // XXX: Derefing these pointers is not safe. + // Need to propagate the unsafety to `start`. + unsafe { + args::init(argc, argv); + logging::init(crate_map); + rust_update_gc_metadata(crate_map); + } + + extern { + fn rust_update_gc_metadata(crate_map: *u8); + } } +/// One-time runtime cleanup. pub fn cleanup() { + args::cleanup(); global_heap::cleanup(); } -pub fn run(main: ~fn()) { - let nthreads = match os::getenv("RUST_THREADS") { - Some(nstr) => FromStr::from_str(nstr).get(), - None => unsafe { - // Using more threads than cores in test code - // to force the OS to preempt them frequently. - // Assuming that this help stress test concurrent types. - util::num_cpus() * 2 - } - }; +/// Execute the main function in a scheduler. +/// +/// Configures the runtime according to the environment, by default +/// using a task scheduler with the same number of threads as cores. +/// Returns a process exit code. +pub fn run(main: ~fn()) -> int { + static DEFAULT_ERROR_CODE: int = 101; + + let nthreads = util::default_sched_threads(); + + // The shared list of sleeping schedulers. Schedulers wake each other + // occassionally to do new work. let sleepers = SleeperList::new(); + // The shared work queue. Temporary until work stealing is implemented. let work_queue = WorkQueue::new(); - let mut handles = ~[]; + // The schedulers. let mut scheds = ~[]; + // Handles to the schedulers. When the main task ends these will be + // sent the Shutdown message to terminate the schedulers. + let mut handles = ~[]; - for uint::range(0, nthreads) |_| { + for nthreads.times { + // Every scheduler is driven by an I/O event loop. let loop_ = ~UvEventLoop::new(); let mut sched = ~Scheduler::new(loop_, work_queue.clone(), sleepers.clone()); let handle = sched.make_handle(); - handles.push(handle); scheds.push(sched); + handles.push(handle); } - let main_cell = Cell::new(main); + // Create a shared cell for transmitting the process exit + // code from the main task to this function. + let exit_code = UnsafeAtomicRcBox::new(AtomicInt::new(0)); + let exit_code_clone = exit_code.clone(); + + // When the main task exits, after all the tasks in the main + // task tree, shut down the schedulers and set the exit code. let handles = Cell::new(handles); - let mut new_task = ~Task::new_root(); - let on_exit: ~fn(bool) = |exit_status| { + let on_exit: ~fn(bool) = |exit_success| { let mut handles = handles.take(); - // Tell schedulers to exit for handles.mut_iter().advance |handle| { handle.send(Shutdown); } - rtassert!(exit_status); + unsafe { + let exit_code = if exit_success { 0 } else { DEFAULT_ERROR_CODE }; + (*exit_code_clone.get()).store(exit_code, SeqCst); + } }; + + // Create and enqueue the main task. + let main_cell = Cell::new(main); + let mut new_task = ~Task::new_root(); new_task.on_exit = Some(on_exit); let main_task = ~Coroutine::with_task(&mut scheds[0].stack_pool, new_task, main_cell.take()); scheds[0].enqueue_task(main_task); + // Run each scheduler in a thread. let mut threads = ~[]; - while !scheds.is_empty() { let sched = scheds.pop(); let sched_cell = Cell::new(sched); @@ -248,7 +288,12 @@ pub fn run(main: ~fn()) { } // Wait for schedulers - let _threads = threads; + { let _threads = threads; } + + // Return the exit code + unsafe { + (*exit_code.get()).load(SeqCst) + } } /// Possible contexts in which Rust code may be executing. diff --git a/src/libstd/rt/sched.rs b/src/libstd/rt/sched.rs index 453d3303db66..bbe4aa25e296 100644 --- a/src/libstd/rt/sched.rs +++ b/src/libstd/rt/sched.rs @@ -646,12 +646,12 @@ impl Scheduler { } } -// The cases for the below function. +// The cases for the below function. enum ResumeAction { SendHome, Requeue, ResumeNow, - Homeless + Homeless } impl SchedHandle { diff --git a/src/libstd/rt/task.rs b/src/libstd/rt/task.rs index e7f87906fe59..97c3b6a749bc 100644 --- a/src/libstd/rt/task.rs +++ b/src/libstd/rt/task.rs @@ -15,6 +15,7 @@ use borrow; use cast::transmute; +use cleanup; use libc::{c_void, uintptr_t}; use ptr; use prelude::*; @@ -118,6 +119,10 @@ impl Task { } _ => () } + + // Destroy remaining boxes + unsafe { cleanup::annihilate(); } + self.destroyed = true; } } @@ -248,6 +253,18 @@ mod test { } } + #[test] + fn comm_shared_chan() { + use comm::*; + + do run_in_newsched_task() { + let (port, chan) = stream(); + let chan = SharedChan::new(chan); + chan.send(10); + assert!(port.recv() == 10); + } + } + #[test] fn linked_failure() { do run_in_newsched_task() { @@ -257,4 +274,45 @@ mod test { assert!(res.is_err()); } } + + #[test] + fn heap_cycles() { + use option::{Option, Some, None}; + + do run_in_newsched_task { + struct List { + next: Option<@mut List>, + } + + let a = @mut List { next: None }; + let b = @mut List { next: Some(a) }; + + a.next = Some(b); + } + } + + // XXX: This is a copy of test_future_result in std::task. + // It can be removed once the scheduler is turned on by default. + #[test] + fn future_result() { + do run_in_newsched_task { + use option::{Some, None}; + use task::*; + + let mut result = None; + let mut builder = task(); + builder.future_result(|r| result = Some(r)); + do builder.spawn {} + assert_eq!(result.unwrap().recv(), Success); + + result = None; + let mut builder = task(); + builder.future_result(|r| result = Some(r)); + builder.unlinked(); + do builder.spawn { + fail!(); + } + assert_eq!(result.unwrap().recv(), Failure); + } + } } diff --git a/src/libstd/rt/test.rs b/src/libstd/rt/test.rs index 36efcd91834b..b0e496840147 100644 --- a/src/libstd/rt/test.rs +++ b/src/libstd/rt/test.rs @@ -74,7 +74,7 @@ pub fn run_in_mt_newsched_task(f: ~fn()) { do run_in_bare_thread { let nthreads = match os::getenv("RUST_TEST_THREADS") { Some(nstr) => FromStr::from_str(nstr).get(), - None => unsafe { + None => { // Using more threads than cores in test code // to force the OS to preempt them frequently. // Assuming that this help stress test concurrent types. diff --git a/src/libstd/rt/util.rs b/src/libstd/rt/util.rs index 904b2f8bbb93..5219ae1d5406 100644 --- a/src/libstd/rt/util.rs +++ b/src/libstd/rt/util.rs @@ -9,8 +9,11 @@ // except according to those terms. use container::Container; +use from_str::FromStr; use iterator::IteratorUtil; use libc; +use option::{Some, None}; +use os; use str::StrSlice; /// Get the number of cores available @@ -24,6 +27,15 @@ pub fn num_cpus() -> uint { } } +/// Get's the number of scheduler threads requested by the environment +/// either `RUST_THREADS` or `num_cpus`. +pub fn default_sched_threads() -> uint { + match os::getenv("RUST_THREADS") { + Some(nstr) => FromStr::from_str(nstr).get(), + None => num_cpus() + } +} + pub fn dumb_println(s: &str) { use io::WriterUtil; let dbg = ::libc::STDERR_FILENO as ::io::fd_t; diff --git a/src/libstd/rt/uv/timer.rs b/src/libstd/rt/uv/timer.rs index 5557a5809875..14465eb7dfd3 100644 --- a/src/libstd/rt/uv/timer.rs +++ b/src/libstd/rt/uv/timer.rs @@ -143,7 +143,7 @@ mod test { let count_ptr: *mut int = &mut count; let mut loop_ = Loop::new(); let mut timer = TimerWatcher::new(&mut loop_); - do timer.start(10, 20) |timer, status| { + do timer.start(1, 2) |timer, status| { assert!(status.is_none()); unsafe { *count_ptr += 1; @@ -160,14 +160,14 @@ mod test { let mut timer2 = TimerWatcher::new(&mut loop_); do timer2.start(10, 0) |timer2, _| { - unsafe { *count_ptr += 1; } + *count_ptr += 1; timer2.close(||()); // Restart the original timer let mut timer = timer; - do timer.start(10, 0) |timer, _| { - unsafe { *count_ptr += 1; } + do timer.start(1, 0) |timer, _| { + *count_ptr += 1; timer.close(||()); } } diff --git a/src/libstd/run.rs b/src/libstd/run.rs index b204cf6cfb04..060de3f4d5d5 100644 --- a/src/libstd/run.rs +++ b/src/libstd/run.rs @@ -915,7 +915,7 @@ priv fn waitpid(pid: pid_t) -> int { #[cfg(test)] mod tests { use io; - use libc::{c_int}; + use libc::{c_int, uintptr_t}; use option::{Option, None, Some}; use os; use path::Path; @@ -958,7 +958,10 @@ mod tests { assert_eq!(status, 0); assert_eq!(output_str.trim().to_owned(), ~"hello"); - assert_eq!(error, ~[]); + // FIXME #7224 + if !running_on_valgrind() { + assert_eq!(error, ~[]); + } } #[test] @@ -1043,7 +1046,10 @@ mod tests { assert_eq!(status, 0); assert_eq!(output_str.trim().to_owned(), ~"hello"); - assert_eq!(error, ~[]); + // FIXME #7224 + if !running_on_valgrind() { + assert_eq!(error, ~[]); + } } #[test] @@ -1057,14 +1063,20 @@ mod tests { assert_eq!(status, 0); assert_eq!(output_str.trim().to_owned(), ~"hello"); - assert_eq!(error, ~[]); + // FIXME #7224 + if !running_on_valgrind() { + assert_eq!(error, ~[]); + } let run::ProcessOutput {status, output, error} = prog.finish_with_output(); assert_eq!(status, 0); assert_eq!(output, ~[]); - assert_eq!(error, ~[]); + // FIXME #7224 + if !running_on_valgrind() { + assert_eq!(error, ~[]); + } } #[test] @@ -1148,6 +1160,7 @@ mod tests { #[test] fn test_inherit_env() { + if running_on_valgrind() { return; } let mut prog = run_env(None); let output = str::from_bytes(prog.finish_with_output().output); @@ -1169,4 +1182,12 @@ mod tests { assert!(output.contains("RUN_TEST_NEW_ENV=123")); } + + fn running_on_valgrind() -> bool { + unsafe { rust_running_on_valgrind() != 0 } + } + + extern { + fn rust_running_on_valgrind() -> uintptr_t; + } } diff --git a/src/libstd/str.rs b/src/libstd/str.rs index 1086fcaa75cf..04f5247782b0 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -23,11 +23,11 @@ use cast; use char; use char::Char; use clone::Clone; -use cmp::{TotalOrd, Ordering, Less, Equal, Greater}; use container::Container; use iter::Times; -use iterator::{Iterator, IteratorUtil, FilterIterator, AdditiveIterator}; +use iterator::{Iterator, IteratorUtil, FilterIterator, AdditiveIterator, MapIterator}; use libc; +use num::Zero; use option::{None, Option, Some}; use old_iter::{BaseIter, EqIter}; use ptr; @@ -37,8 +37,6 @@ use uint; use vec; use vec::{OwnedVector, OwnedCopyableVector, ImmutableVector}; -#[cfg(not(test))] use cmp::{Eq, Ord, Equiv, TotalEq}; - /* Section: Conditions */ @@ -108,21 +106,21 @@ pub fn from_bytes_slice<'a>(vector: &'a [u8]) -> &'a str { } /// Copy a slice into a new unique str -#[inline(always)] +#[inline] pub fn to_owned(s: &str) -> ~str { unsafe { raw::slice_bytes_owned(s, 0, s.len()) } } impl ToStr for ~str { - #[inline(always)] + #[inline] fn to_str(&self) -> ~str { to_owned(*self) } } impl<'self> ToStr for &'self str { - #[inline(always)] + #[inline] fn to_str(&self) -> ~str { to_owned(*self) } } impl ToStr for @str { - #[inline(always)] + #[inline] fn to_str(&self) -> ~str { to_owned(*self) } } @@ -243,26 +241,26 @@ pub trait CharEq { fn only_ascii(&self) -> bool; } impl CharEq for char { - #[inline(always)] + #[inline] fn matches(&self, c: char) -> bool { *self == c } fn only_ascii(&self) -> bool { (*self as uint) < 128 } } impl<'self> CharEq for &'self fn(char) -> bool { - #[inline(always)] + #[inline] fn matches(&self, c: char) -> bool { (*self)(c) } fn only_ascii(&self) -> bool { false } } impl CharEq for extern "Rust" fn(char) -> bool { - #[inline(always)] + #[inline] fn matches(&self, c: char) -> bool { (*self)(c) } fn only_ascii(&self) -> bool { false } } impl<'self, C: CharEq> CharEq for &'self [C] { - #[inline(always)] + #[inline] fn matches(&self, c: char) -> bool { self.iter().any_(|m| m.matches(c)) } @@ -291,6 +289,10 @@ pub type WordIterator<'self> = FilterIterator<'self, &'self str, StrCharSplitIterator<'self, extern "Rust" fn(char) -> bool>>; +/// An iterator over the lines of a string, separated by either `\n` or (`\r\n`). +pub type AnyLineIterator<'self> = + MapIterator<'self, &'self str, &'self str, StrCharSplitIterator<'self, char>>; + impl<'self, Sep: CharEq> Iterator<&'self str> for StrCharSplitIterator<'self, Sep> { #[inline] fn next(&mut self) -> Option<&'self str> { @@ -400,56 +402,6 @@ impl<'self> Iterator<&'self str> for StrStrSplitIterator<'self> { } } -/// Levenshtein Distance between two strings -pub fn levdistance(s: &str, t: &str) -> uint { - - let slen = s.len(); - let tlen = t.len(); - - if slen == 0 { return tlen; } - if tlen == 0 { return slen; } - - let mut dcol = vec::from_fn(tlen + 1, |x| x); - - for s.iter().enumerate().advance |(i, sc)| { - - let mut current = i; - dcol[0] = current + 1; - - for t.iter().enumerate().advance |(j, tc)| { - - let next = dcol[j + 1]; - - if sc == tc { - dcol[j + 1] = current; - } else { - dcol[j + 1] = ::cmp::min(current, next); - dcol[j + 1] = ::cmp::min(dcol[j + 1], dcol[j]) + 1; - } - - current = next; - } - } - - return dcol[tlen]; -} - -/** - * Splits a string into substrings separated by LF ('\n') - * and/or CR LF ("\r\n") - */ -pub fn each_line_any<'a>(s: &'a str, it: &fn(&'a str) -> bool) -> bool { - for s.line_iter().advance |s| { - let l = s.len(); - if l > 0u && s[l - 1u] == '\r' as u8 { - if !it( unsafe { raw::slice_bytes(s, 0, l - 1) } ) { return false; } - } else { - if !it( s ) { return false; } - } - } - return true; -} - /** Splits a string into substrings with possibly internal whitespace, * each of them at most `lim` bytes long. The substrings have leading and trailing * whitespace removed, and are only cut at whitespace boundaries. @@ -576,196 +528,6 @@ pub fn eq(a: &~str, b: &~str) -> bool { eq_slice(*a, *b) } -#[inline] -fn cmp(a: &str, b: &str) -> Ordering { - let low = uint::min(a.len(), b.len()); - - for uint::range(0, low) |idx| { - match a[idx].cmp(&b[idx]) { - Greater => return Greater, - Less => return Less, - Equal => () - } - } - - a.len().cmp(&b.len()) -} - -#[cfg(not(test))] -impl<'self> TotalOrd for &'self str { - #[inline] - fn cmp(&self, other: & &'self str) -> Ordering { cmp(*self, *other) } -} - -#[cfg(not(test))] -impl TotalOrd for ~str { - #[inline] - fn cmp(&self, other: &~str) -> Ordering { cmp(*self, *other) } -} - -#[cfg(not(test))] -impl TotalOrd for @str { - #[inline] - fn cmp(&self, other: &@str) -> Ordering { cmp(*self, *other) } -} - -/// Bytewise slice less than -#[inline] -fn lt(a: &str, b: &str) -> bool { - let (a_len, b_len) = (a.len(), b.len()); - let end = uint::min(a_len, b_len); - - let mut i = 0; - while i < end { - let (c_a, c_b) = (a[i], b[i]); - if c_a < c_b { return true; } - if c_a > c_b { return false; } - i += 1; - } - - return a_len < b_len; -} - -/// Bytewise less than or equal -#[inline] -pub fn le(a: &str, b: &str) -> bool { - !lt(b, a) -} - -/// Bytewise greater than or equal -#[inline] -fn ge(a: &str, b: &str) -> bool { - !lt(a, b) -} - -/// Bytewise greater than -#[inline] -fn gt(a: &str, b: &str) -> bool { - !le(a, b) -} - -#[cfg(not(test))] -impl<'self> Eq for &'self str { - #[inline(always)] - fn eq(&self, other: & &'self str) -> bool { - eq_slice((*self), (*other)) - } - #[inline(always)] - fn ne(&self, other: & &'self str) -> bool { !(*self).eq(other) } -} - -#[cfg(not(test))] -impl Eq for ~str { - #[inline(always)] - fn eq(&self, other: &~str) -> bool { - eq_slice((*self), (*other)) - } - #[inline(always)] - fn ne(&self, other: &~str) -> bool { !(*self).eq(other) } -} - -#[cfg(not(test))] -impl Eq for @str { - #[inline(always)] - fn eq(&self, other: &@str) -> bool { - eq_slice((*self), (*other)) - } - #[inline(always)] - fn ne(&self, other: &@str) -> bool { !(*self).eq(other) } -} - -#[cfg(not(test))] -impl<'self> TotalEq for &'self str { - #[inline(always)] - fn equals(&self, other: & &'self str) -> bool { - eq_slice((*self), (*other)) - } -} - -#[cfg(not(test))] -impl TotalEq for ~str { - #[inline(always)] - fn equals(&self, other: &~str) -> bool { - eq_slice((*self), (*other)) - } -} - -#[cfg(not(test))] -impl TotalEq for @str { - #[inline(always)] - fn equals(&self, other: &@str) -> bool { - eq_slice((*self), (*other)) - } -} - -#[cfg(not(test))] -impl Ord for ~str { - #[inline(always)] - fn lt(&self, other: &~str) -> bool { lt((*self), (*other)) } - #[inline(always)] - fn le(&self, other: &~str) -> bool { le((*self), (*other)) } - #[inline(always)] - fn ge(&self, other: &~str) -> bool { ge((*self), (*other)) } - #[inline(always)] - fn gt(&self, other: &~str) -> bool { gt((*self), (*other)) } -} - -#[cfg(not(test))] -impl<'self> Ord for &'self str { - #[inline(always)] - fn lt(&self, other: & &'self str) -> bool { lt((*self), (*other)) } - #[inline(always)] - fn le(&self, other: & &'self str) -> bool { le((*self), (*other)) } - #[inline(always)] - fn ge(&self, other: & &'self str) -> bool { ge((*self), (*other)) } - #[inline(always)] - fn gt(&self, other: & &'self str) -> bool { gt((*self), (*other)) } -} - -#[cfg(not(test))] -impl Ord for @str { - #[inline(always)] - fn lt(&self, other: &@str) -> bool { lt((*self), (*other)) } - #[inline(always)] - fn le(&self, other: &@str) -> bool { le((*self), (*other)) } - #[inline(always)] - fn ge(&self, other: &@str) -> bool { ge((*self), (*other)) } - #[inline(always)] - fn gt(&self, other: &@str) -> bool { gt((*self), (*other)) } -} - -#[cfg(not(test))] -impl<'self, S: Str> Equiv for &'self str { - #[inline(always)] - fn equiv(&self, other: &S) -> bool { eq_slice(*self, other.as_slice()) } -} -#[cfg(not(test))] -impl<'self, S: Str> Equiv for @str { - #[inline(always)] - fn equiv(&self, other: &S) -> bool { eq_slice(*self, other.as_slice()) } -} - -#[cfg(not(test))] -impl<'self, S: Str> Equiv for ~str { - #[inline(always)] - fn equiv(&self, other: &S) -> bool { eq_slice(*self, other.as_slice()) } -} - - -/* -Section: Iterating through strings -*/ - -/// Apply a function to each character -pub fn map(ss: &str, ff: &fn(char) -> char) -> ~str { - let mut result = ~""; - result.reserve(ss.len()); - for ss.iter().advance |cc| { - result.push_char(ff(cc)); - } - result -} - /* Section: Searching */ @@ -820,30 +582,6 @@ pub fn is_utf16(v: &[u16]) -> bool { return true; } -/// Converts to a vector of `u16` encoded as UTF-16 -pub fn to_utf16(s: &str) -> ~[u16] { - let mut u = ~[]; - for s.iter().advance |ch| { - // Arithmetic with u32 literals is easier on the eyes than chars. - let mut ch = ch as u32; - - if (ch & 0xFFFF_u32) == ch { - // The BMP falls through (assuming non-surrogate, as it - // should) - assert!(ch <= 0xD7FF_u32 || ch >= 0xE000_u32); - u.push(ch as u16) - } else { - // Supplementary planes break into surrogates. - assert!(ch >= 0x1_0000_u32 && ch <= 0x10_FFFF_u32); - ch -= 0x1_0000_u32; - let w1 = 0xD800_u16 | ((ch >> 10) as u16); - let w2 = 0xDC00_u16 | ((ch as u16) & 0x3FF_u16); - u.push_all([w1, w2]) - } - } - u -} - /// Iterates over the utf-16 characters in the specified slice, yielding each /// decoded unicode character to the function provided. /// @@ -967,7 +705,7 @@ impl<'self> StrUtil for &'self str { /** * Deprecated. Use the `as_c_str` method on strings instead. */ -#[inline(always)] +#[inline] pub fn as_c_str(s: &str, f: &fn(*libc::c_char) -> T) -> T { s.as_c_str(f) } @@ -980,7 +718,7 @@ pub fn as_c_str(s: &str, f: &fn(*libc::c_char) -> T) -> T { * indexable area for a null byte, as is the case in slices pointing * to full strings, or suffixes of them. */ -#[inline(always)] +#[inline] pub fn as_buf(s: &str, f: &fn(*u8, uint) -> T) -> T { unsafe { let v : *(*u8,uint) = transmute(&s); @@ -989,40 +727,6 @@ pub fn as_buf(s: &str, f: &fn(*u8, uint) -> T) -> T { } } -/** - * Returns the byte offset of an inner slice relative to an enclosing outer slice - * - * # Example - * - * ~~~ {.rust} - * let string = "a\nb\nc"; - * let mut lines = ~[]; - * for string.line_iter().advance |line| { lines.push(line) } - * - * assert!(subslice_offset(string, lines[0]) == 0); // &"a" - * assert!(subslice_offset(string, lines[1]) == 2); // &"b" - * assert!(subslice_offset(string, lines[2]) == 4); // &"c" - * ~~~ - */ -#[inline(always)] -pub fn subslice_offset(outer: &str, inner: &str) -> uint { - do as_buf(outer) |a, a_len| { - do as_buf(inner) |b, b_len| { - let a_start: uint; - let a_end: uint; - let b_start: uint; - let b_end: uint; - unsafe { - a_start = cast::transmute(a); a_end = a_len + cast::transmute(a); - b_start = cast::transmute(b); b_end = b_len + cast::transmute(b); - } - assert!(a_start <= b_start); - assert!(b_end <= a_end); - b_start - a_start - } - } -} - /// Unsafe operations pub mod raw { use cast; @@ -1207,12 +911,138 @@ pub mod raw { #[cfg(not(test))] pub mod traits { use ops::Add; - impl<'self> Add<&'self str,~str> for ~str { - #[inline(always)] + use cmp::{TotalOrd, Ordering, Less, Equal, Greater, Eq, Ord, Equiv, TotalEq}; + use super::{Str, eq_slice}; + + impl<'self> Add<&'self str,~str> for &'self str { + #[inline] fn add(&self, rhs: & &'self str) -> ~str { - self.append((*rhs)) + let mut ret = self.to_owned(); + ret.push_str(*rhs); + ret } } + + impl<'self> TotalOrd for &'self str { + #[inline] + fn cmp(&self, other: & &'self str) -> Ordering { + for self.bytes_iter().zip(other.bytes_iter()).advance |(s_b, o_b)| { + match s_b.cmp(&o_b) { + Greater => return Greater, + Less => return Less, + Equal => () + } + } + + self.len().cmp(&other.len()) + } + } + + impl TotalOrd for ~str { + #[inline] + fn cmp(&self, other: &~str) -> Ordering { self.as_slice().cmp(&other.as_slice()) } + } + + impl TotalOrd for @str { + #[inline] + fn cmp(&self, other: &@str) -> Ordering { self.as_slice().cmp(&other.as_slice()) } + } + + impl<'self> Eq for &'self str { + #[inline] + fn eq(&self, other: & &'self str) -> bool { + eq_slice((*self), (*other)) + } + #[inline] + fn ne(&self, other: & &'self str) -> bool { !(*self).eq(other) } + } + + impl Eq for ~str { + #[inline] + fn eq(&self, other: &~str) -> bool { + eq_slice((*self), (*other)) + } + #[inline] + fn ne(&self, other: &~str) -> bool { !(*self).eq(other) } + } + + impl Eq for @str { + #[inline] + fn eq(&self, other: &@str) -> bool { + eq_slice((*self), (*other)) + } + #[inline] + fn ne(&self, other: &@str) -> bool { !(*self).eq(other) } + } + + impl<'self> TotalEq for &'self str { + #[inline] + fn equals(&self, other: & &'self str) -> bool { + eq_slice((*self), (*other)) + } + } + + impl TotalEq for ~str { + #[inline] + fn equals(&self, other: &~str) -> bool { + eq_slice((*self), (*other)) + } + } + + impl TotalEq for @str { + #[inline] + fn equals(&self, other: &@str) -> bool { + eq_slice((*self), (*other)) + } + } + + impl<'self> Ord for &'self str { + #[inline] + fn lt(&self, other: & &'self str) -> bool { self.cmp(other) == Less } + #[inline] + fn le(&self, other: & &'self str) -> bool { self.cmp(other) != Greater } + #[inline] + fn ge(&self, other: & &'self str) -> bool { self.cmp(other) != Less } + #[inline] + fn gt(&self, other: & &'self str) -> bool { self.cmp(other) == Greater } + } + + impl Ord for ~str { + #[inline] + fn lt(&self, other: &~str) -> bool { self.cmp(other) == Less } + #[inline] + fn le(&self, other: &~str) -> bool { self.cmp(other) != Greater } + #[inline] + fn ge(&self, other: &~str) -> bool { self.cmp(other) != Less } + #[inline] + fn gt(&self, other: &~str) -> bool { self.cmp(other) == Greater } + } + + impl Ord for @str { + #[inline] + fn lt(&self, other: &@str) -> bool { self.cmp(other) == Less } + #[inline] + fn le(&self, other: &@str) -> bool { self.cmp(other) != Greater } + #[inline] + fn ge(&self, other: &@str) -> bool { self.cmp(other) != Less } + #[inline] + fn gt(&self, other: &@str) -> bool { self.cmp(other) == Greater } + } + + impl<'self, S: Str> Equiv for &'self str { + #[inline] + fn equiv(&self, other: &S) -> bool { eq_slice(*self, other.as_slice()) } + } + + impl<'self, S: Str> Equiv for @str { + #[inline] + fn equiv(&self, other: &S) -> bool { eq_slice(*self, other.as_slice()) } + } + + impl<'self, S: Str> Equiv for ~str { + #[inline] + fn equiv(&self, other: &S) -> bool { eq_slice(*self, other.as_slice()) } + } } #[cfg(test)] @@ -1225,17 +1055,17 @@ pub trait Str { } impl<'self> Str for &'self str { - #[inline(always)] + #[inline] fn as_slice<'a>(&'a self) -> &'a str { *self } } impl<'self> Str for ~str { - #[inline(always)] + #[inline] fn as_slice<'a>(&'a self) -> &'a str { let s: &'a str = *self; s } } impl<'self> Str for @str { - #[inline(always)] + #[inline] fn as_slice<'a>(&'a self) -> &'a str { let s: &'a str = *self; s } @@ -1256,6 +1086,7 @@ pub trait StrSlice<'self> { fn matches_index_iter(&self, sep: &'self str) -> StrMatchesIndexIterator<'self>; fn split_str_iter(&self, &'self str) -> StrStrSplitIterator<'self>; fn line_iter(&self) -> StrCharSplitIterator<'self, char>; + fn any_line_iter(&self) -> AnyLineIterator<'self>; fn word_iter(&self) -> WordIterator<'self>; fn ends_with(&self, needle: &str) -> bool; fn is_empty(&self) -> bool; @@ -1282,6 +1113,7 @@ pub trait StrSlice<'self> { fn replace(&self, from: &str, to: &str) -> ~str; fn to_owned(&self) -> ~str; fn to_managed(&self) -> @str; + fn to_utf16(&self) -> ~[u16]; fn is_char_boundary(&self, index: uint) -> bool; fn char_range_at(&self, start: uint) -> CharRange; fn char_at(&self, i: uint) -> char; @@ -1296,6 +1128,12 @@ pub trait StrSlice<'self> { fn repeat(&self, nn: uint) -> ~str; fn slice_shift_char(&self) -> (char, &'self str); + + fn map_chars(&self, ff: &fn(char) -> char) -> ~str; + + fn lev_distance(&self, t: &str) -> uint; + + fn subslice_offset(&self, inner: &str) -> uint; } /// Extension methods for strings @@ -1437,6 +1275,17 @@ impl<'self> StrSlice<'self> for &'self str { fn line_iter(&self) -> StrCharSplitIterator<'self, char> { self.split_options_iter('\n', self.len(), false) } + + /// An iterator over the lines of a string, separated by either + /// `\n` or (`\r\n`). + fn any_line_iter(&self) -> AnyLineIterator<'self> { + do self.line_iter().transform |line| { + let l = line.len(); + if l > 0 && line[l - 1] == '\r' as u8 { line.slice(0, l - 1) } + else { line } + } + } + /// An iterator over the words of a string (subsequences separated /// by any sequence of whitespace). #[inline] @@ -1462,7 +1311,7 @@ impl<'self> StrSlice<'self> for &'self str { #[inline] fn is_alphanumeric(&self) -> bool { self.iter().all(char::is_alphanumeric) } /// Returns the size in bytes not counting the null terminator - #[inline(always)] + #[inline] fn len(&self) -> uint { do as_buf(*self) |_p, n| { n - 1u } } @@ -1586,7 +1435,7 @@ impl<'self> StrSlice<'self> for &'self str { * * # Example * - * ~~~ + * ~~~ {.rust} * assert_eq!("11foo1bar11".trim_chars(&'1'), "foo1bar") * assert_eq!("12foo1bar12".trim_chars(& &['1', '2']), "foo1bar") * assert_eq!("123foo1bar123".trim_chars(&|c: char| c.is_digit()), "foo1bar") @@ -1605,7 +1454,7 @@ impl<'self> StrSlice<'self> for &'self str { * * # Example * - * ~~~ + * ~~~ {.rust} * assert_eq!("11foo1bar11".trim_left_chars(&'1'), "foo1bar11") * assert_eq!("12foo1bar12".trim_left_chars(& &['1', '2']), "foo1bar12") * assert_eq!("123foo1bar123".trim_left_chars(&|c: char| c.is_digit()), "foo1bar123") @@ -1627,7 +1476,7 @@ impl<'self> StrSlice<'self> for &'self str { * * # Example * - * ~~~ + * ~~~ {.rust} * assert_eq!("11foo1bar11".trim_right_chars(&'1'), "11foo1bar") * assert_eq!("12foo1bar12".trim_right_chars(& &['1', '2']), "12foo1bar") * assert_eq!("123foo1bar123".trim_right_chars(&|c: char| c.is_digit()), "123foo1bar") @@ -1679,6 +1528,30 @@ impl<'self> StrSlice<'self> for &'self str { unsafe { ::cast::transmute(v) } } + /// Converts to a vector of `u16` encoded as UTF-16. + fn to_utf16(&self) -> ~[u16] { + let mut u = ~[]; + for self.iter().advance |ch| { + // Arithmetic with u32 literals is easier on the eyes than chars. + let mut ch = ch as u32; + + if (ch & 0xFFFF_u32) == ch { + // The BMP falls through (assuming non-surrogate, as it + // should) + assert!(ch <= 0xD7FF_u32 || ch >= 0xE000_u32); + u.push(ch as u16) + } else { + // Supplementary planes break into surrogates. + assert!(ch >= 0x1_0000_u32 && ch <= 0x10_FFFF_u32); + ch -= 0x1_0000_u32; + let w1 = 0xD800_u16 | ((ch >> 10) as u16); + let w2 = 0xDC00_u16 | ((ch as u16) & 0x3FF_u16); + u.push_all([w1, w2]) + } + } + u + } + /** * Returns false if the index points into the middle of a multi-byte * character sequence. @@ -1921,6 +1794,85 @@ impl<'self> StrSlice<'self> for &'self str { } + /// Apply a function to each character. + fn map_chars(&self, ff: &fn(char) -> char) -> ~str { + let mut result = with_capacity(self.len()); + for self.iter().advance |cc| { + result.push_char(ff(cc)); + } + result + } + + /// Levenshtein Distance between two strings. + fn lev_distance(&self, t: &str) -> uint { + let slen = self.len(); + let tlen = t.len(); + + if slen == 0 { return tlen; } + if tlen == 0 { return slen; } + + let mut dcol = vec::from_fn(tlen + 1, |x| x); + + for self.iter().enumerate().advance |(i, sc)| { + + let mut current = i; + dcol[0] = current + 1; + + for t.iter().enumerate().advance |(j, tc)| { + + let next = dcol[j + 1]; + + if sc == tc { + dcol[j + 1] = current; + } else { + dcol[j + 1] = ::cmp::min(current, next); + dcol[j + 1] = ::cmp::min(dcol[j + 1], dcol[j]) + 1; + } + + current = next; + } + } + + return dcol[tlen]; + } + + + /** + * Returns the byte offset of an inner slice relative to an enclosing outer slice. + * + * Fails if `inner` is not a direct slice contained within self. + * + * # Example + * + * ~~~ {.rust} + * let string = "a\nb\nc"; + * let mut lines = ~[]; + * for string.line_iter().advance |line| { lines.push(line) } + * + * assert!(string.subslice_offset(lines[0]) == 0); // &"a" + * assert!(string.subslice_offset(lines[1]) == 2); // &"b" + * assert!(string.subslice_offset(lines[2]) == 4); // &"c" + * ~~~ + */ + #[inline] + fn subslice_offset(&self, inner: &str) -> uint { + do as_buf(*self) |a, a_len| { + do as_buf(inner) |b, b_len| { + let a_start: uint; + let a_end: uint; + let b_start: uint; + let b_end: uint; + unsafe { + a_start = cast::transmute(a); a_end = a_len + cast::transmute(a); + b_start = cast::transmute(b); b_end = b_len + cast::transmute(b); + } + assert!(a_start <= b_start); + assert!(b_end <= a_end); + b_start - a_start + } + } + } + } #[allow(missing_doc)] @@ -1973,7 +1925,7 @@ pub trait OwnedStr { impl OwnedStr for ~str { /// Appends a string slice to the back of a string, without overallocating - #[inline(always)] + #[inline] fn push_str_no_overallocate(&mut self, rhs: &str) { unsafe { let llen = self.len(); @@ -2126,7 +2078,7 @@ impl OwnedStr for ~str { * * s - A string * * n - The number of bytes to reserve space for */ - #[inline(always)] + #[inline] pub fn reserve(&mut self, n: uint) { unsafe { let v: *mut ~[u8] = cast::transmute(self); @@ -2154,7 +2106,7 @@ impl OwnedStr for ~str { * * s - A string * * n - The number of bytes to reserve space for */ - #[inline(always)] + #[inline] fn reserve_at_least(&mut self, n: uint) { self.reserve(uint::next_power_of_two(n + 1u) - 1u) } @@ -2179,7 +2131,7 @@ impl OwnedStr for ~str { } impl Clone for ~str { - #[inline(always)] + #[inline] fn clone(&self) -> ~str { to_owned(*self) } @@ -2250,6 +2202,22 @@ impl<'self> Iterator for StrBytesRevIterator<'self> { } } +// This works because every lifetime is a sub-lifetime of 'static +impl<'self> Zero for &'self str { + fn zero() -> &'self str { "" } + fn is_zero(&self) -> bool { self.is_empty() } +} + +impl Zero for ~str { + fn zero() -> ~str { ~"" } + fn is_zero(&self) -> bool { self.len() == 0 } +} + +impl Zero for @str { + fn zero() -> @str { @"" } + fn is_zero(&self) -> bool { self.len() == 0 } +} + #[cfg(test)] mod tests { use iterator::IteratorUtil; @@ -2280,10 +2248,10 @@ mod tests { #[test] fn test_le() { - assert!((le(&"", &""))); - assert!((le(&"", &"foo"))); - assert!((le(&"foo", &"foo"))); - assert!((!eq(&~"foo", &~"bar"))); + assert!("" <= ""); + assert!("" <= "foo"); + assert!("foo" <= "foo"); + assert!("foo" != ~"bar"); } #[test] @@ -3003,15 +2971,15 @@ mod tests { let a = "kernelsprite"; let b = a.slice(7, a.len()); let c = a.slice(0, a.len() - 6); - assert_eq!(subslice_offset(a, b), 7); - assert_eq!(subslice_offset(a, c), 0); + assert_eq!(a.subslice_offset(b), 7); + assert_eq!(a.subslice_offset(c), 0); let string = "a\nb\nc"; let mut lines = ~[]; for string.line_iter().advance |line| { lines.push(line) } - assert_eq!(subslice_offset(string, lines[0]), 0); - assert_eq!(subslice_offset(string, lines[1]), 2); - assert_eq!(subslice_offset(string, lines[2]), 4); + assert_eq!(string.subslice_offset(lines[0]), 0); + assert_eq!(string.subslice_offset(lines[1]), 2); + assert_eq!(string.subslice_offset(lines[2]), 4); } #[test] @@ -3019,7 +2987,7 @@ mod tests { fn test_subslice_offset_2() { let a = "alchemiter"; let b = "cruxtruder"; - subslice_offset(a, b); + a.subslice_offset(b); } #[test] @@ -3069,8 +3037,8 @@ mod tests { #[test] fn test_map() { - assert_eq!(~"", map("", |c| unsafe {libc::toupper(c as c_char)} as char)); - assert_eq!(~"YMCA", map("ymca", |c| unsafe {libc::toupper(c as c_char)} as char)); + assert_eq!(~"", "".map_chars(|c| unsafe {libc::toupper(c as c_char)} as char)); + assert_eq!(~"YMCA", "ymca".map_chars(|c| unsafe {libc::toupper(c as c_char)} as char)); } #[test] @@ -3114,10 +3082,10 @@ mod tests { for pairs.each |p| { let (s, u) = copy *p; - assert!(to_utf16(s) == u); + assert!(s.to_utf16() == u); assert!(from_utf16(u) == s); - assert!(from_utf16(to_utf16(s)) == s); - assert!(to_utf16(from_utf16(u)) == u); + assert!(from_utf16(s.to_utf16()) == s); + assert!(from_utf16(u).to_utf16() == u); } } @@ -3188,6 +3156,24 @@ mod tests { assert_eq!("abc".char_range_at_reverse(0).next, 0); } + #[test] + fn test_add() { + macro_rules! t ( + ($s1:expr, $s2:expr, $e:expr) => { + assert_eq!($s1 + $s2, $e); + assert_eq!($s1.to_owned() + $s2, $e); + assert_eq!($s1.to_managed() + $s2, $e); + } + ); + + t!("foo", "bar", ~"foobar"); + t!("foo", @"bar", ~"foobar"); + t!("foo", ~"bar", ~"foobar"); + t!("ศไทย中", "华Việt Nam", ~"ศไทย中华Việt Nam"); + t!("ศไทย中", @"华Việt Nam", ~"ศไทย中华Việt Nam"); + t!("ศไทย中", ~"华Việt Nam", ~"ศไทย中华Việt Nam"); + } + #[test] fn test_iterator() { use iterator::*; @@ -3337,4 +3323,18 @@ mod tests { t("zzz", "zz", ~["","z"]); t("zzzzz", "zz", ~["","","z"]); } + + #[test] + fn test_str_zero() { + use num::Zero; + fn t() { + let s: S = Zero::zero(); + assert_eq!(s.as_slice(), ""); + assert!(s.is_zero()); + } + + t::<&str>(); + t::<@str>(); + t::<~str>(); + } } diff --git a/src/libstd/str/ascii.rs b/src/libstd/str/ascii.rs index 618d5095777a..c71765f911af 100644 --- a/src/libstd/str/ascii.rs +++ b/src/libstd/str/ascii.rs @@ -17,26 +17,27 @@ use cast; use old_iter::BaseIter; use iterator::IteratorUtil; use vec::{CopyableVector, ImmutableVector, OwnedVector}; +use to_bytes::IterBytes; -/// Datatype to hold one ascii character. It is 8 bit long. +/// Datatype to hold one ascii character. It wraps a `u8`, with the highest bit always zero. #[deriving(Clone, Eq)] pub struct Ascii { priv chr: u8 } impl Ascii { /// Converts a ascii character into a `u8`. - #[inline(always)] + #[inline] pub fn to_byte(self) -> u8 { self.chr } /// Converts a ascii character into a `char`. - #[inline(always)] + #[inline] pub fn to_char(self) -> char { self.chr as char } /// Convert to lowercase. - #[inline(always)] + #[inline] pub fn to_lower(self) -> Ascii { if self.chr >= 65 && self.chr <= 90 { Ascii{chr: self.chr | 0x20 } @@ -46,7 +47,7 @@ impl Ascii { } /// Convert to uppercase. - #[inline(always)] + #[inline] pub fn to_upper(self) -> Ascii { if self.chr >= 97 && self.chr <= 122 { Ascii{chr: self.chr & !0x20 } @@ -56,14 +57,14 @@ impl Ascii { } /// Compares two ascii characters of equality, ignoring case. - #[inline(always)] + #[inline] pub fn eq_ignore_case(self, other: Ascii) -> bool { self.to_lower().chr == other.to_lower().chr } } impl ToStr for Ascii { - #[inline(always)] + #[inline] fn to_str(&self) -> ~str { str::from_bytes(['\'' as u8, self.chr, '\'' as u8]) } } @@ -72,18 +73,26 @@ pub trait AsciiCast { /// Convert to an ascii type fn to_ascii(&self) -> T; + /// Convert to an ascii type, not doing any range asserts + unsafe fn to_ascii_nocheck(&self) -> T; + /// Check if convertible to ascii fn is_ascii(&self) -> bool; } impl<'self> AsciiCast<&'self[Ascii]> for &'self [u8] { - #[inline(always)] + #[inline] fn to_ascii(&self) -> &'self[Ascii] { assert!(self.is_ascii()); - unsafe{ cast::transmute(*self) } + unsafe {self.to_ascii_nocheck()} } - #[inline(always)] + #[inline] + unsafe fn to_ascii_nocheck(&self) -> &'self[Ascii] { + cast::transmute(*self) + } + + #[inline] fn is_ascii(&self) -> bool { for self.each |b| { if !b.is_ascii() { return false; } @@ -93,40 +102,55 @@ impl<'self> AsciiCast<&'self[Ascii]> for &'self [u8] { } impl<'self> AsciiCast<&'self[Ascii]> for &'self str { - #[inline(always)] + #[inline] fn to_ascii(&self) -> &'self[Ascii] { assert!(self.is_ascii()); - let (p,len): (*u8, uint) = unsafe{ cast::transmute(*self) }; - unsafe{ cast::transmute((p, len - 1))} + unsafe {self.to_ascii_nocheck()} } - #[inline(always)] + #[inline] + unsafe fn to_ascii_nocheck(&self) -> &'self[Ascii] { + let (p,len): (*u8, uint) = cast::transmute(*self); + cast::transmute((p, len - 1)) + } + + #[inline] fn is_ascii(&self) -> bool { self.bytes_iter().all(|b| b.is_ascii()) } } impl AsciiCast for u8 { - #[inline(always)] + #[inline] fn to_ascii(&self) -> Ascii { assert!(self.is_ascii()); + unsafe {self.to_ascii_nocheck()} + } + + #[inline] + unsafe fn to_ascii_nocheck(&self) -> Ascii { Ascii{ chr: *self } } - #[inline(always)] + #[inline] fn is_ascii(&self) -> bool { *self & 128 == 0u8 } } impl AsciiCast for char { - #[inline(always)] + #[inline] fn to_ascii(&self) -> Ascii { assert!(self.is_ascii()); + unsafe {self.to_ascii_nocheck()} + } + + #[inline] + unsafe fn to_ascii_nocheck(&self) -> Ascii { Ascii{ chr: *self as u8 } } - #[inline(always)] + #[inline] fn is_ascii(&self) -> bool { *self - ('\x7F' & *self) == '\x00' } @@ -135,26 +159,38 @@ impl AsciiCast for char { /// Trait for copyless casting to an ascii vector. pub trait OwnedAsciiCast { /// Take ownership and cast to an ascii vector without trailing zero element. - fn to_ascii_consume(self) -> ~[Ascii]; + fn into_ascii(self) -> ~[Ascii]; + + /// Take ownership and cast to an ascii vector without trailing zero element. + /// Does not perform validation checks. + unsafe fn into_ascii_nocheck(self) -> ~[Ascii]; } impl OwnedAsciiCast for ~[u8] { - #[inline(always)] - fn to_ascii_consume(self) -> ~[Ascii] { + #[inline] + fn into_ascii(self) -> ~[Ascii] { assert!(self.is_ascii()); - unsafe {cast::transmute(self)} + unsafe {self.into_ascii_nocheck()} + } + + #[inline] + unsafe fn into_ascii_nocheck(self) -> ~[Ascii] { + cast::transmute(self) } } impl OwnedAsciiCast for ~str { - #[inline(always)] - fn to_ascii_consume(self) -> ~[Ascii] { + #[inline] + fn into_ascii(self) -> ~[Ascii] { assert!(self.is_ascii()); - let mut s = self; - unsafe { - str::raw::pop_byte(&mut s); - cast::transmute(s) - } + unsafe {self.into_ascii_nocheck()} + } + + #[inline] + unsafe fn into_ascii_nocheck(self) -> ~[Ascii] { + let mut r: ~[Ascii] = cast::transmute(self); + r.pop(); + r } } @@ -169,39 +205,66 @@ pub trait AsciiStr { /// Convert to vector representing a upper cased ascii string. fn to_upper(&self) -> ~[Ascii]; + /// Compares two Ascii strings ignoring case + fn eq_ignore_case(self, other: &[Ascii]) -> bool; } impl<'self> AsciiStr for &'self [Ascii] { - #[inline(always)] + #[inline] fn to_str_ascii(&self) -> ~str { let mut cpy = self.to_owned(); cpy.push(0u8.to_ascii()); unsafe {cast::transmute(cpy)} } - #[inline(always)] + #[inline] fn to_lower(&self) -> ~[Ascii] { self.map(|a| a.to_lower()) } - #[inline(always)] + #[inline] fn to_upper(&self) -> ~[Ascii] { self.map(|a| a.to_upper()) } + + #[inline] + fn eq_ignore_case(self, other: &[Ascii]) -> bool { + do self.iter().zip(other.iter()).all |(&a, &b)| { a.eq_ignore_case(b) } + } } impl ToStrConsume for ~[Ascii] { - #[inline(always)] - fn to_str_consume(self) -> ~str { + #[inline] + fn into_str(self) -> ~str { let mut cpy = self; cpy.push(0u8.to_ascii()); unsafe {cast::transmute(cpy)} } } +impl IterBytes for Ascii { + #[inline] + fn iter_bytes(&self, _lsb0: bool, f: &fn(buf: &[u8]) -> bool) -> bool { + f([self.to_byte()]) + } +} + +/// Trait to convert to a owned byte array by consuming self +pub trait ToBytesConsume { + /// Converts to a owned byte array by consuming self + fn into_bytes(self) -> ~[u8]; +} + +impl ToBytesConsume for ~[Ascii] { + fn into_bytes(self) -> ~[u8] { + unsafe {cast::transmute(self)} + } +} + #[cfg(test)] mod tests { use super::*; + use to_bytes::ToBytes; macro_rules! v2ascii ( ( [$($e:expr),*]) => ( [$(Ascii{chr:$e}),*]); @@ -245,6 +308,8 @@ mod tests { assert_eq!("YMCA".to_ascii().to_lower().to_str_ascii(), ~"ymca"); assert_eq!("abcDEFxyz:.;".to_ascii().to_upper().to_str_ascii(), ~"ABCDEFXYZ:.;"); + assert!("aBcDeF&?#".to_ascii().eq_ignore_case("AbCdEf&?#".to_ascii())); + assert!("".is_ascii()); assert!("a".is_ascii()); assert!(!"\u2009".is_ascii()); @@ -253,21 +318,22 @@ mod tests { #[test] fn test_owned_ascii_vec() { - // FIXME: #4318 Compiler crashes on moving self - //assert_eq!(~"( ;".to_ascii_consume(), v2ascii!(~[40, 32, 59])); - //assert_eq!(~[40u8, 32u8, 59u8].to_ascii_consume(), v2ascii!(~[40, 32, 59])); - //assert_eq!(~"( ;".to_ascii_consume_with_null(), v2ascii!(~[40, 32, 59, 0])); - //assert_eq!(~[40u8, 32u8, 59u8].to_ascii_consume_with_null(), - // v2ascii!(~[40, 32, 59, 0])); + assert_eq!((~"( ;").into_ascii(), v2ascii!(~[40, 32, 59])); + assert_eq!((~[40u8, 32u8, 59u8]).into_ascii(), v2ascii!(~[40, 32, 59])); } #[test] fn test_ascii_to_str() { assert_eq!(v2ascii!([40, 32, 59]).to_str_ascii(), ~"( ;"); } #[test] - fn test_ascii_to_str_consume() { - // FIXME: #4318 Compiler crashes on moving self - //assert_eq!(v2ascii!(~[40, 32, 59]).to_str_consume(), ~"( ;"); + fn test_ascii_into_str() { + assert_eq!(v2ascii!(~[40, 32, 59]).into_str(), ~"( ;"); + } + + #[test] + fn test_ascii_to_bytes() { + assert_eq!(v2ascii!(~[40, 32, 59]).to_bytes(false), ~[40u8, 32u8, 59u8]); + assert_eq!(v2ascii!(~[40, 32, 59]).into_bytes(), ~[40u8, 32u8, 59u8]); } #[test] #[should_fail] diff --git a/src/libstd/sys.rs b/src/libstd/sys.rs index e49ad3485420..523c5d633cf4 100644 --- a/src/libstd/sys.rs +++ b/src/libstd/sys.rs @@ -57,25 +57,25 @@ pub mod rustrt { * Useful for calling certain function in the Rust runtime or otherwise * performing dark magick. */ -#[inline(always)] +#[inline] pub fn get_type_desc() -> *TypeDesc { unsafe { intrinsics::get_tydesc::() as *TypeDesc } } /// Returns a pointer to a type descriptor. -#[inline(always)] +#[inline] pub fn get_type_desc_val(_val: &T) -> *TypeDesc { get_type_desc::() } /// Returns the size of a type -#[inline(always)] +#[inline] pub fn size_of() -> uint { unsafe { intrinsics::size_of::() } } /// Returns the size of the type that `_val` points to -#[inline(always)] +#[inline] pub fn size_of_val(_val: &T) -> uint { size_of::() } @@ -85,14 +85,14 @@ pub fn size_of_val(_val: &T) -> uint { * * Useful for building structures containing variable-length arrays. */ -#[inline(always)] +#[inline] pub fn nonzero_size_of() -> uint { let s = size_of::(); if s == 0 { 1 } else { s } } /// Returns the size of the type of the value that `_val` points to -#[inline(always)] +#[inline] pub fn nonzero_size_of_val(_val: &T) -> uint { nonzero_size_of::() } @@ -104,33 +104,33 @@ pub fn nonzero_size_of_val(_val: &T) -> uint { * This is the alignment used for struct fields. It may be smaller * than the preferred alignment. */ -#[inline(always)] +#[inline] pub fn min_align_of() -> uint { unsafe { intrinsics::min_align_of::() } } /// Returns the ABI-required minimum alignment of the type of the value that /// `_val` points to -#[inline(always)] +#[inline] pub fn min_align_of_val(_val: &T) -> uint { min_align_of::() } /// Returns the preferred alignment of a type -#[inline(always)] +#[inline] pub fn pref_align_of() -> uint { unsafe { intrinsics::pref_align_of::() } } /// Returns the preferred alignment of the type of the value that /// `_val` points to -#[inline(always)] +#[inline] pub fn pref_align_of_val(_val: &T) -> uint { pref_align_of::() } /// Returns the refcount of a shared box (as just before calling this) -#[inline(always)] +#[inline] pub fn refcount(t: @T) -> uint { unsafe { let ref_ptr: *uint = cast::transmute_copy(&t); @@ -180,10 +180,13 @@ impl FailWithCause for &'static str { // FIXME #4427: Temporary until rt::rt_fail_ goes away pub fn begin_unwind_(msg: *c_char, file: *c_char, line: size_t) -> ! { + use cell::Cell; use option::Option; + use either::Left; use rt::{context, OldTaskContext, TaskContext}; use rt::task::{Task, Unwinder}; use rt::local::Local; + use rt::logging::Logger; let context = context(); match context { @@ -200,19 +203,28 @@ pub fn begin_unwind_(msg: *c_char, file: *c_char, line: size_t) -> ! { let msg = str::raw::from_c_str(msg); let file = str::raw::from_c_str(file); - let outmsg = fmt!("%s at line %i of file %s", msg, line as int, file); + let outmsg = fmt!("task failed: '%s' at line %i of file %s", + msg, line as int, file); // XXX: Logging doesn't work correctly in non-task context because it // invokes the local heap if context == TaskContext { - error!(outmsg); + // XXX: Logging doesn't work here - the check to call the log + // function never passes - so calling the log function directly. + let outmsg = Cell::new(outmsg); + do Local::borrow:: |task| { + task.logger.log(Left(outmsg.take())); + } } else { - rtdebug!("%s", outmsg); + rterrln!("%s", outmsg); } gc::cleanup_stack_for_failure(); let task = Local::unsafe_borrow::(); + if (*task).unwinder.unwinding { + rtabort!("unwinding again"); + } (*task).unwinder.begin_unwind(); } } diff --git a/src/libstd/task/spawn.rs b/src/libstd/task/spawn.rs index 9df93d19d216..63eb768d1c9c 100644 --- a/src/libstd/task/spawn.rs +++ b/src/libstd/task/spawn.rs @@ -79,7 +79,6 @@ use cast; use cell::Cell; use container::Map; use comm::{Chan, GenericChan}; -use ptr; use hashmap::HashSet; use task::local_data_priv::{local_get, local_set, OldHandle}; use task::rt::rust_task; @@ -99,10 +98,6 @@ use rt::task::Task; #[cfg(test)] use comm; #[cfg(test)] use task; -macro_rules! move_it ( - { $x:expr } => ( unsafe { let y = *ptr::to_unsafe_ptr(&($x)); y } ) -) - type TaskSet = HashSet<*rust_task>; fn new_taskset() -> TaskSet { @@ -162,14 +157,14 @@ struct AncestorNode { struct AncestorList(Option>); // Accessors for taskgroup arcs and ancestor arcs that wrap the unsafety. -#[inline(always)] +#[inline] fn access_group(x: &TaskGroupArc, blk: &fn(TaskGroupInner) -> U) -> U { unsafe { x.with(blk) } } -#[inline(always)] +#[inline] fn access_ancestors(x: &Exclusive, blk: &fn(x: &mut AncestorNode) -> U) -> U { unsafe { @@ -583,13 +578,29 @@ pub fn spawn_raw(opts: TaskOpts, f: ~fn()) { } } -fn spawn_raw_newsched(_opts: TaskOpts, f: ~fn()) { +fn spawn_raw_newsched(mut opts: TaskOpts, f: ~fn()) { use rt::sched::*; - let task = do Local::borrow::() |running_task| { - ~running_task.new_child() + let mut task = if opts.linked { + do Local::borrow::() |running_task| { + ~running_task.new_child() + } + } else { + // An unlinked task is a new root in the task tree + ~Task::new_root() }; + if opts.notify_chan.is_some() { + let notify_chan = opts.notify_chan.swap_unwrap(); + let notify_chan = Cell::new(notify_chan); + let on_exit: ~fn(bool) = |success| { + notify_chan.take().send( + if success { Success } else { Failure } + ) + }; + task.on_exit = Some(on_exit); + } + let mut sched = Local::take::(); let task = ~Coroutine::with_task(&mut sched.stack_pool, task, f); @@ -644,23 +655,16 @@ fn spawn_raw_oldsched(mut opts: TaskOpts, f: ~fn()) { notify_chan: Option>, f: ~fn()) -> ~fn() { - let child_data = Cell::new((child_arc, ancestors)); + let child_data = Cell::new((notify_chan, child_arc, ancestors)); let result: ~fn() = || { // Agh. Get move-mode items into the closure. FIXME (#2829) - let mut (child_arc, ancestors) = child_data.take(); + let mut (notify_chan, child_arc, ancestors) = child_data.take(); // Child task runs this code. // Even if the below code fails to kick the child off, we must // send Something on the notify channel. - //let mut notifier = None;//notify_chan.map(|c| AutoNotify(c)); - let notifier = match notify_chan { - Some(ref notify_chan_value) => { - let moved_ncv = move_it!(*notify_chan_value); - Some(AutoNotify(moved_ncv)) - } - _ => None - }; + let notifier = notify_chan.map_consume(|c| AutoNotify(c)); if enlist_many(child, &child_arc, &mut ancestors) { let group = @@mut TCB(child, diff --git a/src/libstd/to_bytes.rs b/src/libstd/to_bytes.rs index c0c8b729f9ea..822aab0a0271 100644 --- a/src/libstd/to_bytes.rs +++ b/src/libstd/to_bytes.rs @@ -14,6 +14,7 @@ The `ToBytes` and `IterBytes` traits */ +use cast; use io; use io::Writer; use option::{None, Option, Some}; @@ -48,7 +49,7 @@ pub trait IterBytes { } impl IterBytes for bool { - #[inline(always)] + #[inline] fn iter_bytes(&self, _lsb0: bool, f: Cb) -> bool { f([ *self as u8 @@ -57,7 +58,7 @@ impl IterBytes for bool { } impl IterBytes for u8 { - #[inline(always)] + #[inline] fn iter_bytes(&self, _lsb0: bool, f: Cb) -> bool { f([ *self @@ -66,7 +67,7 @@ impl IterBytes for u8 { } impl IterBytes for u16 { - #[inline(always)] + #[inline] fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { if lsb0 { f([ @@ -83,7 +84,7 @@ impl IterBytes for u16 { } impl IterBytes for u32 { - #[inline(always)] + #[inline] fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { if lsb0 { f([ @@ -104,7 +105,7 @@ impl IterBytes for u32 { } impl IterBytes for u64 { - #[inline(always)] + #[inline] fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { if lsb0 { f([ @@ -133,35 +134,35 @@ impl IterBytes for u64 { } impl IterBytes for i8 { - #[inline(always)] + #[inline] fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { (*self as u8).iter_bytes(lsb0, f) } } impl IterBytes for i16 { - #[inline(always)] + #[inline] fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { (*self as u16).iter_bytes(lsb0, f) } } impl IterBytes for i32 { - #[inline(always)] + #[inline] fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { (*self as u32).iter_bytes(lsb0, f) } } impl IterBytes for i64 { - #[inline(always)] + #[inline] fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { (*self as u64).iter_bytes(lsb0, f) } } impl IterBytes for char { - #[inline(always)] + #[inline] fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { (*self as u32).iter_bytes(lsb0, f) } @@ -169,7 +170,7 @@ impl IterBytes for char { #[cfg(target_word_size = "32")] impl IterBytes for uint { - #[inline(always)] + #[inline] fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { (*self as u32).iter_bytes(lsb0, f) } @@ -177,28 +178,57 @@ impl IterBytes for uint { #[cfg(target_word_size = "64")] impl IterBytes for uint { - #[inline(always)] + #[inline] fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { (*self as u64).iter_bytes(lsb0, f) } } impl IterBytes for int { - #[inline(always)] + #[inline] fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { (*self as uint).iter_bytes(lsb0, f) } } +impl IterBytes for float { + #[inline] + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { + (*self as f64).iter_bytes(lsb0, f) + } +} + +impl IterBytes for f32 { + #[inline] + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { + let i: u32 = unsafe { + // 0.0 == -0.0 so they should also have the same hashcode + cast::transmute(if *self == -0.0 { 0.0 } else { *self }) + }; + i.iter_bytes(lsb0, f) + } +} + +impl IterBytes for f64 { + #[inline] + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { + let i: u64 = unsafe { + // 0.0 == -0.0 so they should also have the same hashcode + cast::transmute(if *self == -0.0 { 0.0 } else { *self }) + }; + i.iter_bytes(lsb0, f) + } +} + impl<'self,A:IterBytes> IterBytes for &'self [A] { - #[inline(always)] + #[inline] fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { self.each(|elt| elt.iter_bytes(lsb0, |b| f(b))) } } impl IterBytes for (A,B) { - #[inline(always)] + #[inline] fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { match *self { (ref a, ref b) => { a.iter_bytes(lsb0, f) && b.iter_bytes(lsb0, f) } @@ -207,7 +237,7 @@ impl IterBytes for (A,B) { } impl IterBytes for (A,B,C) { - #[inline(always)] + #[inline] fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { match *self { (ref a, ref b, ref c) => { @@ -223,28 +253,28 @@ fn borrow<'x,A>(a: &'x [A]) -> &'x [A] { } impl IterBytes for ~[A] { - #[inline(always)] + #[inline] fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { borrow(*self).iter_bytes(lsb0, f) } } impl IterBytes for @[A] { - #[inline(always)] + #[inline] fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { borrow(*self).iter_bytes(lsb0, f) } } impl<'self> IterBytes for &'self str { - #[inline(always)] + #[inline] fn iter_bytes(&self, _lsb0: bool, f: Cb) -> bool { f(self.as_bytes()) } } impl IterBytes for ~str { - #[inline(always)] + #[inline] fn iter_bytes(&self, _lsb0: bool, f: Cb) -> bool { // this should possibly include the null terminator, but that // breaks .find_equiv on hashmaps. @@ -253,7 +283,7 @@ impl IterBytes for ~str { } impl IterBytes for @str { - #[inline(always)] + #[inline] fn iter_bytes(&self, _lsb0: bool, f: Cb) -> bool { // this should possibly include the null terminator, but that // breaks .find_equiv on hashmaps. @@ -262,7 +292,7 @@ impl IterBytes for @str { } impl IterBytes for Option { - #[inline(always)] + #[inline] fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { match *self { Some(ref a) => 0u8.iter_bytes(lsb0, f) && a.iter_bytes(lsb0, f), @@ -272,21 +302,21 @@ impl IterBytes for Option { } impl<'self,A:IterBytes> IterBytes for &'self A { - #[inline(always)] + #[inline] fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { (**self).iter_bytes(lsb0, f) } } impl IterBytes for @A { - #[inline(always)] + #[inline] fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { (**self).iter_bytes(lsb0, f) } } impl IterBytes for ~A { - #[inline(always)] + #[inline] fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { (**self).iter_bytes(lsb0, f) } @@ -295,7 +325,7 @@ impl IterBytes for ~A { // NB: raw-pointer IterBytes does _not_ dereference // to the target; it just gives you the pointer-bytes. impl IterBytes for *const A { - #[inline(always)] + #[inline] fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { (*self as uint).iter_bytes(lsb0, f) } diff --git a/src/libstd/to_str.rs b/src/libstd/to_str.rs index bfda92d46a28..3e782e728fe3 100644 --- a/src/libstd/to_str.rs +++ b/src/libstd/to_str.rs @@ -31,16 +31,16 @@ pub trait ToStr { /// Trait for converting a type to a string, consuming it in the process. pub trait ToStrConsume { /// Cosume and convert to a string. - fn to_str_consume(self) -> ~str; + fn into_str(self) -> ~str; } impl ToStr for () { - #[inline(always)] + #[inline] fn to_str(&self) -> ~str { ~"()" } } impl ToStr for (A,) { - #[inline(always)] + #[inline] fn to_str(&self) -> ~str { match *self { (ref a,) => { @@ -51,7 +51,7 @@ impl ToStr for (A,) { } impl ToStr for HashMap { - #[inline(always)] + #[inline] fn to_str(&self) -> ~str { let mut (acc, first) = (~"{", true); for self.each |key, value| { @@ -71,7 +71,7 @@ impl ToStr for HashMap { } impl ToStr for HashSet { - #[inline(always)] + #[inline] fn to_str(&self) -> ~str { let mut (acc, first) = (~"{", true); for self.each |element| { @@ -89,7 +89,7 @@ impl ToStr for HashSet { } impl ToStr for (A, B) { - #[inline(always)] + #[inline] fn to_str(&self) -> ~str { // FIXME(#4653): this causes an llvm assertion //let &(ref a, ref b) = self; @@ -102,7 +102,7 @@ impl ToStr for (A, B) { } impl ToStr for (A, B, C) { - #[inline(always)] + #[inline] fn to_str(&self) -> ~str { // FIXME(#4653): this causes an llvm assertion //let &(ref a, ref b, ref c) = self; @@ -119,7 +119,7 @@ impl ToStr for (A, B, C) { } impl<'self,A:ToStr> ToStr for &'self [A] { - #[inline(always)] + #[inline] fn to_str(&self) -> ~str { let mut (acc, first) = (~"[", true); for self.each |elt| { @@ -137,7 +137,7 @@ impl<'self,A:ToStr> ToStr for &'self [A] { } impl ToStr for ~[A] { - #[inline(always)] + #[inline] fn to_str(&self) -> ~str { let mut (acc, first) = (~"[", true); for self.each |elt| { @@ -155,7 +155,7 @@ impl ToStr for ~[A] { } impl ToStr for @[A] { - #[inline(always)] + #[inline] fn to_str(&self) -> ~str { let mut (acc, first) = (~"[", true); for self.each |elt| { diff --git a/src/libstd/trie.rs b/src/libstd/trie.rs index 4bd3946f885f..aaeaa489834f 100644 --- a/src/libstd/trie.rs +++ b/src/libstd/trie.rs @@ -34,17 +34,17 @@ pub struct TrieMap { impl Container for TrieMap { /// Return the number of elements in the map - #[inline(always)] + #[inline] fn len(&const self) -> uint { self.length } /// Return true if the map contains no elements - #[inline(always)] + #[inline] fn is_empty(&const self) -> bool { self.len() == 0 } } impl Mutable for TrieMap { /// Clear the map, removing all values. - #[inline(always)] + #[inline] fn clear(&mut self) { self.root = TrieNode::new(); self.length = 0; @@ -53,37 +53,37 @@ impl Mutable for TrieMap { impl Map for TrieMap { /// Return true if the map contains a value for the specified key - #[inline(always)] + #[inline] fn contains_key(&self, key: &uint) -> bool { self.find(key).is_some() } /// Visit all key-value pairs in order - #[inline(always)] + #[inline] fn each<'a>(&'a self, f: &fn(&uint, &'a T) -> bool) -> bool { self.root.each(f) } /// Visit all keys in order - #[inline(always)] + #[inline] fn each_key(&self, f: &fn(&uint) -> bool) -> bool { self.each(|k, _| f(k)) } /// Visit all values in order - #[inline(always)] + #[inline] fn each_value<'a>(&'a self, f: &fn(&'a T) -> bool) -> bool { self.each(|_, v| f(v)) } /// Iterate over the map and mutate the contained values - #[inline(always)] + #[inline] fn mutate_values(&mut self, f: &fn(&uint, &mut T) -> bool) -> bool { self.root.mutate_values(f) } /// Return a reference to the value corresponding to the key - #[inline(hint)] + #[inline] fn find<'a>(&'a self, key: &uint) -> Option<&'a T> { let mut node: &'a TrieNode = &self.root; let mut idx = 0; @@ -104,7 +104,7 @@ impl Map for TrieMap { } /// Return a mutable reference to the value corresponding to the key - #[inline(always)] + #[inline] fn find_mut<'a>(&'a mut self, key: &uint) -> Option<&'a mut T> { find_mut(&mut self.root.children[chunk(*key, 0)], *key, 1) } @@ -112,14 +112,14 @@ impl Map for TrieMap { /// Insert a key-value pair into the map. An existing value for a /// key is replaced by the new value. Return true if the key did /// not already exist in the map. - #[inline(always)] + #[inline] fn insert(&mut self, key: uint, value: T) -> bool { self.swap(key, value).is_none() } /// Remove a key-value pair from the map. Return true if the key /// was present in the map, otherwise false. - #[inline(always)] + #[inline] fn remove(&mut self, key: &uint) -> bool { self.pop(key).is_some() } @@ -147,25 +147,25 @@ impl Map for TrieMap { impl TrieMap { /// Create an empty TrieMap - #[inline(always)] + #[inline] pub fn new() -> TrieMap { TrieMap{root: TrieNode::new(), length: 0} } /// Visit all key-value pairs in reverse order - #[inline(always)] + #[inline] pub fn each_reverse<'a>(&'a self, f: &fn(&uint, &'a T) -> bool) -> bool { self.root.each_reverse(f) } /// Visit all keys in reverse order - #[inline(always)] + #[inline] pub fn each_key_reverse(&self, f: &fn(&uint) -> bool) -> bool { self.each_reverse(|k, _| f(k)) } /// Visit all values in reverse order - #[inline(always)] + #[inline] pub fn each_value_reverse(&self, f: &fn(&T) -> bool) -> bool { self.each_reverse(|_, v| f(v)) } @@ -178,15 +178,15 @@ pub struct TrieSet { impl BaseIter for TrieSet { /// Visit all values in order - #[inline(always)] + #[inline] fn each(&self, f: &fn(&uint) -> bool) -> bool { self.map.each_key(f) } - #[inline(always)] + #[inline] fn size_hint(&self) -> Option { Some(self.len()) } } impl ReverseIter for TrieSet { /// Visit all values in reverse order - #[inline(always)] + #[inline] fn each_reverse(&self, f: &fn(&uint) -> bool) -> bool { self.map.each_key_reverse(f) } @@ -194,43 +194,43 @@ impl ReverseIter for TrieSet { impl Container for TrieSet { /// Return the number of elements in the set - #[inline(always)] + #[inline] fn len(&const self) -> uint { self.map.len() } /// Return true if the set contains no elements - #[inline(always)] + #[inline] fn is_empty(&const self) -> bool { self.map.is_empty() } } impl Mutable for TrieSet { /// Clear the set, removing all values. - #[inline(always)] + #[inline] fn clear(&mut self) { self.map.clear() } } impl TrieSet { /// Create an empty TrieSet - #[inline(always)] + #[inline] pub fn new() -> TrieSet { TrieSet{map: TrieMap::new()} } /// Return true if the set contains a value - #[inline(always)] + #[inline] pub fn contains(&self, value: &uint) -> bool { self.map.contains_key(value) } /// Add a value to the set. Return true if the value was not already /// present in the set. - #[inline(always)] + #[inline] pub fn insert(&mut self, value: uint) -> bool { self.map.insert(value, ()) } /// Remove a value from the set. Return true if the value was /// present in the set. - #[inline(always)] + #[inline] pub fn remove(&mut self, value: &uint) -> bool { self.map.remove(value) } @@ -242,7 +242,7 @@ struct TrieNode { } impl TrieNode { - #[inline(always)] + #[inline] fn new() -> TrieNode { // FIXME: #5244: [Nothing, ..SIZE] should be possible without Copy TrieNode{count: 0, @@ -291,7 +291,7 @@ impl TrieNode { } // if this was done via a trait, the key could be generic -#[inline(always)] +#[inline] fn chunk(n: uint, idx: uint) -> uint { let sh = uint::bits - (SHIFT * (idx + 1)); (n >> sh) & MASK diff --git a/src/libstd/tuple.rs b/src/libstd/tuple.rs index 589c18de0abf..fefd55c35415 100644 --- a/src/libstd/tuple.rs +++ b/src/libstd/tuple.rs @@ -29,25 +29,25 @@ pub trait CopyableTuple { impl CopyableTuple for (T, U) { /// Return the first element of self - #[inline(always)] + #[inline] fn first(&self) -> T { match *self { - (t, _) => t, + (ref t, _) => copy *t, } } /// Return the second element of self - #[inline(always)] + #[inline] fn second(&self) -> U { match *self { - (_, u) => u, + (_, ref u) => copy *u, } } /// Return the results of swapping the two elements of self - #[inline(always)] + #[inline] fn swap(&self) -> (U, T) { - match *self { + match copy *self { (t, u) => (u, t), } } @@ -63,13 +63,13 @@ pub trait ImmutableTuple { } impl ImmutableTuple for (T, U) { - #[inline(always)] + #[inline] fn first_ref<'a>(&'a self) -> &'a T { match *self { (ref t, _) => t, } } - #[inline(always)] + #[inline] fn second_ref<'a>(&'a self) -> &'a U { match *self { (_, ref u) => u, @@ -83,7 +83,7 @@ pub trait ExtendedTupleOps { } impl<'self,A:Copy,B:Copy> ExtendedTupleOps for (&'self [A], &'self [B]) { - #[inline(always)] + #[inline] fn zip(&self) -> ~[(A, B)] { match *self { (ref a, ref b) => { @@ -92,7 +92,7 @@ impl<'self,A:Copy,B:Copy> ExtendedTupleOps for (&'self [A], &'self [B]) { } } - #[inline(always)] + #[inline] fn map(&self, f: &fn(a: &A, b: &B) -> C) -> ~[C] { match *self { (ref a, ref b) => { @@ -103,7 +103,7 @@ impl<'self,A:Copy,B:Copy> ExtendedTupleOps for (&'self [A], &'self [B]) { } impl ExtendedTupleOps for (~[A], ~[B]) { - #[inline(always)] + #[inline] fn zip(&self) -> ~[(A, B)] { match *self { (ref a, ref b) => { @@ -112,7 +112,7 @@ impl ExtendedTupleOps for (~[A], ~[B]) { } } - #[inline(always)] + #[inline] fn map(&self, f: &fn(a: &A, b: &B) -> C) -> ~[C] { match *self { (ref a, ref b) => { @@ -135,6 +135,7 @@ macro_rules! tuple_impls { pub mod inner { use clone::Clone; #[cfg(not(test))] use cmp::*; + #[cfg(not(test))] use num::Zero; $( pub trait $cloneable_trait<$($T),+> { @@ -143,7 +144,7 @@ macro_rules! tuple_impls { impl<$($T:Clone),+> $cloneable_trait<$($T),+> for ($($T),+) { $( - #[inline(always)] + #[inline] fn $get_fn(&self) -> $T { self.$get_ref_fn().clone() } @@ -156,7 +157,7 @@ macro_rules! tuple_impls { impl<$($T),+> $immutable_trait<$($T),+> for ($($T),+) { $( - #[inline(always)] + #[inline] fn $get_ref_fn<'a>(&'a self) -> &'a $T { match *self { $get_pattern => $ret } } @@ -171,11 +172,11 @@ macro_rules! tuple_impls { #[cfg(not(test))] impl<$($T:Eq),+> Eq for ($($T),+) { - #[inline(always)] + #[inline] fn eq(&self, other: &($($T),+)) -> bool { $(*self.$get_ref_fn() == *other.$get_ref_fn())&&+ } - #[inline(always)] + #[inline] fn ne(&self, other: &($($T),+)) -> bool { !(*self == *other) } @@ -183,7 +184,7 @@ macro_rules! tuple_impls { #[cfg(not(test))] impl<$($T:TotalEq),+> TotalEq for ($($T),+) { - #[inline(always)] + #[inline] fn equals(&self, other: &($($T),+)) -> bool { $(self.$get_ref_fn().equals(other.$get_ref_fn()))&&+ } @@ -191,15 +192,15 @@ macro_rules! tuple_impls { #[cfg(not(test))] impl<$($T:Ord),+> Ord for ($($T),+) { - #[inline(always)] + #[inline] fn lt(&self, other: &($($T),+)) -> bool { lexical_lt!($(self.$get_ref_fn(), other.$get_ref_fn()),+) } - #[inline(always)] + #[inline] fn le(&self, other: &($($T),+)) -> bool { !(*other).lt(&(*self)) } - #[inline(always)] + #[inline] fn ge(&self, other: &($($T),+)) -> bool { !(*self).lt(other) } - #[inline(always)] + #[inline] fn gt(&self, other: &($($T),+)) -> bool { (*other).lt(&(*self)) } } @@ -210,6 +211,18 @@ macro_rules! tuple_impls { lexical_cmp!($(self.$get_ref_fn(), other.$get_ref_fn()),+) } } + + #[cfg(not(test))] + impl<$($T:Zero),+> Zero for ($($T),+) { + #[inline] + fn zero() -> ($($T),+) { + ($(Zero::zero::<$T>()),+) + } + #[inline] + fn is_zero(&self) -> bool { + $(self.$get_ref_fn().is_zero())&&+ + } + } )+ } } diff --git a/src/libstd/unstable/atomics.rs b/src/libstd/unstable/atomics.rs index aa70897ad486..6e7a7e2b129c 100644 --- a/src/libstd/unstable/atomics.rs +++ b/src/libstd/unstable/atomics.rs @@ -82,7 +82,7 @@ impl AtomicFlag { /** * Clears the atomic flag */ - #[inline(always)] + #[inline] pub fn clear(&mut self, order: Ordering) { unsafe {atomic_store(&mut self.v, 0, order)} } @@ -91,7 +91,7 @@ impl AtomicFlag { * Sets the flag if it was previously unset, returns the previous value of the * flag. */ - #[inline(always)] + #[inline] pub fn test_and_set(&mut self, order: Ordering) -> bool { unsafe {atomic_compare_and_swap(&mut self.v, 0, 1, order) > 0} } @@ -102,26 +102,26 @@ impl AtomicBool { AtomicBool { v: if v { 1 } else { 0 } } } - #[inline(always)] + #[inline] pub fn load(&self, order: Ordering) -> bool { unsafe { atomic_load(&self.v, order) > 0 } } - #[inline(always)] + #[inline] pub fn store(&mut self, val: bool, order: Ordering) { let val = if val { 1 } else { 0 }; unsafe { atomic_store(&mut self.v, val, order); } } - #[inline(always)] + #[inline] pub fn swap(&mut self, val: bool, order: Ordering) -> bool { let val = if val { 1 } else { 0 }; unsafe { atomic_swap(&mut self.v, val, order) > 0} } - #[inline(always)] + #[inline] pub fn compare_and_swap(&mut self, old: bool, new: bool, order: Ordering) -> bool { let old = if old { 1 } else { 0 }; let new = if new { 1 } else { 0 }; @@ -135,34 +135,34 @@ impl AtomicInt { AtomicInt { v:v } } - #[inline(always)] + #[inline] pub fn load(&self, order: Ordering) -> int { unsafe { atomic_load(&self.v, order) } } - #[inline(always)] + #[inline] pub fn store(&mut self, val: int, order: Ordering) { unsafe { atomic_store(&mut self.v, val, order); } } - #[inline(always)] + #[inline] pub fn swap(&mut self, val: int, order: Ordering) -> int { unsafe { atomic_swap(&mut self.v, val, order) } } - #[inline(always)] + #[inline] pub fn compare_and_swap(&mut self, old: int, new: int, order: Ordering) -> int { unsafe { atomic_compare_and_swap(&mut self.v, old, new, order) } } /// Returns the old value (like __sync_fetch_and_add). - #[inline(always)] + #[inline] pub fn fetch_add(&mut self, val: int, order: Ordering) -> int { unsafe { atomic_add(&mut self.v, val, order) } } /// Returns the old value (like __sync_fetch_and_sub). - #[inline(always)] + #[inline] pub fn fetch_sub(&mut self, val: int, order: Ordering) -> int { unsafe { atomic_sub(&mut self.v, val, order) } } @@ -173,34 +173,34 @@ impl AtomicUint { AtomicUint { v:v } } - #[inline(always)] + #[inline] pub fn load(&self, order: Ordering) -> uint { unsafe { atomic_load(&self.v, order) } } - #[inline(always)] + #[inline] pub fn store(&mut self, val: uint, order: Ordering) { unsafe { atomic_store(&mut self.v, val, order); } } - #[inline(always)] + #[inline] pub fn swap(&mut self, val: uint, order: Ordering) -> uint { unsafe { atomic_swap(&mut self.v, val, order) } } - #[inline(always)] + #[inline] pub fn compare_and_swap(&mut self, old: uint, new: uint, order: Ordering) -> uint { unsafe { atomic_compare_and_swap(&mut self.v, old, new, order) } } /// Returns the old value (like __sync_fetch_and_add). - #[inline(always)] + #[inline] pub fn fetch_add(&mut self, val: uint, order: Ordering) -> uint { unsafe { atomic_add(&mut self.v, val, order) } } /// Returns the old value (like __sync_fetch_and_sub).. - #[inline(always)] + #[inline] pub fn fetch_sub(&mut self, val: uint, order: Ordering) -> uint { unsafe { atomic_sub(&mut self.v, val, order) } } @@ -211,22 +211,22 @@ impl AtomicPtr { AtomicPtr { p:p } } - #[inline(always)] + #[inline] pub fn load(&self, order: Ordering) -> *mut T { unsafe { atomic_load(&self.p, order) } } - #[inline(always)] + #[inline] pub fn store(&mut self, ptr: *mut T, order: Ordering) { unsafe { atomic_store(&mut self.p, ptr, order); } } - #[inline(always)] + #[inline] pub fn swap(&mut self, ptr: *mut T, order: Ordering) -> *mut T { unsafe { atomic_swap(&mut self.p, ptr, order) } } - #[inline(always)] + #[inline] pub fn compare_and_swap(&mut self, old: *mut T, new: *mut T, order: Ordering) -> *mut T { unsafe { atomic_compare_and_swap(&mut self.p, old, new, order) } } @@ -249,7 +249,7 @@ impl AtomicOption { } } - #[inline(always)] + #[inline] pub fn swap(&mut self, val: ~T, order: Ordering) -> Option<~T> { unsafe { let val = cast::transmute(val); @@ -265,7 +265,7 @@ impl AtomicOption { } } - #[inline(always)] + #[inline] pub fn take(&mut self, order: Ordering) -> Option<~T> { unsafe { self.swap(cast::transmute(0), order) @@ -286,7 +286,7 @@ impl Drop for AtomicOption { } } -#[inline(always)] +#[inline] pub unsafe fn atomic_store(dst: &mut T, val: T, order:Ordering) { let dst = cast::transmute(dst); let val = cast::transmute(val); @@ -297,7 +297,7 @@ pub unsafe fn atomic_store(dst: &mut T, val: T, order:Ordering) { } } -#[inline(always)] +#[inline] pub unsafe fn atomic_load(dst: &T, order:Ordering) -> T { let dst = cast::transmute(dst); @@ -307,7 +307,7 @@ pub unsafe fn atomic_load(dst: &T, order:Ordering) -> T { }) } -#[inline(always)] +#[inline] pub unsafe fn atomic_swap(dst: &mut T, val: T, order: Ordering) -> T { let dst = cast::transmute(dst); let val = cast::transmute(val); @@ -320,7 +320,7 @@ pub unsafe fn atomic_swap(dst: &mut T, val: T, order: Ordering) -> T { } /// Returns the old value (like __sync_fetch_and_add). -#[inline(always)] +#[inline] pub unsafe fn atomic_add(dst: &mut T, val: T, order: Ordering) -> T { let dst = cast::transmute(dst); let val = cast::transmute(val); @@ -333,7 +333,7 @@ pub unsafe fn atomic_add(dst: &mut T, val: T, order: Ordering) -> T { } /// Returns the old value (like __sync_fetch_and_sub). -#[inline(always)] +#[inline] pub unsafe fn atomic_sub(dst: &mut T, val: T, order: Ordering) -> T { let dst = cast::transmute(dst); let val = cast::transmute(val); @@ -345,7 +345,7 @@ pub unsafe fn atomic_sub(dst: &mut T, val: T, order: Ordering) -> T { }) } -#[inline(always)] +#[inline] pub unsafe fn atomic_compare_and_swap(dst:&mut T, old:T, new:T, order: Ordering) -> T { let dst = cast::transmute(dst); let old = cast::transmute(old); diff --git a/src/libstd/unstable/dynamic_lib.rs b/src/libstd/unstable/dynamic_lib.rs index 96aba1d2971e..64dd5bba6bcf 100644 --- a/src/libstd/unstable/dynamic_lib.rs +++ b/src/libstd/unstable/dynamic_lib.rs @@ -15,7 +15,6 @@ Dynamic library facilities. A simple wrapper over the platforms dynamic library facilities */ -use ptr; use cast; use path; use libc; @@ -42,19 +41,15 @@ impl DynamicLibrary { /// Lazily open a dynamic library. When passed None it gives a /// handle to the calling process pub fn open(filename: Option<&path::Path>) -> Result { - let open_wrapper = |raw_ptr| { - do dl::check_for_errors_in { - unsafe { - DynamicLibrary { handle: dl::open(raw_ptr) } + do dl::check_for_errors_in { + unsafe { + DynamicLibrary { handle: + match filename { + Some(name) => dl::open_external(name), + None => dl::open_internal() + } } } - }; - - match filename { - Some(name) => do name.to_str().as_c_str |raw_name| { - open_wrapper(raw_name) - }, - None => open_wrapper(ptr::null()) } } @@ -74,6 +69,7 @@ impl DynamicLibrary { } #[test] +#[ignore(cfg(windows))] priv fn test_loading_cosine () { // The math library does not need to be loaded since it is already // statically linked in @@ -106,13 +102,20 @@ priv fn test_loading_cosine () { #[cfg(target_os = "freebsd")] mod dl { use libc; + use path; use ptr; use str; use task; use result::*; - pub unsafe fn open(filename: *libc::c_char) -> *libc::c_void { - dlopen(filename, Lazy as libc::c_int) + pub unsafe fn open_external(filename: &path::Path) -> *libc::c_void { + do filename.to_str().as_c_str |raw_name| { + dlopen(raw_name, Lazy as libc::c_int) + } + } + + pub unsafe fn open_internal() -> *libc::c_void { + dlopen(ptr::null(), Lazy as libc::c_int) } pub fn check_for_errors_in(f: &fn()->T) -> Result { @@ -159,11 +162,22 @@ mod dl { mod dl { use os; use libc; + use path; + use ptr; + use str; use task; use result::*; - pub unsafe fn open(filename: *libc::c_char) -> *libc::c_void { - LoadLibrary(filename) + pub unsafe fn open_external(filename: &path::Path) -> *libc::c_void { + do os::win32::as_utf16_p(filename.to_str()) |raw_name| { + LoadLibraryW(raw_name) + } + } + + pub unsafe fn open_internal() -> *libc::c_void { + let mut handle = ptr::null(); + GetModuleHandleExW(0 as libc::DWORD, ptr::null(), &handle as **libc::c_void); + handle } pub fn check_for_errors_in(f: &fn()->T) -> Result { @@ -192,7 +206,9 @@ mod dl { #[link_name = "kernel32"] extern "stdcall" { fn SetLastError(error: u32); - fn LoadLibrary(name: *libc::c_char) -> *libc::c_void; + fn LoadLibraryW(name: *u16) -> *libc::c_void; + fn GetModuleHandleExW(dwFlags: libc::DWORD, name: *u16, + handle: **libc::c_void) -> *libc::c_void; fn GetProcAddress(handle: *libc::c_void, name: *libc::c_char) -> *libc::c_void; fn FreeLibrary(handle: *libc::c_void); } diff --git a/src/libstd/unstable/extfmt.rs b/src/libstd/unstable/extfmt.rs index 7d9ce585d7c5..d466488ce5e5 100644 --- a/src/libstd/unstable/extfmt.rs +++ b/src/libstd/unstable/extfmt.rs @@ -673,7 +673,7 @@ pub mod rt { } buf.push_str(s); } - #[inline(always)] + #[inline] pub fn have_flag(flags: u32, f: u32) -> bool { flags & f != 0 } diff --git a/src/libstd/unstable/global.rs b/src/libstd/unstable/global.rs index 96549a83a8cf..f81252274c49 100644 --- a/src/libstd/unstable/global.rs +++ b/src/libstd/unstable/global.rs @@ -105,7 +105,7 @@ unsafe fn global_data_modify_( let dtor: ~fn() = match maybe_dtor { Some(dtor) => dtor, None => { - let dtor: ~fn() = || unsafe { + let dtor: ~fn() = || { let _destroy_value: ~T = transmute(data); }; dtor diff --git a/src/libstd/unstable/intrinsics.rs b/src/libstd/unstable/intrinsics.rs index 908c5e23ab07..134250077853 100644 --- a/src/libstd/unstable/intrinsics.rs +++ b/src/libstd/unstable/intrinsics.rs @@ -130,36 +130,23 @@ pub extern "rust-intrinsic" { /// Equivalent to the `llvm.memcpy.p0i8.0i8.i32` intrinsic, with a size of /// `count` * `size_of::()` and an alignment of `min_align_of::()` - #[cfg(not(stage0))] pub fn memcpy32(dst: *mut T, src: *T, count: u32); /// Equivalent to the `llvm.memcpy.p0i8.0i8.i64` intrinsic, with a size of /// `count` * `size_of::()` and an alignment of `min_align_of::()` - #[cfg(not(stage0))] pub fn memcpy64(dst: *mut T, src: *T, count: u64); - /// Equivalent to the `llvm.memmove.p0i8.0i8.i32` intrinsic. - #[cfg(stage0)] - pub fn memmove32(dst: *mut u8, src: *u8, size: u32); - /// Equivalent to the `llvm.memmove.p0i8.0i8.i64` intrinsic. - #[cfg(stage0)] - pub fn memmove64(dst: *mut u8, src: *u8, size: u64); - /// Equivalent to the `llvm.memmove.p0i8.0i8.i32` intrinsic, with a size of /// `count` * `size_of::()` and an alignment of `min_align_of::()` - #[cfg(not(stage0))] pub fn memmove32(dst: *mut T, src: *T, count: u32); /// Equivalent to the `llvm.memmove.p0i8.0i8.i64` intrinsic, with a size of /// `count` * `size_of::()` and an alignment of `min_align_of::()` - #[cfg(not(stage0))] pub fn memmove64(dst: *mut T, src: *T, count: u64); /// Equivalent to the `llvm.memset.p0i8.i32` intrinsic, with a size of /// `count` * `size_of::()` and an alignment of `min_align_of::()` - #[cfg(not(stage0))] pub fn memset32(dst: *mut T, val: u8, count: u32); /// Equivalent to the `llvm.memset.p0i8.i64` intrinsic, with a size of /// `count` * `size_of::()` and an alignment of `min_align_of::()` - #[cfg(not(stage0))] pub fn memset64(dst: *mut T, val: u8, count: u64); pub fn sqrtf32(x: f32) -> f32; diff --git a/src/libstd/unstable/lang.rs b/src/libstd/unstable/lang.rs index 3d61c1fe144b..f750b31a466b 100644 --- a/src/libstd/unstable/lang.rs +++ b/src/libstd/unstable/lang.rs @@ -14,7 +14,6 @@ use iterator::IteratorUtil; use uint; use cast::transmute; use libc::{c_char, c_uchar, c_void, size_t, uintptr_t, c_int, STDERR_FILENO}; -use managed::raw::BoxRepr; use str; use sys; use rt::{context, OldTaskContext}; @@ -23,14 +22,11 @@ use rt::local::Local; use option::{Option, Some, None}; use io; use rt::global_heap; +use rt::borrowck; #[allow(non_camel_case_types)] pub type rust_task = c_void; -pub static FROZEN_BIT: uint = 1 << (uint::bits - 1); -pub static MUT_BIT: uint = 1 << (uint::bits - 2); -static ALL_BITS: uint = FROZEN_BIT | MUT_BIT; - pub mod rustrt { use unstable::lang::rust_task; use libc::{c_void, c_char, uintptr_t}; @@ -47,15 +43,6 @@ pub mod rustrt { size: uintptr_t) -> *c_char; - #[fast_ffi] - unsafe fn rust_upcall_free_noswitch(ptr: *c_char); - - #[rust_stack] - fn rust_take_task_borrow_list(task: *rust_task) -> *c_void; - - #[rust_stack] - fn rust_set_task_borrow_list(task: *rust_task, map: *c_void); - #[rust_stack] fn rust_try_get_task() -> *rust_task; @@ -78,161 +65,18 @@ pub fn fail_bounds_check(file: *c_char, line: size_t, } } -#[deriving(Eq)] -struct BorrowRecord { - box: *mut BoxRepr, - file: *c_char, - line: size_t -} - -fn try_take_task_borrow_list() -> Option<~[BorrowRecord]> { - unsafe { - let cur_task: *rust_task = rustrt::rust_try_get_task(); - if cur_task.is_not_null() { - let ptr = rustrt::rust_take_task_borrow_list(cur_task); - if ptr.is_null() { - None - } else { - let v: ~[BorrowRecord] = transmute(ptr); - Some(v) - } - } else { - None - } - } -} - -fn swap_task_borrow_list(f: &fn(~[BorrowRecord]) -> ~[BorrowRecord]) { - unsafe { - let cur_task: *rust_task = rustrt::rust_try_get_task(); - if cur_task.is_not_null() { - let mut borrow_list: ~[BorrowRecord] = { - let ptr = rustrt::rust_take_task_borrow_list(cur_task); - if ptr.is_null() { ~[] } else { transmute(ptr) } - }; - borrow_list = f(borrow_list); - rustrt::rust_set_task_borrow_list(cur_task, transmute(borrow_list)); - } - } -} - -pub unsafe fn clear_task_borrow_list() { - // pub because it is used by the box annihilator. - let _ = try_take_task_borrow_list(); -} - -unsafe fn fail_borrowed(box: *mut BoxRepr, file: *c_char, line: size_t) { - debug_borrow("fail_borrowed: ", box, 0, 0, file, line); - - match try_take_task_borrow_list() { - None => { // not recording borrows - let msg = "borrowed"; - do str::as_buf(msg) |msg_p, _| { - fail_(msg_p as *c_char, file, line); - } - } - Some(borrow_list) => { // recording borrows - let mut msg = ~"borrowed"; - let mut sep = " at "; - for borrow_list.rev_iter().advance |entry| { - if entry.box == box { - msg.push_str(sep); - let filename = str::raw::from_c_str(entry.file); - msg.push_str(filename); - msg.push_str(fmt!(":%u", entry.line as uint)); - sep = " and at "; - } - } - do str::as_buf(msg) |msg_p, _| { - fail_(msg_p as *c_char, file, line) - } - } - } -} - // FIXME #4942: Make these signatures agree with exchange_alloc's signatures #[lang="exchange_malloc"] -#[inline(always)] +#[inline] pub unsafe fn exchange_malloc(td: *c_char, size: uintptr_t) -> *c_char { transmute(global_heap::malloc(transmute(td), transmute(size))) } -/// Because this code is so perf. sensitive, use a static constant so that -/// debug printouts are compiled out most of the time. -static ENABLE_DEBUG: bool = false; - -#[inline] -unsafe fn debug_borrow(tag: &'static str, - p: *const T, - old_bits: uint, - new_bits: uint, - filename: *c_char, - line: size_t) { - //! A useful debugging function that prints a pointer + tag + newline - //! without allocating memory. - - if ENABLE_DEBUG && ::rt::env::get().debug_borrow { - debug_borrow_slow(tag, p, old_bits, new_bits, filename, line); - } - - unsafe fn debug_borrow_slow(tag: &'static str, - p: *const T, - old_bits: uint, - new_bits: uint, - filename: *c_char, - line: size_t) { - let dbg = STDERR_FILENO as io::fd_t; - dbg.write_str(tag); - dbg.write_hex(p as uint); - dbg.write_str(" "); - dbg.write_hex(old_bits); - dbg.write_str(" "); - dbg.write_hex(new_bits); - dbg.write_str(" "); - dbg.write_cstr(filename); - dbg.write_str(":"); - dbg.write_hex(line as uint); - dbg.write_str("\n"); - } -} - -trait DebugPrints { - fn write_hex(&self, val: uint); - unsafe fn write_cstr(&self, str: *c_char); -} - -impl DebugPrints for io::fd_t { - fn write_hex(&self, mut i: uint) { - let letters = ['0', '1', '2', '3', '4', '5', '6', '7', '8', - '9', 'a', 'b', 'c', 'd', 'e', 'f']; - static uint_nibbles: uint = ::uint::bytes << 1; - let mut buffer = [0_u8, ..uint_nibbles+1]; - let mut c = uint_nibbles; - while c > 0 { - c -= 1; - buffer[c] = letters[i & 0xF] as u8; - i >>= 4; - } - self.write(buffer.slice(0, uint_nibbles)); - } - - unsafe fn write_cstr(&self, p: *c_char) { - use libc::strlen; - use vec; - - let len = strlen(p); - let p: *u8 = transmute(p); - do vec::raw::buf_as_slice(p, len as uint) |s| { - self.write(s); - } - } -} - // NB: Calls to free CANNOT be allowed to fail, as throwing an exception from // inside a landing pad may corrupt the state of the exception handler. If a // problem occurs, call exit instead. #[lang="exchange_free"] -#[inline(always)] +#[inline] pub unsafe fn exchange_free(ptr: *c_char) { global_heap::free(transmute(ptr)) } @@ -258,138 +102,63 @@ pub unsafe fn local_malloc(td: *c_char, size: uintptr_t) -> *c_char { // problem occurs, call exit instead. #[lang="free"] pub unsafe fn local_free(ptr: *c_char) { - match context() { - OldTaskContext => { - rustrt::rust_upcall_free_noswitch(ptr); - } - _ => { - do Local::borrow:: |task| { - task.heap.free(ptr as *c_void); - } - } - } + ::rt::local_heap::local_free(ptr); } #[lang="borrow_as_imm"] -#[inline(always)] +#[inline] pub unsafe fn borrow_as_imm(a: *u8, file: *c_char, line: size_t) -> uint { - let a: *mut BoxRepr = transmute(a); - let old_ref_count = (*a).header.ref_count; - let new_ref_count = old_ref_count | FROZEN_BIT; - - debug_borrow("borrow_as_imm:", a, old_ref_count, new_ref_count, file, line); - - if (old_ref_count & MUT_BIT) != 0 { - fail_borrowed(a, file, line); - } - - (*a).header.ref_count = new_ref_count; - - old_ref_count + borrowck::borrow_as_imm(a, file, line) } #[lang="borrow_as_mut"] -#[inline(always)] +#[inline] pub unsafe fn borrow_as_mut(a: *u8, file: *c_char, line: size_t) -> uint { - let a: *mut BoxRepr = transmute(a); - let old_ref_count = (*a).header.ref_count; - let new_ref_count = old_ref_count | MUT_BIT | FROZEN_BIT; - - debug_borrow("borrow_as_mut:", a, old_ref_count, new_ref_count, file, line); - - if (old_ref_count & (MUT_BIT|FROZEN_BIT)) != 0 { - fail_borrowed(a, file, line); - } - - (*a).header.ref_count = new_ref_count; - - old_ref_count + borrowck::borrow_as_mut(a, file, line) } - #[lang="record_borrow"] pub unsafe fn record_borrow(a: *u8, old_ref_count: uint, file: *c_char, line: size_t) { - if (old_ref_count & ALL_BITS) == 0 { - // was not borrowed before - let a: *mut BoxRepr = transmute(a); - debug_borrow("record_borrow:", a, old_ref_count, 0, file, line); - do swap_task_borrow_list |borrow_list| { - let mut borrow_list = borrow_list; - borrow_list.push(BorrowRecord {box: a, file: file, line: line}); - borrow_list - } - } + borrowck::record_borrow(a, old_ref_count, file, line) } #[lang="unrecord_borrow"] pub unsafe fn unrecord_borrow(a: *u8, old_ref_count: uint, file: *c_char, line: size_t) { - if (old_ref_count & ALL_BITS) == 0 { - // was not borrowed before, so we should find the record at - // the end of the list - let a: *mut BoxRepr = transmute(a); - debug_borrow("unrecord_borrow:", a, old_ref_count, 0, file, line); - do swap_task_borrow_list |borrow_list| { - let mut borrow_list = borrow_list; - assert!(!borrow_list.is_empty()); - let br = borrow_list.pop(); - if br.box != a || br.file != file || br.line != line { - let err = fmt!("wrong borrow found, br=%?", br); - do str::as_buf(err) |msg_p, _| { - fail_(msg_p as *c_char, file, line) - } - } - borrow_list - } - } + borrowck::unrecord_borrow(a, old_ref_count, file, line) } #[lang="return_to_mut"] -#[inline(always)] +#[inline] pub unsafe fn return_to_mut(a: *u8, orig_ref_count: uint, file: *c_char, line: size_t) { - // Sometimes the box is null, if it is conditionally frozen. - // See e.g. #4904. - if !a.is_null() { - let a: *mut BoxRepr = transmute(a); - let old_ref_count = (*a).header.ref_count; - let new_ref_count = - (old_ref_count & !ALL_BITS) | (orig_ref_count & ALL_BITS); - - debug_borrow("return_to_mut:", - a, old_ref_count, new_ref_count, file, line); - - (*a).header.ref_count = new_ref_count; - } + borrowck::return_to_mut(a, orig_ref_count, file, line) } #[lang="check_not_borrowed"] -#[inline(always)] +#[inline] pub unsafe fn check_not_borrowed(a: *u8, file: *c_char, line: size_t) { - let a: *mut BoxRepr = transmute(a); - let ref_count = (*a).header.ref_count; - debug_borrow("check_not_borrowed:", a, ref_count, 0, file, line); - if (ref_count & FROZEN_BIT) != 0 { - fail_borrowed(a, file, line); - } + borrowck::check_not_borrowed(a, file, line) } #[lang="strdup_uniq"] -#[inline(always)] +#[inline] pub unsafe fn strdup_uniq(ptr: *c_uchar, len: uint) -> ~str { str::raw::from_buf_len(ptr, len) } +#[lang="annihilate"] +pub unsafe fn annihilate() { + ::cleanup::annihilate() +} + #[lang="start"] pub fn start(main: *u8, argc: int, argv: **c_char, crate_map: *u8) -> int { use rt; - use sys::Closure; - use ptr; - use cast; use os; unsafe { @@ -399,17 +168,8 @@ pub fn start(main: *u8, argc: int, argv: **c_char, crate_map as *c_void) as int; } else { return do rt::start(argc, argv as **u8, crate_map) { - unsafe { - // `main` is an `fn() -> ()` that doesn't take an environment - // XXX: Could also call this as an `extern "Rust" fn` once they work - let main = Closure { - code: main as *(), - env: ptr::null(), - }; - let mainfn: &fn() = cast::transmute(main); - - mainfn(); - } + let main: extern "Rust" fn() = transmute(main); + main(); }; } } diff --git a/src/libstd/unstable/mod.rs b/src/libstd/unstable/mod.rs index ae8780501425..0a46ef619afd 100644 --- a/src/libstd/unstable/mod.rs +++ b/src/libstd/unstable/mod.rs @@ -18,11 +18,6 @@ use task; pub mod at_exit; -// Currently only works for *NIXes -#[cfg(target_os = "linux")] -#[cfg(target_os = "android")] -#[cfg(target_os = "macos")] -#[cfg(target_os = "freebsd")] pub mod dynamic_lib; pub mod global; diff --git a/src/libstd/unstable/sync.rs b/src/libstd/unstable/sync.rs index 3cf46bec41a7..162891124f60 100644 --- a/src/libstd/unstable/sync.rs +++ b/src/libstd/unstable/sync.rs @@ -40,7 +40,7 @@ impl UnsafeAtomicRcBox { } } - #[inline(always)] + #[inline] pub unsafe fn get(&self) -> *mut T { let mut data: ~AtomicRcBoxData = cast::transmute(self.data); @@ -50,7 +50,7 @@ impl UnsafeAtomicRcBox { return r; } - #[inline(always)] + #[inline] pub unsafe fn get_immut(&self) -> *T { let mut data: ~AtomicRcBoxData = cast::transmute(self.data); @@ -118,7 +118,7 @@ fn LittleLock() -> LittleLock { } impl LittleLock { - #[inline(always)] + #[inline] pub unsafe fn lock(&self, f: &fn() -> T) -> T { do atomically { rust_lock_little_lock(self.l); @@ -169,7 +169,7 @@ impl Exclusive { // Currently, scheduling operations (i.e., yielding, receiving on a pipe, // accessing the provided condition variable) are prohibited while inside // the exclusive. Supporting that is a work in progress. - #[inline(always)] + #[inline] pub unsafe fn with(&self, f: &fn(x: &mut T) -> U) -> U { let rec = self.x.get(); do (*rec).lock.lock { @@ -183,7 +183,7 @@ impl Exclusive { } } - #[inline(always)] + #[inline] pub unsafe fn with_imm(&self, f: &fn(x: &T) -> U) -> U { do self.with |x| { f(cast::transmute_immut(x)) diff --git a/src/libstd/util.rs b/src/libstd/util.rs index 61c284f580c0..2a5d44c9ce26 100644 --- a/src/libstd/util.rs +++ b/src/libstd/util.rs @@ -16,11 +16,11 @@ use prelude::*; use unstable::intrinsics; /// The identity function. -#[inline(always)] +#[inline] pub fn id(x: T) -> T { x } /// Ignores a value. -#[inline(always)] +#[inline] pub fn ignore(_x: T) { } /// Sets `*ptr` to `new_value`, invokes `op()`, and then restores the @@ -30,7 +30,7 @@ pub fn ignore(_x: T) { } /// an obvious borrowck hazard. Typically passing in `&mut T` will /// cause borrow check errors because it freezes whatever location /// that `&mut T` is stored in (either statically or dynamically). -#[inline(always)] +#[inline] pub fn with( ptr: @mut T, value: T, @@ -46,7 +46,7 @@ pub fn with( * Swap the values at two mutable locations of the same type, without * deinitialising or copying either one. */ -#[inline(always)] +#[inline] pub fn swap(x: &mut T, y: &mut T) { unsafe { // Give ourselves some scratch space to work with @@ -68,7 +68,7 @@ pub fn swap(x: &mut T, y: &mut T) { * Replace the value at a mutable location with a new one, returning the old * value, without deinitialising or copying either one. */ -#[inline(always)] +#[inline] pub fn replace(dest: &mut T, mut src: T) -> T { swap(dest, &mut src); src diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index 211ee12c2910..4339153c43ee 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -19,10 +19,11 @@ use cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater}; use clone::Clone; use old_iter::BaseIter; use old_iter; -use iterator::{Iterator, IteratorUtil}; +use iterator::{Iterator}; use iter::FromIter; use kinds::Copy; use libc; +use num::Zero; use old_iter::CopyableIter; use option::{None, Option, Some}; use ptr::to_unsafe_ptr; @@ -47,12 +48,8 @@ pub mod rustrt { // to ~[] and reserve_shared_actual applies to @[]. #[fast_ffi] unsafe fn vec_reserve_shared(t: *sys::TypeDesc, - v: **raw::VecRepr, + v: *mut *mut raw::VecRepr, n: libc::size_t); - #[fast_ffi] - unsafe fn vec_reserve_shared_actual(t: *sys::TypeDesc, - v: **raw::VecRepr, - n: libc::size_t); } } @@ -78,11 +75,11 @@ pub fn reserve(v: &mut ~[T], n: uint) { use managed; if capacity(v) < n { unsafe { - let ptr: **raw::VecRepr = cast::transmute(v); + let ptr: *mut *mut raw::VecRepr = cast::transmute(v); let td = sys::get_type_desc::(); if ((**ptr).box_header.ref_count == managed::raw::RC_MANAGED_UNIQUE) { - rustrt::vec_reserve_shared_actual(td, ptr, n as libc::size_t); + ::at_vec::raw::reserve_raw(td, ptr, n); } else { rustrt::vec_reserve_shared(td, ptr, n as libc::size_t); } @@ -110,7 +107,7 @@ pub fn reserve_at_least(v: &mut ~[T], n: uint) { } /// Returns the number of elements the vector can hold without reallocating -#[inline(always)] +#[inline] pub fn capacity(v: &const ~[T]) -> uint { unsafe { let repr: **raw::VecRepr = transmute(v); @@ -118,15 +115,6 @@ pub fn capacity(v: &const ~[T]) -> uint { } } -// A botch to tide us over until core and std are fully demuted. -#[allow(missing_doc)] -pub fn uniq_len(v: &const ~[T]) -> uint { - unsafe { - let v: &~[T] = transmute(v); - as_const_buf(*v, |_p, len| len) - } -} - /** * Creates and initializes an owned vector. * @@ -155,8 +143,10 @@ pub fn from_fn(n_elts: uint, op: old_iter::InitOp) -> ~[T] { * to the value `t`. */ pub fn from_elem(n_elts: uint, t: T) -> ~[T] { - // hack: manually inline from_fn for 2x plus speedup (sadly very important, from_elem is a - // bottleneck in borrowck!) + // FIXME (#7136): manually inline from_fn for 2x plus speedup (sadly very + // important, from_elem is a bottleneck in borrowck!). Unfortunately it + // still is substantially slower than using the unsafe + // vec::with_capacity/ptr::set_memory for primitive types. unsafe { let mut v = with_capacity(n_elts); do as_mut_buf(v) |p, _len| { @@ -173,7 +163,7 @@ pub fn from_elem(n_elts: uint, t: T) -> ~[T] { /// Creates a new unique vector with the same contents as the slice pub fn to_owned(t: &[T]) -> ~[T] { - from_fn(t.len(), |i| t[i]) + from_fn(t.len(), |i| copy t[i]) } /// Creates a new vector with a capacity of `capacity` @@ -195,7 +185,7 @@ pub fn with_capacity(capacity: uint) -> ~[T] { * as an argument a function that will push an element * onto the vector being constructed. */ -#[inline(always)] +#[inline] pub fn build_sized(size: uint, builder: &fn(push: &fn(v: A))) -> ~[A] { let mut vec = with_capacity(size); builder(|x| vec.push(x)); @@ -212,7 +202,7 @@ pub fn build_sized(size: uint, builder: &fn(push: &fn(v: A))) -> ~[A] { * as an argument a function that will push an element * onto the vector being constructed. */ -#[inline(always)] +#[inline] pub fn build(builder: &fn(push: &fn(v: A))) -> ~[A] { build_sized(4, builder) } @@ -229,7 +219,7 @@ pub fn build(builder: &fn(push: &fn(v: A))) -> ~[A] { * as an argument a function that will push an element * onto the vector being constructed. */ -#[inline(always)] +#[inline] pub fn build_sized_opt(size: Option, builder: &fn(push: &fn(v: A))) -> ~[A] { @@ -277,7 +267,7 @@ pub fn last_opt<'r,T>(v: &'r [T]) -> Option<&'r T> { } /// Return a slice that points into another slice. -#[inline(always)] +#[inline] pub fn slice<'r,T>(v: &'r [T], start: uint, end: uint) -> &'r [T] { assert!(start <= end); assert!(end <= v.len()); @@ -290,7 +280,7 @@ pub fn slice<'r,T>(v: &'r [T], start: uint, end: uint) -> &'r [T] { } /// Return a slice that points into another slice. -#[inline(always)] +#[inline] pub fn mut_slice<'r,T>(v: &'r mut [T], start: uint, end: uint) -> &'r mut [T] { assert!(start <= end); @@ -304,7 +294,7 @@ pub fn mut_slice<'r,T>(v: &'r mut [T], start: uint, end: uint) } /// Return a slice that points into another slice. -#[inline(always)] +#[inline] pub fn const_slice<'r,T>(v: &'r const [T], start: uint, end: uint) -> &'r const [T] { assert!(start <= end); @@ -447,9 +437,9 @@ pub fn partitioned(v: &[T], f: &fn(&T) -> bool) -> (~[T], ~[T]) { for each(v) |elt| { if f(elt) { - lefts.push(*elt); + lefts.push(copy *elt); } else { - rights.push(*elt); + rights.push(copy *elt); } } @@ -639,7 +629,7 @@ pub fn swap_remove(v: &mut ~[T], index: uint) -> T { } /// Append an element to a vector -#[inline(always)] +#[inline] pub fn push(v: &mut ~[T], initval: T) { unsafe { let repr: **raw::VecRepr = transmute(&mut *v); @@ -654,7 +644,7 @@ pub fn push(v: &mut ~[T], initval: T) { } // This doesn't bother to make sure we have space. -#[inline(always)] // really pretty please +#[inline] // really pretty please unsafe fn push_fast(v: &mut ~[T], initval: T) { let repr: **mut raw::VecRepr = transmute(v); let fill = (**repr).unboxed.fill; @@ -681,7 +671,7 @@ fn push_slow(v: &mut ~[T], initval: T) { /// vec::push_all(&mut a, [2, 3, 4]); /// assert!(a == ~[1, 2, 3, 4]); /// ~~~ -#[inline(always)] +#[inline] pub fn push_all(v: &mut ~[T], rhs: &const [T]) { let new_len = v.len() + rhs.len(); reserve(&mut *v, new_len); @@ -702,7 +692,7 @@ pub fn push_all(v: &mut ~[T], rhs: &const [T]) { /// vec::push_all_move(&mut a, ~[~2, ~3, ~4]); /// assert!(a == ~[~1, ~2, ~3, ~4]); /// ~~~ -#[inline(always)] +#[inline] pub fn push_all_move(v: &mut ~[T], mut rhs: ~[T]) { let new_len = v.len() + rhs.len(); reserve(&mut *v, new_len); @@ -773,7 +763,7 @@ pub fn dedup(v: &mut ~[T]) { /// Iterates over the `rhs` vector, copying each element and appending it to the /// `lhs`. Afterwards, the `lhs` is then returned for use again. -#[inline(always)] +#[inline] pub fn append(lhs: ~[T], rhs: &const [T]) -> ~[T] { let mut v = lhs; v.push_all(rhs); @@ -782,7 +772,7 @@ pub fn append(lhs: ~[T], rhs: &const [T]) -> ~[T] { /// Appends one element to the vector provided. The vector itself is then /// returned for use again. -#[inline(always)] +#[inline] pub fn append_one(lhs: ~[T], x: T) -> ~[T] { let mut v = lhs; v.push(x); @@ -804,7 +794,7 @@ pub fn grow(v: &mut ~[T], n: uint, initval: &T) { let mut i: uint = 0u; while i < n { - v.push(*initval); + v.push(copy *initval); i += 1u; } } @@ -976,7 +966,7 @@ pub fn filter(v: ~[T], f: &fn(t: &T) -> bool) -> ~[T] { pub fn filtered(v: &[T], f: &fn(t: &T) -> bool) -> ~[T] { let mut result = ~[]; for each(v) |elem| { - if f(elem) { result.push(*elem); } + if f(elem) { result.push(copy *elem); } } result } @@ -1032,7 +1022,7 @@ impl<'self, T:Copy> VectorVector for &'self [~[T]] { let mut r = ~[]; let mut first = true; for self.each |&inner| { - if first { first = false; } else { r.push(*sep); } + if first { first = false; } else { r.push(copy *sep); } r.push_all(inner); } r @@ -1050,7 +1040,7 @@ impl<'self, T:Copy> VectorVector for &'self [&'self [T]] { let mut r = ~[]; let mut first = true; for self.each |&inner| { - if first { first = false; } else { r.push(*sep); } + if first { first = false; } else { r.push(copy *sep); } r.push_all(inner); } r @@ -1083,7 +1073,7 @@ pub fn find(v: &[T], f: &fn(t: &T) -> bool) -> Option { */ pub fn find_between(v: &[T], start: uint, end: uint, f: &fn(t: &T) -> bool) -> Option { - position_between(v, start, end, f).map(|i| v[*i]) + position_between(v, start, end, f).map(|i| copy v[*i]) } /** @@ -1109,7 +1099,7 @@ pub fn rfind_between(v: &[T], end: uint, f: &fn(t: &T) -> bool) -> Option { - rposition_between(v, start, end, f).map(|i| v[*i]) + rposition_between(v, start, end, f).map(|i| copy v[*i]) } /// Find the first index containing a matching value @@ -1233,7 +1223,7 @@ pub fn bsearch_elem(v: &[T], x: &T) -> Option { pub fn unzip_slice(v: &[(T, U)]) -> (~[T], ~[U]) { let mut (ts, us) = (~[], ~[]); for each(v) |p| { - let (t, u) = *p; + let (t, u) = copy *p; ts.push(t); us.push(u); } @@ -1268,7 +1258,7 @@ pub fn zip_slice(v: &const [T], u: &const [U]) let mut i = 0u; assert_eq!(sz, u.len()); while i < sz { - zipped.push((v[i], u[i])); + zipped.push((copy v[i], copy u[i])); i += 1u; } zipped @@ -1301,7 +1291,7 @@ pub fn zip(mut v: ~[T], mut u: ~[U]) -> ~[(T, U)] { * * a - The index of the first element * * b - The index of the second element */ -#[inline(always)] +#[inline] pub fn swap(v: &mut [T], a: uint, b: uint) { unsafe { // Can't take two mutable loans from one vector, so instead just cast @@ -1365,8 +1355,8 @@ pub fn reversed(v: &const [T]) -> ~[T] { let mut rs: ~[T] = ~[]; let mut i = v.len(); if i == 0 { return (rs); } else { i -= 1; } - while i != 0 { rs.push(v[i]); i -= 1; } - rs.push(v[0]); + while i != 0 { rs.push(copy v[i]); i -= 1; } + rs.push(copy v[0]); rs } @@ -1409,7 +1399,7 @@ pub fn reversed(v: &const [T]) -> ~[T] { * } * ~~~ */ -#[inline(always)] +#[inline] pub fn each<'r,T>(v: &'r [T], f: &fn(&'r T) -> bool) -> bool { // ^^^^ // NB---this CANNOT be &const [T]! The reason @@ -1435,7 +1425,7 @@ pub fn each<'r,T>(v: &'r [T], f: &fn(&'r T) -> bool) -> bool { /// Like `each()`, but for the case where you have a vector that *may or may /// not* have mutable contents. -#[inline(always)] +#[inline] pub fn each_const(v: &const [T], f: &fn(elem: &const T) -> bool) -> bool { let mut i = 0; let n = v.len(); @@ -1453,7 +1443,7 @@ pub fn each_const(v: &const [T], f: &fn(elem: &const T) -> bool) -> bool { * * Return true to continue, false to break. */ -#[inline(always)] +#[inline] pub fn eachi<'r,T>(v: &'r [T], f: &fn(uint, v: &'r T) -> bool) -> bool { let mut i = 0; for each(v) |p| { @@ -1485,7 +1475,7 @@ pub fn eachi<'r,T>(v: &'r [T], f: &fn(uint, v: &'r T) -> bool) -> bool { */ pub fn each_permutation(values: &[T], fun: &fn(perm : &[T]) -> bool) -> bool { let length = values.len(); - let mut permutation = vec::from_fn(length, |i| values[i]); + let mut permutation = vec::from_fn(length, |i| copy values[i]); if length <= 1 { fun(permutation); return true; @@ -1512,7 +1502,7 @@ pub fn each_permutation(values: &[T], fun: &fn(perm : &[T]) -> bool) -> reverse_part(indices, k+1, length); // fixup permutation based on indices for uint::range(k, length) |i| { - permutation[i] = values[indices[i]]; + permutation[i] = copy values[indices[i]]; } } } @@ -1546,7 +1536,7 @@ pub fn windowed<'r, T>(n: uint, v: &'r [T], it: &fn(&'r [T]) -> bool) -> bool { * Allows for unsafe manipulation of vector contents, which is useful for * foreign interop. */ -#[inline(always)] +#[inline] pub fn as_imm_buf(s: &[T], /* NB---this CANNOT be const, see below */ f: &fn(*T, uint) -> U) -> U { @@ -1565,7 +1555,7 @@ pub fn as_imm_buf(s: &[T], } /// Similar to `as_imm_buf` but passing a `*const T` -#[inline(always)] +#[inline] pub fn as_const_buf(s: &const [T], f: &fn(*const T, uint) -> U) -> U { unsafe { let v : *(*const T,uint) = transmute(&s); @@ -1575,7 +1565,7 @@ pub fn as_const_buf(s: &const [T], f: &fn(*const T, uint) -> U) -> U { } /// Similar to `as_imm_buf` but passing a `*mut T` -#[inline(always)] +#[inline] pub fn as_mut_buf(s: &mut [T], f: &fn(*mut T, uint) -> U) -> U { unsafe { let v : *(*mut T,uint) = transmute(&s); @@ -1618,49 +1608,49 @@ fn equals(a: &[T], b: &[T]) -> bool { #[cfg(not(test))] impl<'self,T:Eq> Eq for &'self [T] { - #[inline(always)] + #[inline] fn eq(&self, other: & &'self [T]) -> bool { eq(*self, *other) } - #[inline(always)] + #[inline] fn ne(&self, other: & &'self [T]) -> bool { !self.eq(other) } } #[cfg(not(test))] impl Eq for ~[T] { - #[inline(always)] + #[inline] fn eq(&self, other: &~[T]) -> bool { eq(*self, *other) } - #[inline(always)] + #[inline] fn ne(&self, other: &~[T]) -> bool { !self.eq(other) } } #[cfg(not(test))] impl Eq for @[T] { - #[inline(always)] + #[inline] fn eq(&self, other: &@[T]) -> bool { eq(*self, *other) } - #[inline(always)] + #[inline] fn ne(&self, other: &@[T]) -> bool { !self.eq(other) } } #[cfg(not(test))] impl<'self,T:TotalEq> TotalEq for &'self [T] { - #[inline(always)] + #[inline] fn equals(&self, other: & &'self [T]) -> bool { equals(*self, *other) } } #[cfg(not(test))] impl TotalEq for ~[T] { - #[inline(always)] + #[inline] fn equals(&self, other: &~[T]) -> bool { equals(*self, *other) } } #[cfg(not(test))] impl TotalEq for @[T] { - #[inline(always)] + #[inline] fn equals(&self, other: &@[T]) -> bool { equals(*self, *other) } } #[cfg(not(test))] impl<'self,T:Eq> Equiv<~[T]> for &'self [T] { - #[inline(always)] + #[inline] fn equiv(&self, other: &~[T]) -> bool { eq(*self, *other) } } @@ -1682,19 +1672,19 @@ fn cmp(a: &[T], b: &[T]) -> Ordering { #[cfg(not(test))] impl<'self,T:TotalOrd> TotalOrd for &'self [T] { - #[inline(always)] + #[inline] fn cmp(&self, other: & &'self [T]) -> Ordering { cmp(*self, *other) } } #[cfg(not(test))] impl TotalOrd for ~[T] { - #[inline(always)] + #[inline] fn cmp(&self, other: &~[T]) -> Ordering { cmp(*self, *other) } } #[cfg(not(test))] impl TotalOrd for @[T] { - #[inline(always)] + #[inline] fn cmp(&self, other: &@[T]) -> Ordering { cmp(*self, *other) } } @@ -1719,37 +1709,37 @@ fn gt(a: &[T], b: &[T]) -> bool { lt(b, a) } #[cfg(not(test))] impl<'self,T:Ord> Ord for &'self [T] { - #[inline(always)] + #[inline] fn lt(&self, other: & &'self [T]) -> bool { lt((*self), (*other)) } - #[inline(always)] + #[inline] fn le(&self, other: & &'self [T]) -> bool { le((*self), (*other)) } - #[inline(always)] + #[inline] fn ge(&self, other: & &'self [T]) -> bool { ge((*self), (*other)) } - #[inline(always)] + #[inline] fn gt(&self, other: & &'self [T]) -> bool { gt((*self), (*other)) } } #[cfg(not(test))] impl Ord for ~[T] { - #[inline(always)] + #[inline] fn lt(&self, other: &~[T]) -> bool { lt((*self), (*other)) } - #[inline(always)] + #[inline] fn le(&self, other: &~[T]) -> bool { le((*self), (*other)) } - #[inline(always)] + #[inline] fn ge(&self, other: &~[T]) -> bool { ge((*self), (*other)) } - #[inline(always)] + #[inline] fn gt(&self, other: &~[T]) -> bool { gt((*self), (*other)) } } #[cfg(not(test))] impl Ord for @[T] { - #[inline(always)] + #[inline] fn lt(&self, other: &@[T]) -> bool { lt((*self), (*other)) } - #[inline(always)] + #[inline] fn le(&self, other: &@[T]) -> bool { le((*self), (*other)) } - #[inline(always)] + #[inline] fn ge(&self, other: &@[T]) -> bool { ge((*self), (*other)) } - #[inline(always)] + #[inline] fn gt(&self, other: &@[T]) -> bool { gt((*self), (*other)) } } @@ -1760,26 +1750,39 @@ pub mod traits { use vec::append; impl<'self,T:Copy> Add<&'self const [T],~[T]> for ~[T] { - #[inline(always)] + #[inline] fn add(&self, rhs: & &'self const [T]) -> ~[T] { append(copy *self, (*rhs)) } } } -impl<'self,T> Container for &'self const [T] { +impl<'self, T> Container for &'self const [T] { /// Returns true if a vector contains no elements #[inline] - fn is_empty(&const self) -> bool { + fn is_empty(&self) -> bool { as_const_buf(*self, |_p, len| len == 0u) } /// Returns the length of a vector #[inline] - fn len(&const self) -> uint { + fn len(&self) -> uint { as_const_buf(*self, |_p, len| len) } +} +impl Container for ~[T] { + /// Returns true if a vector contains no elements + #[inline] + fn is_empty(&self) -> bool { + as_const_buf(*self, |_p, len| len == 0u) + } + + /// Returns the length of a vector + #[inline] + fn len(&self) -> uint { + as_const_buf(*self, |_p, len| len) + } } #[allow(missing_doc)] @@ -1951,7 +1954,7 @@ impl<'self,T> ImmutableVector<'self, T> for &'self [T] { /// Returns a pointer to the element at the given index, without doing /// bounds checking. - #[inline(always)] + #[inline] unsafe fn unsafe_ref(&self, index: uint) -> *T { let (ptr, _): (*T, uint) = transmute(*self); ptr.offset(index) @@ -2022,9 +2025,9 @@ impl<'self,T:Copy> ImmutableCopyableVector for &'self [T] { } /// Returns the element at the given index, without doing bounds checking. - #[inline(always)] + #[inline] unsafe fn unsafe_get(&self, index: uint) -> T { - *self.unsafe_ref(index) + copy *self.unsafe_ref(index) } } @@ -2203,14 +2206,14 @@ impl<'self,T> MutableVector<'self, T> for &'self mut [T] { } } - #[inline(always)] + #[inline] unsafe fn unsafe_mut_ref(&self, index: uint) -> *mut T { let pair_ptr: &(*mut T, uint) = transmute(self); let (ptr, _) = *pair_ptr; ptr.offset(index) } - #[inline(always)] + #[inline] unsafe fn unsafe_set(&self, index: uint, val: T) { *self.unsafe_mut_ref(index) = val; } @@ -2271,7 +2274,7 @@ pub mod raw { * modifing its buffers, so it is up to the caller to ensure that * the vector is actually the specified size. */ - #[inline(always)] + #[inline] pub unsafe fn set_len(v: &mut ~[T], new_len: uint) { let repr: **mut VecRepr = transmute(v); (**repr).unboxed.fill = new_len * sys::nonzero_size_of::(); @@ -2286,7 +2289,7 @@ pub mod raw { * Modifying the vector may cause its buffer to be reallocated, which * would also make any pointers to it invalid. */ - #[inline(always)] + #[inline] pub fn to_ptr(v: &[T]) -> *T { unsafe { let repr: **SliceRepr = transmute(&v); @@ -2295,7 +2298,7 @@ pub mod raw { } /** see `to_ptr()` */ - #[inline(always)] + #[inline] pub fn to_const_ptr(v: &const [T]) -> *const T { unsafe { let repr: **SliceRepr = transmute(&v); @@ -2304,7 +2307,7 @@ pub mod raw { } /** see `to_ptr()` */ - #[inline(always)] + #[inline] pub fn to_mut_ptr(v: &mut [T]) -> *mut T { unsafe { let repr: **SliceRepr = transmute(&v); @@ -2316,7 +2319,7 @@ pub mod raw { * Form a slice from a pointer and length (as a number of units, * not bytes). */ - #[inline(always)] + #[inline] pub unsafe fn buf_as_slice(p: *T, len: uint, f: &fn(v: &[T]) -> U) -> U { @@ -2329,7 +2332,7 @@ pub mod raw { * Form a slice from a pointer and length (as a number of units, * not bytes). */ - #[inline(always)] + #[inline] pub unsafe fn mut_buf_as_slice(p: *mut T, len: uint, f: &fn(v: &mut [T]) -> U) -> U { @@ -2341,9 +2344,9 @@ pub mod raw { /** * Unchecked vector indexing. */ - #[inline(always)] + #[inline] pub unsafe fn get(v: &const [T], i: uint) -> T { - as_const_buf(v, |p, _len| *ptr::const_offset(p, i)) + as_const_buf(v, |p, _len| copy *ptr::const_offset(p, i)) } /** @@ -2351,7 +2354,7 @@ pub mod raw { * old value and hence is only suitable when the vector * is newly allocated. */ - #[inline(always)] + #[inline] pub unsafe fn init_elem(v: &mut [T], i: uint, val: T) { let mut box = Some(val); do as_mut_buf(v) |p, _len| { @@ -2370,7 +2373,7 @@ pub mod raw { * * elts - The number of elements in the buffer */ // Was in raw, but needs to be called by net_tcp::on_tcp_read_cb - #[inline(always)] + #[inline] pub unsafe fn from_buf_raw(ptr: *T, elts: uint) -> ~[T] { let mut dst = with_capacity(elts); set_len(&mut dst, elts); @@ -2384,7 +2387,7 @@ pub mod raw { * Copies `count` bytes from `src` to `dst`. The source and destination * may overlap. */ - #[inline(always)] + #[inline] pub unsafe fn copy_memory(dst: &mut [T], src: &const [T], count: uint) { assert!(dst.len() >= count); @@ -2450,7 +2453,7 @@ pub mod bytes { * Copies `count` bytes from `src` to `dst`. The source and destination * may overlap. */ - #[inline(always)] + #[inline] pub fn copy_memory(dst: &mut [u8], src: &const [u8], count: uint) { // Bound checks are done at vec::raw::copy_memory. unsafe { vec::raw::copy_memory(dst, src, count) } @@ -2461,31 +2464,31 @@ pub mod bytes { // ITERATION TRAIT METHODS impl<'self,A> old_iter::BaseIter for &'self [A] { - #[inline(always)] + #[inline] fn each<'a>(&'a self, blk: &fn(v: &'a A) -> bool) -> bool { each(*self, blk) } - #[inline(always)] + #[inline] fn size_hint(&self) -> Option { Some(self.len()) } } // FIXME(#4148): This should be redundant impl old_iter::BaseIter for ~[A] { - #[inline(always)] + #[inline] fn each<'a>(&'a self, blk: &fn(v: &'a A) -> bool) -> bool { each(*self, blk) } - #[inline(always)] + #[inline] fn size_hint(&self) -> Option { Some(self.len()) } } // FIXME(#4148): This should be redundant impl old_iter::BaseIter for @[A] { - #[inline(always)] + #[inline] fn each<'a>(&'a self, blk: &fn(v: &'a A) -> bool) -> bool { each(*self, blk) } - #[inline(always)] + #[inline] fn size_hint(&self) -> Option { Some(self.len()) } } @@ -2615,23 +2618,6 @@ impl old_iter::CopyableIter for @[A] { } } -impl<'self,A:Copy + Ord> old_iter::CopyableOrderedIter for &'self [A] { - fn min(&self) -> A { old_iter::min(self) } - fn max(&self) -> A { old_iter::max(self) } -} - -// FIXME(#4148): This should be redundant -impl old_iter::CopyableOrderedIter for ~[A] { - fn min(&self) -> A { old_iter::min(self) } - fn max(&self) -> A { old_iter::max(self) } -} - -// FIXME(#4148): This should be redundant -impl old_iter::CopyableOrderedIter for @[A] { - fn min(&self) -> A { old_iter::min(self) } - fn max(&self) -> A { old_iter::max(self) } -} - impl Clone for ~[A] { #[inline] fn clone(&self) -> ~[A] { @@ -2639,6 +2625,22 @@ impl Clone for ~[A] { } } +// This works because every lifetime is a sub-lifetime of 'static +impl<'self, A> Zero for &'self [A] { + fn zero() -> &'self [A] { &'self [] } + fn is_zero(&self) -> bool { self.is_empty() } +} + +impl Zero for ~[A] { + fn zero() -> ~[A] { ~[] } + fn is_zero(&self) -> bool { self.len() == 0 } +} + +impl Zero for @[A] { + fn zero() -> @[A] { @[] } + fn is_zero(&self) -> bool { self.len() == 0 } +} + macro_rules! iterator { /* FIXME: #4375 Cannot attach documentation/attributes to a macro generated struct. (struct $name:ident -> $ptr:ty, $elem:ty) => { @@ -2704,7 +2706,7 @@ pub struct VecMutRevIterator<'self, T> { iterator!{impl VecMutRevIterator -> &'self mut T, -1} impl FromIter for ~[T]{ - #[inline(always)] + #[inline] pub fn from_iter(iter: &fn(f: &fn(T) -> bool) -> bool) -> ~[T] { let mut v = ~[]; for iter |x| { v.push(x) } @@ -4293,4 +4295,20 @@ mod tests { } assert_eq!(v, ~[~[1,2,3],~[1,3,2],~[2,1,3],~[2,3,1],~[3,1,2],~[3,2,1]]); } + + #[test] + fn test_vec_zero() { + use num::Zero; + macro_rules! t ( + ($ty:ty) => { + let v: $ty = Zero::zero(); + assert!(v.is_empty()); + assert!(v.is_zero()); + } + ); + + t!(&[int]); + t!(@[int]); + t!(~[int]); + } } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index e3182916723b..1758433aa737 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -95,7 +95,7 @@ impl Decodable for ident { } impl to_bytes::IterBytes for ident { - #[inline(always)] + #[inline] fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { self.name.iter_bytes(lsb0, f) } diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index cc89db6e1893..a4ded8fea8c4 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -198,7 +198,7 @@ pub fn is_call_expr(e: @expr) -> bool { // This makes def_id hashable impl to_bytes::IterBytes for def_id { - #[inline(always)] + #[inline] fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { self.crate.iter_bytes(lsb0, f) && self.node.iter_bytes(lsb0, f) } @@ -395,30 +395,30 @@ impl id_range { pub fn id_visitor(vfn: @fn(node_id, T)) -> visit::vt { let visit_generics: @fn(&Generics, T) = |generics, t| { for generics.ty_params.each |p| { - vfn(p.id, t); + vfn(p.id, copy t); } for generics.lifetimes.each |p| { - vfn(p.id, t); + vfn(p.id, copy t); } }; visit::mk_vt(@visit::Visitor { visit_mod: |m, sp, id, (t, vt)| { - vfn(id, t); + vfn(id, copy t); visit::visit_mod(m, sp, id, (t, vt)); }, visit_view_item: |vi, (t, vt)| { match vi.node { - view_item_extern_mod(_, _, id) => vfn(id, t), + view_item_extern_mod(_, _, id) => vfn(id, copy t), view_item_use(ref vps) => { for vps.each |vp| { match vp.node { - view_path_simple(_, _, id) => vfn(id, t), - view_path_glob(_, id) => vfn(id, t), + view_path_simple(_, _, id) => vfn(id, copy t), + view_path_glob(_, id) => vfn(id, copy t), view_path_list(_, ref paths, id) => { - vfn(id, t); + vfn(id, copy t); for paths.each |p| { - vfn(p.node.id, t); + vfn(p.node.id, copy t); } } } @@ -429,34 +429,34 @@ pub fn id_visitor(vfn: @fn(node_id, T)) -> visit::vt { }, visit_foreign_item: |ni, (t, vt)| { - vfn(ni.id, t); + vfn(ni.id, copy t); visit::visit_foreign_item(ni, (t, vt)); }, visit_item: |i, (t, vt)| { - vfn(i.id, t); + vfn(i.id, copy t); match i.node { item_enum(ref enum_definition, _) => - for (*enum_definition).variants.each |v| { vfn(v.node.id, t); }, + for (*enum_definition).variants.each |v| { vfn(v.node.id, copy t); }, _ => () } visit::visit_item(i, (t, vt)); }, visit_local: |l, (t, vt)| { - vfn(l.node.id, t); + vfn(l.node.id, copy t); visit::visit_local(l, (t, vt)); }, visit_block: |b, (t, vt)| { - vfn(b.node.id, t); + vfn(b.node.id, copy t); visit::visit_block(b, (t, vt)); }, visit_stmt: |s, (t, vt)| { - vfn(ast_util::stmt_id(s), t); + vfn(ast_util::stmt_id(s), copy t); visit::visit_stmt(s, (t, vt)); }, visit_pat: |p, (t, vt)| { - vfn(p.id, t); + vfn(p.id, copy t); visit::visit_pat(p, (t, vt)); }, @@ -464,36 +464,36 @@ pub fn id_visitor(vfn: @fn(node_id, T)) -> visit::vt { { let r = e.get_callee_id(); for r.iter().advance |callee_id| { - vfn(*callee_id, t); + vfn(*callee_id, copy t); } } - vfn(e.id, t); + vfn(e.id, copy t); visit::visit_expr(e, (t, vt)); }, visit_ty: |ty, (t, vt)| { match ty.node { - ty_path(_, id) => vfn(id, t), + ty_path(_, id) => vfn(id, copy t), _ => { /* fall through */ } } visit::visit_ty(ty, (t, vt)); }, visit_generics: |generics, (t, vt)| { - visit_generics(generics, t); + visit_generics(generics, copy t); visit::visit_generics(generics, (t, vt)); }, visit_fn: |fk, d, a, b, id, (t, vt)| { - vfn(id, t); + vfn(id, copy t); match *fk { visit::fk_item_fn(_, generics, _, _) => { - visit_generics(generics, t); + visit_generics(generics, copy t); } visit::fk_method(_, generics, m) => { - vfn(m.self_id, t); - visit_generics(generics, t); + vfn(m.self_id, copy t); + visit_generics(generics, copy t); } visit::fk_anon(_) | visit::fk_fn_block => { @@ -501,13 +501,13 @@ pub fn id_visitor(vfn: @fn(node_id, T)) -> visit::vt { } for d.inputs.each |arg| { - vfn(arg.id, t) + vfn(arg.id, copy t) } - visit::visit_fn(fk, d, a, b, id, (t, vt)); + visit::visit_fn(fk, d, a, b, id, (copy t, vt)); }, visit_struct_field: |f, (t, vt)| { - vfn(f.node.id, t); + vfn(f.node.id, copy t); visit::visit_struct_field(f, (t, vt)); }, diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index a184d9593908..e096711262fb 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -312,7 +312,7 @@ pub enum inline_attr { /// True if something like #[inline] is found in the list of attrs. pub fn find_inline_attr(attrs: &[ast::attribute]) -> inline_attr { - // FIXME (#2809)---validate the usage of #[inline] and #[inline(always)] + // FIXME (#2809)---validate the usage of #[inline] and #[inline] do attrs.iter().fold(ia_none) |ia,attr| { match attr.node.value.node { ast::meta_word(s) if "inline" == s => ia_hint, diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index 1704b4ef6c5b..e67ca5260b8f 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -318,7 +318,7 @@ pub fn expect(diag: @span_handler, opt: Option, msg: &fn() -> ~str) -> T { match opt { - Some(ref t) => (*t), + Some(ref t) => copy *t, None => diag.handler().bug(msg()) } } diff --git a/src/libsyntax/ext/deriving/generic.rs b/src/libsyntax/ext/deriving/generic.rs index 49b3d3ec861a..22ce305b8575 100644 --- a/src/libsyntax/ext/deriving/generic.rs +++ b/src/libsyntax/ext/deriving/generic.rs @@ -1052,7 +1052,7 @@ f(cx, span, ~[self_1.method(__arg_1_1, __arg_2_1), self_2.method(__arg_1_2, __arg_2_2)]) ~~~ */ -#[inline(always)] +#[inline] pub fn cs_same_method(f: &fn(@ExtCtxt, span, ~[@expr]) -> @expr, enum_nonmatch_f: EnumNonMatchFunc, cx: @ExtCtxt, span: span, @@ -1083,7 +1083,7 @@ Fold together the results of calling the derived method on all the fields. `use_foldl` controls whether this is done left-to-right (`true`) or right-to-left (`false`). */ -#[inline(always)] +#[inline] pub fn cs_same_method_fold(use_foldl: bool, f: &fn(@ExtCtxt, span, @expr, @expr) -> @expr, base: @expr, @@ -1111,7 +1111,7 @@ pub fn cs_same_method_fold(use_foldl: bool, Use a given binop to combine the result of calling the derived method on all the fields. */ -#[inline(always)] +#[inline] pub fn cs_binop(binop: ast::binop, base: @expr, enum_nonmatch_f: EnumNonMatchFunc, cx: @ExtCtxt, span: span, @@ -1130,7 +1130,7 @@ pub fn cs_binop(binop: ast::binop, base: @expr, } /// cs_binop with binop == or -#[inline(always)] +#[inline] pub fn cs_or(enum_nonmatch_f: EnumNonMatchFunc, cx: @ExtCtxt, span: span, substructure: &Substructure) -> @expr { @@ -1139,7 +1139,7 @@ pub fn cs_or(enum_nonmatch_f: EnumNonMatchFunc, cx, span, substructure) } /// cs_binop with binop == and -#[inline(always)] +#[inline] pub fn cs_and(enum_nonmatch_f: EnumNonMatchFunc, cx: @ExtCtxt, span: span, substructure: &Substructure) -> @expr { diff --git a/src/libsyntax/ext/deriving/mod.rs b/src/libsyntax/ext/deriving/mod.rs index 0198ca424d71..f5170d284c60 100644 --- a/src/libsyntax/ext/deriving/mod.rs +++ b/src/libsyntax/ext/deriving/mod.rs @@ -31,6 +31,7 @@ pub mod encodable; pub mod decodable; pub mod rand; pub mod to_str; +pub mod zero; #[path="cmp/eq.rs"] pub mod eq; @@ -98,6 +99,7 @@ pub fn expand_meta_deriving(cx: @ExtCtxt, "Rand" => expand!(rand::expand_deriving_rand), "ToStr" => expand!(to_str::expand_deriving_to_str), + "Zero" => expand!(zero::expand_deriving_zero), ref tname => { cx.span_err(titem.span, fmt!("unknown \ diff --git a/src/libsyntax/ext/deriving/zero.rs b/src/libsyntax/ext/deriving/zero.rs new file mode 100644 index 000000000000..121d8351ee47 --- /dev/null +++ b/src/libsyntax/ext/deriving/zero.rs @@ -0,0 +1,96 @@ +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use core::prelude::*; + +use ast::{meta_item, item, expr}; +use codemap::span; +use ext::base::ExtCtxt; +use ext::build::AstBuilder; +use ext::deriving::generic::*; + +use core::vec; + +pub fn expand_deriving_zero(cx: @ExtCtxt, + span: span, + mitem: @meta_item, + in_items: ~[@item]) + -> ~[@item] { + let trait_def = TraitDef { + path: Path::new(~["std", "num", "Zero"]), + additional_bounds: ~[], + generics: LifetimeBounds::empty(), + methods: ~[ + MethodDef { + name: "zero", + generics: LifetimeBounds::empty(), + explicit_self: None, + args: ~[], + ret_ty: Self, + const_nonmatching: false, + combine_substructure: zero_substructure + }, + MethodDef { + name: "is_zero", + generics: LifetimeBounds::empty(), + explicit_self: borrowed_explicit_self(), + args: ~[], + ret_ty: Literal(Path::new(~["bool"])), + const_nonmatching: false, + combine_substructure: |cx, span, substr| { + cs_and(|cx, span, _, _| cx.span_bug(span, + "Non-matching enum \ + variant in \ + deriving(Zero)"), + cx, span, substr) + } + } + ] + }; + trait_def.expand(cx, span, mitem, in_items) +} + +fn zero_substructure(cx: @ExtCtxt, span: span, substr: &Substructure) -> @expr { + let zero_ident = ~[ + cx.ident_of("std"), + cx.ident_of("num"), + cx.ident_of("Zero"), + cx.ident_of("zero") + ]; + let zero_call = || { + cx.expr_call_global(span, copy zero_ident, ~[]) + }; + + return match *substr.fields { + StaticStruct(_, ref summary) => { + match *summary { + Left(count) => { + if count == 0 { + cx.expr_ident(span, substr.type_ident) + } else { + let exprs = vec::from_fn(count, |_| zero_call()); + cx.expr_call_ident(span, substr.type_ident, exprs) + } + } + Right(ref fields) => { + let zero_fields = do fields.map |ident| { + cx.field_imm(span, *ident, zero_call()) + }; + cx.expr_struct_ident(span, substr.type_ident, zero_fields) + } + } + } + StaticEnum(*) => { + cx.span_fatal(span, "`Zero` cannot be derived for enums, \ + only structs") + } + _ => cx.bug("Non-static method in `deriving(Zero)`") + }; +} diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs index 25166eca7bb0..44e480dc7df2 100644 --- a/src/libsyntax/ext/quote.rs +++ b/src/libsyntax/ext/quote.rs @@ -39,8 +39,6 @@ pub mod rt { use parse; use print::pprust; - use core::str; - pub use ast::*; pub use parse::token::*; pub use parse::new_parser_from_tts; diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 035675e523e7..c1bf979cd319 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -969,7 +969,7 @@ mod test { // change every identifier to "zz" pub fn to_zz() -> @fn(ast::ident)->ast::ident { let zz_id = token::str_to_ident("zz"); - |id| {zz_id} + |_id| {zz_id} } // maybe add to expand.rs... diff --git a/src/libsyntax/opt_vec.rs b/src/libsyntax/opt_vec.rs index 791f7444b622..81f540fd69f2 100644 --- a/src/libsyntax/opt_vec.rs +++ b/src/libsyntax/opt_vec.rs @@ -103,7 +103,7 @@ impl OptVec { } } - #[inline(always)] + #[inline] fn mapi_to_vec(&self, op: &fn(uint, &T) -> B) -> ~[B] { let mut index = 0; old_iter::map_to_vec(self, |a| { @@ -145,31 +145,31 @@ impl BaseIter for OptVec { } impl old_iter::ExtendedIter for OptVec { - #[inline(always)] + #[inline] fn eachi(&self, blk: &fn(v: uint, v: &A) -> bool) -> bool { old_iter::eachi(self, blk) } - #[inline(always)] + #[inline] fn all(&self, blk: &fn(&A) -> bool) -> bool { old_iter::all(self, blk) } - #[inline(always)] + #[inline] fn any(&self, blk: &fn(&A) -> bool) -> bool { old_iter::any(self, blk) } - #[inline(always)] + #[inline] fn foldl(&self, b0: B, blk: &fn(&B, &A) -> B) -> B { old_iter::foldl(self, b0, blk) } - #[inline(always)] + #[inline] fn position(&self, f: &fn(&A) -> bool) -> Option { old_iter::position(self, f) } - #[inline(always)] + #[inline] fn map_to_vec(&self, op: &fn(&A) -> B) -> ~[B] { old_iter::map_to_vec(self, op) } - #[inline(always)] + #[inline] fn flat_map_to_vec>(&self, op: &fn(&A) -> IB) -> ~[B] { old_iter::flat_map_to_vec(self, op) @@ -178,28 +178,21 @@ impl old_iter::ExtendedIter for OptVec { } impl old_iter::EqIter for OptVec { - #[inline(always)] + #[inline] fn contains(&self, x: &A) -> bool { old_iter::contains(self, x) } - #[inline(always)] + #[inline] fn count(&self, x: &A) -> uint { old_iter::count(self, x) } } impl old_iter::CopyableIter for OptVec { - #[inline(always)] + #[inline] fn filter_to_vec(&self, pred: &fn(&A) -> bool) -> ~[A] { old_iter::filter_to_vec(self, pred) } - #[inline(always)] + #[inline] fn to_vec(&self) -> ~[A] { old_iter::to_vec(self) } - #[inline(always)] + #[inline] fn find(&self, f: &fn(&A) -> bool) -> Option { old_iter::find(self, f) } } - -impl old_iter::CopyableOrderedIter for OptVec { - #[inline(always)] - fn min(&self) -> A { old_iter::min(self) } - #[inline(always)] - fn max(&self) -> A { old_iter::max(self) } -} diff --git a/src/libsyntax/parse/comments.rs b/src/libsyntax/parse/comments.rs index b7bb1b3bc535..472f807cd8b6 100644 --- a/src/libsyntax/parse/comments.rs +++ b/src/libsyntax/parse/comments.rs @@ -69,52 +69,59 @@ pub fn strip_doc_comment_decoration(comment: &str) -> ~str { return lines.slice(i, j).to_owned(); } - // drop leftmost columns that contain only values in chars - fn block_trim(lines: ~[~str], chars: ~str, max: Option) -> ~[~str] { - - let mut i = max.get_or_default(uint::max_value); - for lines.each |line| { - if line.trim().is_empty() { - loop; - } + /// remove a "[ \t]*\*" block from each line, if possible + fn horizontal_trim(lines: ~[~str]) -> ~[~str] { + let mut i = uint::max_value; + let mut can_trim = true; + let mut first = true; + for lines.iter().advance |line| { for line.iter().enumerate().advance |(j, c)| { - if j >= i { + if j > i || !"* \t".contains_char(c) { + can_trim = false; break; } - if !chars.contains_char(c) { - i = j; + if c == '*' { + if first { + i = j; + first = false; + } else if i != j { + can_trim = false; + } break; } } + if i > line.len() { + can_trim = false; + } + if !can_trim { + break; + } } - return do lines.map |line| { - let mut chars = ~[]; - for line.iter().advance |c| { chars.push(c) } - if i > chars.len() { - ~"" - } else { - str::from_chars(chars.slice(i, chars.len()).to_owned()) + if can_trim { + do lines.map |line| { + line.slice(i + 1, line.len()).to_owned() } - }; + } else { + lines + } } if comment.starts_with("//") { // FIXME #5475: - // return comment.slice(3u, comment.len()).trim().to_owned(); - let r = comment.slice(3u, comment.len()); return r.trim().to_owned(); - + // return comment.slice(3u, comment.len()).to_owned(); + let r = comment.slice(3u, comment.len()); return r.to_owned(); } if comment.starts_with("/*") { - let mut lines = ~[]; - for str::each_line_any(comment.slice(3u, comment.len() - 2u)) |line| { - lines.push(line.to_owned()) - } + let lines = comment.slice(3u, comment.len() - 2u) + .any_line_iter() + .transform(|s| s.to_owned()) + .collect::<~[~str]>(); + let lines = vertical_trim(lines); - let lines = block_trim(lines, ~"\t ", None); - let lines = block_trim(lines, ~"*", Some(1u)); - let lines = block_trim(lines, ~"\t ", None); + let lines = horizontal_trim(lines); + return lines.connect("\n"); } @@ -372,3 +379,36 @@ pub fn gather_comments_and_literals(span_diagnostic: (comments, literals) } + +#[cfg(test)] +mod test { + use super::*; + + #[test] fn test_block_doc_comment_1() { + let comment = "/**\n * Test \n ** Test\n * Test\n*/"; + let correct_stripped = " Test \n* Test\n Test"; + let stripped = strip_doc_comment_decoration(comment); + assert_eq!(stripped.slice(0, stripped.len()), correct_stripped); + } + + #[test] fn test_block_doc_comment_2() { + let comment = "/**\n * Test\n * Test\n*/"; + let correct_stripped = " Test\n Test"; + let stripped = strip_doc_comment_decoration(comment); + assert_eq!(stripped.slice(0, stripped.len()), correct_stripped); + } + + #[test] fn test_block_doc_comment_3() { + let comment = "/**\n let a: *int;\n *a = 5;\n*/"; + let correct_stripped = " let a: *int;\n *a = 5;"; + let stripped = strip_doc_comment_decoration(comment); + assert_eq!(stripped.slice(0, stripped.len()), correct_stripped); + } + + #[test] fn test_line_doc_comment() { + let comment = "/// Test"; + let correct_stripped = " Test"; + let stripped = strip_doc_comment_decoration(comment); + assert_eq!(stripped.slice(0, stripped.len()), correct_stripped); + } +} diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs index cc7b7fab07e8..bb315bf29339 100644 --- a/src/libsyntax/parse/obsolete.rs +++ b/src/libsyntax/parse/obsolete.rs @@ -68,7 +68,7 @@ pub enum ObsoleteSyntax { } impl to_bytes::IterBytes for ObsoleteSyntax { - #[inline(always)] + #[inline] fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { (*self as uint).iter_bytes(lsb0, f) } diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index e7bc67340f01..273a59f0a3de 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -400,6 +400,7 @@ impl ident_interner { } } + // return a fresh interner, preloaded with special identifiers. fn mk_fresh_ident_interner() -> @ident_interner { // the indices here must correspond to the numbers in @@ -446,39 +447,38 @@ fn mk_fresh_ident_interner() -> @ident_interner { "const", // 37 "copy", // 38 "do", // 39 - "drop", // 40 - "else", // 41 - "enum", // 42 - "extern", // 43 - "false", // 44 - "fn", // 45 - "for", // 46 - "if", // 47 - "impl", // 48 - "let", // 49 - "__log", // 50 - "loop", // 51 - "match", // 52 - "mod", // 53 - "mut", // 54 - "once", // 55 - "priv", // 56 - "pub", // 57 - "pure", // 58 - "ref", // 59 - "return", // 60 + "else", // 40 + "enum", // 41 + "extern", // 42 + "false", // 43 + "fn", // 44 + "for", // 45 + "if", // 46 + "impl", // 47 + "let", // 48 + "__log", // 49 + "loop", // 50 + "match", // 51 + "mod", // 52 + "mut", // 53 + "once", // 54 + "priv", // 55 + "pub", // 56 + "pure", // 57 + "ref", // 58 + "return", // 59 "static", // 29 -- also a special ident "self", // 8 -- also a special ident - "struct", // 61 - "super", // 62 - "true", // 63 - "trait", // 64 - "type", // 65 - "unsafe", // 66 - "use", // 67 - "while", // 68 + "struct", // 60 + "super", // 61 + "true", // 62 + "trait", // 63 + "type", // 64 + "unsafe", // 65 + "use", // 66 + "while", // 67 - "be", // 69 + "be", // 68 ]; @ident_interner { @@ -498,9 +498,7 @@ pub fn get_ident_interner() -> @ident_interner { Some(interner) => *interner, None => { let interner = mk_fresh_ident_interner(); - unsafe { - local_data::local_data_set(key, @interner); - } + local_data::local_data_set(key, @interner); interner } } @@ -615,41 +613,41 @@ pub mod keywords { pub fn to_ident(&self) -> ident { match *self { As => ident { name: 35, ctxt: 0 }, - Break => ident { name: 36, ctxt: 0 }, - Const => ident { name: 37, ctxt: 0 }, - Copy => ident { name: 38, ctxt: 0 }, - Do => ident { name: 39, ctxt: 0 }, - Else => ident { name: 41, ctxt: 0 }, - Enum => ident { name: 42, ctxt: 0 }, - Extern => ident { name: 43, ctxt: 0 }, - False => ident { name: 44, ctxt: 0 }, - Fn => ident { name: 45, ctxt: 0 }, - For => ident { name: 46, ctxt: 0 }, - If => ident { name: 47, ctxt: 0 }, - Impl => ident { name: 48, ctxt: 0 }, - Let => ident { name: 49, ctxt: 0 }, - __Log => ident { name: 50, ctxt: 0 }, - Loop => ident { name: 51, ctxt: 0 }, - Match => ident { name: 52, ctxt: 0 }, - Mod => ident { name: 53, ctxt: 0 }, - Mut => ident { name: 54, ctxt: 0 }, - Once => ident { name: 55, ctxt: 0 }, - Priv => ident { name: 56, ctxt: 0 }, - Pub => ident { name: 57, ctxt: 0 }, - Pure => ident { name: 58, ctxt: 0 }, - Ref => ident { name: 59, ctxt: 0 }, - Return => ident { name: 60, ctxt: 0 }, - Static => ident { name: 29, ctxt: 0 }, - Self => ident { name: 8, ctxt: 0 }, - Struct => ident { name: 61, ctxt: 0 }, - Super => ident { name: 62, ctxt: 0 }, - True => ident { name: 63, ctxt: 0 }, - Trait => ident { name: 64, ctxt: 0 }, - Type => ident { name: 65, ctxt: 0 }, - Unsafe => ident { name: 66, ctxt: 0 }, - Use => ident { name: 67, ctxt: 0 }, - While => ident { name: 68, ctxt: 0 }, - Be => ident { name: 69, ctxt: 0 }, + Break => ident { name: 36, ctxt: 0 }, + Const => ident { name: 37, ctxt: 0 }, + Copy => ident { name: 38, ctxt: 0 }, + Do => ident { name: 39, ctxt: 0 }, + Else => ident { name: 40, ctxt: 0 }, + Enum => ident { name: 41, ctxt: 0 }, + Extern => ident { name: 42, ctxt: 0 }, + False => ident { name: 43, ctxt: 0 }, + Fn => ident { name: 44, ctxt: 0 }, + For => ident { name: 45, ctxt: 0 }, + If => ident { name: 46, ctxt: 0 }, + Impl => ident { name: 47, ctxt: 0 }, + Let => ident { name: 48, ctxt: 0 }, + __Log => ident { name: 49, ctxt: 0 }, + Loop => ident { name: 50, ctxt: 0 }, + Match => ident { name: 51, ctxt: 0 }, + Mod => ident { name: 52, ctxt: 0 }, + Mut => ident { name: 53, ctxt: 0 }, + Once => ident { name: 54, ctxt: 0 }, + Priv => ident { name: 55, ctxt: 0 }, + Pub => ident { name: 56, ctxt: 0 }, + Pure => ident { name: 57, ctxt: 0 }, + Ref => ident { name: 58, ctxt: 0 }, + Return => ident { name: 59, ctxt: 0 }, + Static => ident { name: 29, ctxt: 0 }, + Self => ident { name: 8, ctxt: 0 }, + Struct => ident { name: 60, ctxt: 0 }, + Super => ident { name: 61, ctxt: 0 }, + True => ident { name: 62, ctxt: 0 }, + Trait => ident { name: 63, ctxt: 0 }, + Type => ident { name: 64, ctxt: 0 }, + Unsafe => ident { name: 65, ctxt: 0 }, + Use => ident { name: 66, ctxt: 0 }, + While => ident { name: 67, ctxt: 0 }, + Be => ident { name: 68, ctxt: 0 }, } } } @@ -665,7 +663,7 @@ pub fn is_keyword(kw: keywords::Keyword, tok: &Token) -> bool { pub fn is_any_keyword(tok: &Token) -> bool { match *tok { token::IDENT(sid, false) => match sid.name { - 8 | 29 | 35 .. 69 => true, + 8 | 29 | 35 .. 68 => true, _ => false, }, _ => false @@ -675,7 +673,7 @@ pub fn is_any_keyword(tok: &Token) -> bool { pub fn is_strict_keyword(tok: &Token) -> bool { match *tok { token::IDENT(sid, false) => match sid.name { - 8 | 29 | 35 .. 68 => true, + 8 | 29 | 35 .. 67 => true, _ => false, }, _ => false, @@ -685,13 +683,14 @@ pub fn is_strict_keyword(tok: &Token) -> bool { pub fn is_reserved_keyword(tok: &Token) -> bool { match *tok { token::IDENT(sid, false) => match sid.name { - 69 => true, + 68 => true, _ => false, }, _ => false, } } + #[cfg(test)] mod test { use super::*; diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 7eec9e2ee896..e72d9b502dcd 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -322,7 +322,7 @@ pub fn commasep(s: @ps, b: breaks, elts: &[IN], op: &fn(@ps, IN)) { let mut first = true; for elts.each |elt| { if first { first = false; } else { word_space(s, ","); } - op(s, *elt); + op(s, copy *elt); } end(s); } @@ -334,13 +334,13 @@ pub fn commasep_cmnt(s: @ps, b: breaks, elts: &[IN], op: &fn(@ps, IN), let len = elts.len(); let mut i = 0u; for elts.each |elt| { - maybe_print_comment(s, get_span(*elt).hi); - op(s, *elt); + maybe_print_comment(s, get_span(copy *elt).hi); + op(s, copy *elt); i += 1u; if i < len { word(s.s, ","); - maybe_print_trailing_comment(s, get_span(*elt), - Some(get_span(elts[i]).hi)); + maybe_print_trailing_comment(s, get_span(copy *elt), + Some(get_span(copy elts[i]).hi)); space_if_not_bol(s); } } @@ -2118,7 +2118,7 @@ pub fn print_string(s: @ps, st: &str) { pub fn to_str(t: T, f: @fn(@ps, T), intr: @ident_interner) -> ~str { do io::with_str_writer |wr| { let s = rust_printer(wr, intr); - f(s, t); + f(s, copy t); eof(s.s); } } diff --git a/src/libsyntax/syntax.rc b/src/libsyntax/syntax.rc index 78fbcab213c8..278600bc0394 100644 --- a/src/libsyntax/syntax.rc +++ b/src/libsyntax/syntax.rc @@ -30,17 +30,8 @@ extern mod core(name = "std"); extern mod extra(name = "extra"); // For deriving(Encodable) purposes... -#[cfg(stage0)] -extern mod std(name = "extra"); -#[cfg(not(stage0))] extern mod std(name = "std"); -// For bootstrapping purposes. -#[cfg(stage0)] -pub use core::str; -#[cfg(stage0)] -pub use core::unstable; - use core::prelude::*; pub mod util { diff --git a/src/libsyntax/util/interner.rs b/src/libsyntax/util/interner.rs index d4f183ada7b6..bd5c178e7fe7 100644 --- a/src/libsyntax/util/interner.rs +++ b/src/libsyntax/util/interner.rs @@ -36,7 +36,7 @@ impl Interner { pub fn prefill(init: &[T]) -> Interner { let rv = Interner::new(); - for init.each() |v| { rv.intern(*v); } + for init.each() |v| { rv.intern(copy *v); } rv } @@ -48,7 +48,7 @@ impl Interner { let vect = &mut *self.vect; let new_idx = vect.len(); - self.map.insert(val, new_idx); + self.map.insert(copy val, new_idx); vect.push(val); new_idx } @@ -63,7 +63,7 @@ impl Interner { new_idx } - pub fn get(&self, idx: uint) -> T { self.vect[idx] } + pub fn get(&self, idx: uint) -> T { copy self.vect[idx] } pub fn len(&self) -> uint { let vect = &*self.vect; vect.len() } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 6e753a8cc58e..f24c393d7b48 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -127,15 +127,15 @@ pub fn visit_crate(c: &crate, (e, v): (E, vt)) { } pub fn visit_mod(m: &_mod, _sp: span, _id: node_id, (e, v): (E, vt)) { - for m.view_items.each |vi| { (v.visit_view_item)(*vi, (e, v)); } - for m.items.each |i| { (v.visit_item)(*i, (e, v)); } + for m.view_items.each |vi| { (v.visit_view_item)(*vi, (copy e, v)); } + for m.items.each |i| { (v.visit_item)(*i, (copy e, v)); } } pub fn visit_view_item(_vi: @view_item, (_e, _v): (E, vt)) { } pub fn visit_local(loc: @local, (e, v): (E, vt)) { - (v.visit_pat)(loc.node.pat, (e, v)); - (v.visit_ty)(loc.node.ty, (e, v)); + (v.visit_pat)(loc.node.pat, (copy e, v)); + (v.visit_ty)(loc.node.ty, (copy e, v)); match loc.node.init { None => (), Some(ex) => (v.visit_expr)(ex, (e, v)) @@ -149,8 +149,8 @@ fn visit_trait_ref(tref: @ast::trait_ref, (e, v): (E, vt)) { pub fn visit_item(i: @item, (e, v): (E, vt)) { match i.node { item_const(t, ex) => { - (v.visit_ty)(t, (e, v)); - (v.visit_expr)(ex, (e, v)); + (v.visit_ty)(t, (copy e, v)); + (v.visit_expr)(ex, (copy e, v)); } item_fn(ref decl, purity, abi, ref generics, ref body) => { (v.visit_fn)( @@ -170,15 +170,15 @@ pub fn visit_item(i: @item, (e, v): (E, vt)) { } item_mod(ref m) => (v.visit_mod)(m, i.span, i.id, (e, v)), item_foreign_mod(ref nm) => { - for nm.view_items.each |vi| { (v.visit_view_item)(*vi, (e, v)); } - for nm.items.each |ni| { (v.visit_foreign_item)(*ni, (e, v)); } + for nm.view_items.each |vi| { (v.visit_view_item)(*vi, (copy e, v)); } + for nm.items.each |ni| { (v.visit_foreign_item)(*ni, (copy e, v)); } } item_ty(t, ref tps) => { - (v.visit_ty)(t, (e, v)); + (v.visit_ty)(t, (copy e, v)); (v.visit_generics)(tps, (e, v)); } item_enum(ref enum_definition, ref tps) => { - (v.visit_generics)(tps, (e, v)); + (v.visit_generics)(tps, (copy e, v)); visit_enum_def( enum_definition, tps, @@ -186,24 +186,24 @@ pub fn visit_item(i: @item, (e, v): (E, vt)) { ); } item_impl(ref tps, ref traits, ty, ref methods) => { - (v.visit_generics)(tps, (e, v)); + (v.visit_generics)(tps, (copy e, v)); for traits.iter().advance |&p| { - visit_trait_ref(p, (e, v)); + visit_trait_ref(p, (copy e, v)); } - (v.visit_ty)(ty, (e, v)); + (v.visit_ty)(ty, (copy e, v)); for methods.each |m| { - visit_method_helper(*m, (e, v)) + visit_method_helper(*m, (copy e, v)) } } item_struct(struct_def, ref generics) => { - (v.visit_generics)(generics, (e, v)); + (v.visit_generics)(generics, (copy e, v)); (v.visit_struct_def)(struct_def, i.ident, generics, i.id, (e, v)); } item_trait(ref generics, ref traits, ref methods) => { - (v.visit_generics)(generics, (e, v)); - for traits.each |p| { visit_path(p.path, (e, v)); } + (v.visit_generics)(generics, (copy e, v)); + for traits.each |p| { visit_path(p.path, (copy e, v)); } for methods.each |m| { - (v.visit_trait_method)(m, (e, v)); + (v.visit_trait_method)(m, (copy e, v)); } } item_mac(ref m) => visit_mac(m, (e, v)) @@ -216,15 +216,19 @@ pub fn visit_enum_def(enum_definition: &ast::enum_def, for enum_definition.variants.each |vr| { match vr.node.kind { tuple_variant_kind(ref variant_args) => { - for variant_args.each |va| { (v.visit_ty)(va.ty, (e, v)); } + for variant_args.each |va| { + (v.visit_ty)(va.ty, (copy e, v)); + } } struct_variant_kind(struct_def) => { (v.visit_struct_def)(struct_def, vr.node.name, tps, - vr.node.id, (e, v)); + vr.node.id, (copy e, v)); } } // Visit the disr expr if it exists - for vr.node.disr_expr.iter().advance |ex| { (v.visit_expr)(*ex, (e, v)) } + for vr.node.disr_expr.iter().advance |ex| { + (v.visit_expr)(*ex, (copy e, v)) + } } } @@ -238,71 +242,75 @@ pub fn visit_ty(t: @Ty, (e, v): (E, vt)) { }, ty_tup(ref ts) => { for ts.each |tt| { - (v.visit_ty)(*tt, (e, v)); + (v.visit_ty)(*tt, (copy e, v)); } }, ty_closure(ref f) => { - for f.decl.inputs.each |a| { (v.visit_ty)(a.ty, (e, v)); } + for f.decl.inputs.each |a| { (v.visit_ty)(a.ty, (copy e, v)); } (v.visit_ty)(f.decl.output, (e, v)); }, ty_bare_fn(ref f) => { - for f.decl.inputs.each |a| { (v.visit_ty)(a.ty, (e, v)); } + for f.decl.inputs.each |a| { (v.visit_ty)(a.ty, (copy e, v)); } (v.visit_ty)(f.decl.output, (e, v)); }, ty_path(p, _) => visit_path(p, (e, v)), ty_fixed_length_vec(ref mt, ex) => { - (v.visit_ty)(mt.ty, (e, v)); - (v.visit_expr)(ex, (e, v)); + (v.visit_ty)(mt.ty, (copy e, v)); + (v.visit_expr)(ex, (copy e, v)); }, ty_nil | ty_bot | ty_mac(_) | ty_infer => () } } pub fn visit_path(p: @Path, (e, v): (E, vt)) { - for p.types.each |tp| { (v.visit_ty)(*tp, (e, v)); } + for p.types.each |tp| { (v.visit_ty)(*tp, (copy e, v)); } } pub fn visit_pat(p: @pat, (e, v): (E, vt)) { match p.node { pat_enum(path, ref children) => { - visit_path(path, (e, v)); + visit_path(path, (copy e, v)); for children.iter().advance |children| { - for children.iter().advance |child| { (v.visit_pat)(*child, (e, v)); } + for children.iter().advance |child| { + (v.visit_pat)(*child, (copy e, v)); + } } } pat_struct(path, ref fields, _) => { - visit_path(path, (e, v)); + visit_path(path, (copy e, v)); for fields.each |f| { - (v.visit_pat)(f.pat, (e, v)); + (v.visit_pat)(f.pat, (copy e, v)); } } pat_tup(ref elts) => { for elts.each |elt| { - (v.visit_pat)(*elt, (e, v)) + (v.visit_pat)(*elt, (copy e, v)) } }, pat_box(inner) | pat_uniq(inner) | pat_region(inner) => { (v.visit_pat)(inner, (e, v)) }, pat_ident(_, path, ref inner) => { - visit_path(path, (e, v)); - for inner.iter().advance |subpat| { (v.visit_pat)(*subpat, (e, v)) } + visit_path(path, (copy e, v)); + for inner.iter().advance |subpat| { + (v.visit_pat)(*subpat, (copy e, v)) + } } pat_lit(ex) => (v.visit_expr)(ex, (e, v)), pat_range(e1, e2) => { - (v.visit_expr)(e1, (e, v)); + (v.visit_expr)(e1, (copy e, v)); (v.visit_expr)(e2, (e, v)); } pat_wild => (), pat_vec(ref before, ref slice, ref after) => { for before.each |elt| { - (v.visit_pat)(*elt, (e, v)); + (v.visit_pat)(*elt, (copy e, v)); } for slice.iter().advance |elt| { - (v.visit_pat)(*elt, (e, v)); + (v.visit_pat)(*elt, (copy e, v)); } for after.each |tail| { - (v.visit_pat)(*tail, (e, v)); + (v.visit_pat)(*tail, (copy e, v)); } } } @@ -311,7 +319,7 @@ pub fn visit_pat(p: @pat, (e, v): (E, vt)) { pub fn visit_foreign_item(ni: @foreign_item, (e, v): (E, vt)) { match ni.node { foreign_item_fn(ref fd, _, ref generics) => { - visit_fn_decl(fd, (e, v)); + visit_fn_decl(fd, (copy e, v)); (v.visit_generics)(generics, (e, v)); } foreign_item_const(t) => { @@ -324,7 +332,7 @@ pub fn visit_ty_param_bounds(bounds: @OptVec, (e, v): (E, vt)) { for bounds.each |bound| { match *bound { - TraitTyParamBound(ty) => visit_trait_ref(ty, (e, v)), + TraitTyParamBound(ty) => visit_trait_ref(ty, (copy e, v)), RegionTyParamBound => {} } } @@ -332,14 +340,14 @@ pub fn visit_ty_param_bounds(bounds: @OptVec, pub fn visit_generics(generics: &Generics, (e, v): (E, vt)) { for generics.ty_params.each |tp| { - visit_ty_param_bounds(tp.bounds, (e, v)); + visit_ty_param_bounds(tp.bounds, (copy e, v)); } } pub fn visit_fn_decl(fd: &fn_decl, (e, v): (E, vt)) { for fd.inputs.each |a| { - (v.visit_pat)(a.pat, (e, v)); - (v.visit_ty)(a.ty, (e, v)); + (v.visit_pat)(a.pat, (copy e, v)); + (v.visit_ty)(a.ty, (copy e, v)); } (v.visit_ty)(fd.output, (e, v)); } @@ -365,15 +373,15 @@ pub fn visit_method_helper(m: &method, (e, v): (E, vt)) { pub fn visit_fn(fk: &fn_kind, decl: &fn_decl, body: &blk, _sp: span, _id: node_id, (e, v): (E, vt)) { - visit_fn_decl(decl, (e, v)); + visit_fn_decl(decl, (copy e, v)); let generics = generics_of_fn(fk); - (v.visit_generics)(&generics, (e, v)); + (v.visit_generics)(&generics, (copy e, v)); (v.visit_block)(body, (e, v)); } pub fn visit_ty_method(m: &ty_method, (e, v): (E, vt)) { - for m.decl.inputs.each |a| { (v.visit_ty)(a.ty, (e, v)); } - (v.visit_generics)(&m.generics, (e, v)); + for m.decl.inputs.each |a| { (v.visit_ty)(a.ty, (copy e, v)); } + (v.visit_generics)(&m.generics, (copy e, v)); (v.visit_ty)(m.decl.output, (e, v)); } @@ -392,7 +400,7 @@ pub fn visit_struct_def( (e, v): (E, vt) ) { for sd.fields.each |f| { - (v.visit_struct_field)(*f, (e, v)); + (v.visit_struct_field)(*f, (copy e, v)); } } @@ -406,10 +414,10 @@ pub fn visit_struct_method(m: @method, (e, v): (E, vt)) { pub fn visit_block(b: &blk, (e, v): (E, vt)) { for b.node.view_items.each |vi| { - (v.visit_view_item)(*vi, (e, v)); + (v.visit_view_item)(*vi, (copy e, v)); } for b.node.stmts.each |s| { - (v.visit_stmt)(*s, (e, v)); + (v.visit_stmt)(*s, (copy e, v)); } visit_expr_opt(b.node.expr, (e, v)); } @@ -435,7 +443,7 @@ pub fn visit_expr_opt(eo: Option<@expr>, (e, v): (E, vt)) { } pub fn visit_exprs(exprs: &[@expr], (e, v): (E, vt)) { - for exprs.each |ex| { (v.visit_expr)(*ex, (e, v)); } + for exprs.each |ex| { (v.visit_expr)(*ex, (copy e, v)); } } pub fn visit_mac(_m: &mac, (_e, _v): (E, vt)) { @@ -444,53 +452,57 @@ pub fn visit_mac(_m: &mac, (_e, _v): (E, vt)) { pub fn visit_expr(ex: @expr, (e, v): (E, vt)) { match ex.node { - expr_vstore(x, _) => (v.visit_expr)(x, (e, v)), - expr_vec(ref es, _) => visit_exprs(*es, (e, v)), + expr_vstore(x, _) => (v.visit_expr)(x, (copy e, v)), + expr_vec(ref es, _) => visit_exprs(*es, (copy e, v)), expr_repeat(element, count, _) => { - (v.visit_expr)(element, (e, v)); - (v.visit_expr)(count, (e, v)); + (v.visit_expr)(element, (copy e, v)); + (v.visit_expr)(count, (copy e, v)); } expr_struct(p, ref flds, base) => { - visit_path(p, (e, v)); - for flds.each |f| { (v.visit_expr)(f.node.expr, (e, v)); } - visit_expr_opt(base, (e, v)); + visit_path(p, (copy e, v)); + for flds.each |f| { + (v.visit_expr)(f.node.expr, (copy e, v)); + } + visit_expr_opt(base, (copy e, v)); } expr_tup(ref elts) => { - for elts.each |el| { (v.visit_expr)(*el, (e, v)) } + for elts.each |el| { (v.visit_expr)(*el, (copy e, v)) } } expr_call(callee, ref args, _) => { - visit_exprs(*args, (e, v)); - (v.visit_expr)(callee, (e, v)); + visit_exprs(*args, (copy e, v)); + (v.visit_expr)(callee, (copy e, v)); } expr_method_call(_, callee, _, ref tys, ref args, _) => { - visit_exprs(*args, (e, v)); - for tys.each |tp| { (v.visit_ty)(*tp, (e, v)); } - (v.visit_expr)(callee, (e, v)); + visit_exprs(*args, (copy e, v)); + for tys.each |tp| { + (v.visit_ty)(*tp, (copy e, v)); + } + (v.visit_expr)(callee, (copy e, v)); } expr_binary(_, _, a, b) => { - (v.visit_expr)(a, (e, v)); - (v.visit_expr)(b, (e, v)); + (v.visit_expr)(a, (copy e, v)); + (v.visit_expr)(b, (copy e, v)); } expr_addr_of(_, x) | expr_unary(_, _, x) | - expr_loop_body(x) | expr_do_body(x) => (v.visit_expr)(x, (e, v)), + expr_loop_body(x) | expr_do_body(x) => (v.visit_expr)(x, (copy e, v)), expr_lit(_) => (), expr_cast(x, t) => { - (v.visit_expr)(x, (e, v)); - (v.visit_ty)(t, (e, v)); + (v.visit_expr)(x, (copy e, v)); + (v.visit_ty)(t, (copy e, v)); } expr_if(x, ref b, eo) => { - (v.visit_expr)(x, (e, v)); - (v.visit_block)(b, (e, v)); - visit_expr_opt(eo, (e, v)); + (v.visit_expr)(x, (copy e, v)); + (v.visit_block)(b, (copy e, v)); + visit_expr_opt(eo, (copy e, v)); } expr_while(x, ref b) => { - (v.visit_expr)(x, (e, v)); - (v.visit_block)(b, (e, v)); + (v.visit_expr)(x, (copy e, v)); + (v.visit_block)(b, (copy e, v)); } - expr_loop(ref b, _) => (v.visit_block)(b, (e, v)), + expr_loop(ref b, _) => (v.visit_block)(b, (copy e, v)), expr_match(x, ref arms) => { - (v.visit_expr)(x, (e, v)); - for arms.each |a| { (v.visit_arm)(a, (e, v)); } + (v.visit_expr)(x, (copy e, v)); + for arms.each |a| { (v.visit_arm)(a, (copy e, v)); } } expr_fn_block(ref decl, ref body) => { (v.visit_fn)( @@ -499,44 +511,46 @@ pub fn visit_expr(ex: @expr, (e, v): (E, vt)) { body, ex.span, ex.id, - (e, v) + (copy e, v) ); } - expr_block(ref b) => (v.visit_block)(b, (e, v)), + expr_block(ref b) => (v.visit_block)(b, (copy e, v)), expr_assign(a, b) => { - (v.visit_expr)(b, (e, v)); - (v.visit_expr)(a, (e, v)); + (v.visit_expr)(b, (copy e, v)); + (v.visit_expr)(a, (copy e, v)); } - expr_copy(a) => (v.visit_expr)(a, (e, v)), + expr_copy(a) => (v.visit_expr)(a, (copy e, v)), expr_assign_op(_, _, a, b) => { - (v.visit_expr)(b, (e, v)); - (v.visit_expr)(a, (e, v)); + (v.visit_expr)(b, (copy e, v)); + (v.visit_expr)(a, (copy e, v)); } expr_field(x, _, ref tys) => { - (v.visit_expr)(x, (e, v)); - for tys.each |tp| { (v.visit_ty)(*tp, (e, v)); } + (v.visit_expr)(x, (copy e, v)); + for tys.each |tp| { + (v.visit_ty)(*tp, (copy e, v)); + } } expr_index(_, a, b) => { - (v.visit_expr)(a, (e, v)); - (v.visit_expr)(b, (e, v)); + (v.visit_expr)(a, (copy e, v)); + (v.visit_expr)(b, (copy e, v)); } - expr_path(p) => visit_path(p, (e, v)), + expr_path(p) => visit_path(p, (copy e, v)), expr_self => (), expr_break(_) => (), expr_again(_) => (), - expr_ret(eo) => visit_expr_opt(eo, (e, v)), + expr_ret(eo) => visit_expr_opt(eo, (copy e, v)), expr_log(lv, x) => { - (v.visit_expr)(lv, (e, v)); - (v.visit_expr)(x, (e, v)); + (v.visit_expr)(lv, (copy e, v)); + (v.visit_expr)(x, (copy e, v)); } - expr_mac(ref mac) => visit_mac(mac, (e, v)), - expr_paren(x) => (v.visit_expr)(x, (e, v)), + expr_mac(ref mac) => visit_mac(mac, (copy e, v)), + expr_paren(x) => (v.visit_expr)(x, (copy e, v)), expr_inline_asm(ref a) => { for a.inputs.each |&(_, in)| { - (v.visit_expr)(in, (e, v)); + (v.visit_expr)(in, (copy e, v)); } for a.outputs.each |&(_, out)| { - (v.visit_expr)(out, (e, v)); + (v.visit_expr)(out, (copy e, v)); } } } @@ -544,9 +558,9 @@ pub fn visit_expr(ex: @expr, (e, v): (E, vt)) { } pub fn visit_arm(a: &arm, (e, v): (E, vt)) { - for a.pats.iter().advance |p| { (v.visit_pat)(*p, (e, v)); } - visit_expr_opt(a.guard, (e, v)); - (v.visit_block)(&a.body, (e, v)); + for a.pats.iter().advance |p| { (v.visit_pat)(*p, (copy e, v)); } + visit_expr_opt(a.guard, (copy e, v)); + (v.visit_block)(&a.body, (copy e, v)); } // Simpler, non-context passing interface. Always walks the whole tree, simply diff --git a/src/rt/arch/i386/morestack.S b/src/rt/arch/i386/morestack.S index 1b2768208056..a95e183a1d12 100644 --- a/src/rt/arch/i386/morestack.S +++ b/src/rt/arch/i386/morestack.S @@ -207,12 +207,14 @@ MORESTACK: subl $12, %esp // Save the return value of the function we allocated space for + movl %edx, 4(%esp) movl %eax, (%esp) call UPCALL_DEL_STACK // And restore it movl (%esp), %eax + movl 4(%esp), %edx addl $12,%esp diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp index fe4e75fb8d21..51e2849eb548 100644 --- a/src/rt/rust_builtin.cpp +++ b/src/rt/rust_builtin.cpp @@ -17,6 +17,7 @@ #include "sync/timer.h" #include "sync/rust_thread.h" #include "rust_abi.h" +#include "vg/valgrind.h" #include @@ -67,11 +68,10 @@ rust_env_pairs() { } #endif -extern "C" CDECL void -vec_reserve_shared_actual(type_desc* ty, rust_vec_box** vp, - size_t n_elts) { +extern "C" CDECL void * +rust_local_realloc(rust_opaque_box *ptr, size_t size) { rust_task *task = rust_get_current_task(); - reserve_vec_exact_shared(task, vp, n_elts * ty->size); + return task->boxed.realloc(ptr, size); } // This is completely misnamed. @@ -590,12 +590,18 @@ rust_log_console_on() { log_console_on(); } -extern void log_console_off(rust_env *env); +extern void log_console_off(); extern "C" CDECL void rust_log_console_off() { - rust_task *task = rust_get_current_task(); - log_console_off(task->kernel->env); + log_console_off(); +} + +extern bool should_log_console(); + +extern "C" CDECL uintptr_t +rust_should_log_console() { + return (uintptr_t)should_log_console(); } extern "C" CDECL void @@ -731,17 +737,10 @@ rust_task_deref(rust_task *task) { // Must call on rust stack. extern "C" CDECL void rust_call_tydesc_glue(void *root, size_t *tydesc, size_t glue_index) { -#ifdef _RUST_STAGE0 - void (*glue_fn)(void *, void *, void *, void *) = - (void (*)(void *, void *, void *, void *))tydesc[glue_index]; - if (glue_fn) - glue_fn(0, 0, 0, root); -#else void (*glue_fn)(void *, void *, void *) = (void (*)(void *, void *, void *))tydesc[glue_index]; if (glue_fn) glue_fn(0, 0, root); -#endif } // Don't run on the Rust stack! @@ -761,11 +760,7 @@ public: virtual void run() { record_sp_limit(0); -#ifdef _RUST_STAGE0 - fn.f(NULL, fn.env, NULL); -#else fn.f(fn.env, NULL); -#endif } }; @@ -887,6 +882,12 @@ rust_delete_memory_region(memory_region *region) { delete region; } +extern "C" CDECL boxed_region* +rust_current_boxed_region() { + rust_task *task = rust_get_current_task(); + return &task->boxed; +} + extern "C" CDECL boxed_region* rust_new_boxed_region(memory_region *region, uintptr_t poison_on_free) { @@ -903,6 +904,11 @@ rust_boxed_region_malloc(boxed_region *region, type_desc *td, size_t size) { return region->malloc(td, size); } +extern "C" CDECL rust_opaque_box* +rust_boxed_region_realloc(boxed_region *region, rust_opaque_box *ptr, size_t size) { + return region->realloc(ptr, size); +} + extern "C" CDECL void rust_boxed_region_free(boxed_region *region, rust_opaque_box *box) { region->free(box); @@ -930,6 +936,11 @@ rust_begin_unwind(uintptr_t token) { #endif } +extern "C" CDECL uintptr_t +rust_running_on_valgrind() { + return RUNNING_ON_VALGRIND; +} + extern int get_num_cpus(); extern "C" CDECL uintptr_t @@ -937,6 +948,24 @@ rust_get_num_cpus() { return get_num_cpus(); } +static lock_and_signal global_args_lock; +static uintptr_t global_args_ptr = 0; + +extern "C" CDECL void +rust_take_global_args_lock() { + global_args_lock.lock(); +} + +extern "C" CDECL void +rust_drop_global_args_lock() { + global_args_lock.unlock(); +} + +extern "C" CDECL uintptr_t* +rust_get_global_args_ptr() { + return &global_args_ptr; +} + // // Local Variables: // mode: C++ diff --git a/src/rt/rust_gc_metadata.cpp b/src/rt/rust_gc_metadata.cpp index fbf0575b31dc..e37856255a7d 100644 --- a/src/rt/rust_gc_metadata.cpp +++ b/src/rt/rust_gc_metadata.cpp @@ -79,6 +79,11 @@ rust_gc_metadata() { return (void *)global_safe_points; } +extern "C" CDECL void +rust_update_gc_metadata(const void* map) { + update_gc_metadata(map); +} + // // Local Variables: // mode: C++ diff --git a/src/rt/rust_log.cpp b/src/rt/rust_log.cpp index df24f569495b..8179c53e96d5 100644 --- a/src/rt/rust_log.cpp +++ b/src/rt/rust_log.cpp @@ -43,11 +43,15 @@ log_console_on() { * overridden by the environment. */ void -log_console_off(rust_env *env) { +log_console_off() { scoped_lock with(_log_lock); - if (env->logspec == NULL) { - _log_to_console = false; - } + _log_to_console = false; +} + +bool +should_log_console() { + scoped_lock with(_log_lock); + return _log_to_console; } rust_log::rust_log(rust_sched_loop *sched_loop) : diff --git a/src/rt/rust_task.cpp b/src/rt/rust_task.cpp index f9b588b78501..fe1b4622137e 100644 --- a/src/rt/rust_task.cpp +++ b/src/rt/rust_task.cpp @@ -162,11 +162,7 @@ void task_start_wrapper(spawn_args *a) bool threw_exception = false; try { -#ifdef _RUST_STAGE0 - a->f(NULL, a->envptr, a->argptr); -#else a->f(a->envptr, a->argptr); -#endif } catch (rust_task *ex) { assert(ex == task && "Expected this task to be thrown for unwinding"); threw_exception = true; @@ -187,11 +183,7 @@ void task_start_wrapper(spawn_args *a) if(env) { // free the environment (which should be a unique closure). const type_desc *td = env->td; -#ifdef _RUST_STAGE0 - td->drop_glue(NULL, NULL, NULL, box_body(env)); -#else td->drop_glue(NULL, NULL, box_body(env)); -#endif task->kernel->region()->free(env); } diff --git a/src/rt/rust_type.h b/src/rt/rust_type.h index b50c08379de7..6d36d2c960a2 100644 --- a/src/rt/rust_type.h +++ b/src/rt/rust_type.h @@ -21,19 +21,11 @@ struct rust_opaque_box; // - the main function: has a NULL environment, but uses the void* arg // - unique closures of type fn~(): have a non-NULL environment, but // no arguments (and hence the final void*) is harmless -#ifdef _RUST_STAGE0 -typedef void (*CDECL spawn_fn)(void *, rust_opaque_box*, void *); -#else typedef void (*CDECL spawn_fn)(rust_opaque_box*, void *); -#endif struct type_desc; -#ifdef _RUST_STAGE0 -typedef void CDECL (glue_fn)(void *, void *, const type_desc **, void *); -#else typedef void CDECL (glue_fn)(void *, const type_desc **, void *); -#endif // Corresponds to the boxed data in the @ region. The body follows the // header; you can obtain a ptr via box_body() below. diff --git a/src/rt/rust_util.h b/src/rt/rust_util.h index 5b8378b0ad35..242c2ef0a81a 100644 --- a/src/rt/rust_util.h +++ b/src/rt/rust_util.h @@ -57,16 +57,6 @@ vec_data(rust_vec *v) { return reinterpret_cast(v->data); } -inline void reserve_vec_exact_shared(rust_task* task, rust_vec_box** vpp, - size_t size) { - rust_opaque_box** ovpp = (rust_opaque_box**)vpp; - if (size > (*vpp)->body.alloc) { - *vpp = (rust_vec_box*)task->boxed.realloc( - *ovpp, size + sizeof(rust_vec)); - (*vpp)->body.alloc = size; - } -} - inline void reserve_vec_exact(rust_vec_box** vpp, size_t size) { if (size > (*vpp)->body.alloc) { diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index 4d7fa589f6fa..b604f60cba6e 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -37,6 +37,7 @@ rust_list_dir_wfd_size rust_list_dir_wfd_fp_buf rust_log_console_on rust_log_console_off +rust_should_log_console rust_set_environ rust_unset_sigprocmask rust_sched_current_nonlazy_threads @@ -52,7 +53,7 @@ rust_get_stack_segment rust_get_c_stack rust_log_str start_task -vec_reserve_shared_actual +rust_local_realloc vec_reserve_shared task_clear_event_reject task_wait_event @@ -186,6 +187,7 @@ rust_call_tydesc_glue tdefl_compress_mem_to_heap tinfl_decompress_mem_to_heap rust_gc_metadata +rust_update_gc_metadata rust_uv_ip4_port rust_uv_ip6_port rust_uv_tcp_getpeername @@ -237,6 +239,7 @@ rust_delete_memory_region rust_new_boxed_region rust_delete_boxed_region rust_boxed_region_malloc +rust_boxed_region_realloc rust_boxed_region_free rust_try rust_begin_unwind @@ -247,4 +250,7 @@ rust_valgrind_stack_deregister rust_take_env_lock rust_drop_env_lock rust_update_log_settings +rust_running_on_valgrind rust_get_num_cpus +rust_get_global_args_ptr +rust_current_boxed_region diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index 53b291ff470d..32b6df4e1dd5 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -63,3 +63,8 @@ extern "C" LLVMPassRef LLVMCreatePass(const char * PassName) { return (LLVMPassRef)0; } } + +extern "C" void LLVMDestroyPass(LLVMPassRef PassRef) { + Pass *p = unwrap(PassRef); + delete p; +} diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index ba87624e2dde..614c1723c5fb 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -560,3 +560,228 @@ extern "C" bool LLVMRustStartMultithreading() { assert(lock.release()); return ret; } + + +typedef DIBuilder* DIBuilderRef; + +template +DIT unwrapDI(LLVMValueRef ref) { + return DIT(ref ? unwrap(ref) : NULL); +} + +extern "C" DIBuilderRef LLVMDIBuilderCreate(LLVMModuleRef M) { + return new DIBuilder(*unwrap(M)); +} + +extern "C" void LLVMDIBuilderDispose(DIBuilderRef Builder) { + delete Builder; +} + +extern "C" void LLVMDIBuilderFinalize(DIBuilderRef Builder) { + Builder->finalize(); +} + +extern "C" void LLVMDIBuilderCreateCompileUnit( + DIBuilderRef Builder, + unsigned Lang, + const char* File, + const char* Dir, + const char* Producer, + bool isOptimized, + const char* Flags, + unsigned RuntimeVer, + const char* SplitName) { + Builder->createCompileUnit(Lang, File, Dir, Producer, isOptimized, + Flags, RuntimeVer, SplitName); +} + +extern "C" LLVMValueRef LLVMDIBuilderCreateFile( + DIBuilderRef Builder, + const char* Filename, + const char* Directory) { + return wrap(Builder->createFile(Filename, Directory)); +} + +extern "C" LLVMValueRef LLVMDIBuilderCreateSubroutineType( + DIBuilderRef Builder, + LLVMValueRef File, + LLVMValueRef ParameterTypes) { + return wrap(Builder->createSubroutineType( + unwrapDI(File), + unwrapDI(ParameterTypes))); +} + +extern "C" LLVMValueRef LLVMDIBuilderCreateFunction( + DIBuilderRef Builder, + LLVMValueRef Scope, + const char* Name, + const char* LinkageName, + LLVMValueRef File, + unsigned LineNo, + LLVMValueRef Ty, + bool isLocalToUnit, + bool isDefinition, + unsigned ScopeLine, + unsigned Flags, + bool isOptimized, + LLVMValueRef Fn, + LLVMValueRef TParam, + LLVMValueRef Decl) { + return wrap(Builder->createFunction( + unwrapDI(Scope), Name, LinkageName, + unwrapDI(File), LineNo, + unwrapDI(Ty), isLocalToUnit, isDefinition, ScopeLine, + Flags, isOptimized, + unwrap(Fn), + unwrapDI(TParam), + unwrapDI(Decl))); +} + +extern "C" LLVMValueRef LLVMDIBuilderCreateBasicType( + DIBuilderRef Builder, + const char* Name, + uint64_t SizeInBits, + uint64_t AlignInBits, + unsigned Encoding) { + return wrap(Builder->createBasicType( + Name, SizeInBits, + AlignInBits, Encoding)); +} + +extern "C" LLVMValueRef LLVMDIBuilderCreatePointerType( + DIBuilderRef Builder, + LLVMValueRef PointeeTy, + uint64_t SizeInBits, + uint64_t AlignInBits, + const char* Name) { + return wrap(Builder->createPointerType( + unwrapDI(PointeeTy), SizeInBits, AlignInBits, Name)); +} + +extern "C" LLVMValueRef LLVMDIBuilderCreateStructType( + DIBuilderRef Builder, + LLVMValueRef Scope, + const char* Name, + LLVMValueRef File, + unsigned LineNumber, + uint64_t SizeInBits, + uint64_t AlignInBits, + unsigned Flags, + LLVMValueRef DerivedFrom, + LLVMValueRef Elements, + unsigned RunTimeLang, + LLVMValueRef VTableHolder) { + return wrap(Builder->createStructType( + unwrapDI(Scope), Name, + unwrapDI(File), LineNumber, + SizeInBits, AlignInBits, Flags, + unwrapDI(DerivedFrom), + unwrapDI(Elements), RunTimeLang, + unwrapDI(VTableHolder))); +} + +extern "C" LLVMValueRef LLVMDIBuilderCreateMemberType( + DIBuilderRef Builder, + LLVMValueRef Scope, + const char* Name, + LLVMValueRef File, + unsigned LineNo, + uint64_t SizeInBits, + uint64_t AlignInBits, + uint64_t OffsetInBits, + unsigned Flags, + LLVMValueRef Ty) { + return wrap(Builder->createMemberType( + unwrapDI(Scope), Name, + unwrapDI(File), LineNo, + SizeInBits, AlignInBits, OffsetInBits, Flags, + unwrapDI(Ty))); +} + +extern "C" LLVMValueRef LLVMDIBuilderCreateLexicalBlock( + DIBuilderRef Builder, + LLVMValueRef Scope, + LLVMValueRef File, + unsigned Line, + unsigned Col) { + return wrap(Builder->createLexicalBlock( + unwrapDI(Scope), + unwrapDI(File), Line, Col)); +} + +extern "C" LLVMValueRef LLVMDIBuilderCreateLocalVariable( + DIBuilderRef Builder, + unsigned Tag, + LLVMValueRef Scope, + const char* Name, + LLVMValueRef File, + unsigned LineNo, + LLVMValueRef Ty, + bool AlwaysPreserve, + unsigned Flags, + unsigned ArgNo) { + return wrap(Builder->createLocalVariable(Tag, + unwrapDI(Scope), Name, + unwrapDI(File), + LineNo, + unwrapDI(Ty), AlwaysPreserve, Flags, ArgNo)); +} + +extern "C" LLVMValueRef LLVMDIBuilderCreateArrayType( + DIBuilderRef Builder, + uint64_t Size, + uint64_t AlignInBits, + LLVMValueRef Ty, + LLVMValueRef Subscripts) { + return wrap(Builder->createArrayType(Size, AlignInBits, + unwrapDI(Ty), + unwrapDI(Subscripts))); +} + +extern "C" LLVMValueRef LLVMDIBuilderCreateVectorType( + DIBuilderRef Builder, + uint64_t Size, + uint64_t AlignInBits, + LLVMValueRef Ty, + LLVMValueRef Subscripts) { + return wrap(Builder->createVectorType(Size, AlignInBits, + unwrapDI(Ty), + unwrapDI(Subscripts))); +} + +extern "C" LLVMValueRef LLVMDIBuilderGetOrCreateSubrange( + DIBuilderRef Builder, + int64_t Lo, + int64_t Count) { + return wrap(Builder->getOrCreateSubrange(Lo, Count)); +} + +extern "C" LLVMValueRef LLVMDIBuilderGetOrCreateArray( + DIBuilderRef Builder, + LLVMValueRef* Ptr, + unsigned Count) { + return wrap(Builder->getOrCreateArray( + ArrayRef(reinterpret_cast(Ptr), Count))); +} + +extern "C" LLVMValueRef LLVMDIBuilderInsertDeclareAtEnd( + DIBuilderRef Builder, + LLVMValueRef Val, + LLVMValueRef VarInfo, + LLVMBasicBlockRef InsertAtEnd) { + return wrap(Builder->insertDeclare( + unwrap(Val), + unwrapDI(VarInfo), + unwrap(InsertAtEnd))); +} + +extern "C" LLVMValueRef LLVMDIBuilderInsertDeclareBefore( + DIBuilderRef Builder, + LLVMValueRef Val, + LLVMValueRef VarInfo, + LLVMValueRef InsertBefore) { + return wrap(Builder->insertDeclare( + unwrap(Val), + unwrapDI(VarInfo), + unwrap(InsertBefore))); +} diff --git a/src/rustllvm/rustllvm.def.in b/src/rustllvm/rustllvm.def.in index f53971657819..d5f03ac604b7 100644 --- a/src/rustllvm/rustllvm.def.in +++ b/src/rustllvm/rustllvm.def.in @@ -588,3 +588,23 @@ LLVMInlineAsm LLVMInitializePasses LLVMAddPass LLVMCreatePass +LLVMDestroyPass +LLVMDIBuilderCreate +LLVMDIBuilderDispose +LLVMDIBuilderFinalize +LLVMDIBuilderCreateCompileUnit +LLVMDIBuilderCreateLocalVariable +LLVMDIBuilderCreateFunction +LLVMDIBuilderCreateFile +LLVMDIBuilderCreateLexicalBlock +LLVMDIBuilderCreateBasicType +LLVMDIBuilderCreatePointerType +LLVMDIBuilderCreateMemberType +LLVMDIBuilderCreateStructType +LLVMDIBuilderGetOrCreateSubrange +LLVMDIBuilderCreateArrayType +LLVMDIBuilderCreateVectorType +LLVMDIBuilderCreateSubroutineType +LLVMDIBuilderGetOrCreateArray +LLVMDIBuilderInsertDeclareAtEnd +LLVMDIBuilderInsertDeclareBefore diff --git a/src/rustllvm/rustllvm.h b/src/rustllvm/rustllvm.h index 6f11202800cd..d4202abd2854 100644 --- a/src/rustllvm/rustllvm.h +++ b/src/rustllvm/rustllvm.h @@ -43,6 +43,8 @@ #include "llvm/Transforms/IPO.h" #include "llvm/Transforms/Instrumentation.h" #include "llvm/Transforms/Vectorize.h" +#include "llvm/DebugInfo.h" +#include "llvm/DIBuilder.h" #include "llvm-c/Core.h" #include "llvm-c/BitReader.h" #include "llvm-c/ExecutionEngine.h" diff --git a/src/snapshots.txt b/src/snapshots.txt index a68d2205cfba..1aaf5fee26ab 100644 --- a/src/snapshots.txt +++ b/src/snapshots.txt @@ -1,3 +1,11 @@ +S 2013-06-21 6759ce4 + macos-i386 6e5395d2fda1db356f64af28ba525031bf9871c7 + macos-x86_64 7b8ded4e1ba1e999a5614eea3a4acacb2c7cef1d + winnt-i386 8337460667b1ea67d5a7aeeb7ba34c0b87e44b83 + freebsd-x86_64 21e5219ac858795c757a3ac894a6c3e88b43f74d + linux-i386 f02609c28f05d9feb9ba4b5f34940a77f22d76f2 + linux-x86_64 951c9fe9082393c5761bac3163ea59c253f1bece + S 2013-05-17 2d28d64 macos-i386 abadafb33c9f858543351c822fb468195163559f macos-x86_64 4a484693f73bcc8ce2a85708fd4f0c3f6e34969d diff --git a/src/test/auxiliary/cci_capture_clause.rs b/src/test/auxiliary/cci_capture_clause.rs index e58b28aa3ded..e45bfc8ea5dc 100644 --- a/src/test/auxiliary/cci_capture_clause.rs +++ b/src/test/auxiliary/cci_capture_clause.rs @@ -14,7 +14,7 @@ use std::task; pub fn foo(x: T) -> Port { let (p, c) = stream(); do task::spawn() { - c.send(x); + c.send(copy x); } p } diff --git a/src/test/auxiliary/cci_nested_lib.rs b/src/test/auxiliary/cci_nested_lib.rs index 5701912b5f6f..c0b98f2af07c 100644 --- a/src/test/auxiliary/cci_nested_lib.rs +++ b/src/test/auxiliary/cci_nested_lib.rs @@ -25,7 +25,7 @@ pub fn alist_add(lst: &alist, k: A, v: B) { pub fn alist_get(lst: &alist, k: A) -> B { let eq_fn = lst.eq_fn; for lst.data.each |entry| { - if eq_fn(entry.key, k) { return entry.value; } + if eq_fn(copy entry.key, copy k) { return copy entry.value; } } fail!(); } diff --git a/src/test/bench/msgsend-pipes-shared.rs b/src/test/bench/msgsend-pipes-shared.rs index 9fbc1d4590de..7a9be7548849 100644 --- a/src/test/bench/msgsend-pipes-shared.rs +++ b/src/test/bench/msgsend-pipes-shared.rs @@ -30,9 +30,7 @@ use std::ptr; use std::uint; use std::vec; -macro_rules! move_out ( - { $x:expr } => { unsafe { let y = *ptr::to_unsafe_ptr(&($x)); y } } -) +fn move_out(x: T) {} enum request { get_count, @@ -91,7 +89,7 @@ fn run(args: &[~str]) { //error!("sending stop message"); to_child.send(stop); - move_out!(to_child); + move_out(to_child); let result = from_child.recv(); let end = extra::time::precise_time_s(); let elapsed = end - start; diff --git a/src/test/bench/msgsend-pipes.rs b/src/test/bench/msgsend-pipes.rs index 2663bb266706..796072c84858 100644 --- a/src/test/bench/msgsend-pipes.rs +++ b/src/test/bench/msgsend-pipes.rs @@ -25,9 +25,7 @@ use std::task; use std::uint; use std::vec; -macro_rules! move_out ( - { $x:expr } => { unsafe { let y = *ptr::to_unsafe_ptr(&($x)); y } } -) +fn move_out(x: T) {} enum request { get_count, @@ -87,7 +85,7 @@ fn run(args: &[~str]) { //error!("sending stop message"); to_child.send(stop); - move_out!(to_child); + move_out(to_child); let result = from_child.recv(); let end = extra::time::precise_time_s(); let elapsed = end - start; diff --git a/src/test/bench/msgsend-ring-pipes.rs b/src/test/bench/msgsend-ring-pipes.rs index f2bb77b26ef5..0f6ca37a3fbb 100644 --- a/src/test/bench/msgsend-ring-pipes.rs +++ b/src/test/bench/msgsend-ring-pipes.rs @@ -34,10 +34,6 @@ proto! ring ( } ) -macro_rules! move_out ( - ($x:expr) => { unsafe { let y = *ptr::to_unsafe_ptr(&$x); y } } -) - fn thread_ring(i: uint, count: uint, num_chan: ring::client::num, @@ -54,7 +50,7 @@ fn thread_ring(i: uint, match recv(port) { ring::num(_n, p) => { //log(error, _n); - num_port = Some(move_out!(p)); + num_port = Some(p); } } }; diff --git a/src/test/bench/shootout-fasta-redux.rs b/src/test/bench/shootout-fasta-redux.rs index 8b587f02ad6d..8c8b26afa08b 100644 --- a/src/test/bench/shootout-fasta-redux.rs +++ b/src/test/bench/shootout-fasta-redux.rs @@ -95,7 +95,8 @@ impl RepeatFasta { let alu: &[u8] = self.alu.as_bytes(); copy_memory(buf, alu, alu_len); - copy_memory(vec::mut_slice(buf, alu_len, buf.len()), + let buf_len = buf.len(); + copy_memory(vec::mut_slice(buf, alu_len, buf_len), alu, LINE_LEN); diff --git a/src/test/bench/shootout-k-nucleotide-pipes.rs b/src/test/bench/shootout-k-nucleotide-pipes.rs index b7969fb0552e..e12df5811eee 100644 --- a/src/test/bench/shootout-k-nucleotide-pipes.rs +++ b/src/test/bench/shootout-k-nucleotide-pipes.rs @@ -36,15 +36,15 @@ fn sort_and_fmt(mm: &HashMap<~[u8], uint>, total: uint) -> ~str { fn le_by_val(kv0: &(TT,UU), kv1: &(TT,UU)) -> bool { - let (_, v0) = *kv0; - let (_, v1) = *kv1; + let (_, v0) = copy *kv0; + let (_, v1) = copy *kv1; return v0 >= v1; } fn le_by_key(kv0: &(TT,UU), kv1: &(TT,UU)) -> bool { - let (k0, _) = *kv0; - let (k1, _) = *kv1; + let (k0, _) = copy *kv0; + let (k1, _) = copy *kv1; return k0 <= k1; } diff --git a/src/test/bench/task-perf-one-million.rs b/src/test/bench/task-perf-one-million.rs index e1a5253444f8..e1366a3a8694 100644 --- a/src/test/bench/task-perf-one-million.rs +++ b/src/test/bench/task-perf-one-million.rs @@ -10,6 +10,8 @@ // Test for concurrent tasks +// xfail-test OOM on linux-32 without opts + use std::comm::*; use std::os; use std::task; diff --git a/src/test/compile-fail/infinite-instantiation.rs b/src/test/compile-fail/infinite-instantiation.rs index 605453d1bca2..377b2016bcbe 100644 --- a/src/test/compile-fail/infinite-instantiation.rs +++ b/src/test/compile-fail/infinite-instantiation.rs @@ -23,7 +23,7 @@ impl to_opt for uint { impl to_opt for Option { fn to_option(&self) -> Option> { - Some(*self) + Some(copy *self) } } diff --git a/src/test/compile-fail/kindck-owned.rs b/src/test/compile-fail/kindck-owned.rs index 27cc07ed123b..ec84551f7b0a 100644 --- a/src/test/compile-fail/kindck-owned.rs +++ b/src/test/compile-fail/kindck-owned.rs @@ -9,12 +9,13 @@ // except according to those terms. fn copy1(t: T) -> @fn() -> T { - let result: @fn() -> T = || t; //~ ERROR value may contain borrowed pointers + let result: @fn() -> T = || copy t; + //~^ ERROR value may contain borrowed pointers result } fn copy2(t: T) -> @fn() -> T { - let result: @fn() -> T = || t; + let result: @fn() -> T = || copy t; result } diff --git a/src/test/debug-info/basic-types.rs b/src/test/debug-info/basic-types.rs index 20da6b557f18..616740c850c5 100644 --- a/src/test/debug-info/basic-types.rs +++ b/src/test/debug-info/basic-types.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// xfail-test +// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249 // Caveats - gdb prints any 8-bit value (meaning rust i8 and u8 values) // as its numerical value along with its associated ASCII char, there @@ -17,8 +17,9 @@ // its numerical value. // compile-flags:-Z extra-debug-info -// debugger:break 67 +// debugger:break _zzz // debugger:run +// debugger:finish // debugger:print b // check:$1 = false // debugger:print i @@ -66,5 +67,7 @@ fn main() { let f: float = 1.5; let f32: f32 = 2.5; let f64: f64 = 3.5; - let _z = (); + _zzz(); } + +fn _zzz() {()} diff --git a/src/test/debug-info/box.rs b/src/test/debug-info/box.rs index 54aa0c12578b..4a3a65a90550 100644 --- a/src/test/debug-info/box.rs +++ b/src/test/debug-info/box.rs @@ -12,8 +12,9 @@ // compile-flags:-Z extra-debug-info // debugger:set print pretty off -// debugger:break 29 +// debugger:break _zzz // debugger:run +// debugger:finish // debugger:print a->boxed // check:$1 = 1 // debugger:print b->boxed @@ -28,5 +29,7 @@ fn main() { let b = ~(2, 3.5); let c = @4; let d = @false; - let _z = 0; + _zzz(); } + +fn _zzz() {()} diff --git a/src/test/debug-info/struct.rs b/src/test/debug-info/struct.rs index 16ba6cda5900..ddfac9cbeea8 100644 --- a/src/test/debug-info/struct.rs +++ b/src/test/debug-info/struct.rs @@ -8,12 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// xfail-test +// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249 // compile-flags:-Z extra-debug-info // debugger:set print pretty off -// debugger:break 29 +// debugger:break _zzz // debugger:run +// debugger:finish // debugger:print pair // check:$1 = {x = 1, y = 2} // debugger:print pair.x @@ -28,5 +29,7 @@ struct Pair { fn main() { let pair = Pair { x: 1, y: 2 }; - let _z = (); + _zzz(); } + +fn _zzz() {()} \ No newline at end of file diff --git a/src/test/debug-info/tuple.rs b/src/test/debug-info/tuple.rs index 35e2977f562e..a50996871cee 100644 --- a/src/test/debug-info/tuple.rs +++ b/src/test/debug-info/tuple.rs @@ -8,16 +8,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// xfail-test +// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249 // compile-flags:-Z extra-debug-info // debugger:set print pretty off -// debugger:break 20 +// debugger:break _zzz // debugger:run +// debugger:finish // debugger:print t // check:$1 = {4, 5.5, true} fn main() { let t = (4, 5.5, true); - let _z = (); + _zzz(); } + +fn _zzz() {()} \ No newline at end of file diff --git a/src/test/debug-info/vec.rs b/src/test/debug-info/vec.rs index 3876f1c46d48..f198a53729eb 100644 --- a/src/test/debug-info/vec.rs +++ b/src/test/debug-info/vec.rs @@ -12,8 +12,9 @@ // compile-flags:-Z extra-debug-info // debugger:set print pretty off -// debugger:break 29 +// debugger:break _zzz // debugger:run +// debugger:finish // debugger:print a // check:$1 = {1, 2, 3} // debugger:print b.vec[0] @@ -28,5 +29,7 @@ fn main() { let b = &[4, 5, 6]; let c = @[7, 8, 9]; let d = ~[10, 11, 12]; - let _z = 0; + _zzz(); } + +fn _zzz() {()} diff --git a/src/test/run-pass/alignment-gep-tup-like-1.rs b/src/test/run-pass/alignment-gep-tup-like-1.rs index bf96d6cfab52..6f1b4b815213 100644 --- a/src/test/run-pass/alignment-gep-tup-like-1.rs +++ b/src/test/run-pass/alignment-gep-tup-like-1.rs @@ -13,7 +13,7 @@ struct pair { } fn f(a: A, b: u16) -> @fn() -> (A, u16) { - let result: @fn() -> (A, u16) = || (a, b); + let result: @fn() -> (A, u16) = || (copy a, b); result } diff --git a/src/test/run-pass/alignment-gep-tup-like-2.rs b/src/test/run-pass/alignment-gep-tup-like-2.rs index 6bf4e96bc053..753e5339de9d 100644 --- a/src/test/run-pass/alignment-gep-tup-like-2.rs +++ b/src/test/run-pass/alignment-gep-tup-like-2.rs @@ -24,7 +24,7 @@ fn make_cycle(a: A) { } fn f(a: A, b: B) -> @fn() -> (A, B) { - let result: @fn() -> (A, B) = || (a, b); + let result: @fn() -> (A, B) = || (copy a, copy b); result } diff --git a/src/test/run-pass/auto-encode.rs b/src/test/run-pass/auto-encode.rs index 7b03a699e783..6e5b837e0aaf 100644 --- a/src/test/run-pass/auto-encode.rs +++ b/src/test/run-pass/auto-encode.rs @@ -41,6 +41,10 @@ fn test_ebml or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// just make sure this compiles: - -fn bar(x: *~int) -> ~int { - unsafe { - let y = *x; - return y; - } -} - -pub fn main() { -} diff --git a/src/test/run-pass/borrowed-ptr-pattern.rs b/src/test/run-pass/borrowed-ptr-pattern.rs index e0af2e80508c..86e8f600cd53 100644 --- a/src/test/run-pass/borrowed-ptr-pattern.rs +++ b/src/test/run-pass/borrowed-ptr-pattern.rs @@ -10,7 +10,7 @@ fn foo(x: &T) -> T{ match x { - &a => a + &ref a => copy *a } } diff --git a/src/test/run-pass/box-unbox.rs b/src/test/run-pass/box-unbox.rs index e7dc43656798..f4fb10fea724 100644 --- a/src/test/run-pass/box-unbox.rs +++ b/src/test/run-pass/box-unbox.rs @@ -12,7 +12,7 @@ struct Box {c: @T} -fn unbox(b: Box) -> T { return *b.c; } +fn unbox(b: Box) -> T { return copy *b.c; } pub fn main() { let foo: int = 17; diff --git a/src/test/run-pass/close-over-big-then-small-data.rs b/src/test/run-pass/close-over-big-then-small-data.rs index 736c0f919417..69da3c8d9862 100644 --- a/src/test/run-pass/close-over-big-then-small-data.rs +++ b/src/test/run-pass/close-over-big-then-small-data.rs @@ -17,7 +17,7 @@ struct Pair { } fn f(a: A, b: u16) -> @fn() -> (A, u16) { - let result: @fn() -> (A, u16) = || (a, b); + let result: @fn() -> (A, u16) = || (copy a, b); result } diff --git a/src/test/run-pass/deriving-zero.rs b/src/test/run-pass/deriving-zero.rs new file mode 100644 index 000000000000..2ee57624112f --- /dev/null +++ b/src/test/run-pass/deriving-zero.rs @@ -0,0 +1,40 @@ +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::util; +use std::num::Zero; + +#[deriving(Zero)] +struct A; +#[deriving(Zero)] +struct B(int); +#[deriving(Zero)] +struct C(int, int); +#[deriving(Zero)] +struct D { a: int } +#[deriving(Zero)] +struct E { a: int, b: int } + +#[deriving(Zero)] +struct Lots { + a: ~str, + b: @str, + c: Option, + d: u8, + e: char, + f: float, + g: (f32, char), + h: ~[util::NonCopyable], + i: @mut (int, int), +} + +fn main() { + assert!(Zero::zero::().is_zero()); +} diff --git a/src/test/run-pass/expr-block-generic-box2.rs b/src/test/run-pass/expr-block-generic-box2.rs index 5d26fbdd7893..9cf047d425c3 100644 --- a/src/test/run-pass/expr-block-generic-box2.rs +++ b/src/test/run-pass/expr-block-generic-box2.rs @@ -14,7 +14,7 @@ type compare = @fn(T, T) -> bool; fn test_generic(expected: T, eq: compare) { - let actual: T = { expected }; + let actual: T = { copy expected }; assert!((eq(expected, actual))); } diff --git a/src/test/run-pass/expr-block-generic-unique2.rs b/src/test/run-pass/expr-block-generic-unique2.rs index 0d70bff36497..25bf553ff35c 100644 --- a/src/test/run-pass/expr-block-generic-unique2.rs +++ b/src/test/run-pass/expr-block-generic-unique2.rs @@ -14,7 +14,7 @@ type compare = @fn(T, T) -> bool; fn test_generic(expected: T, eq: compare) { - let actual: T = { expected }; + let actual: T = { copy expected }; assert!((eq(expected, actual))); } diff --git a/src/test/run-pass/expr-block-generic.rs b/src/test/run-pass/expr-block-generic.rs index e507700e6b28..afb1a4c76bbb 100644 --- a/src/test/run-pass/expr-block-generic.rs +++ b/src/test/run-pass/expr-block-generic.rs @@ -16,7 +16,7 @@ type compare = @fn(T, T) -> bool; fn test_generic(expected: T, eq: compare) { - let actual: T = { expected }; + let actual: T = { copy expected }; assert!((eq(expected, actual))); } diff --git a/src/test/run-pass/expr-if-generic-box2.rs b/src/test/run-pass/expr-if-generic-box2.rs index 12193037e119..186d15c3490a 100644 --- a/src/test/run-pass/expr-if-generic-box2.rs +++ b/src/test/run-pass/expr-if-generic-box2.rs @@ -14,7 +14,7 @@ type compare = @fn(T, T) -> bool; fn test_generic(expected: T, not_expected: T, eq: compare) { - let actual: T = if true { expected } else { not_expected }; + let actual: T = if true { copy expected } else { not_expected }; assert!((eq(expected, actual))); } diff --git a/src/test/run-pass/expr-if-generic.rs b/src/test/run-pass/expr-if-generic.rs index 8d2ce83c8794..2e6db3bba07f 100644 --- a/src/test/run-pass/expr-if-generic.rs +++ b/src/test/run-pass/expr-if-generic.rs @@ -15,7 +15,7 @@ type compare = @fn(T, T) -> bool; fn test_generic(expected: T, not_expected: T, eq: compare) { - let actual: T = if true { expected } else { not_expected }; + let actual: T = if true { copy expected } else { not_expected }; assert!((eq(expected, actual))); } diff --git a/src/test/run-pass/expr-match-generic-box2.rs b/src/test/run-pass/expr-match-generic-box2.rs index c5c89b428255..64aa4ce3609a 100644 --- a/src/test/run-pass/expr-match-generic-box2.rs +++ b/src/test/run-pass/expr-match-generic-box2.rs @@ -14,7 +14,7 @@ type compare = @fn(T, T) -> bool; fn test_generic(expected: T, eq: compare) { - let actual: T = match true { true => { expected }, _ => fail!("wat") }; + let actual: T = match true { true => { copy expected }, _ => fail!("wat") }; assert!((eq(expected, actual))); } diff --git a/src/test/run-pass/expr-match-generic.rs b/src/test/run-pass/expr-match-generic.rs index 04a229f22800..bd87e7207d14 100644 --- a/src/test/run-pass/expr-match-generic.rs +++ b/src/test/run-pass/expr-match-generic.rs @@ -14,7 +14,7 @@ type compare = @fn(T, T) -> bool; fn test_generic(expected: T, eq: compare) { - let actual: T = match true { true => { expected }, _ => fail!("wat") }; + let actual: T = match true { true => { copy expected }, _ => fail!("wat") }; assert!((eq(expected, actual))); } diff --git a/src/test/run-pass/extern-pub.rs b/src/test/run-pass/extern-pub.rs index 29b0457fc050..e722c4f5c6a9 100644 --- a/src/test/run-pass/extern-pub.rs +++ b/src/test/run-pass/extern-pub.rs @@ -1,11 +1,7 @@ use std::libc; -use std::sys; -use std::vec; extern { - pub unsafe fn vec_reserve_shared_actual(t: *sys::TypeDesc, - v: **vec::raw::VecRepr, - n: libc::size_t); + pub unsafe fn debug_get_stk_seg() -> *libc::c_void; } pub fn main() { diff --git a/src/test/run-pass/generic-derived-type.rs b/src/test/run-pass/generic-derived-type.rs index 9e266a3f2080..649fe3433b46 100644 --- a/src/test/run-pass/generic-derived-type.rs +++ b/src/test/run-pass/generic-derived-type.rs @@ -15,8 +15,7 @@ fn g(x: X) -> X { return x; } struct Pair {a: T, b: T} fn f(t: T) -> Pair { - - let x: Pair = Pair {a: t, b: t}; + let x: Pair = Pair {a: copy t, b: t}; return g::>(x); } diff --git a/src/test/run-pass/issue-2718.rs b/src/test/run-pass/issue-2718.rs index 4ef83e405be4..014aebeff9da 100644 --- a/src/test/run-pass/issue-2718.rs +++ b/src/test/run-pass/issue-2718.rs @@ -233,9 +233,7 @@ pub mod pingpong { let addr : *::pipes::send_packet = match &p { &ping(ref x) => { cast::transmute(x) } }; - let liberated_value = *addr; - cast::forget(p); - liberated_value + fail!() } } @@ -244,9 +242,7 @@ pub mod pingpong { let addr : *::pipes::send_packet = match &p { &pong(ref x) => { cast::transmute(x) } }; - let liberated_value = *addr; - cast::forget(p); - liberated_value + fail!() } } diff --git a/src/test/run-pass/ivec-add.rs b/src/test/run-pass/ivec-add.rs index 80168daf62d0..7cee6b4e8de6 100644 --- a/src/test/run-pass/ivec-add.rs +++ b/src/test/run-pass/ivec-add.rs @@ -8,9 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn double(a: T) -> ~[T] { return ~[a] + ~[a]; } +fn double(a: T) -> ~[T] { return ~[copy a] + ~[a]; } -fn double_int(a: int) -> ~[int] { return ~[a] + ~[a]; } +fn double_int(a: int) -> ~[int] { return ~[copy a] + ~[a]; } pub fn main() { let mut d = double(1); diff --git a/src/test/run-pass/kindck-owned-trait-contains-1.rs b/src/test/run-pass/kindck-owned-trait-contains-1.rs index 35b5e077e7af..c51094d26c88 100644 --- a/src/test/run-pass/kindck-owned-trait-contains-1.rs +++ b/src/test/run-pass/kindck-owned-trait-contains-1.rs @@ -11,7 +11,7 @@ trait repeat { fn get(&self) -> A; } impl repeat for @A { - fn get(&self) -> A { **self } + fn get(&self) -> A { copy **self } } fn repeater(v: @A) -> @repeat { diff --git a/src/test/run-pass/morestack6.rs b/src/test/run-pass/morestack6.rs index 1dc8503aeb22..0e0bf2a13e17 100644 --- a/src/test/run-pass/morestack6.rs +++ b/src/test/run-pass/morestack6.rs @@ -23,7 +23,6 @@ mod rustrt { pub fn rust_get_sched_id() -> libc::intptr_t; pub fn rust_get_argc() -> libc::c_int; pub fn get_task_id() -> libc::intptr_t; - pub fn rust_sched_threads(); pub fn rust_get_task(); } } @@ -31,7 +30,6 @@ mod rustrt { fn calllink01() { unsafe { rustrt::rust_get_sched_id(); } } fn calllink02() { unsafe { rustrt::rust_get_argc(); } } fn calllink08() { unsafe { rustrt::get_task_id(); } } -fn calllink09() { unsafe { rustrt::rust_sched_threads(); } } fn calllink10() { unsafe { rustrt::rust_get_task(); } } fn runtest(f: extern fn(), frame_backoff: u32) { @@ -64,7 +62,6 @@ pub fn main() { calllink01, calllink02, calllink08, - calllink09, calllink10 ]; let mut rng = rand::rng(); diff --git a/src/test/run-pass/pipe-bank-proto.rs b/src/test/run-pass/pipe-bank-proto.rs index d723fa322094..7ac38966faa3 100644 --- a/src/test/run-pass/pipe-bank-proto.rs +++ b/src/test/run-pass/pipe-bank-proto.rs @@ -45,24 +45,18 @@ proto! bank ( } ) -macro_rules! move_it ( - { $x:expr } => { unsafe { let y = *ptr::to_unsafe_ptr(&($x)); y } } -) - fn switch(endp: pipes::RecvPacket, f: &fn(v: Option) -> U) -> U { f(pipes::try_recv(endp)) } -fn move_it(x: T) -> T { x } - macro_rules! follow ( { $($message:path$(($($x: ident),+))||* -> $next:ident $e:expr)+ } => ( |m| match m { $(Some($message($($($x,)+)* next)) => { - let $next = move_it!(next); + let $next = next; $e })+ _ => { fail!() } } @@ -96,7 +90,7 @@ fn bank_client(bank: bank::client::login) { let bank = client::login(bank, ~"theincredibleholk", ~"1234"); let bank = match try_recv(bank) { Some(ok(connected)) => { - move_it!(connected) + connected } Some(invalid(_)) => { fail!("login unsuccessful") } None => { fail!("bank closed the connection") } diff --git a/src/test/run-pass/reflect-visit-data.rs b/src/test/run-pass/reflect-visit-data.rs index f4ccd038afee..e091554a3572 100644 --- a/src/test/run-pass/reflect-visit-data.rs +++ b/src/test/run-pass/reflect-visit-data.rs @@ -486,9 +486,9 @@ struct Stuff { } impl my_visitor { - pub fn get(&self, f: &fn(T)) { + pub fn get(&self, f: &fn(T)) { unsafe { - f(*(self.ptr1 as *T)); + f(copy *(self.ptr1 as *T)); } } diff --git a/src/test/run-pass/resource-generic.rs b/src/test/run-pass/resource-generic.rs index 41eafb0293af..7a18cd02c2de 100644 --- a/src/test/run-pass/resource-generic.rs +++ b/src/test/run-pass/resource-generic.rs @@ -20,7 +20,7 @@ struct finish { impl Drop for finish { fn finalize(&self) { unsafe { - (self.arg.fin)(self.arg.val); + (self.arg.fin)(copy self.arg.val); } } } diff --git a/src/test/run-pass/sized-borrowed-pointer b/src/test/run-pass/sized-borrowed-pointer deleted file mode 100755 index 275622161d34..000000000000 Binary files a/src/test/run-pass/sized-borrowed-pointer and /dev/null differ diff --git a/src/test/run-pass/sized-owned-pointer b/src/test/run-pass/sized-owned-pointer deleted file mode 100755 index 3a290ba47ffb..000000000000 Binary files a/src/test/run-pass/sized-owned-pointer and /dev/null differ diff --git a/src/test/run-pass/static-method-test.rs b/src/test/run-pass/static-method-test.rs index 4dde143f686b..2d6b2141c5c7 100644 --- a/src/test/run-pass/static-method-test.rs +++ b/src/test/run-pass/static-method-test.rs @@ -21,7 +21,7 @@ trait bool_like { } fn andand(x1: T, x2: T) -> T { - bool_like::select(x1, x2, x1) + bool_like::select(copy x1, x2, x1) } impl bool_like for bool { diff --git a/src/test/run-pass/unfoldr-cross-crate.rs b/src/test/run-pass/unfoldr-cross-crate.rs new file mode 100644 index 000000000000..4e98543ae826 --- /dev/null +++ b/src/test/run-pass/unfoldr-cross-crate.rs @@ -0,0 +1,34 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::iterator::*; + +// UnfoldrIterator had a bug with 'self that mean it didn't work +// cross-crate + +fn main() { + fn count(st: &mut uint) -> Option { + if *st < 10 { + let ret = Some(*st); + *st += 1; + ret + } else { + None + } + } + + let mut it = UnfoldrIterator::new(count, 0); + let mut i = 0; + for it.advance |counted| { + assert_eq!(counted, i); + i += 1; + } + assert_eq!(i, 10); +}