]> git.lizzy.rs Git - rust.git/commitdiff
auto merge of #16440 : bheesham/rust/master, r=brson
authorbors <bors@rust-lang.org>
Thu, 14 Aug 2014 09:31:19 +0000 (09:31 +0000)
committerbors <bors@rust-lang.org>
Thu, 14 Aug 2014 09:31:19 +0000 (09:31 +0000)
  * `rust.md`: changes for consistency

  * `guide-ffi.md`: wrapped inline code

NOTE: This is a duplicate of #16375. I completely messed up that fork, so I made a new fork.

160 files changed:
src/compiletest/header.rs
src/compiletest/runtest.rs
src/doc/guide-runtime.md
src/doc/guide-testing.md
src/doc/guide-unsafe.md
src/doc/guide.md
src/doc/rust.md
src/etc/unicode.py
src/libcollections/bitv.rs
src/libcollections/btree.rs
src/libcollections/dlist.rs
src/libcollections/hash/mod.rs
src/libcollections/hash/sip.rs
src/libcollections/priority_queue.rs
src/libcollections/ringbuf.rs
src/libcollections/slice.rs
src/libcollections/smallintmap.rs
src/libcollections/str.rs
src/libcollections/string.rs
src/libcollections/trie.rs
src/libcollections/vec.rs
src/libcore/fmt/float.rs
src/libcore/fmt/mod.rs
src/libcore/fmt/num.rs
src/libcore/intrinsics.rs
src/libcore/option.rs
src/libcore/prelude.rs
src/libcore/slice.rs
src/libcore/str.rs
src/libcoretest/lib.rs
src/libcoretest/slice.rs [new file with mode: 0644]
src/libfourcc/lib.rs
src/libgraphviz/maybe_owned_vec.rs
src/libgreen/sched.rs
src/libhexfloat/lib.rs
src/libnative/io/process.rs
src/libnum/rational.rs
src/librand/isaac.rs
src/libregex/parse.rs
src/libregex/vm.rs
src/librlibc/lib.rs
src/librustc/driver/config.rs
src/librustc/driver/driver.rs
src/librustc/driver/mod.rs
src/librustc/front/test.rs
src/librustc/lint/builtin.rs
src/librustc/metadata/common.rs
src/librustc/middle/astencode.rs
src/librustc/middle/borrowck/gather_loans/mod.rs
src/librustc/middle/borrowck/gather_loans/restrictions.rs
src/librustc/middle/borrowck/mod.rs
src/librustc/middle/check_loop.rs
src/librustc/middle/expr_use_visitor.rs
src/librustc/middle/freevars.rs
src/librustc/middle/liveness.rs
src/librustc/middle/mem_categorization.rs
src/librustc/middle/resolve.rs
src/librustc/middle/save/mod.rs
src/librustc/middle/trans/base.rs
src/librustc/middle/trans/callee.rs
src/librustc/middle/trans/closure.rs
src/librustc/middle/trans/common.rs
src/librustc/middle/trans/controlflow.rs
src/librustc/middle/trans/debuginfo.rs
src/librustc/middle/trans/expr.rs
src/librustc/middle/trans/foreign.rs
src/librustc/middle/trans/glue.rs
src/librustc/middle/trans/inline.rs
src/librustc/middle/trans/intrinsic.rs
src/librustc/middle/trans/meth.rs
src/librustc/middle/trans/monomorphize.rs
src/librustc/middle/trans/reflect.rs
src/librustc/middle/ty.rs
src/librustc/middle/typeck/check/mod.rs
src/librustc/middle/typeck/check/regionck.rs
src/librustc/middle/typeck/check/writeback.rs
src/librustc/middle/typeck/infer/test.rs
src/librustdoc/lib.rs
src/libsemver/lib.rs
src/libserialize/json.rs
src/libstd/ascii.rs
src/libstd/c_vec.rs
src/libstd/collections/hashmap.rs
src/libstd/dynamic_lib.rs
src/libstd/io/buffered.rs
src/libstd/io/comm_adapters.rs
src/libstd/io/extensions.rs
src/libstd/io/fs.rs
src/libstd/io/mem.rs
src/libstd/io/mod.rs
src/libstd/io/net/ip.rs
src/libstd/io/net/tcp.rs
src/libstd/io/net/unix.rs
src/libstd/io/process.rs
src/libstd/io/signal.rs
src/libstd/io/stdio.rs
src/libstd/io/test.rs
src/libstd/io/timer.rs
src/libstd/lib.rs
src/libstd/num/i16.rs
src/libstd/num/i32.rs
src/libstd/num/i64.rs
src/libstd/num/i8.rs
src/libstd/num/int.rs
src/libstd/num/strconv.rs
src/libstd/num/u16.rs
src/libstd/num/u32.rs
src/libstd/num/u64.rs
src/libstd/num/u8.rs
src/libstd/num/uint.rs
src/libstd/os.rs
src/libstd/path/mod.rs
src/libstd/path/posix.rs
src/libstd/path/windows.rs
src/libstd/prelude.rs
src/libstd/rand/os.rs
src/libstd/rt/backtrace.rs
src/libstd/task.rs
src/libstd/time/duration.rs [new file with mode: 0644]
src/libstd/time/mod.rs [new file with mode: 0644]
src/libsync/atomic.rs
src/libsync/comm/duplex.rs
src/libsync/comm/mod.rs
src/libsyntax/ast.rs
src/libsyntax/ast_map/blocks.rs
src/libsyntax/crateid.rs
src/libsyntax/ext/build.rs
src/libsyntax/ext/expand.rs
src/libsyntax/ext/quote.rs
src/libsyntax/fold.rs
src/libsyntax/parse/lexer/mod.rs
src/libsyntax/parse/mod.rs
src/libsyntax/parse/parser.rs
src/libsyntax/print/pprust.rs
src/libsyntax/visit.rs
src/libunicode/normalize.rs
src/libunicode/tables.rs
src/liburl/lib.rs
src/libuuid/lib.rs
src/test/auxiliary/macro_crate_test.rs
src/test/compile-fail-fulldeps/macro-crate-cannot-read-embedded-ident.rs [new file with mode: 0644]
src/test/compile-fail/borrowck-closures-unique-imm.rs [new file with mode: 0644]
src/test/compile-fail/borrowck-for-loop-correct-cmt-for-pattern.rs [new file with mode: 0644]
src/test/compile-fail/intrinsic-return-address.rs [new file with mode: 0644]
src/test/compile-fail/lint-stability.rs
src/test/compile-fail/pattern-ident-path-generics.rs [new file with mode: 0644]
src/test/run-make/cannot-read-embedded-idents/Makefile [new file with mode: 0644]
src/test/run-make/cannot-read-embedded-idents/create_and_compile.rs [new file with mode: 0644]
src/test/run-make/many-crates-but-no-match/Makefile
src/test/run-pass/capture-clauses-boxed-closures.rs [new file with mode: 0644]
src/test/run-pass/capture-clauses-unboxed-closures.rs [new file with mode: 0644]
src/test/run-pass/core-run-destroy.rs
src/test/run-pass/format-nan.rs [new file with mode: 0644]
src/test/run-pass/intrinsic-return-address.rs [new file with mode: 0644]
src/test/run-pass/issue-12684.rs
src/test/run-pass/issue-12699.rs
src/test/run-pass/issue-15763.rs [new file with mode: 0644]
src/test/run-pass/issue-9396.rs
src/test/run-pass/tcp-connect-timeouts.rs
src/test/run-pass/tcp-stress.rs

index aa96f3e272712e87165309ab37f122e01f122dbf..f6cd217b580cd24be78747dc23cca861906771ef 100644 (file)
@@ -233,7 +233,7 @@ fn parse_exec_env(line: &str) -> Option<(String, String)> {
     parse_name_value_directive(line, "exec-env").map(|nv| {
         // nv is either FOO or FOO=BAR
         let mut strs: Vec<String> = nv.as_slice()
-                                      .splitn('=', 1)
+                                      .splitn(1, '=')
                                       .map(|s| s.to_string())
                                       .collect();
 
index a9c7673d4ddfbff90feca391b653d4f339954792..318609f44fda6c03e23e4cdaea8494b370f7dbdf 100644 (file)
@@ -30,6 +30,7 @@
 use std::str;
 use std::string::String;
 use std::task;
+use std::time::Duration;
 use test::MetricMap;
 
 pub fn run(config: Config, testfile: String) {
@@ -400,7 +401,7 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) {
                 .expect(format!("failed to exec `{}`", config.adb_path).as_slice());
             loop {
                 //waiting 1 second for gdbserver start
-                timer::sleep(1000);
+                timer::sleep(Duration::milliseconds(1000));
                 let result = task::try(proc() {
                     tcp::TcpStream::connect("127.0.0.1", 5039).unwrap();
                 });
index 1367bdc07555fb1ee3650e1db560a8d24040861b..24b5834ef7c085fc6ffdf8f667b799063e783a2c 100644 (file)
@@ -128,7 +128,7 @@ itself, yet again implying that they are not defined in the standard library.
 The full complement of runtime features is defined by the [`Runtime`
 trait](std/rt/trait.Runtime.html) and the [`Task`
 struct](std/rt/task/struct.Task.html). A `Task` is constant among all runtime
-implementations, but each runtime implements has its own implementation of the
+implementations, but each runtime has its own implementation of the
 `Runtime` trait.
 
 The local `Task` stores the runtime value inside of itself, and then ownership
index 1d6513972a6d26f59e2776a8ae1401fc472e283e..6fb198fbd2ba4053aa3a809cfe1f6cca975732bc 100644 (file)
@@ -198,7 +198,7 @@ per-iteration speed of.
 
 For benchmarks relating to processing/generating data, one can set the
 `bytes` field to the number of bytes consumed/produced in each
-iteration; this will used to show the throughput of the benchmark.
+iteration; this will be used to show the throughput of the benchmark.
 This must be the amount used in each iteration, *not* the total
 amount.
 
index 8349c8ebcb6489e72d288c967186b6e9a1722cf8..2ff63055480834843fa3444796c9431585c5a6ed 100644 (file)
@@ -137,7 +137,7 @@ explicitly with, respectively, `value as *const T` and `value as *mut T`).
 
 Going the opposite direction, from `*const` to a reference `&`, is not
 safe. A `&T` is always valid, and so, at a minimum, the raw pointer
-`*const T` has to be a valid to a valid instance of type `T`. Furthermore,
+`*const T` has to point to a valid instance of type `T`. Furthermore,
 the resulting pointer must satisfy the aliasing and mutability laws of
 references. The compiler assumes these properties are true for any
 references, no matter how they are created, and so any conversion from
index ecde51538e2c798cb51e7d14c26ae9b108c5f224..c615a335b120940f5865642196bf00f4345d2df6 100644 (file)
@@ -666,7 +666,7 @@ This is not the same as this, which won't compile:
 ```{ignore}
 let x = 5i;
 
-let y: int = if x == 5 { 10i; } else { 15i; };
+let y: int = if x == 5i { 10i; } else { 15i; };
 ```
 
 Note the semicolons after the 10 and 15. Rust will give us the following error:
index ba3ff533849fa17859c28e4f147d1a4b15ba2139..f9560b4a50963cdb6500de848c96807b40267b58 100644 (file)
@@ -1356,6 +1356,9 @@ A *static item* is a named _constant value_ stored in the global data section of
 Immutable static items are stored in the read-only data section.
 The constant value bound to a static item is, like all constant values, evaluated at compile time.
 Static items have the `static` lifetime, which outlives all other lifetimes in a Rust program.
+Only values stored in the global data section (such as string constants
+and static items) can have the `static` lifetime;
+dynamically constructed values cannot safely be assigned the `static` lifetime.
 Static items are declared with the `static` keyword.
 A static item must have a _constant expression_ giving its definition.
 
@@ -1870,13 +1873,13 @@ type int8_t = i8;
 - `crate_id` - specify the this crate's crate ID.
 - `crate_type` - see [linkage](#linkage).
 - `feature` - see [compiler features](#compiler-features).
+- `no_builtins` - disable optimizing certain code patterns to invocations of
+                  library functions that are assumed to exist
 - `no_main` - disable emitting the `main` symbol. Useful when some other
   object being linked to defines `main`.
 - `no_start` - disable linking to the `native` crate, which specifies the
   "start" language item.
 - `no_std` - disable linking to the `std` crate.
-- `no_builtins` - disable optimizing certain code patterns to invocations of
-                  library functions that are assumed to exist
 
 ### Module-only attributes
 
@@ -1890,10 +1893,10 @@ type int8_t = i8;
 
 ### Function-only attributes
 
-- `plugin_registrar` - mark this function as the registration point for
-  compiler plugins, such as loadable syntax extensions.
 - `main` - indicates that this function should be passed to the entry point,
   rather than the function in the crate root named `main`.
+- `plugin_registrar` - mark this function as the registration point for
+  compiler plugins, such as loadable syntax extensions.
 - `start` - indicates that this function should be used as the entry point,
   overriding the "start" language item.  See the "start" [language
   item](#language-items) for more details.
@@ -1932,6 +1935,12 @@ interpreted:
   symbol for this item to its identifier.
 - `packed` - on structs or enums, eliminate any padding that would be used to
   align fields.
+- `phase` - on `extern crate` statements, allows specifying which "phase" of
+  compilation the crate should be loaded for. Currently, there are two
+  choices: `link` and `plugin`. `link` is the default. `plugin` will load the
+  crate at compile-time and use any syntax extensions or lints that the crate
+  defines. They can both be specified, `#[phase(link, plugin)]` to use a crate
+  both at runtime and compiletime.
 - `repr` - on C-like enums, this sets the underlying type used for
   representation. Useful for FFI. Takes one argument, which is the primitive
   type this enum should be represented for, or `C`, which specifies that it
@@ -1949,12 +1958,6 @@ interpreted:
 - `unsafe_no_drop_flag` - on structs, remove the flag that prevents
   destructors from being run twice. Destructors might be run multiple times on
   the same object with this attribute.
-- `phase` - on `extern crate` statements, allows specifying which "phase" of
-  compilation the crate should be loaded for. Currently, there are two
-  choices: `link` and `plugin`. `link` is the default. `plugin` will load the
-  crate at compile-time and use any syntax extensions or lints that the crate
-  defines. They can both be specified, `#[phase(link, plugin)]` to use a crate
-  both at runtime and compiletime.
 
 ### Conditional compilation
 
@@ -2021,12 +2024,12 @@ which the attribute applies.
 
 For any lint check `C`:
 
- * `warn(C)` warns about violations of `C` but continues compilation,
- * `deny(C)` signals an error after encountering a violation of `C`,
  * `allow(C)` overrides the check for `C` so that violations will go
     unreported,
+ * `deny(C)` signals an error after encountering a violation of `C`,
  * `forbid(C)` is the same as `deny(C)`, but also forbids changing the lint
-    level afterwards.
+    level afterwards,
+ * `warn(C)` warns about violations of `C` but continues compilation.
 
 The lint checks supported by the compiler can be found via `rustc -W help`,
 along with their default settings.
@@ -2105,16 +2108,16 @@ A complete list of the built-in language items follows:
 
 #### Built-in Traits
 
+* `copy`
+  : Types that do not move ownership when used by-value.
+* `drop`
+  : Have destructors.
 * `send`
   : Able to be sent across task boundaries.
 * `sized`
   : Has a size known at compile time.
-* `copy`
-  : Types that do not move ownership when used by-value.
 * `sync`
   : Able to be safely shared between tasks when aliased.
-* `drop`
-  : Have destructors.
 
 #### Operators
 
@@ -2146,6 +2149,8 @@ These language items are traits:
   : Elements have a right shift operation.
 * `index`
   : Elements can be indexed.
+* `index_mut`
+  : ___Needs filling in___
 * `eq`
   : Elements can be compared for equality.
 * `ord`
@@ -2155,9 +2160,14 @@ These language items are traits:
 * `deref_mut`
   : `*` can be applied, yielding a mutable reference to another type
 
-
 These are functions:
 
+* `fn`
+  : ___Needs filling in___
+* `fn_mut`
+  : ___Needs filling in___
+* `fn_once`
+  : ___Needs filling in___
 * `str_eq`
   : Compare two strings (`&str`) for equality.
 * `strdup_uniq`
@@ -2166,48 +2176,73 @@ These are functions:
 
 #### Types
 
-* `unsafe`
-  : A type whose contents can be mutated through an immutable reference
 * `type_id`
   : The type returned by the `type_id` intrinsic.
+* `unsafe`
+  : A type whose contents can be mutated through an immutable reference
 
 #### Marker types
 
 These types help drive the compiler's analysis
 
-* `covariant_type`
-  : The type parameter should be considered covariant
-* `contravariant_type`
-  : The type parameter should be considered contravariant
-* `invariant_type`
-  : The type parameter should be considered invariant
-* `covariant_lifetime`
-  : The lifetime parameter should be considered covariant
-* `contravariant_lifetime`
-  : The lifetime parameter should be considered contravariant
-* `invariant_lifetime`
-  : The lifetime parameter should be considered invariant
-* `no_send_bound`
-  : This type does not implement "send", even if eligible
+* `begin_unwind`
+  : ___Needs filling in___
 * `no_copy_bound`
   : This type does not implement "copy", even if eligible
+* `no_send_bound`
+  : This type does not implement "send", even if eligible
 * `no_sync_bound`
   : This type does not implement "sync", even if eligible
 * `managed_bound`
   : This type implements "managed"
-
+* `eh_personality`
+  : ___Needs filling in___
+* `exchange_free`
+  : Free memory that was allocated on the exchange heap.
+* `exchange_malloc`
+  : Allocate memory on the exchange heap.
+* `closure_exchange_malloc`
+  : ___Needs filling in___
 * `fail_`
   : Abort the program with an error.
 * `fail_bounds_check`
   : Abort the program with a bounds check error.
-* `exchange_malloc`
-  : Allocate memory on the exchange heap.
-* `exchange_free`
-  : Free memory that was allocated on the exchange heap.
-* `malloc`
-  : Allocate memory on the managed heap.
 * `free`
   : Free memory that was allocated on the managed heap.
+* `gc`
+  : ___Needs filling in___
+* `exchange_heap`
+  : ___Needs filling in___
+* `managed_heap`
+  : ___Needs filling in___
+* `iterator`
+  : ___Needs filling in___
+* `contravariant_lifetime`
+  : The lifetime parameter should be considered contravariant
+* `covariant_lifetime`
+  : The lifetime parameter should be considered covariant
+* `invariant_lifetime`
+  : The lifetime parameter should be considered invariant
+* `malloc`
+  : Allocate memory on the managed heap.
+* `opaque`
+  : ___Needs filling in___
+* `owned_box`
+  : ___Needs filling in___
+* `stack_exhausted`
+  : ___Needs filling in___
+* `start`
+  : ___Needs filling in___
+* `contravariant_type`
+  : The type parameter should be considered contravariant
+* `covariant_type`
+  : The type parameter should be considered covariant
+* `invariant_type`
+  : The type parameter should be considered invariant
+* `ty_desc`
+  : ___Needs filling in___
+* `ty_visitor`
+  : ___Needs filling in___
 
 > **Note:** This list is likely to become out of date. We should auto-generate it
 > from `librustc/middle/lang_items.rs`.
@@ -2276,12 +2311,12 @@ Supported traits for `deriving` are:
 * Comparison traits: `PartialEq`, `Eq`, `PartialOrd`, `Ord`.
 * Serialization: `Encodable`, `Decodable`. These require `serialize`.
 * `Clone`, to create `T` from `&T` via a copy.
-* `Hash`, to iterate over the bytes in a data type.
-* `Rand`, to create a random instance of a data type.
 * `Default`, to create an empty instance of a data type.
-* `Zero`, to create a zero instance of a numeric data type.
 * `FromPrimitive`, to create an instance from a numeric primitive.
+* `Hash`, to iterate over the bytes in a data type.
+* `Rand`, to create a random instance of a data type.
 * `Show`, to format a value using the `{}` formatter.
+* `Zero`, to create a zero instance of a numeric data type.
 
 ### Stability
 
@@ -2375,34 +2410,48 @@ considered off, and using the features will result in a compiler error.
 
 The currently implemented features of the reference compiler are:
 
-* `macro_rules` - The definition of new macros. This does not encompass
-                  macro-invocation, that is always enabled by default, this only
-                  covers the definition of new macros. There are currently
-                  various problems with invoking macros, how they interact with
-                  their environment, and possibly how they are used outside of
-                  location in which they are defined. Macro definitions are
-                  likely to change slightly in the future, so they are currently
-                  hidden behind this feature.
+* `asm` - The `asm!` macro provides a means for inline assembly. This is often
+          useful, but the exact syntax for this feature along with its semantics
+          are likely to change, so this macro usage must be opted into.
+
+* `concat_idents` - Allows use of the `concat_idents` macro, which is in many
+                    ways insufficient for concatenating identifiers, and may
+                    be removed entirely for something more wholsome.
+
+* `default_type_params` - Allows use of default type parameters. The future of
+                          this feature is uncertain.
 
 * `globs` - Importing everything in a module through `*`. This is currently a
             large source of bugs in name resolution for Rust, and it's not clear
             whether this will continue as a feature or not. For these reasons,
             the glob import statement has been hidden behind this feature flag.
 
-* `struct_variant` - Structural enum variants (those with named fields). It is
-                     currently unknown whether this style of enum variant is as
-                     fully supported as the tuple-forms, and it's not certain
-                     that this style of variant should remain in the language.
-                     For now this style of variant is hidden behind a feature
-                     flag.
+* `intrinsics` - Allows use of the "rust-intrinsics" ABI. Compiler intrinsics
+                 are inherently unstable and no promise about them is made.
 
-* `once_fns` - Onceness guarantees a closure is only executed once. Defining a
-               closure as `once` is unlikely to be supported going forward. So
-               they are hidden behind this feature until they are to be removed.
+* `lang_items` - Allows use of the `#[lang]` attribute. Like `intrinsics`,
+                 lang items are inherently unstable and no promise about
+                 them is made.
 
-* `asm` - The `asm!` macro provides a means for inline assembly. This is often
-          useful, but the exact syntax for this feature along with its semantics
-          are likely to change, so this macro usage must be opted into.
+* `link_args` - This attribute is used to specify custom flags to the linker,
+                but usage is strongly discouraged. The compiler's usage of the
+                system linker is not guaranteed to continue in the future, and
+                if the system linker is not used then specifying custom flags
+                doesn't have much meaning.
+
+* `linkage` - Allows use of the `linkage` attribute, which is not portable.
+
+* `log_syntax` - Allows use of the `log_syntax` macro attribute, which is a
+                 nasty hack that will certainly be removed.
+
+* `macro_rules` - The definition of new macros. This does not encompass
+                  macro-invocation, that is always enabled by default, this only
+                  covers the definition of new macros. There are currently
+                  various problems with invoking macros, how they interact with
+                  their environment, and possibly how they are used outside of
+                  location in which they are defined. Macro definitions are
+                  likely to change slightly in the future, so they are currently
+                  hidden behind this feature.
 
 * `managed_boxes` - Usage of `@` is gated due to many
                     planned changes to this feature. In the past, this has meant
@@ -2417,20 +2466,14 @@ The currently implemented features of the reference compiler are:
                        now until the specification of identifiers is fully
                        fleshed out.
 
-* `thread_local` - The usage of the `#[thread_local]` attribute is experimental
-                   and should be seen as unstable. This attribute is used to
-                   declare a `static` as being unique per-thread leveraging
-                   LLVM's implementation which works in concert with the kernel
-                   loader and dynamic linker. This is not necessarily available
-                   on all platforms, and usage of it is discouraged (rust
-                   focuses more on task-local data instead of thread-local
-                   data).
+* `once_fns` - Onceness guarantees a closure is only executed once. Defining a
+               closure as `once` is unlikely to be supported going forward. So
+               they are hidden behind this feature until they are to be removed.
 
-* `link_args` - This attribute is used to specify custom flags to the linker,
-                but usage is strongly discouraged. The compiler's usage of the
-                system linker is not guaranteed to continue in the future, and
-                if the system linker is not used then specifying custom flags
-                doesn't have much meaning.
+* `overloaded_calls` - Allow implementing the `Fn*` family of traits on user
+                       types, allowing overloading the call operator (`()`).
+                       This feature may still undergo changes before being
+                       stabilized.
 
 * `phase` - Usage of the `#[phase]` attribute allows loading compiler plugins
             for custom lints or syntax extensions. The implementation is considered
@@ -2442,56 +2485,48 @@ The currently implemented features of the reference compiler are:
                        in need of a overhaul, and it is not clear that plugins
                        defined using this will continue to work.
 
-* `log_syntax` - Allows use of the `log_syntax` macro attribute, which is a
-                 nasty hack that will certainly be removed.
-
-* `trace_macros` - Allows use of the `trace_macros` macro, which is a nasty
-                   hack that will certainly be removed.
-
-* `concat_idents` - Allows use of the `concat_idents` macro, which is in many
-                    ways insufficient for concatenating identifiers, and may
-                    be removed entirely for something more wholsome.
-
-* `unsafe_destructor` - Allows use of the `#[unsafe_destructor]` attribute,
-                        which is considered wildly unsafe and will be
-                        obsoleted by language improvements.
-
-* `intrinsics` - Allows use of the "rust-intrinsics" ABI. Compiler intrinsics
-                 are inherently unstable and no promise about them is made.
-
-* `lang_items` - Allows use of the `#[lang]` attribute. Like `intrinsics`,
-                 lang items are inherently unstable and no promise about
-                 them is made.
-
-* `simd` - Allows use of the `#[simd]` attribute, which is overly simple and
-           not the SIMD interface we want to expose in the long term.
-
-* `default_type_params` - Allows use of default type parameters. The future of
-                          this feature is uncertain.
-
 * `quote` - Allows use of the `quote_*!` family of macros, which are
             implemented very poorly and will likely change significantly
             with a proper implementation.
 
-* `linkage` - Allows use of the `linkage` attribute, which is not portable.
+* `rustc_diagnostic_macros`- A mysterious feature, used in the implementation
+                             of rustc, not meant for mortals.
+
+* `simd` - Allows use of the `#[simd]` attribute, which is overly simple and
+           not the SIMD interface we want to expose in the long term.
 
 * `struct_inherit` - Allows using struct inheritance, which is barely
                      implemented and will probably be removed. Don't use this.
 
-* `overloaded_calls` - Allow implementing the `Fn*` family of traits on user
-                       types, allowing overloading the call operator (`()`).
-                       This feature may still undergo changes before being
-                       stabilized.
+* `struct_variant` - Structural enum variants (those with named fields). It is
+                     currently unknown whether this style of enum variant is as
+                     fully supported as the tuple-forms, and it's not certain
+                     that this style of variant should remain in the language.
+                     For now this style of variant is hidden behind a feature
+                     flag.
+
+* `thread_local` - The usage of the `#[thread_local]` attribute is experimental
+                   and should be seen as unstable. This attribute is used to
+                   declare a `static` as being unique per-thread leveraging
+                   LLVM's implementation which works in concert with the kernel
+                   loader and dynamic linker. This is not necessarily available
+                   on all platforms, and usage of it is discouraged (rust
+                   focuses more on task-local data instead of thread-local
+                   data).
+
+* `trace_macros` - Allows use of the `trace_macros` macro, which is a nasty
+                   hack that will certainly be removed.
 
 * `unboxed_closure_sugar` - Allows using `|Foo| -> Bar` as a trait bound
                             meaning one of the `Fn` traits.  Still
                             experimental.
 
-* `rustc_diagnostic_macros`- A mysterious feature, used in the implementation
-                             of rustc, not meant for mortals.
-
 * `unboxed_closures` - A work in progress feature with many known bugs.
 
+* `unsafe_destructor` - Allows use of the `#[unsafe_destructor]` attribute,
+                        which is considered wildly unsafe and will be
+                        obsoleted by language improvements.
+
 If a feature is promoted to a language feature, then all existing programs will
 start to receive compilation warnings about #[feature] directives which enabled
 the new feature (because the directive is no longer necessary). However, if
@@ -3621,7 +3656,10 @@ There are four varieties of pointer in Rust:
     References arise by (automatic) conversion from owning pointers, managed pointers,
     or by applying the borrowing operator `&` to some other value,
     including [lvalues, rvalues or temporaries](#lvalues,-rvalues-and-temporaries).
-    References are written `&content`, or in some cases `&'f content` for some lifetime-variable `f`,
+    A borrow expression is written `&content`.
+
+    A reference type is written `&'f type` for some lifetime-variable `f`,
+    or just `&type` when the lifetime can be elided;
     for example `&int` means a reference to an integer.
     Copying a reference is a "shallow" operation:
     it involves only copying the pointer itself.
index 5424cd3b3ab98e1c0e203927d81a184d57068d9e..7663cd1e3466abb3d0bfb1ff5d67d455e8aa86f7 100755 (executable)
@@ -293,13 +293,12 @@ def emit_bsearch_range_table(f):
     f.write("""
 fn bsearch_range_table(c: char, r: &'static [(char,char)]) -> bool {
     use core::cmp::{Equal, Less, Greater};
-    use core::slice::ImmutableVector;
-    use core::option::None;
-    r.bsearch(|&(lo,hi)| {
+    use core::slice::ImmutableSlice;
+    r.binary_search(|&(lo,hi)| {
         if lo <= c && c <= hi { Equal }
         else if hi < c { Less }
         else { Greater }
-    }) != None
+    }).found().is_some()
 }\n
 """)
 
@@ -352,9 +351,10 @@ def emit_conversions_module(f, lowerupper, upperlower):
     f.write("pub mod conversions {")
     f.write("""
     use core::cmp::{Equal, Less, Greater};
-    use core::slice::ImmutableVector;
+    use core::slice::ImmutableSlice;
     use core::tuple::Tuple2;
     use core::option::{Option, Some, None};
+    use core::slice;
 
     pub fn to_lower(c: char) -> char {
         match bsearch_case_table(c, LuLl_table) {
@@ -371,11 +371,14 @@ def emit_conversions_module(f, lowerupper, upperlower):
     }
 
     fn bsearch_case_table(c: char, table: &'static [(char, char)]) -> Option<uint> {
-        table.bsearch(|&(key, _)| {
+        match table.binary_search(|&(key, _)| {
             if c == key { Equal }
             else if key < c { Less }
             else { Greater }
-        })
+        }) {
+            slice::Found(i) => Some(i),
+            slice::NotFound(_) => None,
+        }
     }
 
 """)
@@ -387,8 +390,8 @@ def emit_conversions_module(f, lowerupper, upperlower):
 
 def emit_grapheme_module(f, grapheme_table, grapheme_cats):
     f.write("""pub mod grapheme {
-    use core::option::{Some, None};
-    use core::slice::ImmutableVector;
+    use core::slice::ImmutableSlice;
+    use core::slice;
 
     #[allow(non_camel_case_types)]
     #[deriving(Clone)]
@@ -400,16 +403,16 @@ def emit_grapheme_module(f, grapheme_table, grapheme_cats):
 
     fn bsearch_range_value_table(c: char, r: &'static [(char, char, GraphemeCat)]) -> GraphemeCat {
         use core::cmp::{Equal, Less, Greater};
-        match r.bsearch(|&(lo, hi, _)| {
+        match r.binary_search(|&(lo, hi, _)| {
             if lo <= c && c <= hi { Equal }
             else if hi < c { Less }
             else { Greater }
         }) {
-            Some(idx) => {
+            slice::Found(idx) => {
                 let (_, _, cat) = r[idx];
                 cat
             }
-            None => GC_Any
+            slice::NotFound(_) => GC_Any
         }
     }
 
@@ -427,20 +430,21 @@ def emit_grapheme_module(f, grapheme_table, grapheme_cats):
 def emit_charwidth_module(f, width_table):
     f.write("pub mod charwidth {\n")
     f.write("    use core::option::{Option, Some, None};\n")
-    f.write("    use core::slice::ImmutableVector;\n")
+    f.write("    use core::slice::ImmutableSlice;\n")
+    f.write("    use core::slice;\n")
     f.write("""
     fn bsearch_range_value_table(c: char, is_cjk: bool, r: &'static [(char, char, u8, u8)]) -> u8 {
         use core::cmp::{Equal, Less, Greater};
-        match r.bsearch(|&(lo, hi, _, _)| {
+        match r.binary_search(|&(lo, hi, _, _)| {
             if lo <= c && c <= hi { Equal }
             else if hi < c { Less }
             else { Greater }
         }) {
-            Some(idx) => {
+            slice::Found(idx) => {
                 let (_, _, r_ncjk, r_cjk) = r[idx];
                 if is_cjk { r_cjk } else { r_ncjk }
             }
-            None => 1
+            slice::NotFound(_) => 1
         }
     }
 """)
@@ -525,19 +529,19 @@ def emit_norm_module(f, canon, compat, combine, norm_props):
 
     f.write("""
     fn bsearch_range_value_table(c: char, r: &'static [(char, char, u8)]) -> u8 {
-        use core::option::{Some, None};
         use core::cmp::{Equal, Less, Greater};
-        use core::slice::ImmutableVector;
-        match r.bsearch(|&(lo, hi, _)| {
+        use core::slice::ImmutableSlice;
+        use core::slice;
+        match r.binary_search(|&(lo, hi, _)| {
             if lo <= c && c <= hi { Equal }
             else if hi < c { Less }
             else { Greater }
         }) {
-            Some(idx) => {
+            slice::Found(idx) => {
                 let (_, _, result) = r[idx];
                 result
             }
-            None => 0
+            slice::NotFound(_) => 0
         }
     }\n
 """)
index 14d4f90a077cf878b1c40a2ecdcb03d3b4a43dcd..7745a0d887ee8ad7281087ea5b14b8dc6fe5e437 100644 (file)
@@ -264,7 +264,7 @@ pub fn get(&self, i: uint) -> bool {
         assert!(i < self.nbits);
         let w = i / uint::BITS;
         let b = i % uint::BITS;
-        let x = self.storage.get(w) & (1 << b);
+        let x = self.storage[w] & (1 << b);
         x != 0
     }
 
@@ -289,8 +289,8 @@ pub fn set(&mut self, i: uint, x: bool) {
         let w = i / uint::BITS;
         let b = i % uint::BITS;
         let flag = 1 << b;
-        *self.storage.get_mut(w) = if x { *self.storage.get(w) | flag }
-                          else { *self.storage.get(w) & !flag };
+        *self.storage.get_mut(w) = if x { self.storage[w] | flag }
+                          else { self.storage[w] & !flag };
     }
 
     /// Set all bits to 1.
@@ -827,7 +827,7 @@ fn clone(&self) -> Bitv {
     fn clone_from(&mut self, source: &Bitv) {
         self.nbits = source.nbits;
         self.storage.reserve(source.storage.len());
-        for (i, w) in self.storage.mut_iter().enumerate() { *w = *source.storage.get(i); }
+        for (i, w) in self.storage.mut_iter().enumerate() { *w = source.storage[i]; }
     }
 }
 
@@ -1146,7 +1146,7 @@ fn other_op(&mut self, other: &BitvSet, f: |uint, uint| -> uint) {
         self_bitv.reserve(other_bitv.capacity());
         // Apply values
         for (i, w) in other_bitv.mask_words(0) {
-            let old = *self_bitv.storage.get(i);
+            let old = self_bitv.storage[i];
             let new = f(old, w);
             *self_bitv.storage.get_mut(i) = new;
         }
@@ -1573,10 +1573,10 @@ fn next(&mut self) -> Option<uint> {
                 // one Bitv might be longer than the other
                 let word_idx = self.next_idx / uint::BITS;
                 let w1 = if word_idx < s_bitv.storage.len() {
-                             *s_bitv.storage.get(word_idx)
+                             s_bitv.storage[word_idx]
                          } else { 0 };
                 let w2 = if word_idx < o_bitv.storage.len() {
-                             *o_bitv.storage.get(word_idx)
+                             o_bitv.storage[word_idx]
                          } else { 0 };
                 self.current_word = (self.merge)(w1, w2);
             }
index 947c87daa846021dcd9d896984ba6d0c15ccea63..4c5f8ef09879e06ee898940db4de26278c771ec4 100644 (file)
@@ -299,14 +299,14 @@ fn bsearch_leaf(&self, k: K) -> Option<uint> {
             midpoint = 0;
         }
         loop {
-            let order = self.elts.get(midpoint).key.cmp(&k);
+            let order = self.elts[midpoint].key.cmp(&k);
             match order {
                 Equal => {
                     return None;
                 }
                 Greater => {
                     if midpoint > 0 {
-                        if self.elts.get(midpoint - 1).key.cmp(&k) == Less {
+                        if self.elts[midpoint - 1].key.cmp(&k) == Less {
                             return Some(midpoint);
                         }
                         else {
@@ -322,7 +322,7 @@ fn bsearch_leaf(&self, k: K) -> Option<uint> {
                 }
                 Less => {
                     if midpoint + 1 < self.elts.len() {
-                        if self.elts.get(midpoint + 1).key.cmp(&k) == Greater {
+                        if self.elts[midpoint + 1].key.cmp(&k) == Greater {
                             return Some(midpoint);
                         }
                         else {
@@ -422,7 +422,7 @@ fn cmp(&self, other: &Leaf<K, V>) -> Ordering {
         if self.elts.len() < other.elts.len() {
             return Less;
         }
-        self.elts.get(0).cmp(other.elts.get(0))
+        self.elts[0].cmp(&other.elts[0])
     }
 }
 
@@ -457,14 +457,14 @@ fn bsearch_branch(&self, k: K) -> Option<uint> {
             midpoint = 0u;
         }
         loop {
-            let order = self.elts.get(midpoint).key.cmp(&k);
+            let order = self.elts[midpoint].key.cmp(&k);
             match order {
                 Equal => {
                     return None;
                 }
                 Greater => {
                     if midpoint > 0 {
-                        if self.elts.get(midpoint - 1).key.cmp(&k) == Less {
+                        if self.elts[midpoint - 1].key.cmp(&k) == Less {
                             return Some(midpoint);
                         }
                         else {
@@ -480,7 +480,7 @@ fn bsearch_branch(&self, k: K) -> Option<uint> {
                 }
                 Less => {
                     if midpoint + 1 < self.elts.len() {
-                        if self.elts.get(midpoint + 1).key.cmp(&k) == Greater {
+                        if self.elts[midpoint + 1].key.cmp(&k) == Greater {
                             return Some(midpoint);
                         }
                         else {
@@ -529,15 +529,15 @@ fn insert(mut self, k: K, v: V, ub: uint) -> (Node<K, V>, bool) {
             Some(i) => {
                 if i == self.elts.len() {
                     let new_outcome = self.clone().rightmost_child.insert(k.clone(),
-                                                                       v.clone(),
-                                                                       ub.clone());
+                                                                          v.clone(),
+                                                                          ub.clone());
                     new_branch = new_outcome.clone().val0();
                     outcome = new_outcome.val1();
                 }
                 else {
-                    let new_outcome = self.elts.get(i).left.clone().insert(k.clone(),
-                                                                                 v.clone(),
-                                                                                 ub.clone());
+                    let new_outcome = self.elts[i].left.clone().insert(k.clone(),
+                                                                       v.clone(),
+                                                                       ub.clone());
                     new_branch = new_outcome.clone().val0();
                     outcome = new_outcome.val1();
                 }
@@ -581,7 +581,7 @@ fn insert(mut self, k: K, v: V, ub: uint) -> (Node<K, V>, bool) {
                 //If we have a new branch node, attempt to insert it into the tree
                 //as with the key-value pair, then check to see if the node is overfull.
                 BranchNode(branch) => {
-                    let new_elt = branch.elts.get(0).clone();
+                    let new_elt = branch.elts[0].clone();
                     let new_elt_index = self.bsearch_branch(new_elt.clone().key);
                     match new_elt_index {
                         None => {
@@ -652,7 +652,7 @@ fn cmp(&self, other: &Branch<K, V>) -> Ordering {
         if self.elts.len() < other.elts.len() {
             return Less;
         }
-        self.elts.get(0).cmp(other.elts.get(0))
+        self.elts[0].cmp(&other.elts[0])
     }
 }
 
index 3d322729aab43c415250dd5f459436d35b6be8b0..8344ad7c79d7b902edb95e2d40ee376aaa1ecd67 100644 (file)
@@ -654,7 +654,7 @@ fn size_hint(&self) -> (uint, Option<uint>) {
 
 impl<A> DoubleEndedIterator<A> for MoveItems<A> {
     #[inline]
-    fn next_back(&mut self) -> Option<A> { self.list.pop_back() }
+    fn next_back(&mut self) -> Option<A> { self.list.pop() }
 }
 
 impl<A> FromIterator<A> for DList<A> {
@@ -667,7 +667,7 @@ fn from_iter<T: Iterator<A>>(iterator: T) -> DList<A> {
 
 impl<A> Extendable<A> for DList<A> {
     fn extend<T: Iterator<A>>(&mut self, mut iterator: T) {
-        for elt in iterator { self.push_back(elt); }
+        for elt in iterator { self.push(elt); }
     }
 }
 
index 6f8b63953e2b495d4f8a60ca6bbd95f05cc96448..dd07e718af418f05f55da322eb84d2635d8c1473 100644 (file)
@@ -296,7 +296,7 @@ mod tests {
     use std::prelude::*;
     use std::mem;
 
-    use slice::ImmutableVector;
+    use slice::ImmutableSlice;
     use super::{Hash, Hasher, Writer};
 
     struct MyWriterHasher;
index 485dc8c5959b74f3d5dae4650bd8451e8398fbcb..b31d811c2c966596aac6c572cc44f458836602c0 100644 (file)
@@ -275,7 +275,7 @@ mod tests {
 
     use str::Str;
     use string::String;
-    use slice::{Vector, ImmutableVector};
+    use slice::{Slice, ImmutableSlice};
     use vec::Vec;
 
     use super::super::{Hash, Writer};
index bf2c8c83d87b6042d33cb7ac72eb7c6eade2be5d..a88a833c9edcab2b3a1a398cd323ec28ec020a96 100644 (file)
@@ -261,7 +261,7 @@ pub fn iter<'a>(&'a self) -> Items<'a, T> {
     ///
     /// ```
     pub fn top<'a>(&'a self) -> Option<&'a T> {
-        if self.is_empty() { None } else { Some(self.data.get(0)) }
+        if self.is_empty() { None } else { Some(&self.data[0]) }
     }
 
     #[deprecated="renamed to `top`"]
@@ -473,7 +473,7 @@ fn siftup(&mut self, start: uint, mut pos: uint) {
 
             while pos > start {
                 let parent = (pos - 1) >> 1;
-                if new > *self.data.get(parent) {
+                if new > self.data[parent] {
                     let x = replace(self.data.get_mut(parent), zeroed());
                     ptr::write(self.data.get_mut(pos), x);
                     pos = parent;
@@ -493,7 +493,7 @@ fn siftdown_range(&mut self, mut pos: uint, end: uint) {
             let mut child = 2 * pos + 1;
             while child < end {
                 let right = child + 1;
-                if right < end && !(*self.data.get(child) > *self.data.get(right)) {
+                if right < end && !(self.data[child] > self.data[right]) {
                     child = right;
                 }
                 let x = replace(self.data.get_mut(child), zeroed());
index 736861a54a43410bef87b0fdc97197f95e3baca9..354beb56d2dc3cbcf8386a2bdaf8d258e92f9418 100644 (file)
@@ -53,7 +53,7 @@ fn clear(&mut self) {
 impl<T> Deque<T> for RingBuf<T> {
     /// Return a reference to the first element in the RingBuf
     fn front<'a>(&'a self) -> Option<&'a T> {
-        if self.nelts > 0 { Some(self.get(0)) } else { None }
+        if self.nelts > 0 { Some(&self[0]) } else { None }
     }
 
     /// Return a mutable reference to the first element in the RingBuf
@@ -63,7 +63,7 @@ fn front_mut<'a>(&'a mut self) -> Option<&'a mut T> {
 
     /// Return a reference to the last element in the RingBuf
     fn back<'a>(&'a self) -> Option<&'a T> {
-        if self.nelts > 0 { Some(self.get(self.nelts - 1)) } else { None }
+        if self.nelts > 0 { Some(&self[self.nelts - 1]) } else { None }
     }
 
     /// Return a mutable reference to the last element in the RingBuf
@@ -152,7 +152,7 @@ pub fn with_capacity(n: uint) -> RingBuf<T> {
     #[deprecated = "prefer using indexing, e.g., ringbuf[0]"]
     pub fn get<'a>(&'a self, i: uint) -> &'a T {
         let idx = self.raw_index(i);
-        match *self.elts.get(idx) {
+        match self.elts[idx] {
             None => fail!(),
             Some(ref v) => v
         }
@@ -362,6 +362,7 @@ pub struct MutItems<'a, T> {
 
 impl<'a, T> Iterator<&'a mut T> for MutItems<'a, T> {
     #[inline]
+    #[allow(deprecated)] // mut_shift_ref
     fn next(&mut self) -> Option<&'a mut T> {
         if self.nelts == 0 {
             return None;
@@ -384,6 +385,7 @@ fn size_hint(&self) -> (uint, Option<uint>) {
 
 impl<'a, T> DoubleEndedIterator<&'a mut T> for MutItems<'a, T> {
     #[inline]
+    #[allow(deprecated)] // mut_shift_ref
     fn next_back(&mut self) -> Option<&'a mut T> {
         if self.nelts == 0 {
             return None;
@@ -481,6 +483,7 @@ fn hash(&self, state: &mut S) {
 
 impl<A> Index<uint, A> for RingBuf<A> {
     #[inline]
+    #[allow(deprecated)]
     fn index<'a>(&'a self, i: &uint) -> &'a A {
         self.get(*i)
     }
@@ -506,7 +509,7 @@ fn from_iter<T: Iterator<A>>(iterator: T) -> RingBuf<A> {
 impl<A> Extendable<A> for RingBuf<A> {
     fn extend<T: Iterator<A>>(&mut self, mut iterator: T) {
         for elt in iterator {
-            self.push_back(elt);
+            self.push(elt);
         }
     }
 }
index f6aaea79bbd316c9a7da99d54e49fc5fa41772cb..aac5b24fa6f02e4bbba57ac5f3ab60af2ad65a1d 100644 (file)
@@ -45,8 +45,8 @@
 ## Traits
 
 A number of traits add methods that allow you to accomplish tasks with slices.
-These traits include `ImmutableVector`, which is defined for `&[T]` types,
-and `MutableVector`, defined for `&mut [T]` types.
+These traits include `ImmutableSlice`, which is defined for `&[T]` types,
+and `MutableSlice`, defined for `&mut [T]` types.
 
 An example is the method `.slice(a, b)` that returns an immutable "view" into
 a `Vec` or another slice from the index interval `[a, b)`:
 use vec::Vec;
 
 pub use core::slice::{ref_slice, mut_ref_slice, Splits, Windows};
-pub use core::slice::{Chunks, Vector, ImmutableVector, ImmutableEqVector};
-pub use core::slice::{ImmutableOrdVector, MutableVector, Items, MutItems};
+pub use core::slice::{Chunks, Slice, ImmutableSlice, ImmutablePartialEqSlice};
+pub use core::slice::{ImmutableOrdSlice, MutableSlice, Items, MutItems};
 pub use core::slice::{MutSplits, MutChunks};
-pub use core::slice::{bytes, MutableCloneableVector};
+pub use core::slice::{bytes, MutableCloneableSlice};
+pub use core::slice::{BinarySearchResult, Found, NotFound};
 
 // Functional utilities
 
@@ -116,7 +117,7 @@ pub trait VectorVector<T> {
     fn connect_vec(&self, sep: &T) -> Vec<T>;
 }
 
-impl<'a, T: Clone, V: Vector<T>> VectorVector<T> for &'a [V] {
+impl<'a, T: Clone, V: Slice<T>> VectorVector<T> for &'a [V] {
     fn concat_vec(&self) -> Vec<T> {
         let size = self.iter().fold(0u, |acc, v| acc + v.as_slice().len());
         let mut result = Vec::with_capacity(size);
@@ -190,7 +191,7 @@ fn new_pos(i: uint, s: Direction) -> uint {
         let max = self.sdir.iter().map(|&x| x).enumerate()
                            .filter(|&(i, sd)|
                                 new_pos(i, sd.dir) < self.sdir.len() &&
-                                self.sdir.get(new_pos(i, sd.dir)).size < sd.size)
+                                self.sdir[new_pos(i, sd.dir)].size < sd.size)
                            .max_by(|&(_, sd)| sd.size);
         match max {
             Some((i, sd)) => {
@@ -558,7 +559,7 @@ unsafe fn step<T>(ptr: &mut *mut T) -> *mut T {
 
 /// Extension methods for vectors such that their elements are
 /// mutable.
-pub trait MutableVectorAllocating<'a, T> {
+pub trait MutableSliceAllocating<'a, T> {
     /// Sort the vector, in place, using `compare` to compare
     /// elements.
     ///
@@ -604,7 +605,7 @@ pub trait MutableVectorAllocating<'a, T> {
     fn move_from(self, src: Vec<T>, start: uint, end: uint) -> uint;
 }
 
-impl<'a,T> MutableVectorAllocating<'a, T> for &'a mut [T] {
+impl<'a,T> MutableSliceAllocating<'a, T> for &'a mut [T] {
     #[inline]
     fn sort_by(self, compare: |&T, &T| -> Ordering) {
         merge_sort(self, compare)
@@ -621,7 +622,7 @@ fn move_from(self, mut src: Vec<T>, start: uint, end: uint) -> uint {
 
 /// Methods for mutable vectors with orderable elements, such as
 /// in-place sorting.
-pub trait MutableOrdVector<T> {
+pub trait MutableOrdSlice<T> {
     /// Sort the vector, in place.
     ///
     /// This is equivalent to `self.sort_by(|a, b| a.cmp(b))`.
@@ -667,7 +668,7 @@ pub trait MutableOrdVector<T> {
     fn prev_permutation(self) -> bool;
 }
 
-impl<'a, T: Ord> MutableOrdVector<T> for &'a mut [T] {
+impl<'a, T: Ord> MutableOrdSlice<T> for &'a mut [T] {
     #[inline]
     fn sort(self) {
         self.sort_by(|a,b| a.cmp(b))
index 39244c7cd5fa60a7dc2c4e3581a97072acb95d8f..4529c8782a19493c6f30e032ef81294ff7b733b1 100644 (file)
@@ -86,7 +86,7 @@ impl<V> Map<uint, V> for SmallIntMap<V> {
     /// Return a reference to the value corresponding to the key.
     fn find<'a>(&'a self, key: &uint) -> Option<&'a V> {
         if *key < self.v.len() {
-            match *self.v.get(*key) {
+            match self.v[*key] {
               Some(ref value) => Some(value),
               None => None
             }
@@ -421,6 +421,7 @@ fn extend<Iter: Iterator<(uint, V)>>(&mut self, mut iter: Iter) {
 
 impl<V> Index<uint, V> for SmallIntMap<V> {
     #[inline]
+    #[allow(deprecated)]
     fn index<'a>(&'a self, i: &uint) -> &'a V {
         self.get(i)
     }
index 270b76fd57fc95cd5949349be4d7c52e6fbaa1de..60ee8cc04f74c667e4f05a9479f91915f581930b 100644 (file)
@@ -251,11 +251,11 @@ fn next(&mut self) -> Option<char> {
         match self.buffer.as_slice().head() {
             Some(&(c, 0)) => {
                 self.sorted = false;
-                self.buffer.shift();
+                self.buffer.remove(0);
                 return Some(c);
             }
             Some(&(c, _)) if self.sorted => {
-                self.buffer.shift();
+                self.buffer.remove(0);
                 return Some(c);
             }
             _ => self.sorted = false
@@ -287,7 +287,7 @@ fn next(&mut self) -> Option<char> {
             self.sorted = true;
         }
 
-        match self.buffer.shift() {
+        match self.buffer.remove(0) {
             Some((c, 0)) => {
                 self.sorted = false;
                 Some(c)
@@ -805,21 +805,21 @@ fn lev_distance(&self, t: &str) -> uint {
 
             for (j, tc) in t.chars().enumerate() {
 
-                let next = *dcol.get(j + 1);
+                let next = dcol[j + 1];
 
                 if sc == tc {
                     *dcol.get_mut(j + 1) = current;
                 } else {
                     *dcol.get_mut(j + 1) = cmp::min(current, next);
-                    *dcol.get_mut(j + 1) = cmp::min(*dcol.get(j + 1),
-                                                    *dcol.get(j)) + 1;
+                    *dcol.get_mut(j + 1) = cmp::min(dcol[j + 1],
+                                                    dcol[j]) + 1;
                 }
 
                 current = next;
             }
         }
 
-        return *dcol.get(tlen);
+        return dcol[tlen];
     }
 
     /// An Iterator over the string in Unicode Normalization Form D
@@ -894,7 +894,7 @@ mod tests {
     use {Collection, MutableSeq};
 
     use super::*;
-    use std::slice::{Vector, ImmutableVector};
+    use std::slice::{Slice, ImmutableSlice};
     use string::String;
     use vec::Vec;
 
@@ -1812,17 +1812,17 @@ fn test_split_char_iterator() {
     fn test_splitn_char_iterator() {
         let data = "\nMäry häd Ã¤ little lämb\nLittle lämb\n";
 
-        let split: Vec<&str> = data.splitn(' ', 3).collect();
+        let split: Vec<&str> = data.splitn(3, ' ').collect();
         assert_eq!(split, vec!["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
 
-        let split: Vec<&str> = data.splitn(|c: char| c == ' ', 3).collect();
+        let split: Vec<&str> = data.splitn(3, |c: char| c == ' ').collect();
         assert_eq!(split, vec!["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
 
         // Unicode
-        let split: Vec<&str> = data.splitn('ä', 3).collect();
+        let split: Vec<&str> = data.splitn(3, 'ä').collect();
         assert_eq!(split, vec!["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
 
-        let split: Vec<&str> = data.splitn(|c: char| c == 'ä', 3).collect();
+        let split: Vec<&str> = data.splitn(3, |c: char| c == 'ä').collect();
         assert_eq!(split, vec!["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
     }
 
@@ -1830,20 +1830,20 @@ fn test_splitn_char_iterator() {
     fn test_rsplitn_char_iterator() {
         let data = "\nMäry häd Ã¤ little lämb\nLittle lämb\n";
 
-        let mut split: Vec<&str> = data.rsplitn(' ', 3).collect();
+        let mut split: Vec<&str> = data.rsplitn(3, ' ').collect();
         split.reverse();
         assert_eq!(split, vec!["\nMäry häd Ã¤", "little", "lämb\nLittle", "lämb\n"]);
 
-        let mut split: Vec<&str> = data.rsplitn(|c: char| c == ' ', 3).collect();
+        let mut split: Vec<&str> = data.rsplitn(3, |c: char| c == ' ').collect();
         split.reverse();
         assert_eq!(split, vec!["\nMäry häd Ã¤", "little", "lämb\nLittle", "lämb\n"]);
 
         // Unicode
-        let mut split: Vec<&str> = data.rsplitn('ä', 3).collect();
+        let mut split: Vec<&str> = data.rsplitn(3, 'ä').collect();
         split.reverse();
         assert_eq!(split, vec!["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
 
-        let mut split: Vec<&str> = data.rsplitn(|c: char| c == 'ä', 3).collect();
+        let mut split: Vec<&str> = data.rsplitn(3, |c: char| c == 'ä').collect();
         split.reverse();
         assert_eq!(split, vec!["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
     }
index 9465fea6dcbee1180669fb8bfd4775e522aebe6f..3b9e2ac72dc4b02952976d03a9bf8ab850ba0c41 100644 (file)
 use core::fmt;
 use core::mem;
 use core::ptr;
-use core::raw::Slice;
+// FIXME: ICE's abound if you import the `Slice` type while importing `Slice` trait
+use RawSlice = core::raw::Slice;
+use core::slice::Slice;
 
 use {Collection, Mutable, MutableSeq};
 use hash;
 use str;
-use str::{CharRange, StrAllocating, MaybeOwned, Owned, Slice};
+use str::{CharRange, StrAllocating, MaybeOwned, Owned};
+use MaybeOwnedSlice = str::Slice; // So many `Slice`s...
 use vec::Vec;
 
 /// A growable string stored as a UTF-8 encoded buffer.
@@ -130,7 +133,7 @@ pub fn from_utf8(vec: Vec<u8>) -> Result<String, Vec<u8>> {
     /// ```
     pub fn from_utf8_lossy<'a>(v: &'a [u8]) -> MaybeOwned<'a> {
         if str::is_utf8(v) {
-            return Slice(unsafe { mem::transmute(v) })
+            return MaybeOwnedSlice(unsafe { mem::transmute(v) })
         }
 
         static TAG_CONT_U8: u8 = 128u8;
@@ -138,7 +141,7 @@ pub fn from_utf8_lossy<'a>(v: &'a [u8]) -> MaybeOwned<'a> {
         let mut i = 0;
         let total = v.len();
         fn unsafe_get(xs: &[u8], i: uint) -> u8 {
-            unsafe { *xs.unsafe_ref(i) }
+            unsafe { *xs.unsafe_get(i) }
         }
         fn safe_get(xs: &[u8], i: uint, total: uint) -> u8 {
             if i >= total {
@@ -496,7 +499,7 @@ pub fn push_char(&mut self, ch: char) {
         unsafe {
             // Attempt to not use an intermediate buffer by just pushing bytes
             // directly onto this string.
-            let slice = Slice {
+            let slice = RawSlice {
                 data: self.vec.as_ptr().offset(cur_len as int),
                 len: 4,
             };
@@ -669,7 +672,7 @@ pub fn pop_char(&mut self) -> Option<char> {
     /// }
     /// ```
     pub unsafe fn shift_byte(&mut self) -> Option<u8> {
-        self.vec.shift()
+        self.vec.remove(0)
     }
 
     /// Removes the first character from the string buffer and returns it.
index c3dcebfc815b1fd4cddbe1715e4d733a30ff7139..dcfe256807467fdeaa9f3f59867153d3e1aa68c9 100644 (file)
@@ -926,7 +926,7 @@ unsafe fn new() -> $name<'a, T> {
                 // such thing as invalid pointers and memory unsafety. The
                 // reason is performance, without doing this we can get the
                 // bench_iter_large microbenchmark down to about 30000 ns/iter
-                // (using .unsafe_ref to index self.stack directly, 38000
+                // (using .unsafe_get to index self.stack directly, 38000
                 // ns/iter with [] checked indexing), but this smashes that down
                 // to 13500 ns/iter.
                 //
index 39fe57038b0b2f4b98fa77e2f0a476b9b3408c1b..b49e8aa01bb4101044108818880a2052256e5a8c 100644 (file)
@@ -13,7 +13,8 @@
 use core::prelude::*;
 
 use alloc::heap::{allocate, reallocate, deallocate};
-use core::raw::Slice;
+use RawSlice = core::raw::Slice;
+use core::slice::Slice;
 use core::cmp::max;
 use core::default::Default;
 use core::fmt;
@@ -24,7 +25,7 @@
 use core::uint;
 
 use {Collection, Mutable, MutableSeq};
-use slice::{MutableOrdVector, MutableVectorAllocating, CloneableVector};
+use slice::{MutableOrdSlice, MutableSliceAllocating, CloneableVector};
 use slice::{Items, MutItems};
 
 
@@ -347,7 +348,7 @@ pub fn push_all(&mut self, other: &[T]) {
             unsafe {
                 ptr::write(
                     self.as_mut_slice().unsafe_mut_ref(len),
-                    other.unsafe_ref(i).clone());
+                    other.unsafe_get(i).clone());
                 self.set_len(len + 1);
             }
         }
@@ -453,6 +454,7 @@ fn clone_from(&mut self, other: &Vec<T>) {
 
 impl<T> Index<uint,T> for Vec<T> {
     #[inline]
+    #[allow(deprecated)] // allow use of get
     fn index<'a>(&'a self, index: &uint) -> &'a T {
         self.get(*index)
     }
@@ -505,7 +507,7 @@ fn partial_cmp(&self, other: &Vec<T>) -> Option<Ordering> {
 
 impl<T: Eq> Eq for Vec<T> {}
 
-impl<T: PartialEq, V: Vector<T>> Equiv<V> for Vec<T> {
+impl<T: PartialEq, V: Slice<T>> Equiv<V> for Vec<T> {
     #[inline]
     fn equiv(&self, other: &V) -> bool { self.as_slice() == other.as_slice() }
 }
@@ -701,7 +703,7 @@ pub fn truncate(&mut self, len: uint) {
                 // decrement len before the read(), so a failure on Drop doesn't
                 // re-drop the just-failed value.
                 self.len -= 1;
-                ptr::read(self.as_slice().unsafe_ref(self.len));
+                ptr::read(self.as_slice().unsafe_get(self.len));
             }
         }
     }
@@ -719,7 +721,7 @@ pub fn truncate(&mut self, len: uint) {
     #[inline]
     pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] {
         unsafe {
-            mem::transmute(Slice {
+            mem::transmute(RawSlice {
                 data: self.as_mut_ptr() as *const T,
                 len: self.len,
             })
@@ -910,8 +912,9 @@ pub fn tail<'a>(&'a self) -> &'a [T] {
     /// assert!(vec.tailn(2) == [3, 4]);
     /// ```
     #[inline]
+    #[deprecated = "use slice_from"]
     pub fn tailn<'a>(&'a self, n: uint) -> &'a [T] {
-        self.as_slice().tailn(n)
+        self.as_slice().slice_from(n)
     }
 
     /// Returns a reference to the last element of a vector, or `None` if it is
@@ -1501,7 +1504,7 @@ pub fn dedup(&mut self) {
     }
 }
 
-impl<T> Vector<T> for Vec<T> {
+impl<T> Slice<T> for Vec<T> {
     /// Work with `self` as a slice.
     ///
     /// # Example
@@ -1514,11 +1517,11 @@ impl<T> Vector<T> for Vec<T> {
     /// ```
     #[inline]
     fn as_slice<'a>(&'a self) -> &'a [T] {
-        unsafe { mem::transmute(Slice { data: self.as_ptr(), len: self.len }) }
+        unsafe { mem::transmute(RawSlice { data: self.as_ptr(), len: self.len }) }
     }
 }
 
-impl<T: Clone, V: Vector<T>> Add<V, Vec<T>> for Vec<T> {
+impl<T: Clone, V: Slice<T>> Add<V, Vec<T>> for Vec<T> {
     #[inline]
     fn add(&self, rhs: &V) -> Vec<T> {
         let mut res = Vec::with_capacity(self.len() + rhs.as_slice().len());
@@ -1603,7 +1606,7 @@ fn pop(&mut self) -> Option<T> {
         } else {
             unsafe {
                 self.len -= 1;
-                Some(ptr::read(self.as_slice().unsafe_ref(self.len())))
+                Some(ptr::read(self.as_slice().unsafe_get(self.len())))
             }
         }
     }
index 1bfa5168cf7960adf8d63eb15cc975509129ec1c..3a07e43e50993d3dbf3b18c63aac7d533b2f6044 100644 (file)
@@ -17,7 +17,7 @@
 use num::{Float, FPNaN, FPInfinite, ToPrimitive, Primitive};
 use num::{Zero, One, cast};
 use result::Ok;
-use slice::{ImmutableVector, MutableVector};
+use slice::{ImmutableSlice, MutableSlice};
 use slice;
 use str::StrSlice;
 
index 48bbc8401fe96987fc6e5eb0d523026bb7d6ad7a..942f7f8b71019f2db0ecdf495b620f86a92caf9b 100644 (file)
 use iter::{Iterator, range};
 use kinds::Copy;
 use mem;
+use num::Float;
 use option::{Option, Some, None};
 use ops::Deref;
 use result::{Ok, Err};
 use result;
-use slice::{Vector, ImmutableVector};
+use slice::{Slice, ImmutableSlice};
 use slice;
 use str::StrSlice;
 use str;
@@ -584,7 +585,7 @@ fn fmt(&self, fmt: &mut Formatter) -> Result {
                                              float::ExpNone,
                                              false,
                                              |bytes| {
-                fmt.pad_integral(*self >= 0.0, "", bytes)
+                fmt.pad_integral(self.is_nan() || *self >= 0.0, "", bytes)
             })
         }
     }
@@ -605,7 +606,7 @@ fn fmt(&self, fmt: &mut Formatter) -> Result {
                                              float::ExpDec,
                                              false,
                                              |bytes| {
-                fmt.pad_integral(*self >= 0.0, "", bytes)
+                fmt.pad_integral(self.is_nan() || *self >= 0.0, "", bytes)
             })
         }
     }
@@ -626,7 +627,7 @@ fn fmt(&self, fmt: &mut Formatter) -> Result {
                                              float::ExpDec,
                                              true,
                                              |bytes| {
-                fmt.pad_integral(*self >= 0.0, "", bytes)
+                fmt.pad_integral(self.is_nan() || *self >= 0.0, "", bytes)
             })
         }
     }
index bba3e4cb9afccdef116e3419940e091cea6d4c34..21cbafdc60538b1052058bca2a832038c2dfacb6 100644 (file)
@@ -18,7 +18,7 @@
 use fmt;
 use iter::DoubleEndedIterator;
 use num::{Int, cast, zero};
-use slice::{ImmutableVector, MutableVector};
+use slice::{ImmutableSlice, MutableSlice};
 
 /// A type that represents a specific radix
 #[doc(hidden)]
index 002babf7df976dd174a3cb84cc4a1973eb1075b3..1dd3d6ce9db9d409df80a7aa3018bac432e6f311 100644 (file)
@@ -310,6 +310,13 @@ fn visit_leave_fn(&mut self, purity: uint, proto: uint,
     /// ```
     pub fn transmute<T,U>(e: T) -> U;
 
+    /// Gives the address for the return value of the enclosing function.
+    ///
+    /// Using this instrinsic in a function that does not use an out pointer
+    /// will trigger a compiler error.
+    #[cfg(not(stage0))]
+    pub fn return_address() -> *const u8;
+
     /// Returns `true` if a type requires drop glue.
     pub fn needs_drop<T>() -> bool;
 
index f8293aeb03d1910651677ceb44175a797730e9ab..74d87712a02ef96cc6d36a44a0f6f3558077fa87 100644 (file)
 
 use cmp::{PartialEq, Eq, Ord};
 use default::Default;
-use slice::Vector;
+use slice::Slice;
 use iter::{Iterator, DoubleEndedIterator, FromIterator, ExactSize};
 use mem;
 use slice;
@@ -518,7 +518,7 @@ pub fn unwrap_or_default(self) -> T {
 // Trait implementations
 /////////////////////////////////////////////////////////////////////////////
 
-impl<T> Vector<T> for Option<T> {
+impl<T> Slice<T> for Option<T> {
     /// Convert from `Option<T>` to `&[T]` (without copying)
     #[inline]
     fn as_slice<'a>(&'a self) -> &'a [T] {
index 5b7c7c8f31a6f2a80a4615801c93f20ac658bdf5..ead48092c4dcf46163cdc8e784b8ab2f00da1428 100644 (file)
@@ -61,6 +61,6 @@
 pub use tuple::{Tuple1, Tuple2, Tuple3, Tuple4};
 pub use tuple::{Tuple5, Tuple6, Tuple7, Tuple8};
 pub use tuple::{Tuple9, Tuple10, Tuple11, Tuple12};
-pub use slice::{ImmutableEqVector, ImmutableOrdVector};
-pub use slice::{MutableVector};
-pub use slice::{Vector, ImmutableVector};
+pub use slice::{ImmutablePartialEqSlice, ImmutableOrdSlice};
+pub use slice::{MutableSlice};
+pub use slice::{Slice, ImmutableSlice};
index d3b761f9665d425f78efd8f101d8f69a02f7434c..93dafc153b6b206878f5547f072e4c6718f1ae4a 100644 (file)
@@ -12,6 +12,7 @@
 //!
 //! For more details `std::slice`.
 
+#![stable]
 #![doc(primitive = "slice")]
 
 // How this module is organized.
 use mem;
 use mem::size_of;
 use kinds::marker;
-use raw::{Repr, Slice};
+use raw::Repr;
+// Avoid conflicts with *both* the Slice trait (buggy) and the `slice::raw` module.
+use RawSlice = raw::Slice;
+
 
 //
 // Extension traits
 //
 
 /// Extension methods for vectors
-pub trait ImmutableVector<'a, T> {
+#[unstable = "may merge with other traits; region parameter may disappear"]
+pub trait ImmutableSlice<'a, T> {
     /**
      * Returns a slice of self spanning the interval [`start`, `end`).
      *
      * Fails when the slice (or part of it) is outside the bounds of self,
      * or when `start` > `end`.
      */
+    #[unstable]
     fn slice(&self, start: uint, end: uint) -> &'a [T];
 
     /**
@@ -68,6 +74,7 @@ pub trait ImmutableVector<'a, T> {
      *
      * Fails when `start` points outside the bounds of self.
      */
+    #[unstable]
     fn slice_from(&self, start: uint) -> &'a [T];
 
     /**
@@ -75,6 +82,7 @@ pub trait ImmutableVector<'a, T> {
      *
      * Fails when `end` points outside the bounds of self.
      */
+    #[unstable]
     fn slice_to(&self, end: uint) -> &'a [T];
 
     /// Divides one slice into two at an index.
@@ -84,24 +92,29 @@ pub trait ImmutableVector<'a, T> {
     /// indices from `[mid, len)` (excluding the index `len` itself).
     ///
     /// Fails if `mid > len`.
+    #[unstable]
     fn split_at(&self, mid: uint) -> (&'a [T], &'a [T]);
 
     /// Returns an iterator over the vector
+    #[unstable = "iterator type may change"]
     fn iter(self) -> Items<'a, T>;
     /// Returns an iterator over the subslices of the vector which are
     /// separated by elements that match `pred`.  The matched element
     /// is not contained in the subslices.
+    #[unstable = "iterator type may change"]
     fn split(self, pred: |&T|: 'a -> bool) -> Splits<'a, T>;
     /// Returns an iterator over the subslices of the vector which are
     /// separated by elements that match `pred`, limited to splitting
     /// at most `n` times.  The matched element is not contained in
     /// the subslices.
+    #[unstable = "iterator type may change"]
     fn splitn(self, n: uint, pred: |&T|: 'a -> bool) -> SplitsN<'a, T>;
     /// Returns an iterator over the subslices of the vector which are
     /// separated by elements that match `pred` limited to splitting
     /// at most `n` times. This starts at the end of the vector and
     /// works backwards.  The matched element is not contained in the
     /// subslices.
+    #[unstable = "iterator type may change"]
     fn rsplitn(self,  n: uint, pred: |&T|: 'a -> bool) -> SplitsN<'a, T>;
 
     /**
@@ -126,6 +139,7 @@ pub trait ImmutableVector<'a, T> {
      * ```
      *
      */
+    #[unstable = "iterator type may change"]
     fn windows(self, size: uint) -> Windows<'a, T>;
     /**
      *
@@ -151,28 +165,42 @@ pub trait ImmutableVector<'a, T> {
      * ```
      *
      */
+    #[unstable = "iterator type may change"]
     fn chunks(self, size: uint) -> Chunks<'a, T>;
 
     /// Returns the element of a vector at the given index, or `None` if the
     /// index is out of bounds
+    #[unstable]
     fn get(&self, index: uint) -> Option<&'a T>;
     /// Returns the first element of a vector, or `None` if it is empty
+    #[unstable = "name may change"]
     fn head(&self) -> Option<&'a T>;
     /// Returns all but the first element of a vector
+    #[unstable = "name may change"]
     fn tail(&self) -> &'a [T];
     /// Returns all but the first `n' elements of a vector
+    #[deprecated = "use slice_from"]
     fn tailn(&self, n: uint) -> &'a [T];
     /// Returns all but the last element of a vector
+    #[unstable = "name may change"]
     fn init(&self) -> &'a [T];
     /// Returns all but the last `n' elements of a vector
+    #[deprecated = "use slice_to but note the arguments are different"]
     fn initn(&self, n: uint) -> &'a [T];
     /// Returns the last element of a vector, or `None` if it is empty.
+    #[unstable = "name may change"]
     fn last(&self) -> Option<&'a T>;
 
     /// Returns a pointer to the element at the given index, without doing
     /// bounds checking.
+    #[deprecated = "renamed to `unsafe_get`"]
     unsafe fn unsafe_ref(self, index: uint) -> &'a T;
 
+    /// Returns a pointer to the element at the given index, without doing
+    /// bounds checking.
+    #[unstable]
+    unsafe fn unsafe_get(self, index: uint) -> &'a T;
+
     /**
      * Returns an unsafe pointer to the vector's buffer
      *
@@ -182,6 +210,7 @@ pub trait ImmutableVector<'a, T> {
      * Modifying the vector may cause its buffer to be reallocated, which
      * would also make any pointers to it invalid.
      */
+    #[unstable]
     fn as_ptr(&self) -> *const T;
 
     /**
@@ -195,8 +224,23 @@ pub trait ImmutableVector<'a, T> {
      * Returns the index where the comparator returned `Equal`, or `None` if
      * not found.
      */
+    #[deprecated = "use binary_search"]
     fn bsearch(&self, f: |&T| -> Ordering) -> Option<uint>;
 
+    /// Binary search a sorted vector with a comparator function.
+    ///
+    /// The comparator function should implement an order consistent
+    /// with the sort order of the underlying vector, returning an
+    /// order code that indicates whether its argument is `Less`,
+    /// `Equal` or `Greater` the desired target.
+    ///
+    /// If the value is found then `Found` is returned, containing the
+    /// index of the matching element; if the value is not found then
+    /// `NotFound` is returned, containing the index where a matching
+    /// element could be inserted while maintaining sorted order.
+    #[unstable]
+    fn binary_search(&self, f: |&T| -> Ordering) -> BinarySearchResult;
+
     /**
      * Returns an immutable reference to the first element in this slice
      * and adjusts the slice in place so that it no longer contains
@@ -213,6 +257,7 @@ pub trait ImmutableVector<'a, T> {
      *
      * Returns `None` if vector is empty
      */
+    #[deprecated = "find some other way. sorry"]
     fn shift_ref(&mut self) -> Option<&'a T>;
 
     /**
@@ -231,16 +276,18 @@ pub trait ImmutableVector<'a, T> {
      *
      * Returns `None` if slice is empty.
      */
+    #[deprecated = "find some other way. sorry"]
     fn pop_ref(&mut self) -> Option<&'a T>;
 }
 
-impl<'a,T> ImmutableVector<'a, T> for &'a [T] {
+#[unstable]
+impl<'a,T> ImmutableSlice<'a, T> for &'a [T] {
     #[inline]
     fn slice(&self, start: uint, end: uint) -> &'a [T] {
         assert!(start <= end);
         assert!(end <= self.len());
         unsafe {
-            transmute(Slice {
+            transmute(RawSlice {
                     data: self.as_ptr().offset(start as int),
                     len: (end - start)
                 })
@@ -331,6 +378,7 @@ fn head(&self) -> Option<&'a T> {
     fn tail(&self) -> &'a [T] { self.slice(1, self.len()) }
 
     #[inline]
+    #[deprecated = "use slice_from"]
     fn tailn(&self, n: uint) -> &'a [T] { self.slice(n, self.len()) }
 
     #[inline]
@@ -339,6 +387,7 @@ fn init(&self) -> &'a [T] {
     }
 
     #[inline]
+    #[deprecated = "use slice_to but note the arguments are different"]
     fn initn(&self, n: uint) -> &'a [T] {
         self.slice(0, self.len() - n)
     }
@@ -349,16 +398,23 @@ fn last(&self) -> Option<&'a T> {
     }
 
     #[inline]
+    #[deprecated = "renamed to `unsafe_get`"]
     unsafe fn unsafe_ref(self, index: uint) -> &'a T {
         transmute(self.repr().data.offset(index as int))
     }
 
+    #[inline]
+    unsafe fn unsafe_get(self, index: uint) -> &'a T {
+        transmute(self.repr().data.offset(index as int))
+    }
+
     #[inline]
     fn as_ptr(&self) -> *const T {
         self.repr().data
     }
 
 
+    #[deprecated = "use binary_search"]
     fn bsearch(&self, f: |&T| -> Ordering) -> Option<uint> {
         let mut base : uint = 0;
         let mut lim : uint = self.len();
@@ -378,9 +434,29 @@ fn bsearch(&self, f: |&T| -> Ordering) -> Option<uint> {
         return None;
     }
 
+    #[unstable]
+    fn binary_search(&self, f: |&T| -> Ordering) -> BinarySearchResult {
+        let mut base : uint = 0;
+        let mut lim : uint = self.len();
+
+        while lim != 0 {
+            let ix = base + (lim >> 1);
+            match f(&self[ix]) {
+                Equal => return Found(ix),
+                Less => {
+                    base = ix + 1;
+                    lim -= 1;
+                }
+                Greater => ()
+            }
+            lim >>= 1;
+        }
+        return NotFound(base);
+    }
+
     fn shift_ref(&mut self) -> Option<&'a T> {
         unsafe {
-            let s: &mut Slice<T> = transmute(self);
+            let s: &mut RawSlice<T> = transmute(self);
             match raw::shift_ptr(s) {
                 Some(p) => Some(&*p),
                 None => None
@@ -390,7 +466,7 @@ fn shift_ref(&mut self) -> Option<&'a T> {
 
     fn pop_ref(&mut self) -> Option<&'a T> {
         unsafe {
-            let s: &mut Slice<T> = transmute(self);
+            let s: &mut RawSlice<T> = transmute(self);
             match raw::pop_ptr(s) {
                 Some(p) => Some(&*p),
                 None => None
@@ -401,7 +477,8 @@ fn pop_ref(&mut self) -> Option<&'a T> {
 
 /// Extension methods for vectors such that their elements are
 /// mutable.
-pub trait MutableVector<'a, T> {
+#[experimental = "may merge with other traits; may lose region param; needs review"]
+pub trait MutableSlice<'a, T> {
     /// Returns a mutable reference to the element at the given index,
     /// or `None` if the index is out of bounds
     fn get_mut(self, index: uint) -> Option<&'a mut T>;
@@ -465,6 +542,7 @@ pub trait MutableVector<'a, T> {
      *
      * Returns `None` if slice is empty
      */
+    #[deprecated = "find some other way. sorry"]
     fn mut_shift_ref(&mut self) -> Option<&'a mut T>;
 
     /**
@@ -483,6 +561,7 @@ pub trait MutableVector<'a, T> {
      *
      * Returns `None` if slice is empty.
      */
+    #[deprecated = "find some other way. sorry"]
     fn mut_pop_ref(&mut self) -> Option<&'a mut T>;
 
     /// Swaps two elements in a vector.
@@ -607,7 +686,8 @@ pub trait MutableVector<'a, T> {
     unsafe fn copy_memory(self, src: &[T]);
 }
 
-impl<'a,T> MutableVector<'a, T> for &'a mut [T] {
+#[experimental = "trait is experimental"]
+impl<'a,T> MutableSlice<'a, T> for &'a mut [T] {
     #[inline]
     fn get_mut(self, index: uint) -> Option<&'a mut T> {
         if index < self.len() { Some(&mut self[index]) } else { None }
@@ -620,7 +700,7 @@ fn mut_slice(self, start: uint, end: uint) -> &'a mut [T] {
         assert!(start <= end);
         assert!(end <= self.len());
         unsafe {
-            transmute(Slice {
+            transmute(RawSlice {
                     data: self.as_mut_ptr().offset(start as int) as *const T,
                     len: (end - start)
                 })
@@ -685,7 +765,7 @@ fn mut_chunks(self, chunk_size: uint) -> MutChunks<'a, T> {
 
     fn mut_shift_ref(&mut self) -> Option<&'a mut T> {
         unsafe {
-            let s: &mut Slice<T> = transmute(self);
+            let s: &mut RawSlice<T> = transmute(self);
             match raw::shift_ptr(s) {
                 // FIXME #13933: this `&` -> `&mut` cast is a little
                 // dubious
@@ -697,7 +777,7 @@ fn mut_shift_ref(&mut self) -> Option<&'a mut T> {
 
     fn mut_pop_ref(&mut self) -> Option<&'a mut T> {
         unsafe {
-            let s: &mut Slice<T> = transmute(self);
+            let s: &mut RawSlice<T> = transmute(self);
             match raw::pop_ptr(s) {
                 // FIXME #13933: this `&` -> `&mut` cast is a little
                 // dubious
@@ -755,7 +835,8 @@ unsafe fn copy_memory(self, src: &[T]) {
 }
 
 /// Extension methods for vectors contain `PartialEq` elements.
-pub trait ImmutableEqVector<T:PartialEq> {
+#[unstable = "may merge with other traits"]
+pub trait ImmutablePartialEqSlice<T:PartialEq> {
     /// Find the first index containing a matching value
     fn position_elem(&self, t: &T) -> Option<uint>;
 
@@ -772,7 +853,8 @@ pub trait ImmutableEqVector<T:PartialEq> {
     fn ends_with(&self, needle: &[T]) -> bool;
 }
 
-impl<'a,T:PartialEq> ImmutableEqVector<T> for &'a [T] {
+#[unstable = "trait is unstable"]
+impl<'a,T:PartialEq> ImmutablePartialEqSlice<T> for &'a [T] {
     #[inline]
     fn position_elem(&self, x: &T) -> Option<uint> {
         self.iter().position(|y| *x == *y)
@@ -802,23 +884,51 @@ fn ends_with(&self, needle: &[T]) -> bool {
 }
 
 /// Extension methods for vectors containing `Ord` elements.
-pub trait ImmutableOrdVector<T: Ord> {
+#[unstable = "may merge with other traits"]
+pub trait ImmutableOrdSlice<T: Ord> {
     /**
      * Binary search a sorted vector for a given element.
      *
      * Returns the index of the element or None if not found.
      */
+    #[deprecated = "use binary_search_elem"]
     fn bsearch_elem(&self, x: &T) -> Option<uint>;
+
+    /**
+     * Binary search a sorted vector for a given element.
+     *
+     * If the value is found then `Found` is returned, containing the
+     * index of the matching element; if the value is not found then
+     * `NotFound` is returned, containing the index where a matching
+     * element could be inserted while maintaining sorted order.
+     */
+    #[unstable]
+    fn binary_search_elem(&self, x: &T) -> BinarySearchResult;
 }
 
-impl<'a, T: Ord> ImmutableOrdVector<T> for &'a [T] {
+#[unstable = "trait is unstable"]
+impl<'a, T: Ord> ImmutableOrdSlice<T> for &'a [T] {
+    #[deprecated = "use binary_search_elem"]
+    #[allow(deprecated)]
     fn bsearch_elem(&self, x: &T) -> Option<uint> {
         self.bsearch(|p| p.cmp(x))
     }
+
+    #[unstable]
+    fn binary_search_elem(&self, x: &T) -> BinarySearchResult {
+        self.binary_search(|p| p.cmp(x))
+    }
 }
 
 /// Trait for &[T] where T is Cloneable
-pub trait MutableCloneableVector<T> {
+#[unstable = "may merge with other traits"]
+pub trait MutableCloneableSlice<T> {
+    /// Copies as many elements from `src` as it can into `self` (the
+    /// shorter of `self.len()` and `src.len()`). Returns the number
+    /// of elements copied.
+    #[deprecated = "renamed to clone_from_slice"]
+    fn copy_from(self, s: &[T]) -> uint { self.clone_from_slice(s) }
+
     /// Copies as many elements from `src` as it can into `self` (the
     /// shorter of `self.len()` and `src.len()`). Returns the number
     /// of elements copied.
@@ -826,7 +936,7 @@ pub trait MutableCloneableVector<T> {
     /// # Example
     ///
     /// ```rust
-    /// use std::slice::MutableCloneableVector;
+    /// use std::slice::MutableCloneableSlice;
     ///
     /// let mut dst = [0i, 0, 0];
     /// let src = [1i, 2];
@@ -838,12 +948,13 @@ pub trait MutableCloneableVector<T> {
     /// assert!(dst.copy_from(src2) == 3);
     /// assert!(dst == [3i, 4, 5]);
     /// ```
-    fn copy_from(self, &[T]) -> uint;
+    fn clone_from_slice(self, &[T]) -> uint;
 }
 
-impl<'a, T:Clone> MutableCloneableVector<T> for &'a mut [T] {
+#[unstable = "trait is unstable"]
+impl<'a, T:Clone> MutableCloneableSlice<T> for &'a mut [T] {
     #[inline]
-    fn copy_from(self, src: &[T]) -> uint {
+    fn clone_from_slice(self, src: &[T]) -> uint {
         for (a, b) in self.mut_iter().zip(src.iter()) {
             a.clone_from(b);
         }
@@ -859,16 +970,19 @@ fn copy_from(self, src: &[T]) -> uint {
 //
 
 /// Any vector that can be represented as a slice.
-pub trait Vector<T> {
+#[unstable = "may merge with other traits"]
+pub trait Slice<T> {
     /// Work with `self` as a slice.
     fn as_slice<'a>(&'a self) -> &'a [T];
 }
 
-impl<'a,T> Vector<T> for &'a [T] {
+#[unstable = "trait is unstable"]
+impl<'a,T> Slice<T> for &'a [T] {
     #[inline(always)]
     fn as_slice<'a>(&'a self) -> &'a [T] { *self }
 }
 
+#[experimental = "trait is experimental"]
 impl<'a, T> Collection for &'a [T] {
     /// Returns the length of a vector
     #[inline]
@@ -877,6 +991,7 @@ fn len(&self) -> uint {
     }
 }
 
+#[unstable = "waiting for DST"]
 impl<'a, T> Default for &'a [T] {
     fn default() -> &'a [T] { &[] }
 }
@@ -891,6 +1006,7 @@ fn default() -> &'a [T] { &[] }
 // The shared definition of the `Item` and `MutItems` iterators
 macro_rules! iterator {
     (struct $name:ident -> $ptr:ty, $elem:ty) => {
+        #[experimental = "needs review"]
         impl<'a, T> Iterator<$elem> for $name<'a, T> {
             #[inline]
             fn next(&mut self) -> Option<$elem> {
@@ -926,6 +1042,7 @@ fn size_hint(&self) -> (uint, Option<uint>) {
             }
         }
 
+        #[experimental = "needs review"]
         impl<'a, T> DoubleEndedIterator<$elem> for $name<'a, T> {
             #[inline]
             fn next_back(&mut self) -> Option<$elem> {
@@ -953,6 +1070,7 @@ fn next_back(&mut self) -> Option<$elem> {
 }
 
 /// Immutable slice iterator
+#[experimental = "needs review"]
 pub struct Items<'a, T> {
     ptr: *const T,
     end: *const T,
@@ -961,12 +1079,15 @@ pub struct Items<'a, T> {
 
 iterator!{struct Items -> *const T, &'a T}
 
+#[experimental = "needs review"]
 impl<'a, T> ExactSize<&'a T> for Items<'a, T> {}
 
+#[experimental = "needs review"]
 impl<'a, T> Clone for Items<'a, T> {
     fn clone(&self) -> Items<'a, T> { *self }
 }
 
+#[experimental = "needs review"]
 impl<'a, T> RandomAccessIterator<&'a T> for Items<'a, T> {
     #[inline]
     fn indexable(&self) -> uint {
@@ -992,6 +1113,7 @@ fn idx(&mut self, index: uint) -> Option<&'a T> {
 }
 
 /// Mutable slice iterator
+#[experimental = "needs review"]
 pub struct MutItems<'a, T> {
     ptr: *mut T,
     end: *mut T,
@@ -1001,16 +1123,19 @@ pub struct MutItems<'a, T> {
 
 iterator!{struct MutItems -> *mut T, &'a mut T}
 
+#[experimental = "needs review"]
 impl<'a, T> ExactSize<&'a mut T> for MutItems<'a, T> {}
 
 /// An iterator over the slices of a vector separated by elements that
 /// match a predicate function.
+#[experimental = "needs review"]
 pub struct Splits<'a, T> {
     v: &'a [T],
     pred: |t: &T|: 'a -> bool,
     finished: bool
 }
 
+#[experimental = "needs review"]
 impl<'a, T> Iterator<&'a [T]> for Splits<'a, T> {
     #[inline]
     fn next(&mut self) -> Option<&'a [T]> {
@@ -1039,6 +1164,7 @@ fn size_hint(&self) -> (uint, Option<uint>) {
     }
 }
 
+#[experimental = "needs review"]
 impl<'a, T> DoubleEndedIterator<&'a [T]> for Splits<'a, T> {
     #[inline]
     fn next_back(&mut self) -> Option<&'a [T]> {
@@ -1060,12 +1186,14 @@ fn next_back(&mut self) -> Option<&'a [T]> {
 
 /// An iterator over the subslices of the vector which are separated
 /// by elements that match `pred`.
+#[experimental = "needs review"]
 pub struct MutSplits<'a, T> {
     v: &'a mut [T],
     pred: |t: &T|: 'a -> bool,
     finished: bool
 }
 
+#[experimental = "needs review"]
 impl<'a, T> Iterator<&'a mut [T]> for MutSplits<'a, T> {
     #[inline]
     fn next(&mut self) -> Option<&'a mut [T]> {
@@ -1102,6 +1230,7 @@ fn size_hint(&self) -> (uint, Option<uint>) {
     }
 }
 
+#[experimental = "needs review"]
 impl<'a, T> DoubleEndedIterator<&'a mut [T]> for MutSplits<'a, T> {
     #[inline]
     fn next_back(&mut self) -> Option<&'a mut [T]> {
@@ -1126,12 +1255,14 @@ fn next_back(&mut self) -> Option<&'a mut [T]> {
 
 /// An iterator over the slices of a vector separated by elements that
 /// match a predicate function, splitting at most a fixed number of times.
+#[experimental = "needs review"]
 pub struct SplitsN<'a, T> {
     iter: Splits<'a, T>,
     count: uint,
     invert: bool
 }
 
+#[experimental = "needs review"]
 impl<'a, T> Iterator<&'a [T]> for SplitsN<'a, T> {
     #[inline]
     fn next(&mut self) -> Option<&'a [T]> {
@@ -1161,11 +1292,13 @@ fn size_hint(&self) -> (uint, Option<uint>) {
 /// An iterator over the (overlapping) slices of length `size` within
 /// a vector.
 #[deriving(Clone)]
+#[experimental = "needs review"]
 pub struct Windows<'a, T> {
     v: &'a [T],
     size: uint
 }
 
+#[experimental = "needs review"]
 impl<'a, T> Iterator<&'a [T]> for Windows<'a, T> {
     #[inline]
     fn next(&mut self) -> Option<&'a [T]> {
@@ -1195,11 +1328,13 @@ fn size_hint(&self) -> (uint, Option<uint>) {
 /// When the vector len is not evenly divided by the chunk size,
 /// the last slice of the iteration will be the remainder.
 #[deriving(Clone)]
+#[experimental = "needs review"]
 pub struct Chunks<'a, T> {
     v: &'a [T],
     size: uint
 }
 
+#[experimental = "needs review"]
 impl<'a, T> Iterator<&'a [T]> for Chunks<'a, T> {
     #[inline]
     fn next(&mut self) -> Option<&'a [T]> {
@@ -1225,6 +1360,7 @@ fn size_hint(&self) -> (uint, Option<uint>) {
     }
 }
 
+#[experimental = "needs review"]
 impl<'a, T> DoubleEndedIterator<&'a [T]> for Chunks<'a, T> {
     #[inline]
     fn next_back(&mut self) -> Option<&'a [T]> {
@@ -1240,6 +1376,7 @@ fn next_back(&mut self) -> Option<&'a [T]> {
     }
 }
 
+#[experimental = "needs review"]
 impl<'a, T> RandomAccessIterator<&'a [T]> for Chunks<'a, T> {
     #[inline]
     fn indexable(&self) -> uint {
@@ -1263,11 +1400,13 @@ fn idx(&mut self, index: uint) -> Option<&'a [T]> {
 /// An iterator over a vector in (non-overlapping) mutable chunks (`size`  elements at a time). When
 /// the vector len is not evenly divided by the chunk size, the last slice of the iteration will be
 /// the remainder.
+#[experimental = "needs review"]
 pub struct MutChunks<'a, T> {
     v: &'a mut [T],
     chunk_size: uint
 }
 
+#[experimental = "needs review"]
 impl<'a, T> Iterator<&'a mut [T]> for MutChunks<'a, T> {
     #[inline]
     fn next(&mut self) -> Option<&'a mut [T]> {
@@ -1294,6 +1433,7 @@ fn size_hint(&self) -> (uint, Option<uint>) {
     }
 }
 
+#[experimental = "needs review"]
 impl<'a, T> DoubleEndedIterator<&'a mut [T]> for MutChunks<'a, T> {
     #[inline]
     fn next_back(&mut self) -> Option<&'a mut [T]> {
@@ -1313,6 +1453,43 @@ fn next_back(&mut self) -> Option<&'a mut [T]> {
 
 
 
+/// The result of calling `binary_search`.
+///
+/// `Found` means the search succeeded, and the contained value is the
+/// index of the matching element. `NotFound` means the search
+/// succeeded, and the contained value is an index where a matching
+/// value could be inserted while maintaining sort order.
+#[deriving(PartialEq, Show)]
+#[experimental = "needs review"]
+pub enum BinarySearchResult {
+    /// The index of the found value.
+    Found(uint),
+    /// The index where the value should have been found.
+    NotFound(uint)
+}
+
+#[experimental = "needs review"]
+impl BinarySearchResult {
+    /// Converts a `Found` to `Some`, `NotFound` to `None`.
+    /// Similar to `Result::ok`.
+    pub fn found(&self) -> Option<uint> {
+        match *self {
+            Found(i) => Some(i),
+            NotFound(_) => None
+        }
+    }
+
+    /// Convert a `Found` to `None`, `NotFound` to `Some`.
+    /// Similar to `Result::err`.
+    pub fn not_found(&self) -> Option<uint> {
+        match *self {
+            Found(_) => None,
+            NotFound(i) => Some(i)
+        }
+    }
+}
+
+
 
 //
 // Free functions
@@ -1321,19 +1498,21 @@ fn next_back(&mut self) -> Option<&'a mut [T]> {
 /**
  * Converts a pointer to A into a slice of length 1 (without copying).
  */
+#[unstable = "waiting for DST"]
 pub fn ref_slice<'a, A>(s: &'a A) -> &'a [A] {
     unsafe {
-        transmute(Slice { data: s, len: 1 })
+        transmute(RawSlice { data: s, len: 1 })
     }
 }
 
 /**
  * Converts a pointer to A into a slice of length 1 (without copying).
  */
+#[unstable = "waiting for DST"]
 pub fn mut_ref_slice<'a, A>(s: &'a mut A) -> &'a mut [A] {
     unsafe {
         let ptr: *const A = transmute(s);
-        transmute(Slice { data: ptr, len: 1 })
+        transmute(RawSlice { data: ptr, len: 1 })
     }
 }
 
@@ -1345,6 +1524,7 @@ pub fn mut_ref_slice<'a, A>(s: &'a mut A) -> &'a mut [A] {
 //
 
 /// Unsafe operations
+#[experimental = "needs review"]
 pub mod raw {
     use mem::transmute;
     use ptr::RawPtr;
@@ -1410,10 +1590,11 @@ pub unsafe fn pop_ptr<T>(slice: &mut Slice<T>) -> Option<*const T> {
 }
 
 /// Operations on `[u8]`.
+#[experimental = "needs review"]
 pub mod bytes {
     use collections::Collection;
     use ptr;
-    use slice::MutableVector;
+    use slice::MutableSlice;
 
     /// A trait for operations on mutable `[u8]`s.
     pub trait MutableByteVector {
@@ -1447,6 +1628,7 @@ pub fn copy_memory(dst: &mut [u8], src: &[u8]) {
 // Boilerplate traits
 //
 
+#[unstable = "waiting for DST"]
 impl<'a,T:PartialEq> PartialEq for &'a [T] {
     fn eq(&self, other: & &'a [T]) -> bool {
         self.len() == other.len() &&
@@ -1458,19 +1640,23 @@ fn ne(&self, other: & &'a [T]) -> bool {
     }
 }
 
+#[unstable = "waiting for DST"]
 impl<'a,T:Eq> Eq for &'a [T] {}
 
-impl<'a,T:PartialEq, V: Vector<T>> Equiv<V> for &'a [T] {
+#[unstable = "waiting for DST"]
+impl<'a,T:PartialEq, V: Slice<T>> Equiv<V> for &'a [T] {
     #[inline]
     fn equiv(&self, other: &V) -> bool { self.as_slice() == other.as_slice() }
 }
 
+#[unstable = "waiting for DST"]
 impl<'a,T:Ord> Ord for &'a [T] {
     fn cmp(&self, other: & &'a [T]) -> Ordering {
         order::cmp(self.iter(), other.iter())
     }
 }
 
+#[unstable = "waiting for DST"]
 impl<'a, T: PartialOrd> PartialOrd for &'a [T] {
     #[inline]
     fn partial_cmp(&self, other: &&'a [T]) -> Option<Ordering> {
index c1166a7621e193e6515c1745248d0f67c5125737..4f7db7b41f38b7403ef1a496250790a34b400d26 100644 (file)
@@ -30,7 +30,7 @@
 use num::{CheckedMul, Saturating};
 use option::{Option, None, Some};
 use raw::Repr;
-use slice::ImmutableVector;
+use slice::ImmutableSlice;
 use slice;
 use uint;
 
@@ -964,7 +964,7 @@ pub mod raw {
     use collections::Collection;
     use ptr::RawPtr;
     use raw::Slice;
-    use slice::{ImmutableVector};
+    use slice::{ImmutableSlice};
     use str::{is_utf8, StrSlice};
 
     /// Converts a slice of bytes to a string slice without checking
@@ -1147,22 +1147,22 @@ pub trait StrSlice<'a> {
     /// # Example
     ///
     /// ```rust
-    /// let v: Vec<&str> = "Mary had a little lambda".splitn(' ', 2).collect();
+    /// let v: Vec<&str> = "Mary had a little lambda".splitn(2, ' ').collect();
     /// assert_eq!(v, vec!["Mary", "had", "a little lambda"]);
     ///
-    /// let v: Vec<&str> = "abc1def2ghi".splitn(|c: char| c.is_digit(), 1).collect();
+    /// let v: Vec<&str> = "abc1def2ghi".splitn(1, |c: char| c.is_digit()).collect();
     /// assert_eq!(v, vec!["abc", "def2ghi"]);
     ///
-    /// let v: Vec<&str> = "lionXXtigerXleopard".splitn('X', 2).collect();
+    /// let v: Vec<&str> = "lionXXtigerXleopard".splitn(2, 'X').collect();
     /// assert_eq!(v, vec!["lion", "", "tigerXleopard"]);
     ///
-    /// let v: Vec<&str> = "abcXdef".splitn('X', 0).collect();
+    /// let v: Vec<&str> = "abcXdef".splitn(0, 'X').collect();
     /// assert_eq!(v, vec!["abcXdef"]);
     ///
-    /// let v: Vec<&str> = "".splitn('X', 1).collect();
+    /// let v: Vec<&str> = "".splitn(1, 'X').collect();
     /// assert_eq!(v, vec![""]);
     /// ```
-    fn splitn<Sep: CharEq>(&self, sep: Sep, count: uint) -> CharSplitsN<'a, Sep>;
+    fn splitn<Sep: CharEq>(&self, count: uint, sep: Sep) -> CharSplitsN<'a, Sep>;
 
     /// An iterator over substrings of `self`, separated by characters
     /// matched by `sep`.
@@ -1197,16 +1197,16 @@ pub trait StrSlice<'a> {
     /// # Example
     ///
     /// ```rust
-    /// let v: Vec<&str> = "Mary had a little lamb".rsplitn(' ', 2).collect();
+    /// let v: Vec<&str> = "Mary had a little lamb".rsplitn(2, ' ').collect();
     /// assert_eq!(v, vec!["lamb", "little", "Mary had a"]);
     ///
-    /// let v: Vec<&str> = "abc1def2ghi".rsplitn(|c: char| c.is_digit(), 1).collect();
+    /// let v: Vec<&str> = "abc1def2ghi".rsplitn(1, |c: char| c.is_digit()).collect();
     /// assert_eq!(v, vec!["ghi", "abc1def"]);
     ///
-    /// let v: Vec<&str> = "lionXXtigerXleopard".rsplitn('X', 2).collect();
+    /// let v: Vec<&str> = "lionXXtigerXleopard".rsplitn(2, 'X').collect();
     /// assert_eq!(v, vec!["leopard", "tiger", "lionX"]);
     /// ```
-    fn rsplitn<Sep: CharEq>(&self, sep: Sep, count: uint) -> CharSplitsN<'a, Sep>;
+    fn rsplitn<Sep: CharEq>(&self, count: uint, sep: Sep) -> CharSplitsN<'a, Sep>;
 
     /// An iterator over the start and end indices of the disjoint
     /// matches of `sep` within `self`.
@@ -1697,7 +1697,7 @@ fn split<Sep: CharEq>(&self, sep: Sep) -> CharSplits<'a, Sep> {
     }
 
     #[inline]
-    fn splitn<Sep: CharEq>(&self, sep: Sep, count: uint)
+    fn splitn<Sep: CharEq>(&self, count: uint, sep: Sep)
         -> CharSplitsN<'a, Sep> {
         CharSplitsN {
             iter: self.split(sep),
@@ -1716,7 +1716,7 @@ fn split_terminator<Sep: CharEq>(&self, sep: Sep)
     }
 
     #[inline]
-    fn rsplitn<Sep: CharEq>(&self, sep: Sep, count: uint)
+    fn rsplitn<Sep: CharEq>(&self, count: uint, sep: Sep)
         -> CharSplitsN<'a, Sep> {
         CharSplitsN {
             iter: self.split(sep),
index 0b8ae09c9a3461ad10bb5393b5d1c28d8d180d6b..3864321586ca67f643efbe9190c3c8dd8e6958ac 100644 (file)
@@ -28,4 +28,5 @@
 mod ptr;
 mod raw;
 mod result;
+mod slice;
 mod tuple;
diff --git a/src/libcoretest/slice.rs b/src/libcoretest/slice.rs
new file mode 100644 (file)
index 0000000..1288756
--- /dev/null
@@ -0,0 +1,35 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::slice::{Found, NotFound};
+
+#[test]
+fn binary_search_not_found() {
+    let b = [1i, 2, 4, 6, 8, 9];
+    assert!(b.binary_search(|v| v.cmp(&6)) == Found(3));
+    let b = [1i, 2, 4, 6, 8, 9];
+    assert!(b.binary_search(|v| v.cmp(&5)) == NotFound(3));
+    let b = [1i, 2, 4, 6, 7, 8, 9];
+    assert!(b.binary_search(|v| v.cmp(&6)) == Found(3));
+    let b = [1i, 2, 4, 6, 7, 8, 9];
+    assert!(b.binary_search(|v| v.cmp(&5)) == NotFound(3));
+    let b = [1i, 2, 4, 6, 8, 9];
+    assert!(b.binary_search(|v| v.cmp(&8)) == Found(4));
+    let b = [1i, 2, 4, 6, 8, 9];
+    assert!(b.binary_search(|v| v.cmp(&7)) == NotFound(4));
+    let b = [1i, 2, 4, 6, 7, 8, 9];
+    assert!(b.binary_search(|v| v.cmp(&8)) == Found(5));
+    let b = [1i, 2, 4, 5, 6, 8, 9];
+    assert!(b.binary_search(|v| v.cmp(&7)) == NotFound(5));
+    let b = [1i, 2, 4, 5, 6, 8, 9];
+    assert!(b.binary_search(|v| v.cmp(&0)) == NotFound(0));
+    let b = [1i, 2, 4, 5, 6, 8];
+    assert!(b.binary_search(|v| v.cmp(&9)) == NotFound(6));
+}
index bac5b6e10135ce784f610e081b6f1e3261a1d52d..e4d61c47cc20c3a53e3366a73a003ff9f4e33ebb 100644 (file)
@@ -42,6 +42,7 @@ fn main() {
 #![crate_name = "fourcc"]
 #![deprecated = "This is now a cargo package located at: \
                  https://github.com/rust-lang/fourcc"]
+#![allow(deprecated)]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![license = "MIT/ASL2"]
index 9e52af72138bba2fb839a25a8554b733956677d6..987f214b153e07d3ba107024563594cf6b27ee2c 100644 (file)
@@ -84,7 +84,7 @@ fn cmp(&self, other: &MaybeOwnedVector<T>) -> Ordering {
     }
 }
 
-impl<'a, T: PartialEq, V: Vector<T>> Equiv<V> for MaybeOwnedVector<'a, T> {
+impl<'a, T: PartialEq, V: Slice<T>> Equiv<V> for MaybeOwnedVector<'a, T> {
     fn equiv(&self, other: &V) -> bool {
         self.as_slice() == other.as_slice()
     }
@@ -99,7 +99,7 @@ fn equiv(&self, other: &V) -> bool {
 // In any case, with `Vector` in place, the client can just use
 // `as_slice` if they prefer that over `match`.
 
-impl<'b,T> slice::Vector<T> for MaybeOwnedVector<'b,T> {
+impl<'b,T> Slice<T> for MaybeOwnedVector<'b,T> {
     fn as_slice<'a>(&'a self) -> &'a [T] {
         match self {
             &Growable(ref v) => v.as_slice(),
index b9144047df5c0b7e3017f3fdeb27bedd594a82d4..e041547082885dbfdccdcb2e27868d42571d16db 100644 (file)
@@ -1029,6 +1029,7 @@ mod test {
     use std::rt::task::TaskOpts;
     use std::rt::task::Task;
     use std::rt::local::Local;
+    use std::time::Duration;
 
     use {TaskState, PoolConfig, SchedPool};
     use basic;
@@ -1291,7 +1292,7 @@ fn test_io_callback() {
         // doesn't exit before emptying the work queue
         pool.spawn(TaskOpts::new(), proc() {
             spawn(proc() {
-                timer::sleep(10);
+                timer::sleep(Duration::milliseconds(10));
             });
         });
 
index 9adeeb2e4c9241997a3da22806604f26e9b225c5..936e7cb4403d49b31f379998c03ba99ad62392bb 100644 (file)
@@ -39,6 +39,7 @@ fn main() {
 #![crate_name = "hexfloat"]
 #![deprecated = "This is now a cargo package located at: \
                  https://github.com/rust-lang/hexfloat"]
+#![allow(deprecated)]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![license = "MIT/ASL2"]
index 77822bbbc20ff8376cb2f192db5297b27f8cd3bb..4b832a4a97efa00946188d1a64a640df39c6bab6 100644 (file)
@@ -80,7 +80,7 @@ fn get_io(io: rtio::StdioContainer,
                 rtio::Ignored => { ret.push(None); Ok(None) }
                 rtio::InheritFd(fd) => {
                     ret.push(None);
-                    Ok(Some(file::FileDesc::new(fd, true)))
+                    Ok(Some(file::FileDesc::new(fd, false)))
                 }
                 rtio::CreatePipe(readable, _writable) => {
                     let (reader, writer) = try!(pipe());
index e0f6b4fb9af66a12ccb06e6f4282d12f6ed65890..f3e4b0b21adf85ba94b9f918bd48fdacd5d3406c 100644 (file)
@@ -341,7 +341,7 @@ impl<T: FromStr + Clone + Integer + PartialOrd>
     FromStr for Ratio<T> {
     /// Parses `numer/denom` or just `numer`.
     fn from_str(s: &str) -> Option<Ratio<T>> {
-        let mut split = s.splitn('/', 1);
+        let mut split = s.splitn(1, '/');
 
         let num = split.next().and_then(|n| FromStr::from_str(n));
         let den = split.next().or(Some("1")).and_then(|d| FromStr::from_str(d));
@@ -357,7 +357,7 @@ impl<T: FromStrRadix + Clone + Integer + PartialOrd>
     FromStrRadix for Ratio<T> {
     /// Parses `numer/denom` where the numbers are in base `radix`.
     fn from_str_radix(s: &str, radix: uint) -> Option<Ratio<T>> {
-        let split: Vec<&str> = s.splitn('/', 1).collect();
+        let split: Vec<&str> = s.splitn(1, '/').collect();
         if split.len() < 2 {
             None
         } else {
index 134e7af507010db11a2f0980e1951c8b73dd2ab3..2fbfa6d6e85a0da393ae2050cb9d7ff963e4ab3f 100644 (file)
@@ -348,7 +348,7 @@ fn isaac64(&mut self) {
         static MP_VEC: [(uint, uint), .. 2] = [(0,MIDPOINT), (MIDPOINT, 0)];
         macro_rules! ind (
             ($x:expr) => {
-                *self.mem.unsafe_ref(($x as uint >> 3) & (RAND_SIZE_64 - 1))
+                *self.mem.unsafe_get(($x as uint >> 3) & (RAND_SIZE_64 - 1))
             }
         );
 
@@ -362,8 +362,8 @@ macro_rules! rngstepp(
                             let mix = if $j == 0 {!mix} else {mix};
 
                             unsafe {
-                                let x = *self.mem.unsafe_ref(base + mr_offset);
-                                a = mix + *self.mem.unsafe_ref(base + m2_offset);
+                                let x = *self.mem.unsafe_get(base + mr_offset);
+                                a = mix + *self.mem.unsafe_get(base + m2_offset);
                                 let y = ind!(x) + a + b;
                                 self.mem.unsafe_set(base + mr_offset, y);
 
@@ -379,8 +379,8 @@ macro_rules! rngstepn(
                             let mix = if $j == 0 {!mix} else {mix};
 
                             unsafe {
-                                let x = *self.mem.unsafe_ref(base + mr_offset);
-                                a = mix + *self.mem.unsafe_ref(base + m2_offset);
+                                let x = *self.mem.unsafe_get(base + mr_offset);
+                                a = mix + *self.mem.unsafe_get(base + m2_offset);
                                 let y = ind!(x) + a + b;
                                 self.mem.unsafe_set(base + mr_offset, y);
 
@@ -416,7 +416,7 @@ fn next_u64(&mut self) -> u64 {
             self.isaac64();
         }
         self.cnt -= 1;
-        unsafe { *self.rsl.unsafe_ref(self.cnt) }
+        unsafe { *self.rsl.unsafe_get(self.cnt) }
     }
 }
 
index a1fd62cecbed973514e937e57b57c5e863d8ef26..13b094a2cf2e6475bfacc54c19ed7a979a1e86d4 100644 (file)
@@ -13,6 +13,7 @@
 use std::fmt;
 use std::iter;
 use std::num;
+use std::slice;
 
 /// Static data containing Unicode ranges for general categories and scripts.
 use unicode::regex::{UNICODE_CLASSES, PERLD, PERLS, PERLW};
@@ -518,7 +519,7 @@ fn parse_counted(&mut self) -> Result<(), Error> {
             min = try!(self.parse_uint(inner.as_slice()));
             max = Some(min);
         } else {
-            let pieces: Vec<&str> = inner.as_slice().splitn(',', 1).collect();
+            let pieces: Vec<&str> = inner.as_slice().splitn(1, ',').collect();
             let (smin, smax) = (pieces[0], pieces[1]);
             if smin.len() == 0 {
                 return self.err("Max repetitions cannot be specified \
@@ -1017,9 +1018,9 @@ fn is_valid_cap(c: char) -> bool {
 }
 
 fn find_class(classes: NamedClasses, name: &str) -> Option<Vec<(char, char)>> {
-    match classes.bsearch(|&(s, _)| s.cmp(&name)) {
-        Some(i) => Some(Vec::from_slice(classes[i].val1())),
-        None => None,
+    match classes.binary_search(|&(s, _)| s.cmp(&name)) {
+        slice::Found(i) => Some(Vec::from_slice(classes[i].val1())),
+        slice::NotFound(_) => None,
     }
 }
 
index b37000df02dbec436e2c862fbb26c711efbbca28..507a7641f2201bf100982cf9cb3b8e2e63527679 100644 (file)
@@ -35,7 +35,7 @@
 
 use std::cmp;
 use std::mem;
-use std::slice::MutableVector;
+use std::slice::MutableSlice;
 use compile::{
     Program,
     Match, OneChar, CharClass, Any, EmptyBegin, EmptyEnd, EmptyWordBoundary,
@@ -222,8 +222,8 @@ fn step(&self, groups: &mut [Option<uint>], nlist: &mut Threads,
                     let negate = flags & FLAG_NEGATED > 0;
                     let casei = flags & FLAG_NOCASE > 0;
                     let found = ranges.as_slice();
-                    let found = found.bsearch(|&rc| class_cmp(casei, c, rc));
-                    let found = found.is_some();
+                    let found = found.binary_search(|&rc| class_cmp(casei, c, rc))
+                        .found().is_some();
                     if found ^ negate {
                         self.add(nlist, pc+1, caps);
                     }
@@ -513,7 +513,7 @@ pub fn is_word(c: Option<char>) -> bool {
     // Try the common ASCII case before invoking binary search.
     match c {
         '_' | '0' .. '9' | 'a' .. 'z' | 'A' .. 'Z' => true,
-        _ => PERLW.bsearch(|&(start, end)| {
+        _ => PERLW.binary_search(|&(start, end)| {
             if c >= start && c <= end {
                 Equal
             } else if start > c {
@@ -521,7 +521,7 @@ pub fn is_word(c: Option<char>) -> bool {
             } else {
                 Less
             }
-        }).is_some()
+        }).found().is_some()
     }
 }
 
index c7295125f42f7504de4c1c22546b748058b9f197..706b5c3325576c212dc72be9055ec4b9a035166c 100644 (file)
@@ -112,7 +112,7 @@ mod test {
     use core::iter::Iterator;
     use core::collections::Collection;
     use core::str::StrSlice;
-    use core::slice::{MutableVector, ImmutableVector};
+    use core::slice::{MutableSlice, ImmutableSlice};
 
     use super::{memcmp, memset, memcpy, memmove};
 
index f4309d9e51b56f7ae14c84349c09fb896aa0fd94..826579b62fcba23a1f08b0da0a43a5325dc67bed 100644 (file)
@@ -353,7 +353,7 @@ pub fn build_codegen_options(matches: &getopts::Matches) -> CodegenOptions
 {
     let mut cg = basic_codegen_options();
     for option in matches.opt_strs("C").move_iter() {
-        let mut iter = option.as_slice().splitn('=', 1);
+        let mut iter = option.as_slice().splitn(1, '=');
         let key = iter.next().unwrap();
         let value = iter.next();
         let option_to_lookup = key.replace("-", "_");
@@ -750,7 +750,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
 
     let mut externs = HashMap::new();
     for arg in matches.opt_strs("extern").iter() {
-        let mut parts = arg.as_slice().splitn('=', 1);
+        let mut parts = arg.as_slice().splitn(1, '=');
         let name = match parts.next() {
             Some(s) => s,
             None => early_error("--extern value must not be empty"),
index 477fc5e1c0f30374080c2e2d3564e31d8c17ff98..5f86745f3f2210cb37dfbed38d8e16fe49dda674 100644 (file)
@@ -360,8 +360,9 @@ pub fn phase_3_run_analysis_passes(sess: Session,
             plugin::build::find_plugin_registrar(
                 sess.diagnostic(), krate)));
 
-    let freevars = time(time_passes, "freevar finding", (), |_|
-                        freevars::annotate_freevars(&def_map, krate));
+    let (freevars, capture_modes) =
+        time(time_passes, "freevar finding", (), |_|
+             freevars::annotate_freevars(&def_map, krate));
 
     let region_map = time(time_passes, "region resolution", (), |_|
                           middle::region::resolve_crate(&sess, krate));
@@ -372,8 +373,15 @@ pub fn phase_3_run_analysis_passes(sess: Session,
     let stability_index = time(time_passes, "stability index", (), |_|
                                stability::Index::build(krate));
 
-    let ty_cx = ty::mk_ctxt(sess, def_map, named_region_map, ast_map,
-                            freevars, region_map, lang_items, stability_index);
+    let ty_cx = ty::mk_ctxt(sess,
+                            def_map,
+                            named_region_map,
+                            ast_map,
+                            freevars,
+                            capture_modes,
+                            region_map,
+                            lang_items,
+                            stability_index);
 
     // passes are timed inside typeck
     typeck::check_crate(&ty_cx, trait_map, krate);
index 05762aa3db2762c709cc8570e48342374ec36218..dc600e0da3ec06ae26253c8ada1eee7ff7f2b918 100644 (file)
@@ -356,7 +356,7 @@ pub enum PpMode {
 }
 
 fn parse_pretty(sess: &Session, name: &str) -> (PpMode, Option<driver::UserIdentifiedItem>) {
-    let mut split = name.splitn('=', 1);
+    let mut split = name.splitn(1, '=');
     let first = split.next().unwrap();
     let opt_second = split.next();
     let first = match first {
index 14cda7d62c35def4dc62053e12af7a95184c1f61..ceb7dcc54560c04931744bf91f3dbaeecdcd0d1d 100644 (file)
@@ -379,7 +379,7 @@ fn mk_test_module(cx: &TestCtxt, reexport_test_harness_main: &Option<InternedStr
     let mainfn = (quote_item!(&cx.ext_cx,
         pub fn main() {
             #![main]
-            use std::slice::Vector;
+            use std::slice::Slice;
             test::test_main_static(::std::os::args().as_slice(), TESTS);
         }
     )).unwrap();
index bde0992dabeef574b9bcd4d5937f1437aa5e67d0..f929860c6864bedd969ec832027a7eba64dca114 100644 (file)
@@ -1479,20 +1479,20 @@ fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
             _ => return
         };
 
-        // stability attributes are promises made across crates; do not
-        // check anything for crate-local usage.
-        if ast_util::is_local(id) { return }
-
         let stability = stability::lookup(cx.tcx, id);
+        let cross_crate = !ast_util::is_local(id);
+
+        // stability attributes are promises made across crates; only
+        // check DEPRECATED for crate-local usage.
         let (lint, label) = match stability {
             // no stability attributes == Unstable
-            None => (UNSTABLE, "unmarked"),
-            Some(attr::Stability { level: attr::Unstable, .. }) =>
-                    (UNSTABLE, "unstable"),
-            Some(attr::Stability { level: attr::Experimental, .. }) =>
-                    (EXPERIMENTAL, "experimental"),
+            None if cross_crate => (UNSTABLE, "unmarked"),
+            Some(attr::Stability { level: attr::Unstable, .. }) if cross_crate =>
+                (UNSTABLE, "unstable"),
+            Some(attr::Stability { level: attr::Experimental, .. }) if cross_crate =>
+                (EXPERIMENTAL, "experimental"),
             Some(attr::Stability { level: attr::Deprecated, .. }) =>
-                    (DEPRECATED, "deprecated"),
+                (DEPRECATED, "deprecated"),
             _ => return
         };
 
index 8ed471ec58a5e7da3a805bb7968d690245d0dc4b..633ad8293491b527ddba9ea1b176d38233086db9 100644 (file)
@@ -141,9 +141,10 @@ pub enum astencode_tag { // Reserves 0x40 -- 0x5f
     tag_table_capture_map = 0x53,
     tag_table_unboxed_closure_type = 0x54,
     tag_table_upvar_borrow_map = 0x55,
+    tag_table_capture_modes = 0x56,
 }
 static first_astencode_tag: uint = tag_ast as uint;
-static last_astencode_tag: uint = tag_table_upvar_borrow_map as uint;
+static last_astencode_tag: uint = tag_table_capture_modes as uint;
 impl astencode_tag {
     pub fn from_uint(value : uint) -> Option<astencode_tag> {
         let is_a_tag = first_astencode_tag <= value && value <= last_astencode_tag;
index 33b663dea1557b5ea208b4d24b196eb5280de252..e31af8b58b9f1bf208950779c65f7bffab7b423a 100644 (file)
@@ -18,8 +18,8 @@
 use metadata::decoder;
 use middle::def;
 use e = metadata::encoder;
+use middle::freevars::{CaptureMode, freevar_entry};
 use middle::freevars;
-use middle::freevars::freevar_entry;
 use middle::region;
 use metadata::tydecode;
 use metadata::tydecode::{DefIdSource, NominalType, TypeWithId, TypeParameter,
@@ -530,9 +530,14 @@ fn encode_freevar_entry(rbml_w: &mut Encoder, fv: &freevar_entry) {
     (*fv).encode(rbml_w).unwrap();
 }
 
+fn encode_capture_mode(rbml_w: &mut Encoder, cm: CaptureMode) {
+    cm.encode(rbml_w).unwrap();
+}
+
 trait rbml_decoder_helper {
     fn read_freevar_entry(&mut self, xcx: &ExtendedDecodeContext)
                           -> freevar_entry;
+    fn read_capture_mode(&mut self) -> CaptureMode;
 }
 
 impl<'a> rbml_decoder_helper for reader::Decoder<'a> {
@@ -541,6 +546,11 @@ fn read_freevar_entry(&mut self, xcx: &ExtendedDecodeContext)
         let fv: freevar_entry = Decodable::decode(self).unwrap();
         fv.tr(xcx)
     }
+
+    fn read_capture_mode(&mut self) -> CaptureMode {
+        let cm: CaptureMode = Decodable::decode(self).unwrap();
+        cm
+    }
 }
 
 impl tr for freevar_entry {
@@ -1096,6 +1106,15 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
         }
     }
 
+    for &cm in tcx.capture_modes.borrow().find(&id).iter() {
+        rbml_w.tag(c::tag_table_capture_modes, |rbml_w| {
+            rbml_w.id(id);
+            rbml_w.tag(c::tag_table_val, |rbml_w| {
+                encode_capture_mode(rbml_w, *cm);
+            })
+        })
+    }
+
     let lid = ast::DefId { krate: ast::LOCAL_CRATE, node: id };
     for &pty in tcx.tcache.borrow().find(&lid).iter() {
         rbml_w.tag(c::tag_table_tcache, |rbml_w| {
@@ -1509,6 +1528,13 @@ fn decode_side_tables(xcx: &ExtendedDecodeContext,
                         let ub: ty::UpvarBorrow = Decodable::decode(val_dsr).unwrap();
                         dcx.tcx.upvar_borrow_map.borrow_mut().insert(upvar_id, ub.tr(xcx));
                     }
+                    c::tag_table_capture_modes => {
+                        let capture_mode = val_dsr.read_capture_mode();
+                        dcx.tcx
+                           .capture_modes
+                           .borrow_mut()
+                           .insert(id, capture_mode);
+                    }
                     c::tag_table_tcache => {
                         let pty = val_dsr.read_polytype(xcx);
                         let lid = ast::DefId { krate: ast::LOCAL_CRATE, node: id };
index 454c3dcd5d3cadd211f996dda5243469ac9a46e6..18323c26dd985629a65765c8d78ecde88716dafa 100644 (file)
@@ -261,6 +261,8 @@ fn guarantee_valid(&mut self,
             self.bccx, borrow_span, cause,
             cmt.clone(), loan_region);
 
+        debug!("guarantee_valid(): restrictions={:?}", restr);
+
         // Create the loan record (if needed).
         let loan = match restr {
             restrictions::Safe => {
index da739faabad93b5ed93b074226dcd62c6d28f547..7d50d07a11e3215a1e69c18ccdf7be89facbc6a6 100644 (file)
@@ -122,9 +122,7 @@ fn restrict(&self,
             }
 
             mc::cat_deref(cmt_base, _, mc::BorrowedPtr(ty::ImmBorrow, lt)) |
-            mc::cat_deref(cmt_base, _, mc::BorrowedPtr(ty::UniqueImmBorrow, lt)) |
-            mc::cat_deref(cmt_base, _, mc::Implicit(ty::ImmBorrow, lt)) |
-            mc::cat_deref(cmt_base, _, mc::Implicit(ty::UniqueImmBorrow, lt)) => {
+            mc::cat_deref(cmt_base, _, mc::Implicit(ty::ImmBorrow, lt)) => {
                 // R-Deref-Imm-Borrowed
                 if !self.bccx.is_subregion_of(self.loan_region, lt) {
                     self.bccx.report(
@@ -142,7 +140,9 @@ fn restrict(&self,
             mc::cat_deref(cmt_base, _, pk) => {
                 match pk {
                     mc::BorrowedPtr(ty::MutBorrow, lt) |
-                    mc::Implicit(ty::MutBorrow, lt) => {
+                    mc::BorrowedPtr(ty::UniqueImmBorrow, lt) |
+                    mc::Implicit(ty::MutBorrow, lt) |
+                    mc::Implicit(ty::UniqueImmBorrow, lt) => {
                         // R-Deref-Mut-Borrowed
                         if !self.bccx.is_subregion_of(self.loan_region, lt) {
                             self.bccx.report(
index 6c5352ed796d689c2e3c76159f22c5ec2d34a8b4..fd1369439c9a492ebbf5c3167569605580627119 100644 (file)
@@ -291,7 +291,7 @@ pub fn closure_to_block(closure_id: ast::NodeId,
     match tcx.map.get(closure_id) {
         ast_map::NodeExpr(expr) => match expr.node {
             ast::ExprProc(_decl, block) |
-            ast::ExprFnBlock(_decl, block) => { block.id }
+            ast::ExprFnBlock(_, _decl, block) => { block.id }
             _ => fail!("encountered non-closure id: {}", closure_id)
         },
         _ => fail!("encountered non-expr id: {}", closure_id)
index 61a2e8407303b730c6ae88ac076e5e293720b666..f973b33ef2c862e7c319855e9b5da0921dfbb5bd 100644 (file)
@@ -46,9 +46,9 @@ fn visit_expr(&mut self, e: &ast::Expr, cx:Context) {
                 self.visit_expr(&**e, cx);
                 self.visit_block(&**b, Loop);
             }
-            ast::ExprFnBlock(_, ref b) |
+            ast::ExprFnBlock(_, _, ref b) |
             ast::ExprProc(_, ref b) |
-            ast::ExprUnboxedFn(_, ref b) => {
+            ast::ExprUnboxedFn(_, _, ref b) => {
                 self.visit_block(&**b, Closure);
             }
             ast::ExprBreak(_) => self.require_loop("break", cx, e.span),
index 605811555a16819b70d69d99a42b614b4c6a0560..7c805b1ac4bcde3917417d0a675376c7db524aed 100644 (file)
@@ -399,10 +399,16 @@ pub fn walk_expr(&mut self, expr: &ast::Expr) {
             ast::ExprForLoop(ref pat, ref head, ref blk, _) => {
                 // The pattern lives as long as the block.
                 debug!("walk_expr for loop case: blk id={}", blk.id);
-                self.walk_expr(&**head);
+                self.consume_expr(&**head);
 
-                let head_cmt = return_if_err!(self.mc.cat_expr(&**head));
-                self.walk_pat(head_cmt, pat.clone());
+                // Fetch the type of the value that the iteration yields to
+                // produce the pattern's categorized mutable type.
+                let pattern_type = ty::node_id_to_type(self.tcx(), pat.id);
+                let pat_cmt = self.mc.cat_rvalue(pat.id,
+                                                 pat.span,
+                                                 ty::ReScope(blk.id),
+                                                 pattern_type);
+                self.walk_pat(pat_cmt, pat.clone());
 
                 self.walk_block(&**blk);
             }
@@ -835,6 +841,7 @@ fn walk_pat(&mut self, cmt_discr: mc::cmt, pat: Gc<ast::Pat>) {
                     }
                     ast::PatIdent(ast::BindByValue(_), _, _) => {
                         let mode = copy_or_move(typer.tcx(), cmt_pat.ty, PatBindingMove);
+                        debug!("walk_pat binding consuming pat");
                         delegate.consume_pat(pat, cmt_pat, mode);
                     }
                     _ => {
index eda567f7d187c1a33745f52b154601c20eac2c57..b092d45e0396ac021cd521979946138898bfc31c 100644 (file)
 use middle::mem_categorization::Typer;
 use middle::resolve;
 use middle::ty;
-use util::nodemap::{DefIdSet, NodeMap, NodeSet};
+use util::nodemap::{NodeMap, NodeSet};
 
+use syntax::ast;
 use syntax::codemap::Span;
-use syntax::{ast};
-use syntax::visit;
 use syntax::visit::Visitor;
+use syntax::visit;
 
-#[deriving(Show)]
+#[deriving(Clone, Decodable, Encodable, Show)]
 pub enum CaptureMode {
     /// Copy/move the value from this llvm ValueRef into the environment.
     CaptureByValue,
@@ -43,12 +43,13 @@ pub struct freevar_entry {
 
 pub type freevar_map = NodeMap<Vec<freevar_entry>>;
 
-pub type UnboxedClosureList = DefIdSet;
+pub type CaptureModeMap = NodeMap<CaptureMode>;
 
 struct CollectFreevarsVisitor<'a> {
     seen: NodeSet,
     refs: Vec<freevar_entry>,
     def_map: &'a resolve::DefMap,
+    capture_mode_map: &'a mut CaptureModeMap,
 }
 
 impl<'a> Visitor<int> for CollectFreevarsVisitor<'a> {
@@ -58,8 +59,27 @@ fn visit_item(&mut self, _: &ast::Item, _: int) {
 
     fn visit_expr(&mut self, expr: &ast::Expr, depth: int) {
         match expr.node {
-            ast::ExprFnBlock(..) | ast::ExprProc(..) |
-            ast::ExprUnboxedFn(..) => {
+            ast::ExprProc(..) => {
+                self.capture_mode_map.insert(expr.id, CaptureByValue);
+                visit::walk_expr(self, expr, depth + 1)
+            }
+            ast::ExprFnBlock(_, _, _) => {
+                // NOTE(stage0): After snapshot, change to:
+                //
+                //let capture_mode = match capture_clause {
+                //    ast::CaptureByValue => CaptureByValue,
+                //    ast::CaptureByRef => CaptureByRef,
+                //};
+                let capture_mode = CaptureByRef;
+                self.capture_mode_map.insert(expr.id, capture_mode);
+                visit::walk_expr(self, expr, depth + 1)
+            }
+            ast::ExprUnboxedFn(capture_clause, _, _) => {
+                let capture_mode = match capture_clause {
+                    ast::CaptureByValue => CaptureByValue,
+                    ast::CaptureByRef => CaptureByRef,
+                };
+                self.capture_mode_map.insert(expr.id, capture_mode);
                 visit::walk_expr(self, expr, depth + 1)
             }
             ast::ExprPath(..) => {
@@ -91,8 +111,6 @@ fn visit_expr(&mut self, expr: &ast::Expr, depth: int) {
             _ => visit::walk_expr(self, expr, depth)
         }
     }
-
-
 }
 
 // Searches through part of the AST for all references to locals or
@@ -100,26 +118,34 @@ fn visit_expr(&mut self, expr: &ast::Expr, depth: int) {
 // Since we want to be able to collect upvars in some arbitrary piece
 // of the AST, we take a walker function that we invoke with a visitor
 // in order to start the search.
-fn collect_freevars(def_map: &resolve::DefMap, blk: &ast::Block) -> Vec<freevar_entry> {
+fn collect_freevars(def_map: &resolve::DefMap,
+                    blk: &ast::Block,
+                    capture_mode_map: &mut CaptureModeMap)
+                    -> Vec<freevar_entry> {
     let mut v = CollectFreevarsVisitor {
         seen: NodeSet::new(),
         refs: Vec::new(),
         def_map: def_map,
+        capture_mode_map: &mut *capture_mode_map,
     };
 
     v.visit_block(blk, 1);
+
     v.refs
 }
 
 struct AnnotateFreevarsVisitor<'a> {
     def_map: &'a resolve::DefMap,
     freevars: freevar_map,
+    capture_mode_map: CaptureModeMap,
 }
 
 impl<'a> Visitor<()> for AnnotateFreevarsVisitor<'a> {
     fn visit_fn(&mut self, fk: &visit::FnKind, fd: &ast::FnDecl,
                 blk: &ast::Block, s: Span, nid: ast::NodeId, _: ()) {
-        let vars = collect_freevars(self.def_map, blk);
+        let vars = collect_freevars(self.def_map,
+                                    blk,
+                                    &mut self.capture_mode_map);
         self.freevars.insert(nid, vars);
         visit::walk_fn(self, fk, fd, blk, s, ());
     }
@@ -131,14 +157,20 @@ fn visit_fn(&mut self, fk: &visit::FnKind, fd: &ast::FnDecl,
 // node of interest rather than building up the free variables in
 // one pass. This could be improved upon if it turns out to matter.
 pub fn annotate_freevars(def_map: &resolve::DefMap, krate: &ast::Crate)
-                         -> freevar_map {
+                         -> (freevar_map, CaptureModeMap) {
     let mut visitor = AnnotateFreevarsVisitor {
         def_map: def_map,
         freevars: NodeMap::new(),
+        capture_mode_map: NodeMap::new(),
     };
     visit::walk_crate(&mut visitor, krate, ());
 
-    visitor.freevars
+    let AnnotateFreevarsVisitor {
+        freevars,
+        capture_mode_map,
+        ..
+    } = visitor;
+    (freevars, capture_mode_map)
 }
 
 pub fn with_freevars<T>(tcx: &ty::ctxt, fid: ast::NodeId, f: |&[freevar_entry]| -> T) -> T {
@@ -148,10 +180,7 @@ pub fn with_freevars<T>(tcx: &ty::ctxt, fid: ast::NodeId, f: |&[freevar_entry]|
     }
 }
 
-pub fn get_capture_mode<T: Typer>(tcx: &T, closure_expr_id: ast::NodeId) -> CaptureMode {
-    let fn_ty = tcx.node_ty(closure_expr_id).ok().expect("couldn't find closure ty?");
-    match ty::ty_closure_store(fn_ty) {
-        ty::RegionTraitStore(..) => CaptureByRef,
-        ty::UniqTraitStore => CaptureByValue
-    }
+pub fn get_capture_mode<T:Typer>(tcx: &T, closure_expr_id: ast::NodeId)
+                        -> CaptureMode {
+    tcx.capture_mode(closure_expr_id)
 }
index 1c31b671a947bafe1118999bdafb28b32e937686..1e4841787883498e1c0bc5b9682cfcb0fc392388 100644 (file)
@@ -965,9 +965,9 @@ fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode)
               self.propagate_through_expr(&**e, succ)
           }
 
-          ExprFnBlock(_, ref blk) |
+          ExprFnBlock(_, _, ref blk) |
           ExprProc(_, ref blk) |
-          ExprUnboxedFn(_, ref blk) => {
+          ExprUnboxedFn(_, _, ref blk) => {
               debug!("{} is an ExprFnBlock, ExprProc, or ExprUnboxedFn",
                      expr_to_string(expr));
 
index 39a7b4aa3d68ec7a512df051f7ada80aa5071032..6ad8bc0c1e9b1b3fb40e83fed57129bcefd82153 100644 (file)
@@ -63,6 +63,7 @@
 #![allow(non_camel_case_types)]
 
 use middle::def;
+use middle::freevars;
 use middle::ty;
 use middle::typeck;
 use util::nodemap::NodeMap;
@@ -270,6 +271,8 @@ pub trait Typer {
     fn is_method_call(&self, id: ast::NodeId) -> bool;
     fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<ast::NodeId>;
     fn upvar_borrow(&self, upvar_id: ty::UpvarId) -> ty::UpvarBorrow;
+    fn capture_mode(&self, closure_expr_id: ast::NodeId)
+                    -> freevars::CaptureMode;
 }
 
 impl MutabilityCategory {
index 95c04ad6607d66ead0852153c3689e4b233ee014..1e4cbdbdb6e5a00e0dcad863bca275dcf616a810 100644 (file)
@@ -5287,9 +5287,9 @@ fn resolve_expr(&mut self, expr: &Expr) {
                 visit::walk_expr(self, expr, ());
             }
 
-            ExprFnBlock(fn_decl, block) |
+            ExprFnBlock(_, fn_decl, block) |
             ExprProc(fn_decl, block) |
-            ExprUnboxedFn(fn_decl, block) => {
+            ExprUnboxedFn(_, fn_decl, block) => {
                 self.resolve_function(FunctionRibKind(expr.id, block.id),
                                       Some(fn_decl), NoTypeParameters,
                                       block);
index c4373a023ccb24044872da32aacd84c97118e570..4a58a8bba99c87a23ee8ba57bd534ea19535dac9 100644 (file)
@@ -1237,7 +1237,7 @@ fn visit_expr(&mut self, ex: &ast::Expr, e: DxrVisitorEnv) {
                                             "Expected struct type, but not ty_struct"),
                 }
             },
-            ast::ExprFnBlock(decl, body) => {
+            ast::ExprFnBlock(_, decl, body) => {
                 if generated_code(body.span) {
                     return
                 }
index 242a820c997ff8e79d315701f09f48e02e2119a5..b7bb383ad3cb2e990beb7bda1369e8223f17f133 100644 (file)
@@ -1122,7 +1122,7 @@ pub fn memcpy_ty(bcx: &Block, dst: ValueRef, src: ValueRef, t: ty::t) {
         let llalign = llalign_of_min(ccx, llty);
         call_memcpy(bcx, dst, src, llsz, llalign as u32);
     } else {
-        Store(bcx, Load(bcx, src), dst);
+        store_ty(bcx, Load(bcx, src), dst, t);
     }
 }
 
@@ -1210,15 +1210,122 @@ pub fn arrayalloca(cx: &Block, ty: Type, v: ValueRef) -> ValueRef {
     p
 }
 
-// Creates and returns space for, or returns the argument representing, the
-// slot where the return value of the function must go.
-pub fn make_return_pointer(fcx: &FunctionContext, output_type: ty::t)
-                           -> ValueRef {
-    if type_of::return_uses_outptr(fcx.ccx, output_type) {
-        get_param(fcx.llfn, 0)
+// Creates the alloca slot which holds the pointer to the slot for the final return value
+pub fn make_return_slot_pointer(fcx: &FunctionContext, output_type: ty::t) -> ValueRef {
+    let lloutputtype = type_of::type_of(fcx.ccx, output_type);
+
+    // We create an alloca to hold a pointer of type `output_type`
+    // which will hold the pointer to the right alloca which has the
+    // final ret value
+    if fcx.needs_ret_allocas {
+        // Let's create the stack slot
+        let slot = AllocaFcx(fcx, lloutputtype.ptr_to(), "llretslotptr");
+
+        // and if we're using an out pointer, then store that in our newly made slot
+        if type_of::return_uses_outptr(fcx.ccx, output_type) {
+            let outptr = get_param(fcx.llfn, 0);
+
+            let b = fcx.ccx.builder();
+            b.position_before(fcx.alloca_insert_pt.get().unwrap());
+            b.store(outptr, slot);
+        }
+
+        slot
+
+    // But if there are no nested returns, we skip the indirection and have a single
+    // retslot
     } else {
-        let lloutputtype = type_of::type_of(fcx.ccx, output_type);
-        AllocaFcx(fcx, lloutputtype, "__make_return_pointer")
+        if type_of::return_uses_outptr(fcx.ccx, output_type) {
+            get_param(fcx.llfn, 0)
+        } else {
+            AllocaFcx(fcx, lloutputtype, "sret_slot")
+        }
+    }
+}
+
+struct CheckForNestedReturnsVisitor {
+    found: bool
+}
+
+impl Visitor<bool> for CheckForNestedReturnsVisitor {
+    fn visit_expr(&mut self, e: &ast::Expr, in_return: bool) {
+        match e.node {
+            ast::ExprRet(..) if in_return => {
+                self.found = true;
+                return;
+            }
+            ast::ExprRet(..) => visit::walk_expr(self, e, true),
+            _ => visit::walk_expr(self, e, in_return)
+        }
+    }
+}
+
+fn has_nested_returns(tcx: &ty::ctxt, id: ast::NodeId) -> bool {
+    match tcx.map.find(id) {
+        Some(ast_map::NodeItem(i)) => {
+            match i.node {
+                ast::ItemFn(_, _, _, _, blk) => {
+                    let mut explicit = CheckForNestedReturnsVisitor { found: false };
+                    let mut implicit = CheckForNestedReturnsVisitor { found: false };
+                    visit::walk_item(&mut explicit, &*i, false);
+                    visit::walk_expr_opt(&mut implicit, blk.expr, true);
+                    explicit.found || implicit.found
+                }
+                _ => tcx.sess.bug("unexpected item variant in has_nested_returns")
+            }
+        }
+        Some(ast_map::NodeTraitMethod(trait_method)) => {
+            match *trait_method {
+                ast::Provided(m) => {
+                    match m.node {
+                        ast::MethDecl(_, _, _, _, _, _, blk, _) => {
+                            let mut explicit = CheckForNestedReturnsVisitor { found: false };
+                            let mut implicit = CheckForNestedReturnsVisitor { found: false };
+                            visit::walk_method_helper(&mut explicit, &*m, false);
+                            visit::walk_expr_opt(&mut implicit, blk.expr, true);
+                            explicit.found || implicit.found
+                        }
+                        ast::MethMac(_) => tcx.sess.bug("unexpanded macro")
+                    }
+                }
+                ast::Required(_) => tcx.sess.bug("unexpected variant: required trait method in \
+                                                  has_nested_returns")
+            }
+        }
+        Some(ast_map::NodeMethod(m)) => {
+            match m.node {
+                ast::MethDecl(_, _, _, _, _, _, blk, _) => {
+                    let mut explicit = CheckForNestedReturnsVisitor { found: false };
+                    let mut implicit = CheckForNestedReturnsVisitor { found: false };
+                    visit::walk_method_helper(&mut explicit, &*m, false);
+                    visit::walk_expr_opt(&mut implicit, blk.expr, true);
+                    explicit.found || implicit.found
+                }
+                ast::MethMac(_) => tcx.sess.bug("unexpanded macro")
+            }
+        }
+        Some(ast_map::NodeExpr(e)) => {
+            match e.node {
+                ast::ExprFnBlock(_, _, blk) |
+                ast::ExprProc(_, blk) |
+                ast::ExprUnboxedFn(_, _, blk) => {
+                    let mut explicit = CheckForNestedReturnsVisitor { found: false };
+                    let mut implicit = CheckForNestedReturnsVisitor { found: false };
+                    visit::walk_expr(&mut explicit, &*e, false);
+                    visit::walk_expr_opt(&mut implicit, blk.expr, true);
+                    explicit.found || implicit.found
+                }
+                _ => tcx.sess.bug("unexpected expr variant in has_nested_returns")
+            }
+        }
+
+        Some(ast_map::NodeVariant(..)) | Some(ast_map::NodeStructCtor(..)) => false,
+
+        // glue, shims, etc
+        None if id == ast::DUMMY_NODE_ID => false,
+
+        _ => tcx.sess.bug(format!("unexpected variant in has_nested_returns: {}",
+                                  tcx.map.path_to_string(id)).as_slice())
     }
 }
 
@@ -1238,8 +1345,7 @@ pub fn new_fn_ctxt<'a>(ccx: &'a CrateContext,
                        output_type: ty::t,
                        param_substs: &'a param_substs,
                        sp: Option<Span>,
-                       block_arena: &'a TypedArena<Block<'a>>,
-                       handle_items: HandleItemsFlag)
+                       block_arena: &'a TypedArena<Block<'a>>)
                        -> FunctionContext<'a> {
     param_substs.validate();
 
@@ -1254,13 +1360,15 @@ pub fn new_fn_ctxt<'a>(ccx: &'a CrateContext,
     let substd_output_type = output_type.substp(ccx.tcx(), param_substs);
     let uses_outptr = type_of::return_uses_outptr(ccx, substd_output_type);
     let debug_context = debuginfo::create_function_debug_context(ccx, id, param_substs, llfndecl);
+    let nested_returns = has_nested_returns(ccx.tcx(), id);
 
     let mut fcx = FunctionContext {
           llfn: llfndecl,
           llenv: None,
-          llretptr: Cell::new(None),
+          llretslotptr: Cell::new(None),
           alloca_insert_pt: Cell::new(None),
           llreturn: Cell::new(None),
+          needs_ret_allocas: nested_returns,
           personality: Cell::new(None),
           caller_expects_out_pointer: uses_outptr,
           llargs: RefCell::new(NodeMap::new()),
@@ -1272,8 +1380,7 @@ pub fn new_fn_ctxt<'a>(ccx: &'a CrateContext,
           block_arena: block_arena,
           ccx: ccx,
           debug_context: debug_context,
-          scopes: RefCell::new(Vec::new()),
-          handle_items: handle_items,
+          scopes: RefCell::new(Vec::new())
     };
 
     if has_env {
@@ -1303,12 +1410,12 @@ pub fn init_function<'a>(fcx: &'a FunctionContext<'a>,
 
     if !return_type_is_void(fcx.ccx, substd_output_type) {
         // If the function returns nil/bot, there is no real return
-        // value, so do not set `llretptr`.
+        // value, so do not set `llretslotptr`.
         if !skip_retptr || fcx.caller_expects_out_pointer {
-            // Otherwise, we normally allocate the llretptr, unless we
+            // Otherwise, we normally allocate the llretslotptr, unless we
             // have been instructed to skip it for immediate return
             // values.
-            fcx.llretptr.set(Some(make_return_pointer(fcx, substd_output_type)));
+            fcx.llretslotptr.set(Some(make_return_slot_pointer(fcx, substd_output_type)));
         }
     }
 
@@ -1533,13 +1640,18 @@ pub fn finish_fn<'a>(fcx: &'a FunctionContext<'a>,
 
 // Builds the return block for a function.
 pub fn build_return_block(fcx: &FunctionContext, ret_cx: &Block, retty: ty::t) {
-    // Return the value if this function immediate; otherwise, return void.
-    if fcx.llretptr.get().is_none() || fcx.caller_expects_out_pointer {
+    if fcx.llretslotptr.get().is_none() ||
+       (!fcx.needs_ret_allocas && fcx.caller_expects_out_pointer) {
         return RetVoid(ret_cx);
     }
 
-    let retptr = Value(fcx.llretptr.get().unwrap());
-    let retval = match retptr.get_dominating_store(ret_cx) {
+    let retslot = if fcx.needs_ret_allocas {
+        Load(ret_cx, fcx.llretslotptr.get().unwrap())
+    } else {
+        fcx.llretslotptr.get().unwrap()
+    };
+    let retptr = Value(retslot);
+    match retptr.get_dominating_store(ret_cx) {
         // If there's only a single store to the ret slot, we can directly return
         // the value that was stored and omit the store and the alloca
         Some(s) => {
@@ -1550,17 +1662,29 @@ pub fn build_return_block(fcx: &FunctionContext, ret_cx: &Block, retty: ty::t) {
                 retptr.erase_from_parent();
             }
 
-            if ty::type_is_bool(retty) {
+            let retval = if ty::type_is_bool(retty) {
                 Trunc(ret_cx, retval, Type::i1(fcx.ccx))
             } else {
                 retval
+            };
+
+            if fcx.caller_expects_out_pointer {
+                store_ty(ret_cx, retval, get_param(fcx.llfn, 0), retty);
+                return RetVoid(ret_cx);
+            } else {
+                return Ret(ret_cx, retval);
             }
         }
-        // Otherwise, load the return value from the ret slot
-        None => load_ty(ret_cx, fcx.llretptr.get().unwrap(), retty)
-    };
-
-    Ret(ret_cx, retval);
+        // Otherwise, copy the return value to the ret slot
+        None => {
+            if fcx.caller_expects_out_pointer {
+                memcpy_ty(ret_cx, get_param(fcx.llfn, 0), retslot, retty);
+                return RetVoid(ret_cx);
+            } else {
+                return Ret(ret_cx, load_ty(ret_cx, retslot, retty));
+            }
+        }
+    }
 }
 
 #[deriving(Clone, Eq, PartialEq)]
@@ -1584,8 +1708,7 @@ pub fn trans_closure(ccx: &CrateContext,
                      abi: Abi,
                      has_env: bool,
                      is_unboxed_closure: IsUnboxedClosureFlag,
-                     maybe_load_env: <'a> |&'a Block<'a>| -> &'a Block<'a>,
-                     handle_items: HandleItemsFlag) {
+                     maybe_load_env: <'a> |&'a Block<'a>| -> &'a Block<'a>) {
     ccx.stats.n_closures.set(ccx.stats.n_closures.get() + 1);
 
     let _icx = push_ctxt("trans_closure");
@@ -1602,8 +1725,7 @@ pub fn trans_closure(ccx: &CrateContext,
                           output_type,
                           param_substs,
                           Some(body.span),
-                          &arena,
-                          handle_items);
+                          &arena);
     let mut bcx = init_function(&fcx, false, output_type);
 
     // cleanup scope for the incoming arguments
@@ -1658,10 +1780,10 @@ pub fn trans_closure(ccx: &CrateContext,
     // emitting should be enabled.
     debuginfo::start_emitting_source_locations(&fcx);
 
-    let dest = match fcx.llretptr.get() {
-        Some(e) => {expr::SaveIn(e)}
+    let dest = match fcx.llretslotptr.get() {
+        Some(_) => expr::SaveIn(fcx.get_ret_slot(bcx, block_ty, "iret_slot")),
         None => {
-            assert!(type_is_zero_size(bcx.ccx(), block_ty))
+            assert!(type_is_zero_size(bcx.ccx(), block_ty));
             expr::Ignore
         }
     };
@@ -1672,6 +1794,13 @@ pub fn trans_closure(ccx: &CrateContext,
     // (trans_block, trans_expr, et cetera).
     bcx = controlflow::trans_block(bcx, body, dest);
 
+    match dest {
+        expr::SaveIn(slot) if fcx.needs_ret_allocas => {
+            Store(bcx, slot, fcx.llretslotptr.get().unwrap());
+        }
+        _ => {}
+    }
+
     match fcx.llreturn.get() {
         Some(_) => {
             Br(bcx, fcx.return_exit_block());
@@ -1705,8 +1834,7 @@ pub fn trans_fn(ccx: &CrateContext,
                 llfndecl: ValueRef,
                 param_substs: &param_substs,
                 id: ast::NodeId,
-                attrs: &[ast::Attribute],
-                handle_items: HandleItemsFlag) {
+                attrs: &[ast::Attribute]) {
     let _s = StatRecorder::new(ccx, ccx.tcx.map.path_to_string(id).to_string());
     debug!("trans_fn(param_substs={})", param_substs.repr(ccx.tcx()));
     let _icx = push_ctxt("trans_fn");
@@ -1726,8 +1854,7 @@ pub fn trans_fn(ccx: &CrateContext,
                   abi,
                   false,
                   NotUnboxedClosure,
-                  |bcx| bcx,
-                  handle_items);
+                  |bcx| bcx);
 }
 
 pub fn trans_enum_variant(ccx: &CrateContext,
@@ -1833,24 +1960,27 @@ fn trans_enum_variant_or_tuple_like_struct(ccx: &CrateContext,
 
     let arena = TypedArena::new();
     let fcx = new_fn_ctxt(ccx, llfndecl, ctor_id, false, result_ty,
-                          param_substs, None, &arena, TranslateItems);
+                          param_substs, None, &arena);
     let bcx = init_function(&fcx, false, result_ty);
 
+    assert!(!fcx.needs_ret_allocas);
+
     let arg_tys = ty::ty_fn_args(ctor_ty);
 
     let arg_datums = create_datums_for_fn_args(&fcx, arg_tys.as_slice());
 
     if !type_is_zero_size(fcx.ccx, result_ty) {
+        let dest = fcx.get_ret_slot(bcx, result_ty, "eret_slot");
         let repr = adt::represent_type(ccx, result_ty);
         for (i, arg_datum) in arg_datums.move_iter().enumerate() {
             let lldestptr = adt::trans_field_ptr(bcx,
                                                  &*repr,
-                                                 fcx.llretptr.get().unwrap(),
+                                                 dest,
                                                  disr,
                                                  i);
             arg_datum.store_to(bcx, lldestptr);
         }
-        adt::trans_set_discr(bcx, &*repr, fcx.llretptr.get().unwrap(), disr);
+        adt::trans_set_discr(bcx, &*repr, dest, disr);
     }
 
     finish_fn(&fcx, bcx, result_ty);
@@ -1932,8 +2062,7 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) {
                                                         llfn,
                                                         &param_substs::empty(),
                                                         item.id,
-                                                        None,
-                                                        TranslateItems);
+                                                        None);
             } else {
                 trans_fn(ccx,
                          &**decl,
@@ -1941,15 +2070,14 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) {
                          llfn,
                          &param_substs::empty(),
                          item.id,
-                         item.attrs.as_slice(),
-                         TranslateItems);
+                         item.attrs.as_slice());
             }
-        } else {
-            // Be sure to travel more than just one layer deep to catch nested
-            // items in blocks and such.
-            let mut v = TransItemVisitor{ ccx: ccx };
-            v.visit_block(&**body, ());
         }
+
+        // Be sure to travel more than just one layer deep to catch nested
+        // items in blocks and such.
+        let mut v = TransItemVisitor{ ccx: ccx };
+        v.visit_block(&**body, ());
       }
       ast::ItemImpl(ref generics, _, _, ref ms) => {
         meth::trans_impl(ccx, item.ident, ms.as_slice(), generics, item.id);
index f186af48321c3d8dd64db0769811eb5e7ca8bfa9..379b53eebbb4f527cdad7f1d8049c61987e5017b 100644 (file)
@@ -334,13 +334,12 @@ pub fn trans_unboxing_shim(bcx: &Block,
     let return_type = ty::ty_fn_ret(boxed_function_type);
     let fcx = new_fn_ctxt(ccx,
                           llfn,
-                          -1,
+                          ast::DUMMY_NODE_ID,
                           false,
                           return_type,
                           &empty_param_substs,
                           None,
-                          &block_arena,
-                          TranslateItems);
+                          &block_arena);
     let mut bcx = init_function(&fcx, false, return_type);
 
     // Create the substituted versions of the self type.
@@ -389,6 +388,11 @@ pub fn trans_unboxing_shim(bcx: &Block,
     for i in range(1, arg_types.len()) {
         llshimmedargs.push(get_param(fcx.llfn, fcx.arg_pos(i) as u32));
     }
+    assert!(!fcx.needs_ret_allocas);
+    let dest = match fcx.llretslotptr.get() {
+        Some(_) => Some(expr::SaveIn(fcx.get_ret_slot(bcx, return_type, "ret_slot"))),
+        None => None
+    };
     bcx = trans_call_inner(bcx,
                            None,
                            function_type,
@@ -399,10 +403,7 @@ pub fn trans_unboxing_shim(bcx: &Block,
                                }
                            },
                            ArgVals(llshimmedargs.as_slice()),
-                           match fcx.llretptr.get() {
-                               None => None,
-                               Some(llretptr) => Some(expr::SaveIn(llretptr)),
-                           }).bcx;
+                           dest).bcx;
 
     bcx = fcx.pop_and_trans_custom_cleanup_scope(bcx, arg_scope);
     finish_fn(&fcx, bcx, return_type);
@@ -758,9 +759,11 @@ pub fn trans_call_inner<'a>(
             assert!(abi == synabi::RustIntrinsic);
             assert!(dest.is_some());
 
+            let call_info = call_info.expect("no call info for intrinsic call?");
             return intrinsic::trans_intrinsic_call(bcx, node, callee_ty,
                                                    arg_cleanup_scope, args,
-                                                   dest.unwrap(), substs);
+                                                   dest.unwrap(), substs,
+                                                   call_info);
         }
         NamedTupleConstructor(substs, disr) => {
             assert!(dest.is_some());
index 98b2ebb70f3cb211c732c68810d8cadb454bd914..44c52a6739ab4de0c8c51d6e1354d2fe1bf62704 100644 (file)
@@ -394,8 +394,7 @@ pub fn trans_expr_fn<'a>(
                   ty::ty_fn_abi(fty),
                   true,
                   NotUnboxedClosure,
-                  |bcx| load_environment(bcx, cdata_ty, &freevars, store),
-                  bcx.fcx.handle_items);
+                  |bcx| load_environment(bcx, cdata_ty, &freevars, store));
     fill_fn_pair(bcx, dest_addr, llfn, llbox);
     bcx
 }
@@ -487,8 +486,7 @@ pub fn trans_unboxed_closure<'a>(
                   ty::ty_fn_abi(function_type),
                   true,
                   IsUnboxedClosure,
-                  |bcx| load_unboxed_closure_environment(bcx, freevars_ptr),
-                  bcx.fcx.handle_items);
+                  |bcx| load_unboxed_closure_environment(bcx, freevars_ptr));
 
     // Don't hoist this to the top of the function. It's perfectly legitimate
     // to have a zero-size unboxed closure (in which case dest will be
@@ -574,16 +572,17 @@ pub fn get_wrapper_for_bare_fn(ccx: &CrateContext,
 
     let arena = TypedArena::new();
     let empty_param_substs = param_substs::empty();
-    let fcx = new_fn_ctxt(ccx, llfn, -1, true, f.sig.output,
-                          &empty_param_substs, None, &arena, TranslateItems);
+    let fcx = new_fn_ctxt(ccx, llfn, ast::DUMMY_NODE_ID, true, f.sig.output,
+                          &empty_param_substs, None, &arena);
     let bcx = init_function(&fcx, true, f.sig.output);
 
     let args = create_datums_for_fn_args(&fcx,
                                          ty::ty_fn_args(closure_ty)
                                             .as_slice());
     let mut llargs = Vec::new();
-    match fcx.llretptr.get() {
+    match fcx.llretslotptr.get() {
         Some(llretptr) => {
+            assert!(!fcx.needs_ret_allocas);
             llargs.push(llretptr);
         }
         None => {}
@@ -591,7 +590,7 @@ pub fn get_wrapper_for_bare_fn(ccx: &CrateContext,
     llargs.extend(args.iter().map(|arg| arg.val));
 
     let retval = Call(bcx, fn_ptr, llargs.as_slice(), None);
-    if type_is_zero_size(ccx, f.sig.output) || fcx.llretptr.get().is_some() {
+    if type_is_zero_size(ccx, f.sig.output) || fcx.llretslotptr.get().is_some() {
         RetVoid(bcx);
     } else {
         Ret(bcx, retval);
index 84f380e862a4d1253ae74b7c53859847029a8bf3..8b36270ee540231d58ce2082da427097b6cd6bc8 100644 (file)
 use llvm::{True, False, Bool};
 use mc = middle::mem_categorization;
 use middle::def;
+use middle::freevars;
 use middle::lang_items::LangItem;
 use middle::subst;
 use middle::subst::Subst;
+use middle::trans::base;
 use middle::trans::build;
 use middle::trans::cleanup;
 use middle::trans::datum;
 use middle::trans::debuginfo;
 use middle::trans::type_::Type;
+use middle::trans::type_of;
 use middle::ty;
 use middle::typeck;
 use util::ppaux::Repr;
@@ -222,12 +225,6 @@ fn substp(&self, tcx: &ty::ctxt, substs: &param_substs) -> T {
 pub type RvalueDatum = datum::Datum<datum::Rvalue>;
 pub type LvalueDatum = datum::Datum<datum::Lvalue>;
 
-#[deriving(Clone, Eq, PartialEq)]
-pub enum HandleItemsFlag {
-    IgnoreItems,
-    TranslateItems,
-}
-
 // Function context.  Every LLVM function we create will have one of
 // these.
 pub struct FunctionContext<'a> {
@@ -240,11 +237,11 @@ pub struct FunctionContext<'a> {
     // The environment argument in a closure.
     pub llenv: Option<ValueRef>,
 
-    // The place to store the return value. If the return type is immediate,
-    // this is an alloca in the function. Otherwise, it's the hidden first
-    // parameter to the function. After function construction, this should
-    // always be Some.
-    pub llretptr: Cell<Option<ValueRef>>,
+    // A pointer to where to store the return value. If the return type is
+    // immediate, this points to an alloca in the function. Otherwise, it's a
+    // pointer to the hidden first parameter of the function. After function
+    // construction, this should always be Some.
+    pub llretslotptr: Cell<Option<ValueRef>>,
 
     // These pub elements: "hoisted basic blocks" containing
     // administrative activities that have to happen in only one place in
@@ -254,13 +251,18 @@ pub struct FunctionContext<'a> {
     pub alloca_insert_pt: Cell<Option<ValueRef>>,
     pub llreturn: Cell<Option<BasicBlockRef>>,
 
+    // If the function has any nested return's, including something like:
+    // fn foo() -> Option<Foo> { Some(Foo { x: return None }) }, then
+    // we use a separate alloca for each return
+    pub needs_ret_allocas: bool,
+
     // The a value alloca'd for calls to upcalls.rust_personality. Used when
     // outputting the resume instruction.
     pub personality: Cell<Option<ValueRef>>,
 
     // True if the caller expects this fn to use the out pointer to
-    // return. Either way, your code should write into llretptr, but if
-    // this value is false, llretptr will be a local alloca.
+    // return. Either way, your code should write into the slot llretslotptr
+    // points to, but if this value is false, that slot will be a local alloca.
     pub caller_expects_out_pointer: bool,
 
     // Maps arguments to allocas created for them in llallocas.
@@ -296,9 +298,6 @@ pub struct FunctionContext<'a> {
 
     // Cleanup scopes.
     pub scopes: RefCell<Vec<cleanup::CleanupScope<'a>> >,
-
-    // How to handle items encountered during translation of this function.
-    pub handle_items: HandleItemsFlag,
 }
 
 impl<'a> FunctionContext<'a> {
@@ -345,6 +344,14 @@ pub fn get_llreturn(&self) -> BasicBlockRef {
         self.llreturn.get().unwrap()
     }
 
+    pub fn get_ret_slot(&self, bcx: &Block, ty: ty::t, name: &str) -> ValueRef {
+        if self.needs_ret_allocas {
+            base::alloca_no_lifetime(bcx, type_of::type_of(bcx.ccx(), ty), name)
+        } else {
+            self.llretslotptr.get().unwrap()
+        }
+    }
+
     pub fn new_block(&'a self,
                      is_lpad: bool,
                      name: &str,
@@ -510,6 +517,11 @@ fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<ast::NodeId> {
     fn upvar_borrow(&self, upvar_id: ty::UpvarId) -> ty::UpvarBorrow {
         self.tcx().upvar_borrow_map.borrow().get_copy(&upvar_id)
     }
+
+    fn capture_mode(&self, closure_expr_id: ast::NodeId)
+                    -> freevars::CaptureMode {
+        self.tcx().capture_modes.borrow().get_copy(&closure_expr_id)
+    }
 }
 
 pub struct Result<'a> {
index 2fd2e69cfc3bcbf31ec72682b5deb2e07a36e56d..a481f92db33916345a1635176feb38926b38d280 100644 (file)
@@ -69,12 +69,8 @@ pub fn trans_stmt<'a>(cx: &'a Block<'a>,
                         debuginfo::create_local_var_metadata(bcx, &**local);
                     }
                 }
-                ast::DeclItem(ref i) => {
-                    match fcx.handle_items {
-                        TranslateItems => trans_item(cx.fcx.ccx, &**i),
-                        IgnoreItems => {}
-                    }
-                }
+                // Inner items are visited by `trans_item`/`trans_meth`.
+                ast::DeclItem(_) => {},
             }
         }
         ast::StmtMac(..) => cx.tcx().sess.bug("unexpanded macro")
@@ -462,13 +458,22 @@ pub fn trans_ret<'a>(bcx: &'a Block<'a>,
     let _icx = push_ctxt("trans_ret");
     let fcx = bcx.fcx;
     let mut bcx = bcx;
-    let dest = match bcx.fcx.llretptr.get() {
-        None => expr::Ignore,
-        Some(retptr) => expr::SaveIn(retptr),
+    let dest = match (fcx.llretslotptr.get(), e) {
+        (Some(_), Some(e)) => {
+            let ret_ty = expr_ty(bcx, &*e);
+            expr::SaveIn(fcx.get_ret_slot(bcx, ret_ty, "ret_slot"))
+        }
+        _ => expr::Ignore,
     };
     match e {
         Some(x) => {
             bcx = expr::trans_into(bcx, &*x, dest);
+            match dest {
+                expr::SaveIn(slot) if fcx.needs_ret_allocas => {
+                    Store(bcx, slot, fcx.llretslotptr.get().unwrap());
+                }
+                _ => {}
+            }
         }
         _ => {}
     }
index c27b0bb8cb1ebeac5eb625248a57800331d4bcfb..ad1c5bf6ef13318bfc2d338b289005d406be164c 100644 (file)
@@ -1150,9 +1150,9 @@ pub fn create_function_debug_context(cx: &CrateContext,
         }
         ast_map::NodeExpr(ref expr) => {
             match expr.node {
-                ast::ExprFnBlock(fn_decl, top_level_block) |
+                ast::ExprFnBlock(_, fn_decl, top_level_block) |
                 ast::ExprProc(fn_decl, top_level_block) |
-                ast::ExprUnboxedFn(fn_decl, top_level_block) => {
+                ast::ExprUnboxedFn(_, fn_decl, top_level_block) => {
                     let name = format!("fn{}", token::gensym("fn"));
                     let name = token::str_to_ident(name.as_slice());
                     (name, fn_decl,
@@ -3618,9 +3618,9 @@ fn walk_expr(cx: &CrateContext,
                 })
             }
 
-            ast::ExprFnBlock(ref decl, ref block) |
+            ast::ExprFnBlock(_, ref decl, ref block) |
             ast::ExprProc(ref decl, ref block) |
-            ast::ExprUnboxedFn(ref decl, ref block) => {
+            ast::ExprUnboxedFn(_, ref decl, ref block) => {
                 with_new_scope(cx,
                                block.span,
                                scope_stack,
index 1dad6e3cb18439684d0ae3301b2e96a0194657a9..7cd2bd631f091666158cd78d8a0b7fb553439ed5 100644 (file)
@@ -782,7 +782,7 @@ fn trans_rvalue_dps_unadjusted<'a>(bcx: &'a Block<'a>,
         ast::ExprVec(..) | ast::ExprRepeat(..) => {
             tvec::trans_fixed_vstore(bcx, expr, expr, dest)
         }
-        ast::ExprFnBlock(ref decl, ref body) |
+        ast::ExprFnBlock(_, ref decl, ref body) |
         ast::ExprProc(ref decl, ref body) => {
             let expr_ty = expr_ty(bcx, expr);
             let store = ty::ty_closure_store(expr_ty);
@@ -790,7 +790,7 @@ fn trans_rvalue_dps_unadjusted<'a>(bcx: &'a Block<'a>,
                    expr_to_string(expr), expr_ty.repr(tcx));
             closure::trans_expr_fn(bcx, store, &**decl, &**body, expr.id, dest)
         }
-        ast::ExprUnboxedFn(decl, body) => {
+        ast::ExprUnboxedFn(_, decl, body) => {
             closure::trans_unboxed_closure(bcx, &*decl, &*body, expr.id, dest)
         }
         ast::ExprCall(ref f, ref args) => {
index 4ca2060ca866d41076fd201e6ec49ef81a47b20f..88bb88da3f043d31117461ef61ea42e89b283fb0 100644 (file)
@@ -577,8 +577,7 @@ pub fn trans_rust_fn_with_foreign_abi(ccx: &CrateContext,
                                       llwrapfn: ValueRef,
                                       param_substs: &param_substs,
                                       id: ast::NodeId,
-                                      hash: Option<&str>,
-                                      handle_items: HandleItemsFlag) {
+                                      hash: Option<&str>) {
     let _icx = push_ctxt("foreign::build_foreign_fn");
 
     let fnty = ty::node_id_to_type(ccx.tcx(), id);
@@ -587,8 +586,7 @@ pub fn trans_rust_fn_with_foreign_abi(ccx: &CrateContext,
 
     unsafe { // unsafe because we call LLVM operations
         // Build up the Rust function (`foo0` above).
-        let llrustfn = build_rust_fn(ccx, decl, body, param_substs, attrs, id,
-                                     hash, handle_items);
+        let llrustfn = build_rust_fn(ccx, decl, body, param_substs, attrs, id, hash);
 
         // Build up the foreign wrapper (`foo` above).
         return build_wrap_fn(ccx, llrustfn, llwrapfn, &tys, mty);
@@ -600,8 +598,7 @@ fn build_rust_fn(ccx: &CrateContext,
                      param_substs: &param_substs,
                      attrs: &[ast::Attribute],
                      id: ast::NodeId,
-                     hash: Option<&str>,
-                     handle_items: HandleItemsFlag)
+                     hash: Option<&str>)
                      -> ValueRef {
         let _icx = push_ctxt("foreign::foreign::build_rust_fn");
         let tcx = ccx.tcx();
@@ -633,7 +630,7 @@ fn build_rust_fn(ccx: &CrateContext,
 
         let llfn = base::decl_internal_rust_fn(ccx, t, ps.as_slice());
         base::set_llvm_fn_attrs(attrs, llfn);
-        base::trans_fn(ccx, decl, body, llfn, param_substs, id, [], handle_items);
+        base::trans_fn(ccx, decl, body, llfn, param_substs, id, []);
         llfn
     }
 
index 40288a33930e5ebdb96131d92b2d24a9490bd1fd..cc7cb16334131831ce80f37a26720cb78520e93e 100644 (file)
@@ -467,8 +467,8 @@ fn make_generic_glue(ccx: &CrateContext,
 
     let arena = TypedArena::new();
     let empty_param_substs = param_substs::empty();
-    let fcx = new_fn_ctxt(ccx, llfn, -1, false, ty::mk_nil(),
-                          &empty_param_substs, None, &arena, TranslateItems);
+    let fcx = new_fn_ctxt(ccx, llfn, ast::DUMMY_NODE_ID, false, ty::mk_nil(),
+                          &empty_param_substs, None, &arena);
 
     let bcx = init_function(&fcx, false, ty::mk_nil());
 
index 877dd647c3b20bb32eb05fd46c96585e7984ca7d..bf39f3a6aa385842d1d2a838aafe61dcbffa9648 100644 (file)
@@ -133,7 +133,7 @@ pub fn maybe_instantiate_inline(ccx: &CrateContext, fn_id: ast::DefId)
           if unparameterized {
               let llfn = get_item_val(ccx, mth.id);
                 trans_fn(ccx, &*mth.pe_fn_decl(), &*mth.pe_body(), llfn,
-                       &param_substs::empty(), mth.id, [], TranslateItems);
+                       &param_substs::empty(), mth.id, []);
           }
           local_def(mth.id)
         }
index fb420a4035d94a25e582f912aa8c385239f592f1..359c8d24f72705c6ef0aa6098400c5680d8d3a38 100644 (file)
@@ -126,7 +126,7 @@ pub fn check_intrinsics(ccx: &CrateContext) {
 pub fn trans_intrinsic_call<'a>(mut bcx: &'a Block<'a>, node: ast::NodeId,
                                 callee_ty: ty::t, cleanup_scope: cleanup::CustomScopeIndex,
                                 args: callee::CallArgs, dest: expr::Dest,
-                                substs: subst::Substs) -> Result<'a> {
+                                substs: subst::Substs, call_info: NodeInfo) -> Result<'a> {
 
     let fcx = bcx.fcx;
     let ccx = fcx.ccx;
@@ -425,6 +425,17 @@ pub fn trans_intrinsic_call<'a>(mut bcx: &'a Block<'a>, node: ast::NodeId,
             with_overflow_intrinsic(bcx, "llvm.umul.with.overflow.i64", ret_ty,
                                     *llargs.get(0), *llargs.get(1)),
 
+        (_, "return_address") => {
+            if !fcx.caller_expects_out_pointer {
+                tcx.sess.span_err(call_info.span,
+                                  "invalid use of `return_address` intrinsic: function \
+                                   does not use out pointer");
+                C_null(Type::i8p(ccx))
+            } else {
+                PointerCast(bcx, llvm::get_param(fcx.llfn, 0), Type::i8p(ccx))
+            }
+        }
+
         // This requires that atomic intrinsics follow a specific naming pattern:
         // "atomic_<operation>[_<ordering>]", and no ordering means SeqCst
         (_, name) if name.starts_with("atomic_") => {
index 7f7b70e075d1d4876fad029c2a521bd05245f399..3578b25c83957edfaade6f1a5a379711255b37d4 100644 (file)
@@ -75,12 +75,10 @@ pub fn trans_impl(ccx: &CrateContext,
                      llfn,
                      &param_substs::empty(),
                      method.id,
-                     [],
-                     TranslateItems);
-        } else {
-            let mut v = TransItemVisitor{ ccx: ccx };
-            visit::walk_method_helper(&mut v, &**method, ());
+                     []);
         }
+        let mut v = TransItemVisitor{ ccx: ccx };
+        visit::walk_method_helper(&mut v, &**method, ());
     }
 }
 
index 070bd89d2896378e71c6c642c011907421a6693e..6d705c7d914e39118788d7d8cad768bb7b1028cf 100644 (file)
@@ -164,10 +164,9 @@ pub fn monomorphic_fn(ccx: &CrateContext,
                   if abi != abi::Rust {
                       foreign::trans_rust_fn_with_foreign_abi(
                           ccx, &**decl, &**body, [], d, &psubsts, fn_id.node,
-                          Some(hash.as_slice()), IgnoreItems);
+                          Some(hash.as_slice()));
                   } else {
-                      trans_fn(ccx, &**decl, &**body, d, &psubsts, fn_id.node, [],
-                               IgnoreItems);
+                      trans_fn(ccx, &**decl, &**body, d, &psubsts, fn_id.node, []);
                   }
 
                   d
@@ -201,8 +200,7 @@ pub fn monomorphic_fn(ccx: &CrateContext,
         ast_map::NodeMethod(mth) => {
             let d = mk_lldecl(abi::Rust);
             set_llvm_fn_attrs(mth.attrs.as_slice(), d);
-            trans_fn(ccx, &*mth.pe_fn_decl(), &*mth.pe_body(), d, &psubsts, mth.id, [],
-                     IgnoreItems);
+            trans_fn(ccx, &*mth.pe_fn_decl(), &*mth.pe_body(), d, &psubsts, mth.id, []);
             d
         }
         ast_map::NodeTraitMethod(method) => {
@@ -211,7 +209,7 @@ pub fn monomorphic_fn(ccx: &CrateContext,
                     let d = mk_lldecl(abi::Rust);
                     set_llvm_fn_attrs(mth.attrs.as_slice(), d);
                     trans_fn(ccx, &*mth.pe_fn_decl(), &*mth.pe_body(), d,
-                             &psubsts, mth.id, [], IgnoreItems);
+                             &psubsts, mth.id, []);
                     d
                 }
                 _ => {
index eb0d77da5519fbc389e4c4376adda48282ca13f3..9caa9f681aadffe42beb6d8b8a03261a45cda3b6 100644 (file)
@@ -310,9 +310,9 @@ pub fn visit_ty(&mut self, t: ty::t) {
                                                     sym.as_slice());
                 let arena = TypedArena::new();
                 let empty_param_substs = param_substs::empty();
-                let fcx = new_fn_ctxt(ccx, llfdecl, -1, false,
+                let fcx = new_fn_ctxt(ccx, llfdecl, ast::DUMMY_NODE_ID, false,
                                       ty::mk_u64(), &empty_param_substs,
-                                      None, &arena, TranslateItems);
+                                      None, &arena);
                 let bcx = init_function(&fcx, false, ty::mk_u64());
 
                 // we know the return type of llfdecl is an int here, so
@@ -321,7 +321,9 @@ pub fn visit_ty(&mut self, t: ty::t) {
                 let arg = get_param(llfdecl, fcx.arg_pos(0u) as c_uint);
                 let arg = BitCast(bcx, arg, llptrty);
                 let ret = adt::trans_get_discr(bcx, &*repr, arg, Some(Type::i64(ccx)));
-                Store(bcx, ret, fcx.llretptr.get().unwrap());
+                assert!(!fcx.needs_ret_allocas);
+                let ret_slot = fcx.get_ret_slot(bcx, ty::mk_u64(), "ret_slot");
+                Store(bcx, ret, ret_slot);
                 match fcx.llreturn.get() {
                     Some(llreturn) => Br(bcx, llreturn),
                     None => {}
index a4588da1bd7dd7361a22669e54bfd057b0036f61..3346b475267b96c953f2fecfb2af3d8082dc4106 100644 (file)
 use middle::const_eval;
 use middle::def;
 use middle::dependency_format;
+use middle::freevars::CaptureModeMap;
+use middle::freevars;
 use middle::lang_items::{FnMutTraitLangItem, OpaqueStructLangItem};
 use middle::lang_items::{TyDescStructLangItem, TyVisitorTraitLangItem};
-use middle::freevars;
 use middle::resolve;
 use middle::resolve_lifetime;
-use middle::subst;
-use middle::subst::{Subst, Substs, VecPerParamSpace};
 use middle::stability;
+use middle::subst::{Subst, Substs, VecPerParamSpace};
+use middle::subst;
 use middle::ty;
 use middle::typeck;
 use middle::typeck::MethodCall;
@@ -384,6 +385,9 @@ pub struct ctxt {
 
     /// Maps any item's def-id to its stability index.
     pub stability: RefCell<stability::Index>,
+
+    /// Maps closures to their capture clauses.
+    pub capture_modes: RefCell<CaptureModeMap>,
 }
 
 pub enum tbox_flag {
@@ -1057,6 +1061,7 @@ pub fn mk_ctxt(s: Session,
                named_region_map: resolve_lifetime::NamedRegionMap,
                map: ast_map::Map,
                freevars: freevars::freevar_map,
+               capture_modes: freevars::CaptureModeMap,
                region_maps: middle::region::RegionMaps,
                lang_items: middle::lang_items::LanguageItems,
                stability: stability::Index)
@@ -1115,7 +1120,8 @@ pub fn mk_ctxt(s: Session,
         unboxed_closure_types: RefCell::new(DefIdMap::new()),
         node_lint_levels: RefCell::new(HashMap::new()),
         transmute_restrictions: RefCell::new(Vec::new()),
-        stability: RefCell::new(stability)
+        stability: RefCell::new(stability),
+        capture_modes: RefCell::new(capture_modes),
     }
 }
 
@@ -4862,6 +4868,11 @@ fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<ast::NodeId> {
     fn upvar_borrow(&self, upvar_id: ty::UpvarId) -> ty::UpvarBorrow {
         self.upvar_borrow_map.borrow().get_copy(&upvar_id)
     }
+
+    fn capture_mode(&self, closure_expr_id: ast::NodeId)
+                    -> freevars::CaptureMode {
+        self.capture_modes.borrow().get_copy(&closure_expr_id)
+    }
 }
 
 /// The category of explicit self.
index 787a4bebc559bd65af2552f5dd76d07958719020..33acb521780080dc58ca6fe9ce426015705b0415 100644 (file)
@@ -3390,7 +3390,7 @@ fn check_fn_for_vec_elements_expected(fcx: &FnCtxt,
       ast::ExprMatch(ref discrim, ref arms) => {
         _match::check_match(fcx, expr, &**discrim, arms.as_slice());
       }
-      ast::ExprFnBlock(ref decl, ref body) => {
+      ast::ExprFnBlock(_, ref decl, ref body) => {
         let region = astconv::opt_ast_region_to_region(fcx,
                                                        fcx.infcx(),
                                                        expr.span,
@@ -3402,7 +3402,7 @@ fn check_fn_for_vec_elements_expected(fcx: &FnCtxt,
                       body.clone(),
                       expected);
       }
-      ast::ExprUnboxedFn(ref decl, ref body) => {
+      ast::ExprUnboxedFn(_, ref decl, ref body) => {
         check_unboxed_closure(fcx,
                               expr,
                               &**decl,
@@ -4986,6 +4986,8 @@ fn param(ccx: &CrateCtxt, n: uint) -> ty::t {
                 (0, vec!(ty::mk_u64(), ty::mk_u64()),
                 ty::mk_tup(tcx, vec!(ty::mk_u64(), ty::mk_bool()))),
 
+            "return_address" => (0, vec![], ty::mk_imm_ptr(tcx, ty::mk_u8())),
+
             ref other => {
                 span_err!(tcx.sess, it.span, E0093,
                     "unrecognized intrinsic function: `{}`", *other);
index d0431de81a359543d4daa30baca6952bacd0024d..47f5c45dde24865f70bccbdc8069268fdfb10892 100644 (file)
@@ -290,6 +290,11 @@ fn temporary_scope(&self, id: ast::NodeId) -> Option<ast::NodeId> {
     fn upvar_borrow(&self, id: ty::UpvarId) -> ty::UpvarBorrow {
         self.fcx.inh.upvar_borrow_map.borrow().get_copy(&id)
     }
+
+    fn capture_mode(&self, closure_expr_id: ast::NodeId)
+                    -> freevars::CaptureMode {
+        self.tcx().capture_modes.borrow().get_copy(&closure_expr_id)
+    }
 }
 
 pub fn regionck_expr(fcx: &FnCtxt, e: &ast::Expr) {
@@ -587,9 +592,9 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
             visit::walk_expr(rcx, expr, ());
         }
 
-        ast::ExprFnBlock(_, ref body) |
+        ast::ExprFnBlock(_, _, ref body) |
         ast::ExprProc(_, ref body) |
-        ast::ExprUnboxedFn(_, ref body) => {
+        ast::ExprUnboxedFn(_, _, ref body) => {
             check_expr_fn_block(rcx, expr, &**body);
         }
 
index d94ac103ceb731ed37f18d15a5e80f5c5c68fcfb..6e6ebd181fbc95bd8917b58c2f19112200fda4e7 100644 (file)
@@ -132,9 +132,9 @@ fn visit_expr(&mut self, e:&ast::Expr, _: ()) {
                                     MethodCall::expr(e.id));
 
         match e.node {
-            ast::ExprFnBlock(ref decl, _) |
+            ast::ExprFnBlock(_, ref decl, _) |
             ast::ExprProc(ref decl, _) |
-            ast::ExprUnboxedFn(ref decl, _) => {
+            ast::ExprUnboxedFn(_, ref decl, _) => {
                 for input in decl.inputs.iter() {
                     let _ = self.visit_node_id(ResolvingExpr(e.span),
                                                input.id);
index 637af96b6321ab23cb2e0521922e89a8e345ff5d..dd00fc62079813c31e3dbc6985ef4709f866f6b8 100644 (file)
@@ -124,12 +124,20 @@ fn test_env(_test_name: &str,
     let lang_items = lang_items::collect_language_items(&krate, &sess);
     let resolve::CrateMap { def_map: def_map, .. } =
         resolve::resolve_crate(&sess, &lang_items, &krate);
-    let freevars_map = freevars::annotate_freevars(&def_map, &krate);
+    let (freevars_map, captures_map) = freevars::annotate_freevars(&def_map,
+                                                                   &krate);
     let named_region_map = resolve_lifetime::krate(&sess, &krate);
     let region_map = region::resolve_crate(&sess, &krate);
     let stability_index = stability::Index::build(&krate);
-    let tcx = ty::mk_ctxt(sess, def_map, named_region_map, ast_map,
-                          freevars_map, region_map, lang_items, stability_index);
+    let tcx = ty::mk_ctxt(sess,
+                          def_map,
+                          named_region_map,
+                          ast_map,
+                          freevars_map,
+                          captures_map,
+                          region_map,
+                          lang_items,
+                          stability_index);
     let infcx = infer::new_infer_ctxt(&tcx);
     let env = Env {krate: krate,
                    tcx: &tcx,
index 6c254b621775cf5d93886a1965d23979991497dc..fb1666bef0d2f467d8757c6b8d6bf244a0e7f596 100644 (file)
@@ -328,7 +328,7 @@ fn acquire_input(input: &str,
 fn parse_externs(matches: &getopts::Matches) -> Result<core::Externs, String> {
     let mut externs = HashMap::new();
     for arg in matches.opt_strs("extern").iter() {
-        let mut parts = arg.as_slice().splitn('=', 1);
+        let mut parts = arg.as_slice().splitn(1, '=');
         let name = match parts.next() {
             Some(s) => s,
             None => {
index 3cc5189c024db7b4a5dcd15f09c6928866bbcfb0..56c0f24509b8ed297800ebdd4fa9d36cd772526e 100644 (file)
@@ -31,6 +31,7 @@
 #![crate_name = "semver"]
 #![deprecated = "This is now a cargo package located at: \
                  https://github.com/rust-lang/semver"]
+#![allow(deprecated)]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![license = "MIT/ASL2"]
index 58d69e38cc6e0fd5d4a96d241a87f21f0627ea7d..51b8985e655a577ba8bbccb760898651b17716a2 100644 (file)
@@ -2800,7 +2800,6 @@ fn check_err<T: Decodable<Decoder, DecoderError>>(to_parse: &'static str,
         }
     }
     #[test]
-    #[ignore] // FIXME(#15763)
     fn test_decode_errors_struct() {
         check_err::<DecodeStruct>("[]", ExpectedError("Object".to_string(), "[]".to_string()));
         check_err::<DecodeStruct>("{\"x\": true, \"y\": true, \"z\": \"\", \"w\": []}",
index e8352dcd40cdc29fcfc9099e4706990de89c85dd..e5f42bd65a30071d21dae7840c6f761cebb8edfe 100644 (file)
@@ -19,7 +19,7 @@
 use iter::Iterator;
 use mem;
 use option::{Option, Some, None};
-use slice::{ImmutableVector, MutableVector, Vector};
+use slice::{ImmutableSlice, MutableSlice, Slice};
 use str::{Str, StrSlice};
 use str;
 use string::String;
index 80fe05fcea5cdf99f1cdc14179c4af21dfd3324d..5f52c0ada5d62d2d4077ab21864a905d839a885d 100644 (file)
@@ -43,7 +43,7 @@
 use ptr::RawPtr;
 use ptr;
 use raw;
-use slice::Vector;
+use slice::Slice;
 
 /// The type representing a foreign chunk of memory
 pub struct CVec<T> {
@@ -145,7 +145,7 @@ pub unsafe fn unwrap(mut self) -> *mut T {
     }
 }
 
-impl<T> Vector<T> for CVec<T> {
+impl<T> Slice<T> for CVec<T> {
     /// View the stored data as a slice.
     fn as_slice<'a>(&'a self) -> &'a [T] {
         unsafe {
index 2de9db1cc93e33ddee3bfd9f5b3f64cc2af27847..b8f8bd41a2d9dacb24121c4376433ac3c1e5eb7c 100644 (file)
@@ -2743,7 +2743,7 @@ mod test_set {
     use prelude::*;
 
     use super::HashSet;
-    use slice::ImmutableEqVector;
+    use slice::ImmutablePartialEqSlice;
     use collections::Collection;
 
     #[test]
index 1ac37458e2493acd1b6f0f95b274187933d7a227..766f92292b1875d5b163bdfa4ef1b89143f61f1a 100644 (file)
@@ -29,7 +29,7 @@
 use os;
 use path::{Path,GenericPath};
 use result::*;
-use slice::{Vector,ImmutableVector};
+use slice::{Slice,ImmutableSlice};
 use str;
 use string::String;
 use vec::Vec;
index 71ec524211824dcad77dc4d52f01ce1a293d5be8..a9b0b33c59ad9ae3b2ef066b0ab8a08c431fab62 100644 (file)
@@ -19,7 +19,7 @@
 use ops::Drop;
 use option::{Some, None, Option};
 use result::{Ok, Err};
-use slice::{ImmutableVector, MutableVector};
+use slice::{ImmutableSlice, MutableSlice};
 use slice;
 use vec::Vec;
 
index cd5887b7add0011d6ebf96cae8caad21019922a6..53b5fbe3894edc099bd9e36ea109b6b4ab76eca9 100644 (file)
@@ -15,7 +15,7 @@
 use io;
 use option::{None, Option, Some};
 use result::{Ok, Err};
-use slice::{bytes, MutableVector, ImmutableVector};
+use slice::{bytes, MutableSlice, ImmutableSlice};
 use str::StrSlice;
 use super::{Reader, Writer, IoResult};
 use vec::Vec;
index 5215aec5dfbfa6e314bd481a22169e3f978cea25..12caa7158658e28693df873b74ab099b4e6505c0 100644 (file)
@@ -21,7 +21,7 @@
 use result::{Ok, Err};
 use io;
 use io::{IoError, IoResult, Reader};
-use slice::{ImmutableVector, Vector};
+use slice::{ImmutableSlice, Slice};
 use ptr::RawPtr;
 
 /// An iterator that reads a single byte on each iteration,
@@ -153,7 +153,7 @@ pub fn u64_to_be_bytes<T>(n: u64, size: uint, f: |v: &[u8]| -> T) -> T {
 pub fn u64_from_be_bytes(data: &[u8], start: uint, size: uint) -> u64 {
     use ptr::{copy_nonoverlapping_memory};
     use mem::from_be64;
-    use slice::MutableVector;
+    use slice::MutableSlice;
 
     assert!(size <= 8u);
 
index 7335511ed857e42781339027bf7a530b7ddd06bd..f95f41509a0f50b9158538476765560b4f265447 100644 (file)
@@ -70,7 +70,7 @@
 use result::{Err, Ok};
 use rt::rtio::LocalIo;
 use rt::rtio;
-use slice::ImmutableVector;
+use slice::ImmutableSlice;
 use string::String;
 use vec::Vec;
 
index 8879f7e25063cb56890d5f57daee1d5cb8717e55..ea9d08171e6cef2794753ab83d141915cd2d0b93 100644 (file)
@@ -19,7 +19,7 @@
 use io;
 use io::{Reader, Writer, Seek, Buffer, IoError, SeekStyle, IoResult};
 use slice;
-use slice::{Vector, ImmutableVector, MutableVector};
+use slice::{Slice, ImmutableSlice, MutableSlice};
 use vec::Vec;
 
 static BUF_CAPACITY: uint = 128;
index d098f9a6479146016bfab81ee7d1c53e82580ca2..c95dd8618ed10a7648e14f8f07939117a3a3d9ad 100644 (file)
@@ -235,7 +235,7 @@ fn file_product(p: &Path) -> IoResult<u32> {
 use boxed::Box;
 use result::{Ok, Err, Result};
 use rt::rtio;
-use slice::{Vector, MutableVector, ImmutableVector};
+use slice::{Slice, MutableSlice, ImmutableSlice};
 use str::{Str, StrSlice};
 use str;
 use string::String;
index 0f864c7be5e274e5a1b754e74bea8e5b6e8d1267..ed76cdc276ba62e8488f284fd2eb98fa2f5fb51c 100644 (file)
@@ -21,7 +21,7 @@
 use iter::Iterator;
 use option::{Option, None, Some};
 use str::StrSlice;
-use slice::{MutableCloneableVector, ImmutableVector, MutableVector};
+use slice::{MutableCloneableSlice, ImmutableSlice, MutableSlice};
 
 pub type Port = u16;
 
index 0b0c22ed88799f3efccb362e12793d42ed6a8d59..7055b9d7a473887c5680905eb889372428f047ca 100644 (file)
 use collections::MutableSeq;
 use io::IoResult;
 use iter::Iterator;
-use slice::ImmutableVector;
+use slice::ImmutableSlice;
 use result::{Ok,Err};
 use io::net::addrinfo::get_host_addresses;
 use io::net::ip::SocketAddr;
 use io::{IoError, ConnectionFailed, InvalidInput};
 use io::{Reader, Writer, Listener, Acceptor};
+use io::{standard_error, TimedOut};
 use from_str::FromStr;
 use kinds::Send;
 use option::{None, Some, Option};
@@ -34,6 +35,7 @@
 use rt::rtio::{IoFactory, LocalIo, RtioSocket, RtioTcpListener};
 use rt::rtio::{RtioTcpAcceptor, RtioTcpStream};
 use rt::rtio;
+use time::Duration;
 
 /// A structure which represents a TCP stream between a local socket and a
 /// remote socket.
@@ -92,7 +94,7 @@ pub fn connect(host: &str, port: u16) -> IoResult<TcpStream> {
     }
 
     /// Creates a TCP connection to a remote socket address, timing out after
-    /// the specified number of milliseconds.
+    /// the specified duration.
     ///
     /// This is the same as the `connect` method, except that if the timeout
     /// specified (in milliseconds) elapses before a connection is made an error
@@ -100,13 +102,20 @@ pub fn connect(host: &str, port: u16) -> IoResult<TcpStream> {
     ///
     /// Note that the `addr` argument may one day be split into a separate host
     /// and port, similar to the API seen in `connect`.
+    ///
+    /// If a `timeout` with zero or negative duration is specified then
+    /// the function returns `Err`, with the error kind set to `TimedOut`.
     #[experimental = "the timeout argument may eventually change types"]
     pub fn connect_timeout(addr: SocketAddr,
-                           timeout_ms: u64) -> IoResult<TcpStream> {
+                           timeout: Duration) -> IoResult<TcpStream> {
+        if timeout <= Duration::milliseconds(0) {
+            return Err(standard_error(TimedOut));
+        }
+
         let SocketAddr { ip, port } = addr;
         let addr = rtio::SocketAddr { ip: super::to_rtio(ip), port: port };
         LocalIo::maybe_raise(|io| {
-            io.tcp_connect(addr, Some(timeout_ms)).map(TcpStream::new)
+            io.tcp_connect(addr, Some(timeout.num_milliseconds() as u64)).map(TcpStream::new)
         }).map_err(IoError::from_rtio_error)
     }
 
@@ -164,13 +173,14 @@ pub fn set_keepalive(&mut self, delay_in_seconds: Option<uint>) -> IoResult<()>
     /// # #![allow(unused_must_use)]
     /// use std::io::timer;
     /// use std::io::TcpStream;
+    /// use std::time::Duration;
     ///
     /// let mut stream = TcpStream::connect("127.0.0.1", 34254).unwrap();
     /// let stream2 = stream.clone();
     ///
     /// spawn(proc() {
     ///     // close this stream after one second
-    ///     timer::sleep(1000);
+    ///     timer::sleep(Duration::seconds(1));
     ///     let mut stream = stream2;
     ///     stream.close_read();
     /// });
index 5e7c421497772faa7f7244326a6a238c3ee10b4e..d88af8dd30aa36ae4e0df1e75a820a923d87ed89 100644 (file)
 use c_str::ToCStr;
 use clone::Clone;
 use io::{Listener, Acceptor, Reader, Writer, IoResult, IoError};
+use io::{standard_error, TimedOut};
 use kinds::Send;
 use boxed::Box;
 use rt::rtio::{IoFactory, LocalIo, RtioUnixListener};
 use rt::rtio::{RtioUnixAcceptor, RtioPipe};
+use time::Duration;
 
 /// A stream which communicates over a named pipe.
 pub struct UnixStream {
@@ -66,11 +68,18 @@ pub fn connect<P: ToCStr>(path: &P) -> IoResult<UnixStream> {
     ///
     /// This function is similar to `connect`, except that if `timeout_ms`
     /// elapses the function will return an error of kind `TimedOut`.
+    ///
+    /// If a `timeout` with zero or negative duration is specified then
+    /// the function returns `Err`, with the error kind set to `TimedOut`.
     #[experimental = "the timeout argument is likely to change types"]
     pub fn connect_timeout<P: ToCStr>(path: &P,
-                                      timeout_ms: u64) -> IoResult<UnixStream> {
+                                      timeout: Duration) -> IoResult<UnixStream> {
+        if timeout <= Duration::milliseconds(0) {
+            return Err(standard_error(TimedOut));
+        }
+
         LocalIo::maybe_raise(|io| {
-            let s = io.unix_connect(&path.to_c_str(), Some(timeout_ms));
+            let s = io.unix_connect(&path.to_c_str(), Some(timeout.num_milliseconds() as u64));
             s.map(|p| UnixStream { obj: p })
         }).map_err(IoError::from_rtio_error)
     }
@@ -499,13 +508,25 @@ pub fn smalltest(server: proc(UnixStream):Send, client: proc(UnixStream):Send) {
 
     iotest!(fn connect_timeout_error() {
         let addr = next_test_unix();
-        assert!(UnixStream::connect_timeout(&addr, 100).is_err());
+        assert!(UnixStream::connect_timeout(&addr, Duration::milliseconds(100)).is_err());
     })
 
     iotest!(fn connect_timeout_success() {
         let addr = next_test_unix();
         let _a = UnixListener::bind(&addr).unwrap().listen().unwrap();
-        assert!(UnixStream::connect_timeout(&addr, 100).is_ok());
+        assert!(UnixStream::connect_timeout(&addr, Duration::milliseconds(100)).is_ok());
+    })
+
+    iotest!(fn connect_timeout_zero() {
+        let addr = next_test_unix();
+        let _a = UnixListener::bind(&addr).unwrap().listen().unwrap();
+        assert!(UnixStream::connect_timeout(&addr, Duration::milliseconds(0)).is_err());
+    })
+
+    iotest!(fn connect_timeout_negative() {
+        let addr = next_test_unix();
+        let _a = UnixListener::bind(&addr).unwrap().listen().unwrap();
+        assert!(UnixStream::connect_timeout(&addr, Duration::milliseconds(-1)).is_err());
     })
 
     iotest!(fn close_readwrite_smoke() {
index 1eee69834948fb24db130a6550d8f9acdef6d6a1..3dd4343c5f4fcd4070f05f720ec91f45ac0fc468 100644 (file)
@@ -378,7 +378,8 @@ pub enum StdioContainer {
     Ignored,
 
     /// The specified file descriptor is inherited for the stream which it is
-    /// specified for.
+    /// specified for. Ownership of the file descriptor is *not* taken, so the
+    /// caller must clean it up.
     InheritFd(libc::c_int),
 
     /// Creates a pipe for the specified file descriptor which will be created
@@ -605,6 +606,7 @@ fn drop(&mut self) {
 
 #[cfg(test)]
 mod tests {
+    extern crate native;
     use io::process::{Command, Process};
     use prelude::*;
 
@@ -974,7 +976,7 @@ pub fn sleeper() -> Process {
                 assert!(!p.wait().unwrap().success());
                 return
             }
-            timer::sleep(100);
+            timer::sleep(Duration::milliseconds(100));
         }
         fail!("never saw the child go away");
     })
@@ -1017,4 +1019,25 @@ pub fn sleeper() -> Process {
         assert!(Process::kill(id, 0).is_ok());
         assert!(Process::kill(id, PleaseExitSignal).is_ok());
     })
+
+    iotest!(fn dont_close_fd_on_command_spawn() {
+        use std::rt::rtio::{Truncate, Write};
+        use native::io::file;
+
+        let path = if cfg!(windows) {
+            Path::new("NUL")
+        } else {
+            Path::new("/dev/null")
+        };
+
+        let mut fdes = match file::open(&path.to_c_str(), Truncate, Write) {
+            Ok(f) => f,
+            Err(_) => fail!("failed to open file descriptor"),
+        };
+
+        let mut cmd = pwd_cmd();
+        let _ = cmd.stdout(InheritFd(fdes.fd()));
+        assert!(cmd.status().unwrap().success());
+        assert!(fdes.inner_write("extra write\n".as_bytes()).is_ok());
+    })
 }
index c126866e7159ae67f1d33f84af6bbd25923912df..1d882bdc0ad9e0fddd53ff318921029f8c43f265 100644 (file)
@@ -30,7 +30,7 @@
 use boxed::Box;
 use result::{Ok, Err};
 use rt::rtio::{IoFactory, LocalIo, RtioSignal, Callback};
-use slice::ImmutableVector;
+use slice::ImmutableSlice;
 use vec::Vec;
 
 /// Signals that can be sent and received
@@ -167,6 +167,7 @@ mod test_unix {
     use comm::Empty;
     use io::timer;
     use super::{Listener, Interrupt};
+    use time::Duration;
 
     fn sigint() {
         unsafe {
@@ -179,7 +180,7 @@ fn test_io_signal_smoketest() {
         let mut signal = Listener::new();
         signal.register(Interrupt).unwrap();
         sigint();
-        timer::sleep(10);
+        timer::sleep(Duration::milliseconds(10));
         match signal.rx.recv() {
             Interrupt => (),
             s => fail!("Expected Interrupt, got {:?}", s),
@@ -193,7 +194,7 @@ fn test_io_signal_two_signal_one_signum() {
         s1.register(Interrupt).unwrap();
         s2.register(Interrupt).unwrap();
         sigint();
-        timer::sleep(10);
+        timer::sleep(Duration::milliseconds(10));
         match s1.rx.recv() {
             Interrupt => (),
             s => fail!("Expected Interrupt, got {:?}", s),
@@ -212,7 +213,7 @@ fn test_io_signal_unregister() {
         s2.register(Interrupt).unwrap();
         s2.unregister(Interrupt);
         sigint();
-        timer::sleep(10);
+        timer::sleep(Duration::milliseconds(10));
         assert_eq!(s2.rx.try_recv(), Err(Empty));
     }
 }
index 5b33c3671b48849a561fd70a7c272119415a45d9..fea161c426a2e1a15a22fc5876fc052cd99cab16 100644 (file)
@@ -41,7 +41,7 @@
 use rt::local::Local;
 use rt::task::Task;
 use rt::rtio::{DontClose, IoFactory, LocalIo, RtioFileStream, RtioTTY};
-use slice::ImmutableVector;
+use slice::ImmutableSlice;
 use str::StrSlice;
 use uint;
 
index 331cfa1a59ef9e5de8570c9cbf042f764533006b..079a9aef648aa77e7480eaf57bbfbe1d80c7959d 100644 (file)
@@ -39,6 +39,7 @@ mod $name {
             use io::process::*;
             use rt::running_on_valgrind;
             use str;
+            use time::Duration;
 
             fn f() $b
 
index 1c9e428dcad82e897897ddcc4f40ba6c2c3a913b..39c6c74e45eef62c59028409b2f1875bd3d0d449 100644 (file)
 
 */
 
+// FIXME: These functions take Durations but only pass ms to the backend impls.
+
 use comm::{Receiver, Sender, channel};
+use time::Duration;
 use io::{IoResult, IoError};
 use kinds::Send;
 use boxed::Box;
 /// # fn main() {}
 /// # fn foo() {
 /// use std::io::Timer;
+/// use std::time::Duration;
 ///
 /// let mut timer = Timer::new().unwrap();
-/// timer.sleep(10); // block the task for awhile
+/// timer.sleep(Duration::milliseconds(10)); // block the task for awhile
 ///
-/// let timeout = timer.oneshot(10);
+/// let timeout = timer.oneshot(Duration::milliseconds(10));
 /// // do some work
 /// timeout.recv(); // wait for the timeout to expire
 ///
-/// let periodic = timer.periodic(10);
+/// let periodic = timer.periodic(Duration::milliseconds(10));
 /// loop {
 ///     periodic.recv();
 ///     // this loop is only executed once every 10ms
 /// # fn main() {}
 /// # fn foo() {
 /// use std::io::timer;
+/// use std::time::Duration;
 ///
 /// // Put this task to sleep for 5 seconds
-/// timer::sleep(5000);
+/// timer::sleep(Duration::seconds(5));
 /// # }
 /// ```
 pub struct Timer {
@@ -69,12 +74,15 @@ pub struct Timer {
 
 struct TimerCallback { tx: Sender<()> }
 
-/// Sleep the current task for `msecs` milliseconds.
-pub fn sleep(msecs: u64) {
+/// Sleep the current task for the specified duration.
+///
+/// When provided a zero or negative `duration`, the function will
+/// return immediately.
+pub fn sleep(duration: Duration) {
     let timer = Timer::new();
     let mut timer = timer.ok().expect("timer::sleep: could not create a Timer");
 
-    timer.sleep(msecs)
+    timer.sleep(duration)
 }
 
 impl Timer {
@@ -87,16 +95,22 @@ pub fn new() -> IoResult<Timer> {
         }).map_err(IoError::from_rtio_error)
     }
 
-    /// Blocks the current task for `msecs` milliseconds.
+    /// Blocks the current task for the specified duration.
     ///
     /// Note that this function will cause any other receivers for this timer to
     /// be invalidated (the other end will be closed).
-    pub fn sleep(&mut self, msecs: u64) {
-        self.obj.sleep(msecs);
+    ///
+    /// When provided a zero or negative `duration`, the function will
+    /// return immediately.
+    pub fn sleep(&mut self, duration: Duration) {
+        // Short-circuit the timer backend for 0 duration
+        let ms = in_ms_u64(duration);
+        if ms == 0 { return }
+        self.obj.sleep(ms);
     }
 
     /// Creates a oneshot receiver which will have a notification sent when
-    /// `msecs` milliseconds has elapsed.
+    /// the specified duration has elapsed.
     ///
     /// This does *not* block the current task, but instead returns immediately.
     ///
@@ -111,9 +125,10 @@ pub fn sleep(&mut self, msecs: u64) {
     ///
     /// ```rust
     /// use std::io::Timer;
+    /// use std::time::Duration;
     ///
     /// let mut timer = Timer::new().unwrap();
-    /// let ten_milliseconds = timer.oneshot(10);
+    /// let ten_milliseconds = timer.oneshot(Duration::milliseconds(10));
     ///
     /// for _ in range(0u, 100) { /* do work */ }
     ///
@@ -123,24 +138,33 @@ pub fn sleep(&mut self, msecs: u64) {
     ///
     /// ```rust
     /// use std::io::Timer;
+    /// use std::time::Duration;
     ///
     /// // Incorrect, method chaining-style:
-    /// let mut five_ms = Timer::new().unwrap().oneshot(5);
+    /// let mut five_ms = Timer::new().unwrap().oneshot(Duration::milliseconds(5));
     /// // The timer object was destroyed, so this will always fail:
     /// // five_ms.recv()
     /// ```
-    pub fn oneshot(&mut self, msecs: u64) -> Receiver<()> {
+    ///
+    /// When provided a zero or negative `duration`, the message will
+    /// be sent immediately.
+    pub fn oneshot(&mut self, duration: Duration) -> Receiver<()> {
         let (tx, rx) = channel();
-        self.obj.oneshot(msecs, box TimerCallback { tx: tx });
+        // Short-circuit the timer backend for 0 duration
+        if in_ms_u64(duration) != 0 {
+            self.obj.oneshot(in_ms_u64(duration), box TimerCallback { tx: tx });
+        } else {
+            tx.send(());
+        }
         return rx
     }
 
     /// Creates a receiver which will have a continuous stream of notifications
-    /// being sent every `msecs` milliseconds.
+    /// being sent each time the specified duration has elapsed.
     ///
     /// This does *not* block the current task, but instead returns
     /// immediately. The first notification will not be received immediately,
-    /// but rather after `msec` milliseconds have passed.
+    /// but rather after the first duration.
     ///
     /// Note that this invalidates any previous receiver which has been created
     /// by this timer, and that the returned receiver will be invalidated once
@@ -153,9 +177,10 @@ pub fn oneshot(&mut self, msecs: u64) -> Receiver<()> {
     ///
     /// ```rust
     /// use std::io::Timer;
+    /// use std::time::Duration;
     ///
     /// let mut timer = Timer::new().unwrap();
-    /// let ten_milliseconds = timer.periodic(10);
+    /// let ten_milliseconds = timer.periodic(Duration::milliseconds(10));
     ///
     /// for _ in range(0u, 100) { /* do work */ }
     ///
@@ -171,15 +196,24 @@ pub fn oneshot(&mut self, msecs: u64) -> Receiver<()> {
     ///
     /// ```rust
     /// use std::io::Timer;
+    /// use std::time::Duration;
     ///
     /// // Incorrect, method chaining-style.
-    /// let mut five_ms = Timer::new().unwrap().periodic(5);
+    /// let mut five_ms = Timer::new().unwrap().periodic(Duration::milliseconds(5));
     /// // The timer object was destroyed, so this will always fail:
     /// // five_ms.recv()
     /// ```
-    pub fn periodic(&mut self, msecs: u64) -> Receiver<()> {
+    ///
+    /// When provided a zero or negative `duration`, the messages will
+    /// be sent without delay.
+    pub fn periodic(&mut self, duration: Duration) -> Receiver<()> {
+        let ms = in_ms_u64(duration);
+        // FIXME: The backend implementations don't ever send a message
+        // if given a 0 ms duration. Temporarily using 1ms. It's
+        // not clear what use a 0ms period is anyway...
+        let ms = if ms == 0 { 1 } else { ms };
         let (tx, rx) = channel();
-        self.obj.period(msecs, box TimerCallback { tx: tx });
+        self.obj.period(ms, box TimerCallback { tx: tx });
         return rx
     }
 }
@@ -190,42 +224,48 @@ fn call(&mut self) {
     }
 }
 
+fn in_ms_u64(d: Duration) -> u64 {
+    let ms = d.num_milliseconds();
+    if ms < 0 { return 0 };
+    return ms as u64;
+}
+
 #[cfg(test)]
 mod test {
     iotest!(fn test_io_timer_sleep_simple() {
         let mut timer = Timer::new().unwrap();
-        timer.sleep(1);
+        timer.sleep(Duration::milliseconds(1));
     })
 
     iotest!(fn test_io_timer_sleep_oneshot() {
         let mut timer = Timer::new().unwrap();
-        timer.oneshot(1).recv();
+        timer.oneshot(Duration::milliseconds(1)).recv();
     })
 
     iotest!(fn test_io_timer_sleep_oneshot_forget() {
         let mut timer = Timer::new().unwrap();
-        timer.oneshot(100000000000);
+        timer.oneshot(Duration::milliseconds(100000000));
     })
 
     iotest!(fn oneshot_twice() {
         let mut timer = Timer::new().unwrap();
-        let rx1 = timer.oneshot(10000);
-        let rx = timer.oneshot(1);
+        let rx1 = timer.oneshot(Duration::milliseconds(10000));
+        let rx = timer.oneshot(Duration::milliseconds(1));
         rx.recv();
         assert_eq!(rx1.recv_opt(), Err(()));
     })
 
     iotest!(fn test_io_timer_oneshot_then_sleep() {
         let mut timer = Timer::new().unwrap();
-        let rx = timer.oneshot(100000000000);
-        timer.sleep(1); // this should invalidate rx
+        let rx = timer.oneshot(Duration::milliseconds(100000000));
+        timer.sleep(Duration::milliseconds(1)); // this should invalidate rx
 
         assert_eq!(rx.recv_opt(), Err(()));
     })
 
     iotest!(fn test_io_timer_sleep_periodic() {
         let mut timer = Timer::new().unwrap();
-        let rx = timer.periodic(1);
+        let rx = timer.periodic(Duration::milliseconds(1));
         rx.recv();
         rx.recv();
         rx.recv();
@@ -233,60 +273,60 @@ mod test {
 
     iotest!(fn test_io_timer_sleep_periodic_forget() {
         let mut timer = Timer::new().unwrap();
-        timer.periodic(100000000000);
+        timer.periodic(Duration::milliseconds(100000000));
     })
 
     iotest!(fn test_io_timer_sleep_standalone() {
-        sleep(1)
+        sleep(Duration::milliseconds(1))
     })
 
     iotest!(fn oneshot() {
         let mut timer = Timer::new().unwrap();
 
-        let rx = timer.oneshot(1);
+        let rx = timer.oneshot(Duration::milliseconds(1));
         rx.recv();
         assert!(rx.recv_opt().is_err());
 
-        let rx = timer.oneshot(1);
+        let rx = timer.oneshot(Duration::milliseconds(1));
         rx.recv();
         assert!(rx.recv_opt().is_err());
     })
 
     iotest!(fn override() {
         let mut timer = Timer::new().unwrap();
-        let orx = timer.oneshot(100);
-        let prx = timer.periodic(100);
-        timer.sleep(1);
+        let orx = timer.oneshot(Duration::milliseconds(100));
+        let prx = timer.periodic(Duration::milliseconds(100));
+        timer.sleep(Duration::milliseconds(1));
         assert_eq!(orx.recv_opt(), Err(()));
         assert_eq!(prx.recv_opt(), Err(()));
-        timer.oneshot(1).recv();
+        timer.oneshot(Duration::milliseconds(1)).recv();
     })
 
     iotest!(fn period() {
         let mut timer = Timer::new().unwrap();
-        let rx = timer.periodic(1);
+        let rx = timer.periodic(Duration::milliseconds(1));
         rx.recv();
         rx.recv();
-        let rx2 = timer.periodic(1);
+        let rx2 = timer.periodic(Duration::milliseconds(1));
         rx2.recv();
         rx2.recv();
     })
 
     iotest!(fn sleep() {
         let mut timer = Timer::new().unwrap();
-        timer.sleep(1);
-        timer.sleep(1);
+        timer.sleep(Duration::milliseconds(1));
+        timer.sleep(Duration::milliseconds(1));
     })
 
     iotest!(fn oneshot_fail() {
         let mut timer = Timer::new().unwrap();
-        let _rx = timer.oneshot(1);
+        let _rx = timer.oneshot(Duration::milliseconds(1));
         fail!();
     } #[should_fail])
 
     iotest!(fn period_fail() {
         let mut timer = Timer::new().unwrap();
-        let _rx = timer.periodic(1);
+        let _rx = timer.periodic(Duration::milliseconds(1));
         fail!();
     } #[should_fail])
 
@@ -298,7 +338,7 @@ mod test {
     iotest!(fn closing_channel_during_drop_doesnt_kill_everything() {
         // see issue #10375
         let mut timer = Timer::new().unwrap();
-        let timer_rx = timer.periodic(1000);
+        let timer_rx = timer.periodic(Duration::milliseconds(1000));
 
         spawn(proc() {
             let _ = timer_rx.recv_opt();
@@ -311,31 +351,31 @@ mod test {
     iotest!(fn reset_doesnt_switch_tasks() {
         // similar test to the one above.
         let mut timer = Timer::new().unwrap();
-        let timer_rx = timer.periodic(1000);
+        let timer_rx = timer.periodic(Duration::milliseconds(1000));
 
         spawn(proc() {
             let _ = timer_rx.recv_opt();
         });
 
-        timer.oneshot(1);
+        timer.oneshot(Duration::milliseconds(1));
     })
 
     iotest!(fn reset_doesnt_switch_tasks2() {
         // similar test to the one above.
         let mut timer = Timer::new().unwrap();
-        let timer_rx = timer.periodic(1000);
+        let timer_rx = timer.periodic(Duration::milliseconds(1000));
 
         spawn(proc() {
             let _ = timer_rx.recv_opt();
         });
 
-        timer.sleep(1);
+        timer.sleep(Duration::milliseconds(1));
     })
 
     iotest!(fn sender_goes_away_oneshot() {
         let rx = {
             let mut timer = Timer::new().unwrap();
-            timer.oneshot(1000)
+            timer.oneshot(Duration::milliseconds(1000))
         };
         assert_eq!(rx.recv_opt(), Err(()));
     })
@@ -343,26 +383,67 @@ mod test {
     iotest!(fn sender_goes_away_period() {
         let rx = {
             let mut timer = Timer::new().unwrap();
-            timer.periodic(1000)
+            timer.periodic(Duration::milliseconds(1000))
         };
         assert_eq!(rx.recv_opt(), Err(()));
     })
 
     iotest!(fn receiver_goes_away_oneshot() {
         let mut timer1 = Timer::new().unwrap();
-        timer1.oneshot(1);
+        timer1.oneshot(Duration::milliseconds(1));
         let mut timer2 = Timer::new().unwrap();
         // while sleeping, the previous timer should fire and not have its
         // callback do something terrible.
-        timer2.sleep(2);
+        timer2.sleep(Duration::milliseconds(2));
     })
 
     iotest!(fn receiver_goes_away_period() {
         let mut timer1 = Timer::new().unwrap();
-        timer1.periodic(1);
+        timer1.periodic(Duration::milliseconds(1));
         let mut timer2 = Timer::new().unwrap();
         // while sleeping, the previous timer should fire and not have its
         // callback do something terrible.
-        timer2.sleep(2);
+        timer2.sleep(Duration::milliseconds(2));
+    })
+
+    iotest!(fn sleep_zero() {
+        let mut timer = Timer::new().unwrap();
+        timer.sleep(Duration::milliseconds(0));
+    })
+
+    iotest!(fn sleep_negative() {
+        let mut timer = Timer::new().unwrap();
+        timer.sleep(Duration::milliseconds(-1000000));
+    })
+
+    iotest!(fn oneshot_zero() {
+        let mut timer = Timer::new().unwrap();
+        let rx = timer.oneshot(Duration::milliseconds(0));
+        rx.recv();
+    })
+
+    iotest!(fn oneshot_negative() {
+        let mut timer = Timer::new().unwrap();
+        let rx = timer.oneshot(Duration::milliseconds(-1000000));
+        rx.recv();
+    })
+
+    iotest!(fn periodic_zero() {
+        let mut timer = Timer::new().unwrap();
+        let rx = timer.periodic(Duration::milliseconds(0));
+        rx.recv();
+        rx.recv();
+        rx.recv();
+        rx.recv();
     })
+
+    iotest!(fn periodic_negative() {
+        let mut timer = Timer::new().unwrap();
+        let rx = timer.periodic(Duration::milliseconds(-1000000));
+        rx.recv();
+        rx.recv();
+        rx.recv();
+        rx.recv();
+    })
+
 }
index 20fc7efeb574f15d4a7a0884286e082dc1504d8e..103cd574e7381d0634b842b30c780cc02d5b2b88 100644 (file)
@@ -233,6 +233,8 @@ fn start(argc: int, argv: *const *const u8) -> int {
 #[cfg(not(test))]
 pub mod gc;
 
+pub mod time;
+
 /* Common traits */
 
 pub mod from_str;
index 9b97513935c80dc87e5d6fdabe48a7d475649264..f5b2f31a127d603f25fc09ea5d8513e885d3380a 100644 (file)
@@ -17,7 +17,7 @@
 use num::{ToStrRadix, FromStrRadix};
 use num::strconv;
 use option::Option;
-use slice::ImmutableVector;
+use slice::ImmutableSlice;
 use string::String;
 
 pub use core::i16::{BITS, BYTES, MIN, MAX};
index 03dcbb0f6d671927aec39d3e0c3cd6941c788b5c..623a10725c826387d8c942b9c0f79efd3e416658 100644 (file)
@@ -17,7 +17,7 @@
 use num::{ToStrRadix, FromStrRadix};
 use num::strconv;
 use option::Option;
-use slice::ImmutableVector;
+use slice::ImmutableSlice;
 use string::String;
 
 pub use core::i32::{BITS, BYTES, MIN, MAX};
index 347b5b4b93ce7f6a14d1ed51b6a1df26f7bd8dfc..ffb1307908c90821941ee8721d7a7ed8c20989f2 100644 (file)
@@ -17,7 +17,7 @@
 use num::{ToStrRadix, FromStrRadix};
 use num::strconv;
 use option::Option;
-use slice::ImmutableVector;
+use slice::ImmutableSlice;
 use string::String;
 
 pub use core::i64::{BITS, BYTES, MIN, MAX};
index fd6f96a0f97be8a9b6b16c24331bcdf69c0cd1d1..4fbb7381238dc77569a6a05aafd84e20d1f9ac45 100644 (file)
@@ -17,7 +17,7 @@
 use num::{ToStrRadix, FromStrRadix};
 use num::strconv;
 use option::Option;
-use slice::ImmutableVector;
+use slice::ImmutableSlice;
 use string::String;
 
 pub use core::i8::{BITS, BYTES, MIN, MAX};
index 1888d6a519e398e727f157a8740fd3970a52387f..7821306f5fc3da122ee4d2f4d027a6920272b1c8 100644 (file)
@@ -17,7 +17,7 @@
 use num::{ToStrRadix, FromStrRadix};
 use num::strconv;
 use option::Option;
-use slice::ImmutableVector;
+use slice::ImmutableSlice;
 use string::String;
 
 pub use core::int::{BITS, BYTES, MIN, MAX};
index 37378518dc8e123b98688ab042bb73734dd94462..407c8ea61d9146eeef1b061eb3ac96d6871586cd 100644 (file)
@@ -20,7 +20,7 @@
 use num;
 use ops::{Add, Sub, Mul, Div, Rem, Neg};
 use option::{None, Option, Some};
-use slice::{ImmutableVector, MutableVector};
+use slice::{ImmutableSlice, MutableSlice};
 use std::cmp::{PartialOrd, PartialEq};
 use str::StrSlice;
 use string::String;
index 727d756106276acb409bbf6551247ace868109fd..0f00f99e980a2a6c387555fd8ca36bbb7b3cdd33 100644 (file)
@@ -17,7 +17,7 @@
 use num::{ToStrRadix, FromStrRadix};
 use num::strconv;
 use option::Option;
-use slice::ImmutableVector;
+use slice::ImmutableSlice;
 use string::String;
 
 pub use core::u16::{BITS, BYTES, MIN, MAX};
index d18bfdf9fbac0e110330f9acefca44fed673fae6..e6c6bc377b7aa304d51cb468c93f06ac091b6768 100644 (file)
@@ -17,7 +17,7 @@
 use num::{ToStrRadix, FromStrRadix};
 use num::strconv;
 use option::Option;
-use slice::ImmutableVector;
+use slice::ImmutableSlice;
 use string::String;
 
 pub use core::u32::{BITS, BYTES, MIN, MAX};
index 53e88a96f332d0ce1fe944474289cafda2a71f35..7eb9e1a082fe872abb009e326cc94657d7048a41 100644 (file)
@@ -17,7 +17,7 @@
 use num::{ToStrRadix, FromStrRadix};
 use num::strconv;
 use option::Option;
-use slice::ImmutableVector;
+use slice::ImmutableSlice;
 use string::String;
 
 pub use core::u64::{BITS, BYTES, MIN, MAX};
index e6cbd14bf417ddf9bd57b78c8aa1ac6dce6751f8..300dd3bcc01a4cfc69f2f7965bb0f614a024f7ec 100644 (file)
@@ -17,7 +17,7 @@
 use num::{ToStrRadix, FromStrRadix};
 use num::strconv;
 use option::Option;
-use slice::ImmutableVector;
+use slice::ImmutableSlice;
 use string::String;
 
 pub use core::u8::{BITS, BYTES, MIN, MAX};
index 41c4caf4006f1403e88fb7d655429698253a9df2..0adc22e321406ebdce3ef58c05d77dec808c8521 100644 (file)
@@ -17,7 +17,7 @@
 use num::{ToStrRadix, FromStrRadix};
 use num::strconv;
 use option::Option;
-use slice::ImmutableVector;
+use slice::ImmutableSlice;
 use string::String;
 
 pub use core::uint::{BITS, BYTES, MIN, MAX};
index 85445e49139352e706f437ca5309af01d20bcfe8..6a00368f9a21ec506e522f60ff3f5837cd37eaaa 100644 (file)
@@ -45,7 +45,7 @@
 use ptr::RawPtr;
 use ptr;
 use result::{Err, Ok, Result};
-use slice::{Vector, ImmutableVector, MutableVector, ImmutableEqVector};
+use slice::{Slice, ImmutableSlice, MutableSlice, ImmutablePartialEqSlice};
 use str::{Str, StrSlice, StrAllocating};
 use string::String;
 use sync::atomic::{AtomicInt, INIT_ATOMIC_INT, SeqCst};
@@ -145,7 +145,7 @@ pub mod win32 {
     use option::{None, Option};
     use option;
     use os::TMPBUF_SZ;
-    use slice::{MutableVector, ImmutableVector};
+    use slice::{MutableSlice, ImmutableSlice};
     use string::String;
     use str::StrSlice;
     use vec::Vec;
index d290a5f8c63c758d12113b5ddf923e844f118838..d24c2e2266d4c68ae5165be33821b77612692fab 100644 (file)
@@ -74,8 +74,8 @@
 use str;
 use str::{MaybeOwned, Str, StrSlice};
 use string::String;
-use slice::Vector;
-use slice::{ImmutableEqVector, ImmutableVector};
+use slice::Slice;
+use slice::{ImmutablePartialEqSlice, ImmutableSlice};
 use vec::Vec;
 
 /// Typedef for POSIX file paths.
index 9a4bc11f5c03a8fd78eef3204c11e497d8937561..0a7817c3e0047dd71c73d79b03f288e18e5cf95c 100644 (file)
@@ -21,8 +21,8 @@
 use option::{Option, None, Some};
 use str::Str;
 use str;
-use slice::{CloneableVector, Splits, Vector, VectorVector,
-            ImmutableEqVector, ImmutableVector};
+use slice::{CloneableVector, Splits, Slice, VectorVector,
+            ImmutablePartialEqSlice, ImmutableSlice};
 use vec::Vec;
 
 use super::{BytesContainer, GenericPath, GenericPathUnsafe};
@@ -367,7 +367,7 @@ pub fn new_opt<T: BytesContainer>(path: T) -> Option<Path> {
 
     /// Returns a normalized byte vector representation of a path, by removing all empty
     /// components, and unnecessary . and .. components.
-    fn normalize<V: Vector<u8>+CloneableVector<u8>>(v: V) -> Vec<u8> {
+    fn normalize<V: Slice<u8>+CloneableVector<u8>>(v: V) -> Vec<u8> {
         // borrowck is being very picky
         let val = {
             let is_abs = !v.as_slice().is_empty() && v.as_slice()[0] == SEP_BYTE;
index c3a217bf940f3a3b716b0e4cb6f89f3a4d103fb3..8402d751bf2c81f54d1e5cfee784325ee1dd4cc8 100644 (file)
@@ -23,7 +23,7 @@
 use iter::{AdditiveIterator, DoubleEndedIterator, Extendable, Iterator, Map};
 use mem;
 use option::{Option, Some, None};
-use slice::{Vector, ImmutableVector};
+use slice::{Slice, ImmutableSlice};
 use str::{CharSplits, Str, StrAllocating, StrVector, StrSlice};
 use string::String;
 use unicode::char::UnicodeChar;
index aa407ce8e0ccbb9de5d5e2637dab8b898ad10bb7..eb6dcc1f1a586d250600d8b3fbfd39fa4a97532d 100644 (file)
 #[doc(no_inline)] pub use tuple::{Tuple5, Tuple6, Tuple7, Tuple8};
 #[doc(no_inline)] pub use tuple::{Tuple9, Tuple10, Tuple11, Tuple12};
 #[doc(no_inline)] pub use slice::{CloneableVector, ImmutableCloneableVector};
-#[doc(no_inline)] pub use slice::{MutableCloneableVector, MutableOrdVector};
-#[doc(no_inline)] pub use slice::{ImmutableVector, MutableVector};
-#[doc(no_inline)] pub use slice::{ImmutableEqVector, ImmutableOrdVector};
-#[doc(no_inline)] pub use slice::{Vector, VectorVector};
-#[doc(no_inline)] pub use slice::MutableVectorAllocating;
+#[doc(no_inline)] pub use slice::{MutableCloneableSlice, MutableOrdSlice};
+#[doc(no_inline)] pub use slice::{ImmutableSlice, MutableSlice};
+#[doc(no_inline)] pub use slice::{ImmutablePartialEqSlice, ImmutableOrdSlice};
+#[doc(no_inline)] pub use slice::{Slice, VectorVector};
+#[doc(no_inline)] pub use slice::MutableSliceAllocating;
 #[doc(no_inline)] pub use string::String;
 #[doc(no_inline)] pub use vec::Vec;
 
index ffe8e539ffba13b9b07516eb393fce74d3354a0a..2be4129883f7421aa9ee966140e7a03adc4bac4b 100644 (file)
@@ -70,7 +70,7 @@ mod imp {
     use rand::Rng;
     use result::{Ok};
     use self::libc::{c_int, size_t};
-    use slice::MutableVector;
+    use slice::MutableSlice;
 
     /// A random number generator that retrieves randomness straight from
     /// the operating system. Platform sources:
@@ -138,7 +138,7 @@ mod imp {
     use rt::stack;
     use self::libc::{DWORD, BYTE, LPCSTR, BOOL};
     use self::libc::types::os::arch::extra::{LONG_PTR};
-    use slice::MutableVector;
+    use slice::MutableSlice;
 
     type HCRYPTPROV = LONG_PTR;
 
index b86937e4213014a69bda32dd68eeaaaff93bb5bd..a4491b2ab1d4695f3e467205c1d8e31694c11d70 100644 (file)
@@ -258,7 +258,7 @@ mod imp {
     pub fn write(w: &mut Writer) -> IoResult<()> {
         use iter::{Iterator, range};
         use result;
-        use slice::{MutableVector};
+        use slice::{MutableSlice};
 
         extern {
             fn backtrace(buf: *mut *mut libc::c_void,
@@ -398,7 +398,7 @@ fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void) -> IoResult<()> {
         use path::GenericPath;
         use ptr::RawPtr;
         use ptr;
-        use slice::{ImmutableVector, MutableVector};
+        use slice::{ImmutableSlice, MutableSlice};
 
         ////////////////////////////////////////////////////////////////////////
         // libbacktrace.h API
@@ -670,7 +670,7 @@ mod imp {
     use path::Path;
     use result::{Ok, Err};
     use rt::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT};
-    use slice::ImmutableVector;
+    use slice::ImmutableSlice;
     use str::StrSlice;
     use dynamic_lib::DynamicLibrary;
 
index 19ad81a04834d606ebaa613928f281f6bf8a220f..9cace9c80ef5ad1a5dd60f1a7dcd923c32bb38c0 100644 (file)
@@ -664,10 +664,11 @@ fn test_stdout() {
 #[test]
 fn task_abort_no_kill_runtime() {
     use std::io::timer;
+    use time::Duration;
     use mem;
 
     let tb = TaskBuilder::new();
     let rx = tb.try_future(proc() {});
     mem::drop(rx);
-    timer::sleep(1000);
+    timer::sleep(Duration::milliseconds(1000));
 }
diff --git a/src/libstd/time/duration.rs b/src/libstd/time/duration.rs
new file mode 100644 (file)
index 0000000..545d1f2
--- /dev/null
@@ -0,0 +1,634 @@
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Temporal quantification
+
+#![experimental]
+
+use {fmt, i32};
+use ops::{Add, Sub, Mul, Div, Neg};
+use option::{Option, Some, None};
+use num;
+use num::{CheckedAdd, CheckedMul};
+use result::{Result, Ok, Err};
+
+
+/// `Duration`'s `days` component should have no more than this value.
+static MIN_DAYS: i32 = i32::MIN;
+/// `Duration`'s `days` component should have no less than this value.
+static MAX_DAYS: i32 = i32::MAX;
+
+/// The number of nanoseconds in seconds.
+static NANOS_PER_SEC: i32 = 1_000_000_000;
+/// The number of (non-leap) seconds in days.
+static SECS_PER_DAY: i32 = 86400;
+
+macro_rules! try_opt(
+    ($e:expr) => (match $e { Some(v) => v, None => return None })
+)
+
+
+// FIXME #16466: This could be represented as (i64 seconds, u32 nanos)
+/// ISO 8601 time duration with nanosecond precision.
+/// This also allows for the negative duration; see individual methods for details.
+#[deriving(PartialEq, Eq, PartialOrd, Ord)]
+pub struct Duration {
+    days: i32,
+    secs: u32,  // Always < SECS_PER_DAY
+    nanos: u32, // Always < NANOS_PR_SECOND
+}
+
+/// The minimum possible `Duration`.
+pub static MIN: Duration = Duration { days: MIN_DAYS, secs: 0, nanos: 0 };
+/// The maximum possible `Duration`.
+pub static MAX: Duration = Duration { days: MAX_DAYS, secs: SECS_PER_DAY as u32 - 1,
+                                      nanos: NANOS_PER_SEC as u32 - 1 };
+
+impl Duration {
+    /// Makes a new `Duration` with given number of weeks.
+    /// Equivalent to `Duration::new(weeks * 7, 0, 0)` with overflow checks.
+    ///
+    /// Fails when the duration is out of bounds.
+    #[inline]
+    pub fn weeks(weeks: i32) -> Duration {
+        let days = weeks.checked_mul(&7).expect("Duration::weeks out of bounds");
+        Duration::days(days)
+    }
+
+    /// Makes a new `Duration` with given number of days.
+    /// Equivalent to `Duration::new(days, 0, 0)`.
+    #[inline]
+    pub fn days(days: i32) -> Duration {
+        Duration { days: days, secs: 0, nanos: 0 }
+    }
+
+    /// Makes a new `Duration` with given number of hours.
+    /// Equivalent to `Duration::new(0, hours * 3600, 0)` with overflow checks.
+    #[inline]
+    pub fn hours(hours: i32) -> Duration {
+        let (days, hours) = div_mod_floor(hours, (SECS_PER_DAY / 3600));
+        let secs = hours * 3600;
+        Duration { secs: secs as u32, ..Duration::days(days) }
+    }
+
+    /// Makes a new `Duration` with given number of minutes.
+    /// Equivalent to `Duration::new(0, mins * 60, 0)` with overflow checks.
+    #[inline]
+    pub fn minutes(mins: i32) -> Duration {
+        let (days, mins) = div_mod_floor(mins, (SECS_PER_DAY / 60));
+        let secs = mins * 60;
+        Duration { secs: secs as u32, ..Duration::days(days) }
+    }
+
+    /// Makes a new `Duration` with given number of seconds.
+    /// Equivalent to `Duration::new(0, secs, 0)`.
+    #[inline]
+    pub fn seconds(secs: i32) -> Duration {
+        let (days, secs) = div_mod_floor(secs, SECS_PER_DAY);
+        Duration { secs: secs as u32, ..Duration::days(days) }
+    }
+
+    /// Makes a new `Duration` with given number of milliseconds.
+    /// Equivalent to `Duration::new(0, 0, millis * 1_000_000)` with overflow checks.
+    #[inline]
+    pub fn milliseconds(millis: i32) -> Duration {
+        let (secs, millis) = div_mod_floor(millis, (NANOS_PER_SEC / 1_000_000));
+        let nanos = millis * 1_000_000;
+        Duration { nanos: nanos as u32, ..Duration::seconds(secs) }
+    }
+
+    /// Makes a new `Duration` with given number of microseconds.
+    /// Equivalent to `Duration::new(0, 0, micros * 1_000)` with overflow checks.
+    #[inline]
+    pub fn microseconds(micros: i32) -> Duration {
+        let (secs, micros) = div_mod_floor(micros, (NANOS_PER_SEC / 1_000));
+        let nanos = micros * 1_000;
+        Duration { nanos: nanos as u32, ..Duration::seconds(secs) }
+    }
+
+    /// Makes a new `Duration` with given number of nanoseconds.
+    /// Equivalent to `Duration::new(0, 0, nanos)`.
+    #[inline]
+    pub fn nanoseconds(nanos: i32) -> Duration {
+        let (secs, nanos) = div_mod_floor(nanos, NANOS_PER_SEC);
+        Duration { nanos: nanos as u32, ..Duration::seconds(secs) }
+    }
+
+    /// Returns a tuple of the number of days, (non-leap) seconds and
+    /// nanoseconds in the duration.  Note that the number of seconds
+    /// and nanoseconds are always positive, so that for example
+    /// `-Duration::seconds(3)` has -1 days and 86,397 seconds.
+    #[inline]
+    fn to_tuple_64(&self) -> (i64, u32, u32) {
+        (self.days as i64, self.secs, self.nanos)
+    }
+
+    /// Negates the duration and returns a tuple like `to_tuple`.
+    /// This does not overflow and thus is internally used for several methods.
+    fn to_negated_tuple_64(&self) -> (i64, u32, u32) {
+        let mut days = -(self.days as i64);
+        let mut secs = -(self.secs as i32);
+        let mut nanos = -(self.nanos as i32);
+        if nanos < 0 {
+            nanos += NANOS_PER_SEC;
+            secs -= 1;
+        }
+        if secs < 0 {
+            secs += SECS_PER_DAY;
+            days -= 1;
+        }
+        (days, secs as u32, nanos as u32)
+    }
+
+    /// Returns the total number of whole weeks in the duration.
+    #[inline]
+    pub fn num_weeks(&self) -> i32 {
+        self.num_days() / 7
+    }
+
+    /// Returns the total number of whole days in the duration.
+    pub fn num_days(&self) -> i32 {
+        if self.days < 0 {
+            let negated = -*self;
+            -negated.days
+        } else {
+            self.days
+        }
+    }
+
+    /// Returns the total number of whole hours in the duration.
+    #[inline]
+    pub fn num_hours(&self) -> i64 {
+        self.num_seconds() / 3600
+    }
+
+    /// Returns the total number of whole minutes in the duration.
+    #[inline]
+    pub fn num_minutes(&self) -> i64 {
+        self.num_seconds() / 60
+    }
+
+    /// Returns the total number of whole seconds in the duration.
+    pub fn num_seconds(&self) -> i64 {
+        // cannot overflow, 2^32 * 86400 < 2^64
+        fn secs((days, secs, _): (i64, u32, u32)) -> i64 {
+            days as i64 * SECS_PER_DAY as i64 + secs as i64
+        }
+        if self.days < 0 {-secs(self.to_negated_tuple_64())} else {secs(self.to_tuple_64())}
+    }
+
+    /// Returns the total number of whole milliseconds in the duration.
+    pub fn num_milliseconds(&self) -> i64 {
+        // cannot overflow, 2^32 * 86400 * 1000 < 2^64
+        fn millis((days, secs, nanos): (i64, u32, u32)) -> i64 {
+            static MILLIS_PER_SEC: i64 = 1_000;
+            static NANOS_PER_MILLI: i64 = 1_000_000;
+            (days as i64 * MILLIS_PER_SEC * SECS_PER_DAY as i64 +
+             secs as i64 * MILLIS_PER_SEC +
+             nanos as i64 / NANOS_PER_MILLI)
+        }
+        if self.days < 0 {-millis(self.to_negated_tuple_64())} else {millis(self.to_tuple_64())}
+    }
+
+    /// Returns the total number of whole microseconds in the duration,
+    /// or `None` on the overflow (exceeding 2^63 microseconds in either directions).
+    pub fn num_microseconds(&self) -> Option<i64> {
+        fn micros((days, secs, nanos): (i64, u32, u32)) -> Option<i64> {
+            static MICROS_PER_SEC: i64 = 1_000_000;
+            static MICROS_PER_DAY: i64 = MICROS_PER_SEC * SECS_PER_DAY as i64;
+            static NANOS_PER_MICRO: i64 = 1_000;
+            let nmicros = try_opt!((days as i64).checked_mul(&MICROS_PER_DAY));
+            let nmicros = try_opt!(nmicros.checked_add(&(secs as i64 * MICROS_PER_SEC)));
+            let nmicros = try_opt!(nmicros.checked_add(&(nanos as i64 / NANOS_PER_MICRO as i64)));
+            Some(nmicros)
+        }
+        if self.days < 0 {
+            // the final negation won't overflow since we start with positive numbers.
+            micros(self.to_negated_tuple_64()).map(|micros| -micros)
+        } else {
+            micros(self.to_tuple_64())
+        }
+    }
+
+    /// Returns the total number of whole nanoseconds in the duration,
+    /// or `None` on the overflow (exceeding 2^63 nanoseconds in either directions).
+    pub fn num_nanoseconds(&self) -> Option<i64> {
+        fn nanos((days, secs, nanos): (i64, u32, u32)) -> Option<i64> {
+            static NANOS_PER_DAY: i64 = NANOS_PER_SEC as i64 * SECS_PER_DAY as i64;
+            let nnanos = try_opt!((days as i64).checked_mul(&NANOS_PER_DAY));
+            let nnanos = try_opt!(nnanos.checked_add(&(secs as i64 * NANOS_PER_SEC as i64)));
+            let nnanos = try_opt!(nnanos.checked_add(&(nanos as i64)));
+            Some(nnanos)
+        }
+        if self.days < 0 {
+            // the final negation won't overflow since we start with positive numbers.
+            nanos(self.to_negated_tuple_64()).map(|micros| -micros)
+        } else {
+            nanos(self.to_tuple_64())
+        }
+    }
+}
+
+impl num::Bounded for Duration {
+    #[inline] fn min_value() -> Duration { MIN }
+    #[inline] fn max_value() -> Duration { MAX }
+}
+
+impl num::Zero for Duration {
+    #[inline]
+    fn zero() -> Duration {
+        Duration { days: 0, secs: 0, nanos: 0 }
+    }
+
+    #[inline]
+    fn is_zero(&self) -> bool {
+        self.days == 0 && self.secs == 0 && self.nanos == 0
+    }
+}
+
+impl Neg<Duration> for Duration {
+    #[inline]
+    fn neg(&self) -> Duration {
+        let (days, secs, nanos) = self.to_negated_tuple_64();
+        Duration { days: days as i32, secs: secs, nanos: nanos } // FIXME can overflow
+    }
+}
+
+impl Add<Duration,Duration> for Duration {
+    fn add(&self, rhs: &Duration) -> Duration {
+        let mut days = self.days + rhs.days;
+        let mut secs = self.secs + rhs.secs;
+        let mut nanos = self.nanos + rhs.nanos;
+        if nanos >= NANOS_PER_SEC as u32 {
+            nanos -= NANOS_PER_SEC as u32;
+            secs += 1;
+        }
+        if secs >= SECS_PER_DAY as u32 {
+            secs -= SECS_PER_DAY as u32;
+            days += 1;
+        }
+        Duration { days: days, secs: secs, nanos: nanos }
+    }
+}
+
+impl num::CheckedAdd for Duration {
+    fn checked_add(&self, rhs: &Duration) -> Option<Duration> {
+        let mut days = try_opt!(self.days.checked_add(&rhs.days));
+        let mut secs = self.secs + rhs.secs;
+        let mut nanos = self.nanos + rhs.nanos;
+        if nanos >= NANOS_PER_SEC as u32 {
+            nanos -= NANOS_PER_SEC as u32;
+            secs += 1;
+        }
+        if secs >= SECS_PER_DAY as u32 {
+            secs -= SECS_PER_DAY as u32;
+            days = try_opt!(days.checked_add(&1));
+        }
+        Some(Duration { days: days, secs: secs, nanos: nanos })
+    }
+}
+
+impl Sub<Duration,Duration> for Duration {
+    fn sub(&self, rhs: &Duration) -> Duration {
+        let mut days = self.days - rhs.days;
+        let mut secs = self.secs as i32 - rhs.secs as i32;
+        let mut nanos = self.nanos as i32 - rhs.nanos as i32;
+        if nanos < 0 {
+            nanos += NANOS_PER_SEC;
+            secs -= 1;
+        }
+        if secs < 0 {
+            secs += SECS_PER_DAY;
+            days -= 1;
+        }
+        Duration { days: days, secs: secs as u32, nanos: nanos as u32 }
+    }
+}
+
+impl num::CheckedSub for Duration {
+    fn checked_sub(&self, rhs: &Duration) -> Option<Duration> {
+        let mut days = try_opt!(self.days.checked_sub(&rhs.days));
+        let mut secs = self.secs as i32 - rhs.secs as i32;
+        let mut nanos = self.nanos as i32 - rhs.nanos as i32;
+        if nanos < 0 {
+            nanos += NANOS_PER_SEC;
+            secs -= 1;
+        }
+        if secs < 0 {
+            secs += SECS_PER_DAY;
+            days = try_opt!(days.checked_sub(&1));
+        }
+        Some(Duration { days: days, secs: secs as u32, nanos: nanos as u32 })
+    }
+}
+
+impl Mul<i32,Duration> for Duration {
+    fn mul(&self, rhs: &i32) -> Duration {
+        /// Given `0 <= y < limit <= 2^30`,
+        /// returns `(h,l)` such that `x * y = h * limit + l` where `0 <= l < limit`.
+        fn mul_i64_u32_limit(x: i64, y: u32, limit: u32) -> (i64,u32) {
+            let y = y as i64;
+            let limit = limit as i64;
+            let (xh, xl) = div_mod_floor_64(x, limit);
+            let (h, l) = (xh * y, xl * y);
+            let (h_, l) = div_rem_64(l, limit);
+            (h + h_, l as u32)
+        }
+
+        let rhs = *rhs as i64;
+        let (secs1, nanos) = mul_i64_u32_limit(rhs, self.nanos, NANOS_PER_SEC as u32);
+        let (days1, secs1) = div_mod_floor_64(secs1, (SECS_PER_DAY as i64));
+        let (days2, secs2) = mul_i64_u32_limit(rhs, self.secs, SECS_PER_DAY as u32);
+        let mut days = self.days as i64 * rhs + days1 + days2;
+        let mut secs = secs1 as u32 + secs2;
+        if secs >= SECS_PER_DAY as u32 {
+            secs -= 1;
+            days += 1;
+        }
+        Duration { days: days as i32, secs: secs, nanos: nanos }
+    }
+}
+
+impl Div<i32,Duration> for Duration {
+    fn div(&self, rhs: &i32) -> Duration {
+        let (rhs, days, secs, nanos) = if *rhs < 0 {
+            let (days, secs, nanos) = self.to_negated_tuple_64();
+            (-(*rhs as i64), days, secs as i64, nanos as i64)
+        } else {
+            (*rhs as i64, self.days as i64, self.secs as i64, self.nanos as i64)
+        };
+
+        let (days, carry) = div_mod_floor_64(days, rhs);
+        let secs = secs + carry * SECS_PER_DAY as i64;
+        let (secs, carry) = div_mod_floor_64(secs, rhs);
+        let nanos = nanos + carry * NANOS_PER_SEC as i64;
+        let nanos = nanos / rhs;
+        Duration { days: days as i32, secs: secs as u32, nanos: nanos as u32 }
+    }
+}
+
+impl fmt::Show for Duration {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let hasdate = self.days != 0;
+        let hastime = (self.secs != 0 || self.nanos != 0) || !hasdate;
+
+        try!(write!(f, "P"));
+        if hasdate {
+            // technically speaking the negative part is not the valid ISO 8601,
+            // but we need to print it anyway.
+            try!(write!(f, "{}D", self.days));
+        }
+        if hastime {
+            if self.nanos == 0 {
+                try!(write!(f, "T{}S", self.secs));
+            } else if self.nanos % 1_000_000 == 0 {
+                try!(write!(f, "T{}.{:03}S", self.secs, self.nanos / 1_000_000));
+            } else if self.nanos % 1_000 == 0 {
+                try!(write!(f, "T{}.{:06}S", self.secs, self.nanos / 1_000));
+            } else {
+                try!(write!(f, "T{}.{:09}S", self.secs, self.nanos));
+            }
+        }
+        Ok(())
+    }
+}
+
+// Copied from libnum
+#[inline]
+fn div_mod_floor(this: i32, other: i32) -> (i32, i32) {
+    (div_floor(this, other), mod_floor(this, other))
+}
+
+#[inline]
+fn div_floor(this: i32, other: i32) -> i32 {
+    match div_rem(this, other) {
+        (d, r) if (r > 0 && other < 0)
+               || (r < 0 && other > 0) => d - 1,
+        (d, _)                         => d,
+    }
+}
+
+#[inline]
+fn mod_floor(this: i32, other: i32) -> i32 {
+    match this % other {
+        r if (r > 0 && other < 0)
+          || (r < 0 && other > 0) => r + other,
+        r                         => r,
+    }
+}
+
+#[inline]
+fn div_rem(this: i32, other: i32) -> (i32, i32) {
+    (this / other, this % other)
+}
+
+#[inline]
+fn div_mod_floor_64(this: i64, other: i64) -> (i64, i64) {
+    (div_floor_64(this, other), mod_floor_64(this, other))
+}
+
+#[inline]
+fn div_floor_64(this: i64, other: i64) -> i64 {
+    match div_rem_64(this, other) {
+        (d, r) if (r > 0 && other < 0)
+               || (r < 0 && other > 0) => d - 1,
+        (d, _)                         => d,
+    }
+}
+
+#[inline]
+fn mod_floor_64(this: i64, other: i64) -> i64 {
+    match this % other {
+        r if (r > 0 && other < 0)
+          || (r < 0 && other > 0) => r + other,
+        r                         => r,
+    }
+}
+
+#[inline]
+fn div_rem_64(this: i64, other: i64) -> (i64, i64) {
+    (this / other, this % other)
+}
+
+#[cfg(test)]
+mod tests {
+    use super::{Duration, MIN_DAYS, MAX_DAYS, MIN, MAX};
+    use {i32, i64};
+    use num::{Zero, CheckedAdd, CheckedSub};
+    use option::{Some, None};
+    use to_string::ToString;
+
+    #[test]
+    fn test_duration() {
+        let d: Duration = Zero::zero();
+        assert_eq!(d, Zero::zero());
+        assert!(Duration::seconds(1) != Zero::zero());
+        assert_eq!(Duration::seconds(1) + Duration::seconds(2), Duration::seconds(3));
+        assert_eq!(Duration::seconds(86399) + Duration::seconds(4),
+                   Duration::days(1) + Duration::seconds(3));
+        assert_eq!(Duration::days(10) - Duration::seconds(1000), Duration::seconds(863000));
+        assert_eq!(Duration::days(10) - Duration::seconds(1000000), Duration::seconds(-136000));
+        assert_eq!(Duration::days(2) + Duration::seconds(86399) + Duration::nanoseconds(1234567890),
+                   Duration::days(3) + Duration::nanoseconds(234567890));
+        assert_eq!(-Duration::days(3), Duration::days(-3));
+        assert_eq!(-(Duration::days(3) + Duration::seconds(70)),
+                   Duration::days(-4) + Duration::seconds(86400-70));
+    }
+
+    #[test]
+    fn test_duration_num_days() {
+        let d: Duration = Zero::zero();
+        assert_eq!(d.num_days(), 0);
+        assert_eq!(Duration::days(1).num_days(), 1);
+        assert_eq!(Duration::days(-1).num_days(), -1);
+        assert_eq!(Duration::seconds(86399).num_days(), 0);
+        assert_eq!(Duration::seconds(86401).num_days(), 1);
+        assert_eq!(Duration::seconds(-86399).num_days(), 0);
+        assert_eq!(Duration::seconds(-86401).num_days(), -1);
+        assert_eq!(Duration::days(i32::MAX).num_days(), i32::MAX);
+        assert_eq!(Duration::days(i32::MIN).num_days(), i32::MIN);
+        assert_eq!(MAX.num_days(), MAX_DAYS);
+        assert_eq!(MIN.num_days(), MIN_DAYS);
+    }
+
+    #[test]
+    fn test_duration_num_seconds() {
+        let d: Duration = Zero::zero();
+        assert_eq!(d.num_seconds(), 0);
+        assert_eq!(Duration::seconds(1).num_seconds(), 1);
+        assert_eq!(Duration::seconds(-1).num_seconds(), -1);
+        assert_eq!(Duration::milliseconds(999).num_seconds(), 0);
+        assert_eq!(Duration::milliseconds(1001).num_seconds(), 1);
+        assert_eq!(Duration::milliseconds(-999).num_seconds(), 0);
+        assert_eq!(Duration::milliseconds(-1001).num_seconds(), -1);
+        assert_eq!(Duration::seconds(i32::MAX).num_seconds(), i32::MAX as i64);
+        assert_eq!(Duration::seconds(i32::MIN).num_seconds(), i32::MIN as i64);
+        assert_eq!(MAX.num_seconds(), (MAX_DAYS as i64 + 1) * 86400 - 1);
+        assert_eq!(MIN.num_seconds(), MIN_DAYS as i64 * 86400);
+    }
+
+    #[test]
+    fn test_duration_num_milliseconds() {
+        let d: Duration = Zero::zero();
+        assert_eq!(d.num_milliseconds(), 0);
+        assert_eq!(Duration::milliseconds(1).num_milliseconds(), 1);
+        assert_eq!(Duration::milliseconds(-1).num_milliseconds(), -1);
+        assert_eq!(Duration::microseconds(999).num_milliseconds(), 0);
+        assert_eq!(Duration::microseconds(1001).num_milliseconds(), 1);
+        assert_eq!(Duration::microseconds(-999).num_milliseconds(), 0);
+        assert_eq!(Duration::microseconds(-1001).num_milliseconds(), -1);
+        assert_eq!(Duration::milliseconds(i32::MAX).num_milliseconds(), i32::MAX as i64);
+        assert_eq!(Duration::milliseconds(i32::MIN).num_milliseconds(), i32::MIN as i64);
+        assert_eq!(MAX.num_milliseconds(), (MAX_DAYS as i64 + 1) * 86400_000 - 1);
+        assert_eq!(MIN.num_milliseconds(), MIN_DAYS as i64 * 86400_000);
+    }
+
+    #[test]
+    fn test_duration_num_microseconds() {
+        let d: Duration = Zero::zero();
+        assert_eq!(d.num_microseconds(), Some(0));
+        assert_eq!(Duration::microseconds(1).num_microseconds(), Some(1));
+        assert_eq!(Duration::microseconds(-1).num_microseconds(), Some(-1));
+        assert_eq!(Duration::nanoseconds(999).num_microseconds(), Some(0));
+        assert_eq!(Duration::nanoseconds(1001).num_microseconds(), Some(1));
+        assert_eq!(Duration::nanoseconds(-999).num_microseconds(), Some(0));
+        assert_eq!(Duration::nanoseconds(-1001).num_microseconds(), Some(-1));
+        assert_eq!(Duration::microseconds(i32::MAX).num_microseconds(), Some(i32::MAX as i64));
+        assert_eq!(Duration::microseconds(i32::MIN).num_microseconds(), Some(i32::MIN as i64));
+        assert_eq!(MAX.num_microseconds(), None);
+        assert_eq!(MIN.num_microseconds(), None);
+
+        // overflow checks
+        static MICROS_PER_DAY: i64 = 86400_000_000;
+        assert_eq!(Duration::days((i64::MAX / MICROS_PER_DAY) as i32).num_microseconds(),
+                   Some(i64::MAX / MICROS_PER_DAY * MICROS_PER_DAY));
+        assert_eq!(Duration::days((i64::MIN / MICROS_PER_DAY) as i32).num_microseconds(),
+                   Some(i64::MIN / MICROS_PER_DAY * MICROS_PER_DAY));
+        assert_eq!(Duration::days((i64::MAX / MICROS_PER_DAY + 1) as i32).num_microseconds(), None);
+        assert_eq!(Duration::days((i64::MIN / MICROS_PER_DAY - 1) as i32).num_microseconds(), None);
+    }
+
+    #[test]
+    fn test_duration_num_nanoseconds() {
+        let d: Duration = Zero::zero();
+        assert_eq!(d.num_nanoseconds(), Some(0));
+        assert_eq!(Duration::nanoseconds(1).num_nanoseconds(), Some(1));
+        assert_eq!(Duration::nanoseconds(-1).num_nanoseconds(), Some(-1));
+        assert_eq!(Duration::nanoseconds(i32::MAX).num_nanoseconds(), Some(i32::MAX as i64));
+        assert_eq!(Duration::nanoseconds(i32::MIN).num_nanoseconds(), Some(i32::MIN as i64));
+        assert_eq!(MAX.num_nanoseconds(), None);
+        assert_eq!(MIN.num_nanoseconds(), None);
+
+        // overflow checks
+        static NANOS_PER_DAY: i64 = 86400_000_000_000;
+        assert_eq!(Duration::days((i64::MAX / NANOS_PER_DAY) as i32).num_nanoseconds(),
+                   Some(i64::MAX / NANOS_PER_DAY * NANOS_PER_DAY));
+        assert_eq!(Duration::days((i64::MIN / NANOS_PER_DAY) as i32).num_nanoseconds(),
+                   Some(i64::MIN / NANOS_PER_DAY * NANOS_PER_DAY));
+        assert_eq!(Duration::days((i64::MAX / NANOS_PER_DAY + 1) as i32).num_nanoseconds(), None);
+        assert_eq!(Duration::days((i64::MIN / NANOS_PER_DAY - 1) as i32).num_nanoseconds(), None);
+    }
+
+    #[test]
+    fn test_duration_checked_ops() {
+        assert_eq!(Duration::days(MAX_DAYS).checked_add(&Duration::seconds(86399)),
+                   Some(Duration::days(MAX_DAYS - 1) + Duration::seconds(86400+86399)));
+        assert!(Duration::days(MAX_DAYS).checked_add(&Duration::seconds(86400)).is_none());
+
+        assert_eq!(Duration::days(MIN_DAYS).checked_sub(&Duration::seconds(0)),
+                   Some(Duration::days(MIN_DAYS)));
+        assert!(Duration::days(MIN_DAYS).checked_sub(&Duration::seconds(1)).is_none());
+    }
+
+    #[test]
+    fn test_duration_mul() {
+        let d: Duration = Zero::zero();
+        assert_eq!(d * i32::MAX, d);
+        assert_eq!(d * i32::MIN, d);
+        assert_eq!(Duration::nanoseconds(1) * 0, Zero::zero());
+        assert_eq!(Duration::nanoseconds(1) * 1, Duration::nanoseconds(1));
+        assert_eq!(Duration::nanoseconds(1) * 1_000_000_000, Duration::seconds(1));
+        assert_eq!(Duration::nanoseconds(1) * -1_000_000_000, -Duration::seconds(1));
+        assert_eq!(-Duration::nanoseconds(1) * 1_000_000_000, -Duration::seconds(1));
+        assert_eq!(Duration::nanoseconds(30) * 333_333_333,
+                   Duration::seconds(10) - Duration::nanoseconds(10));
+        assert_eq!((Duration::nanoseconds(1) + Duration::seconds(1) + Duration::days(1)) * 3,
+                   Duration::nanoseconds(3) + Duration::seconds(3) + Duration::days(3));
+    }
+
+    #[test]
+    fn test_duration_div() {
+        let d: Duration = Zero::zero();
+        assert_eq!(d / i32::MAX, d);
+        assert_eq!(d / i32::MIN, d);
+        assert_eq!(Duration::nanoseconds(123_456_789) / 1, Duration::nanoseconds(123_456_789));
+        assert_eq!(Duration::nanoseconds(123_456_789) / -1, -Duration::nanoseconds(123_456_789));
+        assert_eq!(-Duration::nanoseconds(123_456_789) / -1, Duration::nanoseconds(123_456_789));
+        assert_eq!(-Duration::nanoseconds(123_456_789) / 1, -Duration::nanoseconds(123_456_789));
+    }
+
+    #[test]
+    fn test_duration_fmt() {
+        let d: Duration = Zero::zero();
+        assert_eq!(d.to_string(), "PT0S".to_string());
+        assert_eq!(Duration::days(42).to_string(), "P42D".to_string());
+        assert_eq!(Duration::days(-42).to_string(), "P-42D".to_string());
+        assert_eq!(Duration::seconds(42).to_string(), "PT42S".to_string());
+        assert_eq!(Duration::milliseconds(42).to_string(), "PT0.042S".to_string());
+        assert_eq!(Duration::microseconds(42).to_string(), "PT0.000042S".to_string());
+        assert_eq!(Duration::nanoseconds(42).to_string(), "PT0.000000042S".to_string());
+        assert_eq!((Duration::days(7) + Duration::milliseconds(6543)).to_string(),
+                   "P7DT6.543S".to_string());
+
+        // the format specifier should have no effect on `Duration`
+        assert_eq!(format!("{:30}", Duration::days(1) + Duration::milliseconds(2345)),
+                   "P1DT2.345S".to_string());
+    }
+}
diff --git a/src/libstd/time/mod.rs b/src/libstd/time/mod.rs
new file mode 100644 (file)
index 0000000..436fa5e
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Temporal quantification.
+
+pub use self::duration::Duration;
+
+pub mod duration;
index 31b993d8bab468b3f795ac8727c8b858cf855002..301d444b1b15b83279e3cec9f0671e80be5f0967 100644 (file)
 //! }
 //! ```
 
+#![allow(deprecated)]
+
 use core::prelude::*;
 
 use alloc::boxed::Box;
index 44dd63cbf6c010cfd63058c9d6700e4b00922fa4..587827d2bc576c56e729dc2fc9dab59753ac9e09 100644 (file)
@@ -15,6 +15,7 @@
 */
 
 #![allow(missing_doc)]
+#![allow(deprecated)]
 #![deprecated = "This type is replaced by having a pair of channels. This type \
                  is not fully composable with other channels in terms of \
                  or possible semantics on a duplex stream. It will be removed \
index 45016b97566ceab20dbbf8d46302fdecd0ed90d0..e4df661b56201946dc852f7e75144b8357e12da5 100644 (file)
 //!
 //! ```no_run
 //! use std::io::timer::Timer;
+//! use std::time::Duration;
 //!
 //! let (tx, rx) = channel::<int>();
 //! let mut timer = Timer::new().unwrap();
-//! let timeout = timer.oneshot(10000);
+//! let timeout = timer.oneshot(Duration::seconds(10));
 //!
 //! loop {
 //!     select! {
 //!
 //! ```no_run
 //! use std::io::timer::Timer;
+//! use std::time::Duration;
 //!
 //! let (tx, rx) = channel::<int>();
 //! let mut timer = Timer::new().unwrap();
 //!
 //! loop {
-//!     let timeout = timer.oneshot(5000);
+//!     let timeout = timer.oneshot(Duration::seconds(5));
 //!
 //!     select! {
 //!         val = rx.recv() => println!("Received {}", val),
index 629b21875c9b61b37904f3e65f52e2c5e35009e8..46039a70fb21d720cf5cd1266050fe2d2b187f86 100644 (file)
@@ -55,6 +55,12 @@ pub fn new(name: Name) -> Ident { Ident {name: name, ctxt: EMPTY_CTXT}}
     pub fn as_str<'a>(&'a self) -> &'a str {
         self.name.as_str()
     }
+
+    pub fn encode_with_hygiene(&self) -> String {
+        format!("\x00name_{:u},ctxt_{:u}\x00",
+                self.name.uint(),
+                self.ctxt)
+    }
 }
 
 impl Show for Ident {
@@ -520,9 +526,9 @@ pub enum Expr_ {
     // FIXME #6993: change to Option<Name> ... or not, if these are hygienic.
     ExprLoop(P<Block>, Option<Ident>),
     ExprMatch(Gc<Expr>, Vec<Arm>),
-    ExprFnBlock(P<FnDecl>, P<Block>),
+    ExprFnBlock(CaptureClause, P<FnDecl>, P<Block>),
     ExprProc(P<FnDecl>, P<Block>),
-    ExprUnboxedFn(P<FnDecl>, P<Block>),
+    ExprUnboxedFn(CaptureClause, P<FnDecl>, P<Block>),
     ExprBlock(P<Block>),
 
     ExprAssign(Gc<Expr>, Gc<Expr>),
@@ -553,6 +559,12 @@ pub enum Expr_ {
     ExprParen(Gc<Expr>)
 }
 
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
+pub enum CaptureClause {
+    CaptureByValue,
+    CaptureByRef,
+}
+
 /// When the main rust parser encounters a syntax-extension invocation, it
 /// parses the arguments to the invocation as a token-tree. This is a very
 /// loose structure, such that all sorts of different AST-fragments can
index a522f80554327f89a297c2c6107c821923cad6bb..83af390c4edc3e2f995bf5145eb45c8bce7de83f 100644 (file)
@@ -206,7 +206,7 @@ fn handle<'a, A>(&'a self,
             },
             ast_map::NodeMethod(ref m) => method(&**m),
             ast_map::NodeExpr(ref e) => match e.node {
-                ast::ExprFnBlock(ref decl, ref block) =>
+                ast::ExprFnBlock(_, ref decl, ref block) =>
                     closure(ClosureParts::new(*decl, *block, e.id, e.span)),
                 ast::ExprProc(ref decl, ref block) =>
                     closure(ClosureParts::new(*decl, *block, e.id, e.span)),
index b9298cca4f87d8c53e79ec65e96fceb36292429f..67605360a48cb665d1b4621aca5650012f4b174f 100644 (file)
@@ -51,7 +51,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 
 impl FromStr for CrateId {
     fn from_str(s: &str) -> Option<CrateId> {
-        let pieces: Vec<&str> = s.splitn('#', 1).collect();
+        let pieces: Vec<&str> = s.splitn(1, '#').collect();
         let path = pieces.get(0).to_string();
 
         if path.as_slice().starts_with("/") || path.as_slice().ends_with("/") ||
@@ -60,7 +60,7 @@ fn from_str(s: &str) -> Option<CrateId> {
         }
 
         let path_pieces: Vec<&str> = path.as_slice()
-                                         .rsplitn('/', 1)
+                                         .rsplitn(1, '/')
                                          .collect();
         let inferred_name = *path_pieces.get(0);
 
@@ -68,7 +68,7 @@ fn from_str(s: &str) -> Option<CrateId> {
             (inferred_name.to_string(), None)
         } else {
             let hash_pieces: Vec<&str> = pieces.get(1)
-                                               .splitn(':', 1)
+                                               .splitn(1, ':')
                                                .collect();
             let (hash_name, hash_version) = if hash_pieces.len() == 1 {
                 ("", *hash_pieces.get(0))
index 0e687c02c1daf080c678316a4d28e51027522471..f7eddca4b7aed4d25c2ffd39aed3a5eab2edb537 100644 (file)
@@ -876,14 +876,14 @@ fn expr_loop(&self, span: Span, block: P<ast::Block>) -> Gc<ast::Expr> {
 
     fn lambda_fn_decl(&self, span: Span,
                       fn_decl: P<ast::FnDecl>, blk: P<ast::Block>) -> Gc<ast::Expr> {
-        self.expr(span, ast::ExprFnBlock(fn_decl, blk))
+        self.expr(span, ast::ExprFnBlock(ast::CaptureByRef, fn_decl, blk))
     }
     fn lambda(&self, span: Span, ids: Vec<ast::Ident> , blk: P<ast::Block>) -> Gc<ast::Expr> {
         let fn_decl = self.fn_decl(
             ids.iter().map(|id| self.arg(span, *id, self.ty_infer(span))).collect(),
             self.ty_infer(span));
 
-        self.expr(span, ast::ExprFnBlock(fn_decl, blk))
+        self.expr(span, ast::ExprFnBlock(ast::CaptureByRef, fn_decl, blk))
     }
     fn lambda0(&self, span: Span, blk: P<ast::Block>) -> Gc<ast::Expr> {
         self.lambda(span, Vec::new(), blk)
index 808532d55bb2e924ead563cadc2a41d4fd9464c1..d918b28d4dc8f31cf8a8625e7bcf326e4dce35ad 100644 (file)
@@ -74,10 +74,12 @@ fn expand_expr(e: Gc<ast::Expr>, fld: &mut MacroExpander) -> Gc<ast::Expr> {
             fld.cx.expr(e.span, ast::ExprForLoop(pat, head, body, opt_ident))
         }
 
-        ast::ExprFnBlock(fn_decl, block) => {
+        ast::ExprFnBlock(capture_clause, fn_decl, block) => {
             let (rewritten_fn_decl, rewritten_block)
                 = expand_and_rename_fn_decl_and_block(&*fn_decl, block, fld);
-            let new_node = ast::ExprFnBlock(rewritten_fn_decl, rewritten_block);
+            let new_node = ast::ExprFnBlock(capture_clause,
+                                            rewritten_fn_decl,
+                                            rewritten_block);
             box(GC) ast::Expr{id:e.id, node: new_node, span: fld.new_span(e.span)}
         }
 
index cc07b5312589f84b05c314014f2e441397a372c2..d7d6c20b475a688a2bebc48a57100fcc2124db19 100644 (file)
@@ -97,6 +97,15 @@ pub trait ToSource {
         fn to_source(&self) -> String;
     }
 
+    // FIXME (Issue #16472): This should go away after ToToken impls
+    // are revised to go directly to token-trees.
+    trait ToSourceWithHygiene : ToSource {
+        // Takes a thing and generates a string containing rust code
+        // for it, encoding Idents as special byte sequences to
+        // maintain hygiene across serialization and deserialization.
+        fn to_source_with_hygiene(&self) -> String;
+    }
+
     macro_rules! impl_to_source(
         (Gc<$t:ty>, $pp:ident) => (
             impl ToSource for Gc<$t> {
@@ -104,6 +113,11 @@ fn to_source(&self) -> String {
                     pprust::$pp(&**self)
                 }
             }
+            impl ToSourceWithHygiene for Gc<$t> {
+                fn to_source_with_hygiene(&self) -> String {
+                    pprust::with_hygiene::$pp(&**self)
+                }
+            }
         );
         ($t:ty, $pp:ident) => (
             impl ToSource for $t {
@@ -111,6 +125,11 @@ fn to_source(&self) -> String {
                     pprust::$pp(self)
                 }
             }
+            impl ToSourceWithHygiene for $t {
+                fn to_source_with_hygiene(&self) -> String {
+                    pprust::with_hygiene::$pp(self)
+                }
+            }
         );
     )
 
@@ -122,6 +141,15 @@ fn slice_to_source<'a, T: ToSource>(sep: &'static str, xs: &'a [T]) -> String {
             .to_string()
     }
 
+    fn slice_to_source_with_hygiene<'a, T: ToSourceWithHygiene>(
+        sep: &'static str, xs: &'a [T]) -> String {
+        xs.iter()
+            .map(|i| i.to_source_with_hygiene())
+            .collect::<Vec<String>>()
+            .connect(sep)
+            .to_string()
+    }
+
     macro_rules! impl_to_source_slice(
         ($t:ty, $sep:expr) => (
             impl<'a> ToSource for &'a [$t] {
@@ -129,6 +157,12 @@ fn to_source(&self) -> String {
                     slice_to_source($sep, *self)
                 }
             }
+
+            impl<'a> ToSourceWithHygiene for &'a [$t] {
+                fn to_source_with_hygiene(&self) -> String {
+                    slice_to_source_with_hygiene($sep, *self)
+                }
+            }
         )
     )
 
@@ -138,6 +172,12 @@ fn to_source(&self) -> String {
         }
     }
 
+    impl ToSourceWithHygiene for ast::Ident {
+        fn to_source_with_hygiene(&self) -> String {
+            self.encode_with_hygiene()
+        }
+    }
+
     impl_to_source!(ast::Ty, ty_to_string)
     impl_to_source!(ast::Block, block_to_string)
     impl_to_source!(ast::Arg, arg_to_string)
@@ -156,6 +196,11 @@ fn to_source(&self) -> String {
             pprust::attribute_to_string(&dummy_spanned(*self))
         }
     }
+    impl ToSourceWithHygiene for ast::Attribute_ {
+        fn to_source_with_hygiene(&self) -> String {
+            self.to_source()
+        }
+    }
 
     impl<'a> ToSource for &'a str {
         fn to_source(&self) -> String {
@@ -164,12 +209,22 @@ fn to_source(&self) -> String {
             pprust::lit_to_string(&lit)
         }
     }
+    impl<'a> ToSourceWithHygiene for &'a str {
+        fn to_source_with_hygiene(&self) -> String {
+            self.to_source()
+        }
+    }
 
     impl ToSource for () {
         fn to_source(&self) -> String {
             "()".to_string()
         }
     }
+    impl ToSourceWithHygiene for () {
+        fn to_source_with_hygiene(&self) -> String {
+            self.to_source()
+        }
+    }
 
     impl ToSource for bool {
         fn to_source(&self) -> String {
@@ -177,6 +232,11 @@ fn to_source(&self) -> String {
             pprust::lit_to_string(&lit)
         }
     }
+    impl ToSourceWithHygiene for bool {
+        fn to_source_with_hygiene(&self) -> String {
+            self.to_source()
+        }
+    }
 
     impl ToSource for char {
         fn to_source(&self) -> String {
@@ -184,6 +244,11 @@ fn to_source(&self) -> String {
             pprust::lit_to_string(&lit)
         }
     }
+    impl ToSourceWithHygiene for char {
+        fn to_source_with_hygiene(&self) -> String {
+            self.to_source()
+        }
+    }
 
     macro_rules! impl_to_source_int(
         (signed, $t:ty, $tag:ident) => (
@@ -194,6 +259,11 @@ fn to_source(&self) -> String {
                     pprust::lit_to_string(&dummy_spanned(lit))
                 }
             }
+            impl ToSourceWithHygiene for $t {
+                fn to_source_with_hygiene(&self) -> String {
+                    self.to_source()
+                }
+            }
         );
         (unsigned, $t:ty, $tag:ident) => (
             impl ToSource for $t {
@@ -202,6 +272,11 @@ fn to_source(&self) -> String {
                     pprust::lit_to_string(&dummy_spanned(lit))
                 }
             }
+            impl ToSourceWithHygiene for $t {
+                fn to_source_with_hygiene(&self) -> String {
+                    self.to_source()
+                }
+            }
         );
     )
 
@@ -223,7 +298,7 @@ macro_rules! impl_to_tokens(
         ($t:ty) => (
             impl ToTokens for $t {
                 fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
-                    cx.parse_tts(self.to_source())
+                    cx.parse_tts_with_hygiene(self.to_source_with_hygiene())
                 }
             }
         )
@@ -233,7 +308,7 @@ macro_rules! impl_to_tokens_lifetime(
         ($t:ty) => (
             impl<'a> ToTokens for $t {
                 fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
-                    cx.parse_tts(self.to_source())
+                    cx.parse_tts_with_hygiene(self.to_source_with_hygiene())
                 }
             }
         )
@@ -272,7 +347,13 @@ pub trait ExtParseUtils {
         fn parse_item(&self, s: String) -> Gc<ast::Item>;
         fn parse_expr(&self, s: String) -> Gc<ast::Expr>;
         fn parse_stmt(&self, s: String) -> Gc<ast::Stmt>;
-        fn parse_tts(&self, s: String) -> Vec<ast::TokenTree> ;
+        fn parse_tts(&self, s: String) -> Vec<ast::TokenTree>;
+    }
+
+    trait ExtParseUtilsWithHygiene {
+        // FIXME (Issue #16472): This should go away after ToToken impls
+        // are revised to go directly to token-trees.
+        fn parse_tts_with_hygiene(&self, s: String) -> Vec<ast::TokenTree>;
     }
 
     impl<'a> ExtParseUtils for ExtCtxt<'a> {
@@ -315,6 +396,18 @@ fn parse_tts(&self, s: String) -> Vec<ast::TokenTree> {
         }
     }
 
+    impl<'a> ExtParseUtilsWithHygiene for ExtCtxt<'a> {
+
+        fn parse_tts_with_hygiene(&self, s: String) -> Vec<ast::TokenTree> {
+            use parse::with_hygiene::parse_tts_from_source_str;
+            parse_tts_from_source_str("<quote expansion>".to_string(),
+                                      s,
+                                      self.cfg(),
+                                      self.parse_sess())
+        }
+
+    }
+
 }
 
 pub fn expand_quote_tokens(cx: &mut ExtCtxt,
index 80325c64349e8414cc6b72b2b5d871715017d54c..02f1f4646a4669b4d9aa15872e6d8209b4570b15 100644 (file)
@@ -1094,16 +1094,18 @@ pub fn noop_fold_expr<T: Folder>(e: Gc<Expr>, folder: &mut T) -> Gc<Expr> {
             ExprMatch(folder.fold_expr(expr),
                       arms.iter().map(|x| folder.fold_arm(x)).collect())
         }
-        ExprFnBlock(ref decl, ref body) => {
-            ExprFnBlock(folder.fold_fn_decl(&**decl),
+        ExprFnBlock(capture_clause, ref decl, ref body) => {
+            ExprFnBlock(capture_clause,
+                        folder.fold_fn_decl(&**decl),
                         folder.fold_block(body.clone()))
         }
         ExprProc(ref decl, ref body) => {
             ExprProc(folder.fold_fn_decl(&**decl),
                      folder.fold_block(body.clone()))
         }
-        ExprUnboxedFn(ref decl, ref body) => {
-            ExprUnboxedFn(folder.fold_fn_decl(&**decl),
+        ExprUnboxedFn(capture_clause, ref decl, ref body) => {
+            ExprUnboxedFn(capture_clause,
+                          folder.fold_fn_decl(&**decl),
                           folder.fold_block(*body))
         }
         ExprBlock(ref blk) => ExprBlock(folder.fold_block(*blk)),
index 625c03ec13db941025fa6940cd4e6a059ef4a675..e5275af5ccabef1e71f26972a5eebd1e35bb901d 100644 (file)
@@ -17,7 +17,9 @@
 use parse::token::{str_to_ident};
 
 use std::char;
+use std::fmt;
 use std::mem::replace;
+use std::num;
 use std::rc::Rc;
 use std::str;
 
@@ -55,6 +57,11 @@ pub struct StringReader<'a> {
     /* cached: */
     pub peek_tok: token::Token,
     pub peek_span: Span,
+
+    // FIXME (Issue #16472): This field should go away after ToToken impls
+    // are revised to go directly to token-trees.
+    /// Is \x00<name>,<ctxt>\x00 is interpreted as encoded ast::Ident?
+    read_embedded_ident: bool,
 }
 
 impl<'a> Reader for StringReader<'a> {
@@ -106,6 +113,17 @@ fn peek(&self) -> TokenAndSpan {
     }
 }
 
+// FIXME (Issue #16472): This function should go away after
+// ToToken impls are revised to go directly to token-trees.
+pub fn make_reader_with_embedded_idents<'b>(span_diagnostic: &'b SpanHandler,
+                                            filemap: Rc<codemap::FileMap>)
+                                            -> StringReader<'b> {
+    let mut sr = StringReader::new_raw(span_diagnostic, filemap);
+    sr.read_embedded_ident = true;
+    sr.advance_token();
+    sr
+}
+
 impl<'a> StringReader<'a> {
     /// For comments.rs, which hackily pokes into pos and curr
     pub fn new_raw<'b>(span_diagnostic: &'b SpanHandler,
@@ -120,6 +138,7 @@ pub fn new_raw<'b>(span_diagnostic: &'b SpanHandler,
             /* dummy values; not read */
             peek_tok: token::EOF,
             peek_span: codemap::DUMMY_SP,
+            read_embedded_ident: false,
         };
         sr.bump();
         sr
@@ -512,6 +531,81 @@ fn scan_block_comment(&mut self) -> Option<TokenAndSpan> {
         })
     }
 
+    // FIXME (Issue #16472): The scan_embedded_hygienic_ident function
+    // should go away after we revise the syntax::ext::quote::ToToken
+    // impls to go directly to token-trees instead of thing -> string
+    // -> token-trees.  (The function is currently used to resolve
+    // Issues #15750 and #15962.)
+    //
+    // Since this function is only used for certain internal macros,
+    // and the functionality it provides is not exposed to end user
+    // programs, pnkfelix deliberately chose to write it in a way that
+    // favors rustc debugging effectiveness over runtime efficiency.
+
+    /// Scan through input of form \x00name_NNNNNN,ctxt_CCCCCCC\x00
+    /// where: `NNNNNN` is a string of characters forming an integer
+    /// (the name) and `CCCCCCC` is a string of characters forming an
+    /// integer (the ctxt), separate by a comma and delimited by a
+    /// `\x00` marker.
+    #[inline(never)]
+    fn scan_embedded_hygienic_ident(&mut self) -> ast::Ident {
+        fn bump_expecting_char<'a,D:fmt::Show>(r: &mut StringReader<'a>,
+                                               c: char,
+                                               described_c: D,
+                                               where: &str) {
+            match r.curr {
+                Some(r_c) if r_c == c => r.bump(),
+                Some(r_c) => fail!("expected {}, hit {}, {}", described_c, r_c, where),
+                None      => fail!("expected {}, hit EOF, {}", described_c, where),
+            }
+        }
+
+        let where = "while scanning embedded hygienic ident";
+
+        // skip over the leading `\x00`
+        bump_expecting_char(self, '\x00', "nul-byte", where);
+
+        // skip over the "name_"
+        for c in "name_".chars() {
+            bump_expecting_char(self, c, c, where);
+        }
+
+        let start_bpos = self.last_pos;
+        let base = 10;
+
+        // find the integer representing the name
+        self.scan_digits(base);
+        let encoded_name : u32 = self.with_str_from(start_bpos, |s| {
+            num::from_str_radix(s, 10).unwrap_or_else(|| {
+                fail!("expected digits representing a name, got `{}`, {}, range [{},{}]",
+                      s, where, start_bpos, self.last_pos);
+            })
+        });
+
+        // skip over the `,`
+        bump_expecting_char(self, ',', "comma", where);
+
+        // skip over the "ctxt_"
+        for c in "ctxt_".chars() {
+            bump_expecting_char(self, c, c, where);
+        }
+
+        // find the integer representing the ctxt
+        let start_bpos = self.last_pos;
+        self.scan_digits(base);
+        let encoded_ctxt : ast::SyntaxContext = self.with_str_from(start_bpos, |s| {
+            num::from_str_radix(s, 10).unwrap_or_else(|| {
+                fail!("expected digits representing a ctxt, got `{}`, {}", s, where);
+            })
+        });
+
+        // skip over the `\x00`
+        bump_expecting_char(self, '\x00', "nul-byte", where);
+
+        ast::Ident { name: ast::Name(encoded_name),
+                     ctxt: encoded_ctxt, }
+    }
+
     /// Scan through any digits (base `radix`) or underscores, and return how
     /// many digits there were.
     fn scan_digits(&mut self, radix: uint) -> uint {
@@ -839,6 +933,17 @@ fn next_token_inner(&mut self) -> token::Token {
             return self.scan_number(c.unwrap());
         }
 
+        if self.read_embedded_ident {
+            match (c.unwrap(), self.nextch(), self.nextnextch()) {
+                ('\x00', Some('n'), Some('a')) => {
+                    let ast_ident = self.scan_embedded_hygienic_ident();
+                    let is_mod_name = self.curr_is(':') && self.nextch_is(':');
+                    return token::IDENT(ast_ident, is_mod_name);
+                }
+                _ => {}
+            }
+        }
+
         match c.expect("next_token_inner called at EOF") {
           // One-byte tokens.
           ';' => { self.bump(); return token::SEMI; }
index 5b70ed609d98f05ff06ca31cb2901a57107a1796..af1f296a6ca312eada90eea6740b029a56ae2ee3 100644 (file)
@@ -144,6 +144,8 @@ pub fn parse_stmt_from_source_str(name: String,
     maybe_aborted(p.parse_stmt(attrs),p)
 }
 
+// Note: keep in sync with `with_hygiene::parse_tts_from_source_str`
+// until #16472 is resolved.
 pub fn parse_tts_from_source_str(name: String,
                                  source: String,
                                  cfg: ast::CrateConfig,
@@ -160,6 +162,8 @@ pub fn parse_tts_from_source_str(name: String,
     maybe_aborted(p.parse_all_token_trees(),p)
 }
 
+// Note: keep in sync with `with_hygiene::new_parser_from_source_str`
+// until #16472 is resolved.
 // Create a new parser from a source string
 pub fn new_parser_from_source_str<'a>(sess: &'a ParseSess,
                                       cfg: ast::CrateConfig,
@@ -192,6 +196,8 @@ pub fn new_sub_parser_from_file<'a>(sess: &'a ParseSess,
     p
 }
 
+// Note: keep this in sync with `with_hygiene::filemap_to_parser` until
+// #16472 is resolved.
 /// Given a filemap and config, return a parser
 pub fn filemap_to_parser<'a>(sess: &'a ParseSess,
                              filemap: Rc<FileMap>,
@@ -248,6 +254,8 @@ pub fn string_to_filemap(sess: &ParseSess, source: String, path: String)
     sess.span_diagnostic.cm.new_filemap(path, source)
 }
 
+// Note: keep this in sync with `with_hygiene::filemap_to_tts` (apart
+// from the StringReader constructor), until #16472 is resolved.
 /// Given a filemap, produce a sequence of token-trees
 pub fn filemap_to_tts(sess: &ParseSess, filemap: Rc<FileMap>)
     -> Vec<ast::TokenTree> {
@@ -267,6 +275,67 @@ pub fn tts_to_parser<'a>(sess: &'a ParseSess,
     Parser::new(sess, cfg, box trdr)
 }
 
+// FIXME (Issue #16472): The `with_hygiene` mod should go away after
+// ToToken impls are revised to go directly to token-trees.
+pub mod with_hygiene {
+    use ast;
+    use codemap::FileMap;
+    use parse::parser::Parser;
+    use std::rc::Rc;
+    use super::ParseSess;
+    use super::{maybe_aborted, string_to_filemap, tts_to_parser};
+
+    // Note: keep this in sync with `super::parse_tts_from_source_str` until
+    // #16472 is resolved.
+    pub fn parse_tts_from_source_str(name: String,
+                                     source: String,
+                                     cfg: ast::CrateConfig,
+                                     sess: &ParseSess) -> Vec<ast::TokenTree> {
+        let mut p = new_parser_from_source_str(
+            sess,
+            cfg,
+            name,
+            source
+        );
+        p.quote_depth += 1u;
+        // right now this is re-creating the token trees from ... token trees.
+        maybe_aborted(p.parse_all_token_trees(),p)
+    }
+
+    // Note: keep this in sync with `super::new_parser_from_source_str` until
+    // #16472 is resolved.
+    // Create a new parser from a source string
+    fn new_parser_from_source_str<'a>(sess: &'a ParseSess,
+                                      cfg: ast::CrateConfig,
+                                      name: String,
+                                      source: String) -> Parser<'a> {
+        filemap_to_parser(sess, string_to_filemap(sess, source, name), cfg)
+    }
+
+    // Note: keep this in sync with `super::filemap_to_parserr` until
+    // #16472 is resolved.
+    /// Given a filemap and config, return a parser
+    fn filemap_to_parser<'a>(sess: &'a ParseSess,
+                             filemap: Rc<FileMap>,
+                             cfg: ast::CrateConfig) -> Parser<'a> {
+        tts_to_parser(sess, filemap_to_tts(sess, filemap), cfg)
+    }
+
+    // Note: keep this in sync with `super::filemap_to_tts` until
+    // #16472 is resolved.
+    /// Given a filemap, produce a sequence of token-trees
+    fn filemap_to_tts(sess: &ParseSess, filemap: Rc<FileMap>)
+                      -> Vec<ast::TokenTree> {
+        // it appears to me that the cfg doesn't matter here... indeed,
+        // parsing tt's probably shouldn't require a parser at all.
+        use make_reader = super::lexer::make_reader_with_embedded_idents;
+        let cfg = Vec::new();
+        let srdr = make_reader(&sess.span_diagnostic, filemap);
+        let mut p1 = Parser::new(sess, cfg, box srdr);
+        p1.parse_all_token_trees()
+    }
+}
+
 /// Abort if necessary
 pub fn maybe_aborted<T>(result: T, mut p: Parser) -> T {
     p.abort_if_errors();
index 7ea000d3aac41924ac07987f46603c435a960bef..f0920603ad12e15a4b5debee8003ee95acb15e95 100644 (file)
@@ -17,6 +17,7 @@
 use ast::{Mod, BiAdd, Arg, Arm, Attribute, BindByRef, BindByValue};
 use ast::{BiBitAnd, BiBitOr, BiBitXor, Block};
 use ast::{BlockCheckMode, UnBox};
+use ast::{CaptureByRef, CaptureByValue, CaptureClause};
 use ast::{Crate, CrateConfig, Decl, DeclItem};
 use ast::{DeclLocal, DefaultBlock, UnDeref, BiDiv, EMPTY_CTXT, EnumDef, ExplicitSelf};
 use ast::{Expr, Expr_, ExprAddrOf, ExprMatch, ExprAgain};
@@ -1985,7 +1986,7 @@ pub fn parse_bottom_expr(&mut self) -> Gc<Expr> {
                                     ExprBlock(blk));
             },
             token::BINOP(token::OR) |  token::OROR => {
-                return self.parse_lambda_expr();
+                return self.parse_lambda_expr(CaptureByValue);
             },
             // FIXME #13626: Should be able to stick in
             // token::SELF_KEYWORD_NAME
@@ -2036,6 +2037,9 @@ pub fn parse_bottom_expr(&mut self) -> Gc<Expr> {
                 hi = self.last_span.hi;
             },
             _ => {
+                if self.eat_keyword(keywords::Ref) {
+                    return self.parse_lambda_expr(CaptureByRef);
+                }
                 if self.eat_keyword(keywords::Proc) {
                     let decl = self.parse_proc_decl();
                     let body = self.parse_expr();
@@ -2696,7 +2700,8 @@ pub fn parse_if_expr(&mut self) -> Gc<Expr> {
     }
 
     // `|args| expr`
-    pub fn parse_lambda_expr(&mut self) -> Gc<Expr> {
+    pub fn parse_lambda_expr(&mut self, capture_clause: CaptureClause)
+                             -> Gc<Expr> {
         let lo = self.span.lo;
         let (decl, is_unboxed) = self.parse_fn_block_decl();
         let body = self.parse_expr();
@@ -2710,9 +2715,13 @@ pub fn parse_lambda_expr(&mut self) -> Gc<Expr> {
         });
 
         if is_unboxed {
-            self.mk_expr(lo, body.span.hi, ExprUnboxedFn(decl, fakeblock))
+            self.mk_expr(lo,
+                         body.span.hi,
+                         ExprUnboxedFn(capture_clause, decl, fakeblock))
         } else {
-            self.mk_expr(lo, body.span.hi, ExprFnBlock(decl, fakeblock))
+            self.mk_expr(lo,
+                         body.span.hi,
+                         ExprFnBlock(capture_clause, decl, fakeblock))
         }
     }
 
@@ -3157,7 +3166,16 @@ pub fn parse_pat(&mut self) -> Gc<Pat> {
                             }
                           },
                           _ => {
-                              if !enum_path.global && enum_path.segments.len() == 1 {
+                              if !enum_path.global &&
+                                    enum_path.segments.len() == 1 &&
+                                    enum_path.segments
+                                             .get(0)
+                                             .lifetimes
+                                             .len() == 0 &&
+                                    enum_path.segments
+                                             .get(0)
+                                             .types
+                                             .len() == 0 {
                                   // it could still be either an enum
                                   // or an identifier pattern, resolve
                                   // will sort it out:
index 9d4b7343c8a156fa63e039549773934a59199a8e..ed285e2aa443a58d809b13ef6e82706df800b46c 100644 (file)
@@ -58,7 +58,8 @@ pub struct State<'a> {
     literals: Option<Vec<comments::Literal> >,
     cur_cmnt_and_lit: CurrentCommentAndLiteral,
     boxes: Vec<pp::Breaks>,
-    ann: &'a PpAnn
+    ann: &'a PpAnn,
+    encode_idents_with_hygiene: bool,
 }
 
 pub fn rust_printer(writer: Box<io::Writer>) -> State<'static> {
@@ -78,7 +79,8 @@ pub fn rust_printer_annotated<'a>(writer: Box<io::Writer>,
             cur_lit: 0
         },
         boxes: Vec::new(),
-        ann: ann
+        ann: ann,
+        encode_idents_with_hygiene: false,
     }
 }
 
@@ -148,7 +150,8 @@ pub fn new(cm: &'a CodeMap,
                 cur_lit: 0
             },
             boxes: Vec::new(),
-            ann: ann
+            ann: ann,
+            encode_idents_with_hygiene: false,
         }
     }
 }
@@ -169,70 +172,77 @@ pub fn to_string(f: |&mut State| -> IoResult<()>) -> String {
     }
 }
 
+// FIXME (Issue #16472): the thing_to_string_impls macro should go away
+// after we revise the syntax::ext::quote::ToToken impls to go directly
+// to token-trees instea of thing -> string -> token-trees.
+
+macro_rules! thing_to_string_impls {
+    ($to_string:ident) => {
+
 pub fn ty_to_string(ty: &ast::Ty) -> String {
-    to_string(|s| s.print_type(ty))
+    $to_string(|s| s.print_type(ty))
 }
 
 pub fn pat_to_string(pat: &ast::Pat) -> String {
-    to_string(|s| s.print_pat(pat))
+    $to_string(|s| s.print_pat(pat))
 }
 
 pub fn arm_to_string(arm: &ast::Arm) -> String {
-    to_string(|s| s.print_arm(arm))
+    $to_string(|s| s.print_arm(arm))
 }
 
 pub fn expr_to_string(e: &ast::Expr) -> String {
-    to_string(|s| s.print_expr(e))
+    $to_string(|s| s.print_expr(e))
 }
 
 pub fn lifetime_to_string(e: &ast::Lifetime) -> String {
-    to_string(|s| s.print_lifetime(e))
+    $to_string(|s| s.print_lifetime(e))
 }
 
 pub fn tt_to_string(tt: &ast::TokenTree) -> String {
-    to_string(|s| s.print_tt(tt))
+    $to_string(|s| s.print_tt(tt))
 }
 
 pub fn tts_to_string(tts: &[ast::TokenTree]) -> String {
-    to_string(|s| s.print_tts(tts))
+    $to_string(|s| s.print_tts(tts))
 }
 
 pub fn stmt_to_string(stmt: &ast::Stmt) -> String {
-    to_string(|s| s.print_stmt(stmt))
+    $to_string(|s| s.print_stmt(stmt))
 }
 
 pub fn item_to_string(i: &ast::Item) -> String {
-    to_string(|s| s.print_item(i))
+    $to_string(|s| s.print_item(i))
 }
 
 pub fn generics_to_string(generics: &ast::Generics) -> String {
-    to_string(|s| s.print_generics(generics))
+    $to_string(|s| s.print_generics(generics))
 }
 
 pub fn ty_method_to_string(p: &ast::TypeMethod) -> String {
-    to_string(|s| s.print_ty_method(p))
+    $to_string(|s| s.print_ty_method(p))
 }
 
 pub fn method_to_string(p: &ast::Method) -> String {
-    to_string(|s| s.print_method(p))
+    $to_string(|s| s.print_method(p))
 }
 
 pub fn fn_block_to_string(p: &ast::FnDecl) -> String {
-    to_string(|s| s.print_fn_block_args(p, false))
+    $to_string(|s| s.print_fn_block_args(p, false))
 }
 
 pub fn path_to_string(p: &ast::Path) -> String {
-    to_string(|s| s.print_path(p, false))
+    $to_string(|s| s.print_path(p, false))
 }
 
 pub fn ident_to_string(id: &ast::Ident) -> String {
-    to_string(|s| s.print_ident(*id))
+    $to_string(|s| s.print_ident(*id))
 }
 
 pub fn fun_to_string(decl: &ast::FnDecl, fn_style: ast::FnStyle, name: ast::Ident,
                   opt_explicit_self: Option<ast::ExplicitSelf_>,
                   generics: &ast::Generics) -> String {
-    to_string(|s| {
+    $to_string(|s| {
         try!(s.print_fn(decl, Some(fn_style), abi::Rust,
                         name, generics, opt_explicit_self, ast::Inherited));
         try!(s.end()); // Close the head box
@@ -241,7 +251,7 @@ pub fn fun_to_string(decl: &ast::FnDecl, fn_style: ast::FnStyle, name: ast::Iden
 }
 
 pub fn block_to_string(blk: &ast::Block) -> String {
-    to_string(|s| {
+    $to_string(|s| {
         // containing cbox, will be closed by print-block at }
         try!(s.cbox(indent_unit));
         // head-ibox, will be closed by print-block after {
@@ -251,31 +261,57 @@ pub fn block_to_string(blk: &ast::Block) -> String {
 }
 
 pub fn meta_item_to_string(mi: &ast::MetaItem) -> String {
-    to_string(|s| s.print_meta_item(mi))
+    $to_string(|s| s.print_meta_item(mi))
 }
 
 pub fn attribute_to_string(attr: &ast::Attribute) -> String {
-    to_string(|s| s.print_attribute(attr))
+    $to_string(|s| s.print_attribute(attr))
 }
 
 pub fn lit_to_string(l: &ast::Lit) -> String {
-    to_string(|s| s.print_literal(l))
+    $to_string(|s| s.print_literal(l))
 }
 
 pub fn explicit_self_to_string(explicit_self: ast::ExplicitSelf_) -> String {
-    to_string(|s| s.print_explicit_self(explicit_self, ast::MutImmutable).map(|_| {}))
+    $to_string(|s| s.print_explicit_self(explicit_self, ast::MutImmutable).map(|_| {}))
 }
 
 pub fn variant_to_string(var: &ast::Variant) -> String {
-    to_string(|s| s.print_variant(var))
+    $to_string(|s| s.print_variant(var))
 }
 
 pub fn arg_to_string(arg: &ast::Arg) -> String {
-    to_string(|s| s.print_arg(arg))
+    $to_string(|s| s.print_arg(arg))
 }
 
 pub fn mac_to_string(arg: &ast::Mac) -> String {
-    to_string(|s| s.print_mac(arg))
+    $to_string(|s| s.print_mac(arg))
+}
+
+} }
+
+thing_to_string_impls!(to_string)
+
+// FIXME (Issue #16472): the whole `with_hygiene` mod should go away
+// after we revise the syntax::ext::quote::ToToken impls to go directly
+// to token-trees instea of thing -> string -> token-trees.
+
+pub mod with_hygiene {
+    use abi;
+    use ast;
+    use std::io::IoResult;
+    use super::indent_unit;
+
+    // This function is the trick that all the rest of the routines
+    // hang on.
+    pub fn to_string_hyg(f: |&mut super::State| -> IoResult<()>) -> String {
+        super::to_string(|s| {
+            s.encode_idents_with_hygiene = true;
+            f(s)
+        })
+    }
+
+    thing_to_string_impls!(to_string_hyg)
 }
 
 pub fn visibility_qualified(vis: ast::Visibility, s: &str) -> String {
@@ -1437,7 +1473,9 @@ pub fn print_expr(&mut self, expr: &ast::Expr) -> IoResult<()> {
                 }
                 try!(self.bclose_(expr.span, indent_unit));
             }
-            ast::ExprFnBlock(ref decl, ref body) => {
+            ast::ExprFnBlock(capture_clause, ref decl, ref body) => {
+                try!(self.print_capture_clause(capture_clause));
+
                 // in do/for blocks we don't want to show an empty
                 // argument list, but at this point we don't know which
                 // we are inside.
@@ -1467,7 +1505,9 @@ pub fn print_expr(&mut self, expr: &ast::Expr) -> IoResult<()> {
                 // empty box to satisfy the close.
                 try!(self.ibox(0));
             }
-            ast::ExprUnboxedFn(ref decl, ref body) => {
+            ast::ExprUnboxedFn(capture_clause, ref decl, ref body) => {
+                try!(self.print_capture_clause(capture_clause));
+
                 // in do/for blocks we don't want to show an empty
                 // argument list, but at this point we don't know which
                 // we are inside.
@@ -1672,7 +1712,12 @@ pub fn print_decl(&mut self, decl: &ast::Decl) -> IoResult<()> {
     }
 
     pub fn print_ident(&mut self, ident: ast::Ident) -> IoResult<()> {
-        word(&mut self.s, token::get_ident(ident).get())
+        if self.encode_idents_with_hygiene {
+            let encoded = ident.encode_with_hygiene();
+            word(&mut self.s, encoded.as_slice())
+        } else {
+            word(&mut self.s, token::get_ident(ident).get())
+        }
     }
 
     pub fn print_name(&mut self, name: ast::Name) -> IoResult<()> {
@@ -2030,6 +2075,14 @@ pub fn print_fn_block_args(&mut self,
         self.maybe_print_comment(decl.output.span.lo)
     }
 
+    pub fn print_capture_clause(&mut self, capture_clause: ast::CaptureClause)
+                                -> IoResult<()> {
+        match capture_clause {
+            ast::CaptureByValue => Ok(()),
+            ast::CaptureByRef => self.word_space("ref"),
+        }
+    }
+
     pub fn print_proc_args(&mut self, decl: &ast::FnDecl) -> IoResult<()> {
         try!(word(&mut self.s, "proc"));
         try!(word(&mut self.s, "("));
index 647e81db1f1c03a28be271fd542a6c8b6c0eabff..372cee9ad0988a858556ba46f3c5026196988194 100644 (file)
@@ -787,7 +787,7 @@ pub fn walk_expr<E: Clone, V: Visitor<E>>(visitor: &mut V, expression: &Expr, en
                 visitor.visit_arm(arm, env.clone())
             }
         }
-        ExprFnBlock(ref function_declaration, ref body) => {
+        ExprFnBlock(_, ref function_declaration, ref body) => {
             visitor.visit_fn(&FkFnBlock,
                              &**function_declaration,
                              &**body,
@@ -795,7 +795,7 @@ pub fn walk_expr<E: Clone, V: Visitor<E>>(visitor: &mut V, expression: &Expr, en
                              expression.id,
                              env.clone())
         }
-        ExprUnboxedFn(ref function_declaration, ref body) => {
+        ExprUnboxedFn(_, ref function_declaration, ref body) => {
             visitor.visit_fn(&FkFnBlock,
                              &**function_declaration,
                              &**body,
index ec31181e8a7483f93ce1219b0fafde67ba39aeb4..a60e95c38272bf4f08c071587cc23a7a99a991d9 100644 (file)
 
 use core::cmp::{Equal, Less, Greater};
 use core::option::{Option, Some, None};
-use core::slice::ImmutableVector;
+use core::slice;
+use core::slice::ImmutableSlice;
 use tables::normalization::{canonical_table, compatibility_table, composition_table};
 
 fn bsearch_table<T>(c: char, r: &'static [(char, &'static [T])]) -> Option<&'static [T]> {
-    match r.bsearch(|&(val, _)| {
+    match r.binary_search(|&(val, _)| {
         if c == val { Equal }
         else if val < c { Less }
         else { Greater }
     }) {
-        Some(idx) => {
+        slice::Found(idx) => {
             let (_, result) = r[idx];
             Some(result)
         }
-        None => None
+        slice::NotFound(_) => None
     }
 }
 
@@ -82,16 +83,16 @@ pub fn compose(a: char, b: char) -> Option<char> {
         match bsearch_table(a, composition_table) {
             None => None,
             Some(candidates) => {
-                match candidates.bsearch(|&(val, _)| {
+                match candidates.binary_search(|&(val, _)| {
                     if b == val { Equal }
                     else if val < b { Less }
                     else { Greater }
                 }) {
-                    Some(idx) => {
+                    slice::Found(idx) => {
                         let (_, result) = candidates[idx];
                         Some(result)
                     }
-                    None => None
+                    slice::NotFound(_) => None
                 }
             }
         }
index 4332fc596c997c8541f78aa679fe1d41029d07a9..d6010cd8d7bfbbd467664ccb9b1c237e2d44cf1e 100644 (file)
 
 fn bsearch_range_table(c: char, r: &'static [(char,char)]) -> bool {
     use core::cmp::{Equal, Less, Greater};
-    use core::slice::ImmutableVector;
-    use core::option::None;
-    r.bsearch(|&(lo,hi)| {
+    use core::slice::ImmutableSlice;
+    r.binary_search(|&(lo,hi)| {
         if lo <= c && c <= hi { Equal }
         else if hi < c { Less }
         else { Greater }
-    }) != None
+    }).found().is_some()
 }
 
 pub mod general_category {
@@ -6228,19 +6227,19 @@ pub mod normalization {
 
 
     fn bsearch_range_value_table(c: char, r: &'static [(char, char, u8)]) -> u8 {
-        use core::option::{Some, None};
         use core::cmp::{Equal, Less, Greater};
-        use core::slice::ImmutableVector;
-        match r.bsearch(|&(lo, hi, _)| {
+        use core::slice::ImmutableSlice;
+        use core::slice;
+        match r.binary_search(|&(lo, hi, _)| {
             if lo <= c && c <= hi { Equal }
             else if hi < c { Less }
             else { Greater }
         }) {
-            Some(idx) => {
+            slice::Found(idx) => {
                 let (_, _, result) = r[idx];
                 result
             }
-            None => 0
+            slice::NotFound(_) => 0
         }
     }
 
@@ -6354,9 +6353,10 @@ pub fn canonical_combining_class(c: char) -> u8 {
 
 pub mod conversions {
     use core::cmp::{Equal, Less, Greater};
-    use core::slice::ImmutableVector;
+    use core::slice::ImmutableSlice;
     use core::tuple::Tuple2;
     use core::option::{Option, Some, None};
+    use core::slice;
 
     pub fn to_lower(c: char) -> char {
         match bsearch_case_table(c, LuLl_table) {
@@ -6373,11 +6373,14 @@ pub fn to_upper(c: char) -> char {
     }
 
     fn bsearch_case_table(c: char, table: &'static [(char, char)]) -> Option<uint> {
-        table.bsearch(|&(key, _)| {
+        match table.binary_search(|&(key, _)| {
             if c == key { Equal }
             else if key < c { Less }
             else { Greater }
-        })
+        }) {
+            slice::Found(i) => Some(i),
+            slice::NotFound(_) => None,
+        }
     }
 
     static LuLl_table: &'static [(char, char)] = &[
@@ -6915,20 +6918,21 @@ fn bsearch_case_table(c: char, table: &'static [(char, char)]) -> Option<uint> {
 
 pub mod charwidth {
     use core::option::{Option, Some, None};
-    use core::slice::ImmutableVector;
+    use core::slice::ImmutableSlice;
+    use core::slice;
 
     fn bsearch_range_value_table(c: char, is_cjk: bool, r: &'static [(char, char, u8, u8)]) -> u8 {
         use core::cmp::{Equal, Less, Greater};
-        match r.bsearch(|&(lo, hi, _, _)| {
+        match r.binary_search(|&(lo, hi, _, _)| {
             if lo <= c && c <= hi { Equal }
             else if hi < c { Less }
             else { Greater }
         }) {
-            Some(idx) => {
+            slice::Found(idx) => {
                 let (_, _, r_ncjk, r_cjk) = r[idx];
                 if is_cjk { r_cjk } else { r_ncjk }
             }
-            None => 1
+            slice::NotFound(_) => 1
         }
     }
 
@@ -7112,8 +7116,8 @@ pub fn width(c: char, is_cjk: bool) -> Option<uint> {
 }
 
 pub mod grapheme {
-    use core::option::{Some, None};
-    use core::slice::ImmutableVector;
+    use core::slice::ImmutableSlice;
+    use core::slice;
 
     #[allow(non_camel_case_types)]
     #[deriving(Clone)]
@@ -7132,16 +7136,16 @@ pub enum GraphemeCat {
 
     fn bsearch_range_value_table(c: char, r: &'static [(char, char, GraphemeCat)]) -> GraphemeCat {
         use core::cmp::{Equal, Less, Greater};
-        match r.bsearch(|&(lo, hi, _)| {
+        match r.binary_search(|&(lo, hi, _)| {
             if lo <= c && c <= hi { Equal }
             else if hi < c { Less }
             else { Greater }
         }) {
-            Some(idx) => {
+            slice::Found(idx) => {
                 let (_, _, cat) = r[idx];
                 cat
             }
-            None => GC_Any
+            slice::NotFound(_) => GC_Any
         }
     }
 
index 0221b95b40434b23c721bdebd3a8df0b6e7cecb9..9ced6cb62af00f0c310167f6720f498782f9db30 100644 (file)
@@ -12,6 +12,7 @@
 
 #![crate_name = "url"]
 #![deprecated="This is being removed. Use rust-url instead. http://servo.github.io/rust-url/"]
+#![allow(deprecated)]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![license = "MIT/ASL2"]
@@ -395,7 +396,7 @@ fn maybe_push_value(map: &mut HashMap<String, Vec<String>>,
 }
 
 fn split_char_first(s: &str, c: char) -> (&str, &str) {
-    let mut iter = s.splitn(c, 1);
+    let mut iter = s.splitn(1, c);
 
     match (iter.next(), iter.next()) {
         (Some(a), Some(b)) => (a, b),
index d922dde6f85372c6e5d92c13305b10555ec51bf4..78c8fbad959ee458f96370a840c28a8a78b2f193 100644 (file)
@@ -59,6 +59,7 @@ fn main() {
 #![crate_name = "uuid"]
 #![deprecated = "This is now a cargo package located at: \
                  https://github.com/rust-lang/uuid"]
+#![allow(deprecated)]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![license = "MIT/ASL2"]
index 4936bff5768c96896ef2ddfe7bbd150d44f9416c..f6e96cca5c19c91fdd8943cacab42ed8ffaa0ea3 100644 (file)
@@ -31,6 +31,7 @@ macro_rules! unexported_macro (() => (3i))
 #[plugin_registrar]
 pub fn plugin_registrar(reg: &mut Registry) {
     reg.register_macro("make_a_1", expand_make_a_1);
+    reg.register_macro("forged_ident", expand_forged_ident);
     reg.register_syntax_extension(
         token::intern("into_foo"),
         ItemModifier(expand_into_foo));
@@ -52,4 +53,29 @@ fn expand_into_foo(cx: &mut ExtCtxt, sp: Span, attr: Gc<MetaItem>, it: Gc<Item>)
     }
 }
 
+fn expand_forged_ident(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> Box<MacResult> {
+    use syntax::ext::quote::rt::*;
+
+    if !tts.is_empty() {
+        cx.span_fatal(sp, "forged_ident takes no arguments");
+    }
+
+    // Most of this is modelled after the expansion of the `quote_expr!`
+    // macro ...
+    let parse_sess = cx.parse_sess();
+    let cfg = cx.cfg();
+
+    // ... except this is where we inject a forged identifier,
+    // and deliberately do not call `cx.parse_tts_with_hygiene`
+    // (because we are testing that this will be *rejected*
+    //  by the default parser).
+
+    let expr = {
+        let tt = cx.parse_tts("\x00name_2,ctxt_0\x00".to_string());
+        let mut parser = new_parser_from_tts(parse_sess, cfg, tt);
+        parser.parse_expr()
+    };
+    MacExpr::new(expr)
+}
+
 pub fn foo() {}
diff --git a/src/test/compile-fail-fulldeps/macro-crate-cannot-read-embedded-ident.rs b/src/test/compile-fail-fulldeps/macro-crate-cannot-read-embedded-ident.rs
new file mode 100644 (file)
index 0000000..268b6e6
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:macro_crate_test.rs
+// ignore-stage1
+// ignore-android
+// error-pattern: unknown start of token: \x00
+
+// Issue #15750 and #15962 : this test is checking that the standard
+// parser rejects embedded idents.  pnkfelix did not want to attempt
+// to make a test file that itself used the embedded ident input form,
+// since he worrid that would be difficult to work with in many text
+// editors, so instead he made a macro that expands into the embedded
+// ident form.
+
+#![feature(phase)]
+
+#[phase(plugin)]
+extern crate macro_crate_test;
+
+fn main() {
+    let x = 0;
+    assert_eq!(3, forged_ident!());
+}
diff --git a/src/test/compile-fail/borrowck-closures-unique-imm.rs b/src/test/compile-fail/borrowck-closures-unique-imm.rs
new file mode 100644 (file)
index 0000000..dfe5de0
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct Foo {
+    x: int,
+}
+
+pub fn main() {
+    let mut this = &mut Foo {
+        x: 1,
+    };
+    let r = || {
+        let p = &this.x;
+        &mut this.x; //~ ERROR cannot borrow
+    };
+    r()
+}
+
diff --git a/src/test/compile-fail/borrowck-for-loop-correct-cmt-for-pattern.rs b/src/test/compile-fail/borrowck-for-loop-correct-cmt-for-pattern.rs
new file mode 100644 (file)
index 0000000..93a4383
--- /dev/null
@@ -0,0 +1,33 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Issue #16205.
+
+struct Foo {
+    a: [Box<int>, ..3],
+}
+
+fn main() {
+    let mut y = 1i;
+    let x = Some(&mut y);
+    for &a in x.iter() {    //~ ERROR cannot move out
+    }
+
+    let f = Foo {
+        a: [box 3, box 4, box 5],
+    };
+    for &a in f.a.iter() {  //~ ERROR cannot move out
+    }
+
+    let x = Some(box 1i);
+    for &a in x.iter() {    //~ ERROR cannot move out
+    }
+}
+
diff --git a/src/test/compile-fail/intrinsic-return-address.rs b/src/test/compile-fail/intrinsic-return-address.rs
new file mode 100644 (file)
index 0000000..9c1db40
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![allow(warnings)]
+#![feature(intrinsics)]
+
+extern "rust-intrinsic" {
+    fn return_address() -> *const u8;
+}
+
+unsafe fn f() {
+    let _ = return_address();
+    //~^ ERROR invalid use of `return_address` intrinsic: function does not use out pointer
+}
+
+unsafe fn g() -> int {
+    let _ = return_address();
+    //~^ ERROR invalid use of `return_address` intrinsic: function does not use out pointer
+    0
+}
+
+fn main() {}
+
+
index 3a9380befbcb4460401308c7574c492fdc1574bd..f5cee22ac2c050c74f1939c26fa2f0d609eef186 100644 (file)
@@ -329,19 +329,19 @@ pub enum Enum {
     pub struct LockedTupleStruct(int);
 
     fn test() {
-        // None of the following should generate errors, because
-        // stability attributes now have meaning only *across* crates,
-        // not within a single crate.
+        // Only the deprecated cases of the following should generate
+        // errors, because other stability attributes now have meaning
+        // only *across* crates, not within a single crate.
 
         let foo = MethodTester;
 
-        deprecated();
-        foo.method_deprecated();
-        foo.trait_deprecated();
+        deprecated(); //~ ERROR use of deprecated item
+        foo.method_deprecated(); //~ ERROR use of deprecated item
+        foo.trait_deprecated(); //~ ERROR use of deprecated item
 
-        deprecated_text();
-        foo.method_deprecated_text();
-        foo.trait_deprecated_text();
+        deprecated_text(); //~ ERROR use of deprecated item: text
+        foo.method_deprecated_text(); //~ ERROR use of deprecated item: text
+        foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text
 
         experimental();
         foo.method_experimental();
@@ -387,8 +387,7 @@ fn test() {
         foo.method_locked_text();
         foo.trait_locked_text();
 
-
-        let _ = DeprecatedStruct { i: 0 };
+        let _ = DeprecatedStruct { i: 0 }; //~ ERROR use of deprecated item
         let _ = ExperimentalStruct { i: 0 };
         let _ = UnstableStruct { i: 0 };
         let _ = UnmarkedStruct { i: 0 };
@@ -396,7 +395,7 @@ fn test() {
         let _ = FrozenStruct { i: 0 };
         let _ = LockedStruct { i: 0 };
 
-        let _ = DeprecatedUnitStruct;
+        let _ = DeprecatedUnitStruct; //~ ERROR use of deprecated item
         let _ = ExperimentalUnitStruct;
         let _ = UnstableUnitStruct;
         let _ = UnmarkedUnitStruct;
@@ -404,7 +403,7 @@ fn test() {
         let _ = FrozenUnitStruct;
         let _ = LockedUnitStruct;
 
-        let _ = DeprecatedVariant;
+        let _ = DeprecatedVariant; //~ ERROR use of deprecated item
         let _ = ExperimentalVariant;
         let _ = UnstableVariant;
         let _ = UnmarkedVariant;
@@ -412,7 +411,7 @@ fn test() {
         let _ = FrozenVariant;
         let _ = LockedVariant;
 
-        let _ = DeprecatedTupleStruct (1);
+        let _ = DeprecatedTupleStruct (1); //~ ERROR use of deprecated item
         let _ = ExperimentalTupleStruct (1);
         let _ = UnstableTupleStruct (1);
         let _ = UnmarkedTupleStruct (1);
@@ -422,8 +421,8 @@ fn test() {
     }
 
     fn test_method_param<F: Trait>(foo: F) {
-        foo.trait_deprecated();
-        foo.trait_deprecated_text();
+        foo.trait_deprecated(); //~ ERROR use of deprecated item
+        foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text
         foo.trait_experimental();
         foo.trait_experimental_text();
         foo.trait_unstable();
@@ -433,8 +432,8 @@ fn test_method_param<F: Trait>(foo: F) {
     }
 
     fn test_method_object(foo: &Trait) {
-        foo.trait_deprecated();
-        foo.trait_deprecated_text();
+        foo.trait_deprecated(); //~ ERROR use of deprecated item
+        foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text
         foo.trait_experimental();
         foo.trait_experimental_text();
         foo.trait_unstable();
diff --git a/src/test/compile-fail/pattern-ident-path-generics.rs b/src/test/compile-fail/pattern-ident-path-generics.rs
new file mode 100644 (file)
index 0000000..ab77e37
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    match Some("foo") {
+        None::<int> => {}   //~ ERROR mismatched types
+        Some(_) => {}
+    }
+}
+
diff --git a/src/test/run-make/cannot-read-embedded-idents/Makefile b/src/test/run-make/cannot-read-embedded-idents/Makefile
new file mode 100644 (file)
index 0000000..0d047be
--- /dev/null
@@ -0,0 +1,28 @@
+-include ../tools.mk
+
+# Issue #15750, #15962 : This test ensures that our special embedded
+# ident syntax hack is not treated as legitimate input by the lexer in
+# normal mode.
+#
+# It is modelled after the `unicode-input/` test, since we need to
+# create files with syntax that can trip up normal text editting tools
+# (namely text with embedded nul-bytes).
+
+# This test attempts to run rustc itself from the compiled binary; but
+# that means that you need to set the LD_LIBRARY_PATH for rustc itself
+# while running create_and_compile, and that won't work for stage1.
+
+# FIXME ignore windows
+ifndef IS_WINDOWS
+ifeq ($(RUST_BUILD_STAGE),1)
+DOTEST=
+else
+DOTEST=dotest
+endif
+endif
+
+all: $(DOTEST)
+
+dotest:
+       $(RUSTC) create_and_compile.rs
+       $(call RUN,create_and_compile)  "$(RUSTC)" "$(TMPDIR)"
diff --git a/src/test/run-make/cannot-read-embedded-idents/create_and_compile.rs b/src/test/run-make/cannot-read-embedded-idents/create_and_compile.rs
new file mode 100644 (file)
index 0000000..2d8fa35
--- /dev/null
@@ -0,0 +1,44 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::os;
+use std::io::{File, Command};
+
+// creates broken.rs, which has the Ident \x00name_0,ctxt_0\x00
+// embedded within it, and then attempts to compile broken.rs with the
+// provided `rustc`
+
+fn main() {
+    let args = os::args();
+    let rustc = args[1].as_slice();
+    let tmpdir = Path::new(args[2].as_slice());
+
+    let main_file = tmpdir.join("broken.rs");
+    let _ = File::create(&main_file).unwrap()
+        .write_str("pub fn main() {
+                   let \x00name_0,ctxt_0\x00 = 3i;
+                   println!(\"{}\", \x00name_0,ctxt_0\x00);
+        }");
+
+    // rustc is passed to us with --out-dir and -L etc., so we
+    // can't exec it directly
+    let result = Command::new("sh")
+        .arg("-c")
+        .arg(format!("{} {}",
+                     rustc,
+                     main_file.as_str()
+                     .unwrap()).as_slice())
+        .output().unwrap();
+    let err = String::from_utf8_lossy(result.error.as_slice());
+
+    // positive test so that this test will be updated when the
+    // compiler changes.
+    assert!(err.as_slice().contains("unknown start of token"))
+}
index 4d80c09c26b337572f81066f83e58eb0ab386b4c..da5fc78f3284e4b8ab5d991b0cfab86c0c820d8c 100644 (file)
@@ -20,13 +20,13 @@ all:
        mkdir -p $(A1) $(A2) $(A3)
        $(RUSTC) --crate-type=rlib crateA1.rs
        mv $(TMPDIR)/$(call RLIB_GLOB,crateA) $(A1)
-       $(RUSTC) --crate-type=rlib -L$(A1) crateB.rs
+       $(RUSTC) --crate-type=rlib -L $(A1) crateB.rs
        $(RUSTC) --crate-type=rlib crateA2.rs
        mv $(TMPDIR)/$(call RLIB_GLOB,crateA) $(A2)
        $(RUSTC) --crate-type=rlib crateA3.rs
        mv $(TMPDIR)/$(call RLIB_GLOB,crateA) $(A3)
        # Ensure crateC fails to compile since A1 is "missing" and A2/A3 hashes do not match
-       $(RUSTC) -L$(A2) -L$(A3) crateC.rs >$(LOG) 2>&1 || true
+       $(RUSTC) -L $(A2) -L $(A3) crateC.rs >$(LOG) 2>&1 || true
        grep "error: found possibly newer version of crate \`crateA\` which \`crateB\` depends on" $(LOG)
        grep "note: perhaps this crate needs to be recompiled?" $(LOG)
        grep "note: crate \`crateA\` path #1:" $(LOG)
diff --git a/src/test/run-pass/capture-clauses-boxed-closures.rs b/src/test/run-pass/capture-clauses-boxed-closures.rs
new file mode 100644 (file)
index 0000000..c88b449
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn each<T>(x: &[T], f: |&T|) {
+    for val in x.iter() {
+        f(val)
+    }
+}
+
+fn main() {
+    let mut sum = 0u;
+    let elems = [ 1u, 2, 3, 4, 5 ];
+    each(elems, ref |val| sum += *val);
+    assert_eq!(sum, 15);
+}
+
diff --git a/src/test/run-pass/capture-clauses-unboxed-closures.rs b/src/test/run-pass/capture-clauses-unboxed-closures.rs
new file mode 100644 (file)
index 0000000..99e6d6e
--- /dev/null
@@ -0,0 +1,29 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-test
+//
+// This is ignored because it depends on #16122.
+
+#![feature(overloaded_calls, unboxed_closures)]
+
+fn each<'a,T,F:|&mut: &'a T|>(x: &'a [T], mut f: F) {
+    for val in x.iter() {
+        f(val)
+    }
+}
+
+fn main() {
+    let mut sum = 0u;
+    let elems = [ 1u, 2, 3, 4, 5 ];
+    each(elems, ref |&mut: val: &uint| sum += *val);
+    assert_eq!(sum, 15);
+}
+
index 34f1e681608a367ad99d80e2d4c363bd4e4ded98..9cee83a8598c752503962207f83c4dbff24e254d 100644 (file)
@@ -25,6 +25,7 @@
 extern crate rustuv;
 
 use std::io::{Process, Command};
+use std::time::Duration;
 
 macro_rules! succeed( ($e:expr) => (
     match $e { Ok(..) => {}, Err(e) => fail!("failure: {}", e) }
@@ -115,7 +116,7 @@ pub fn test_destroy_actually_kills(force: bool) {
     // Don't let this test time out, this should be quick
     let (tx, rx1) = channel();
     let mut t = timer::Timer::new().unwrap();
-    let rx2 = t.oneshot(1000);
+    let rx2 = t.oneshot(Duration::milliseconds(1000));
     spawn(proc() {
         select! {
             () = rx2.recv() => unsafe { libc::exit(1) },
diff --git a/src/test/run-pass/format-nan.rs b/src/test/run-pass/format-nan.rs
new file mode 100644 (file)
index 0000000..1024bc2
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub fn main() {
+    use std::f64;
+    let x = "NaN".to_string();
+    assert_eq!(format!("{}", f64::NAN), x);
+    assert_eq!(format!("{:e}", f64::NAN), x);
+    assert_eq!(format!("{:E}", f64::NAN), x);
+}
+
diff --git a/src/test/run-pass/intrinsic-return-address.rs b/src/test/run-pass/intrinsic-return-address.rs
new file mode 100644 (file)
index 0000000..91af669
--- /dev/null
@@ -0,0 +1,43 @@
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(intrinsics)]
+
+use std::ptr;
+
+struct Point {
+    x: f32,
+    y: f32,
+    z: f32,
+}
+
+extern "rust-intrinsic" {
+    fn return_address() -> *const u8;
+}
+
+fn f(result: &mut uint) -> Point {
+    unsafe {
+        *result = return_address() as uint;
+        Point {
+            x: 1.0,
+            y: 2.0,
+            z: 3.0,
+        }
+    }
+
+}
+
+fn main() {
+    let mut intrinsic_reported_address = 0;
+    let pt = f(&mut intrinsic_reported_address);
+    let actual_address = &pt as *const Point as uint;
+    assert_eq!(intrinsic_reported_address, actual_address);
+}
+
index 37e675b52ebd886d342c73f6a6f9b1e77960fad2..e21338746be2c91ff62e99b4d1b129a1cf2776bc 100644 (file)
@@ -13,6 +13,8 @@
 extern crate green;
 extern crate rustuv;
 
+use std::time::Duration;
+
 #[start]
 fn start(argc: int, argv: *const *const u8) -> int {
     green::start(argc, argv, rustuv::event_loop, main)
@@ -24,6 +26,6 @@ fn main() {
 
 fn customtask() {
     let mut timer = std::io::timer::Timer::new().unwrap();
-    let periodic = timer.periodic(10);
+    let periodic = timer.periodic(Duration::milliseconds(10));
     periodic.recv();
 }
index c24128f97e372a47954b24ce7b98182e3ad2a6df..6b6e770bc99a43bb802dccda18a2acca50bb1c2f 100644 (file)
@@ -12,6 +12,7 @@
 extern crate native;
 
 use std::io::timer;
+use std::time::Duration;
 
 #[start]
 fn start(argc: int, argv: *const *const u8) -> int {
@@ -19,5 +20,5 @@ fn start(argc: int, argv: *const *const u8) -> int {
 }
 
 fn main() {
-    timer::sleep(250);
+    timer::sleep(Duration::milliseconds(250));
 }
diff --git a/src/test/run-pass/issue-15763.rs b/src/test/run-pass/issue-15763.rs
new file mode 100644 (file)
index 0000000..6e3599b
--- /dev/null
@@ -0,0 +1,96 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+
+#[deriving(PartialEq, Show)]
+struct Bar {
+    x: int
+}
+impl Drop for Bar {
+    fn drop(&mut self) {
+        assert_eq!(self.x, 22);
+    }
+}
+
+#[deriving(PartialEq, Show)]
+struct Foo {
+    x: Bar,
+    a: int
+}
+
+fn foo() -> Result<Foo, int> {
+    return Ok(Foo {
+        x: Bar { x: 22 },
+        a: return Err(32)
+    });
+}
+
+fn baz() -> Result<Foo, int> {
+    Ok(Foo {
+        x: Bar { x: 22 },
+        a: return Err(32)
+    })
+}
+
+// explicit immediate return
+fn aa() -> int {
+    return 3;
+}
+
+// implicit immediate return
+fn bb() -> int {
+    3
+}
+
+// implicit outptr return
+fn cc() -> Result<int, int> {
+    Ok(3)
+}
+
+// explicit outptr return
+fn dd() -> Result<int, int> {
+    return Ok(3);
+}
+
+trait A {
+    fn aaa(self) -> int {
+        3
+    }
+    fn bbb(self) -> int {
+        return 3;
+    }
+    fn ccc(self) -> Result<int, int> {
+        Ok(3)
+    }
+    fn ddd(self) -> Result<int, int> {
+        return Ok(3);
+    }
+}
+
+impl A for int {}
+
+fn main() {
+    assert_eq!(foo(), Err(32));
+    assert_eq!(baz(), Err(32));
+
+    assert_eq!(aa(), 3);
+    assert_eq!(bb(), 3);
+    assert_eq!(cc().unwrap(), 3);
+    assert_eq!(dd().unwrap(), 3);
+
+    let i = box 32i as Box<A>;
+    assert_eq!(i.aaa(), 3);
+    let i = box 32i as Box<A>;
+    assert_eq!(i.bbb(), 3);
+    let i = box 32i as Box<A>;
+    assert_eq!(i.ccc().unwrap(), 3);
+    let i = box 32i as Box<A>;
+    assert_eq!(i.ddd().unwrap(), 3);
+}
index 9f08f1db41057a6b5c9935172166d5a4b85d2abe..c16319a16f2821e4b1dad17ae4a88cb8908b3b13 100644 (file)
 
 use std::comm;
 use std::io::timer::Timer;
+use std::time::Duration;
 
 pub fn main() {
     let (tx, rx) = channel();
     spawn(proc (){
         let mut timer = Timer::new().unwrap();
-        timer.sleep(10);
+        timer.sleep(Duration::milliseconds(10));
         tx.send(());
     });
     loop {
index 6f6fff15814d556f8865acac9353475f5bb09718..c1d93033ab6fea9ef85430d51f413c7e30c91402 100644 (file)
@@ -38,6 +38,7 @@ mod $name {
             use std::io::net::tcp::*;
             use std::io::test::*;
             use std::io;
+            use std::time::Duration;
 
             fn f() $b
 
@@ -72,7 +73,7 @@ fn f() $b
 
     let mut v = Vec::new();
     for _ in range(0u, 10000) {
-        match TcpStream::connect_timeout(addr, 100) {
+        match TcpStream::connect_timeout(addr, Duration::milliseconds(100)) {
             Ok(e) => v.push(e),
             Err(ref e) if e.kind == io::TimedOut => return,
             Err(e) => fail!("other error: {}", e),
@@ -87,11 +88,22 @@ fn f() $b
     let port = addr.port;
     let _l = TcpListener::bind(host.as_slice(), port).unwrap().listen();
 
-    assert!(TcpStream::connect_timeout(addr, 1000).is_ok());
+    assert!(TcpStream::connect_timeout(addr, Duration::milliseconds(1000)).is_ok());
 })
 
 iotest!(fn timeout_error() {
     let addr = next_test_ip4();
 
-    assert!(TcpStream::connect_timeout(addr, 1000).is_err());
+    assert!(TcpStream::connect_timeout(addr, Duration::milliseconds(1000)).is_err());
 })
+
+    iotest!(fn connect_timeout_zero() {
+        let addr = next_test_ip4();
+        assert!(TcpStream::connect_timeout(addr, Duration::milliseconds(0)).is_err());
+    })
+
+    iotest!(fn connect_timeout_negative() {
+        let addr = next_test_ip4();
+        assert!(TcpStream::connect_timeout(addr, Duration::milliseconds(-1)).is_err());
+    })
+
index f52a3455e4157684c16b98c5b29828db88b4f125..864d005f37344a710c85e78afc514fcea1d17de5 100644 (file)
@@ -23,6 +23,7 @@
 use std::io::net::tcp::{TcpListener, TcpStream};
 use std::io::{Acceptor, Listener};
 use std::task::TaskBuilder;
+use std::time::Duration;
 
 #[start]
 fn start(argc: int, argv: *const *const u8) -> int {
@@ -33,7 +34,7 @@ fn main() {
     // This test has a chance to time out, try to not let it time out
     spawn(proc() {
         use std::io::timer;
-        timer::sleep(30 * 1000);
+        timer::sleep(Duration::milliseconds(30 * 1000));
         println!("timed out!");
         unsafe { libc::exit(1) }
     });