]> git.lizzy.rs Git - rust.git/commitdiff
auto merge of #16474 : MatejLach/rust/cargorun_fix, r=steveklabnik
authorbors <bors@rust-lang.org>
Thu, 14 Aug 2014 23:01:17 +0000 (23:01 +0000)
committerbors <bors@rust-lang.org>
Thu, 14 Aug 2014 23:01:17 +0000 (23:01 +0000)
This fixes #16451.

While moving things around, I also removed a bunch of unnecessary whitespace, however I can put it back in if that's undesired.

Thanks.

204 files changed:
src/compiletest/header.rs
src/compiletest/runtest.rs
src/doc/guide-ffi.md
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/hash/mod.rs
src/libcollections/hash/sip.rs
src/libcollections/ringbuf.rs
src/libcollections/slice.rs
src/libcollections/str.rs
src/libcollections/string.rs
src/libcollections/trie.rs
src/libcollections/vec.rs
src/libcore/cmp.rs
src/libcore/fmt/float.rs
src/libcore/fmt/mod.rs
src/libcore/fmt/num.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/libgraphviz/maybe_owned_vec.rs
src/libgreen/sched.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/config.rs
src/librustc/front/feature_gate.rs
src/librustc/front/test.rs
src/librustc/lint/builtin.rs
src/librustc/lint/context.rs
src/librustc/lint/mod.rs
src/librustc/metadata/common.rs
src/librustc/metadata/csearch.rs
src/librustc/metadata/decoder.rs
src/librustc/metadata/encoder.rs
src/librustc/metadata/tydecode.rs
src/librustc/metadata/tyencode.rs
src/librustc/middle/astencode.rs
src/librustc/middle/borrowck/mod.rs
src/librustc/middle/check_loop.rs
src/librustc/middle/dead.rs
src/librustc/middle/expr_use_visitor.rs
src/librustc/middle/freevars.rs
src/librustc/middle/kind.rs
src/librustc/middle/liveness.rs
src/librustc/middle/mem_categorization.rs
src/librustc/middle/privacy.rs
src/librustc/middle/reachable.rs
src/librustc/middle/resolve.rs
src/librustc/middle/save/mod.rs
src/librustc/middle/stability.rs
src/librustc/middle/trans/adt.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/debuginfo.rs
src/librustc/middle/trans/expr.rs
src/librustc/middle/trans/foreign.rs
src/librustc/middle/trans/inline.rs
src/librustc/middle/trans/meth.rs
src/librustc/middle/trans/monomorphize.rs
src/librustc/middle/trans/reflect.rs
src/librustc/middle/trans/type_of.rs
src/librustc/middle/ty.rs
src/librustc/middle/ty_fold.rs
src/librustc/middle/typeck/astconv.rs
src/librustc/middle/typeck/check/method.rs
src/librustc/middle/typeck/check/mod.rs
src/librustc/middle/typeck/check/regionck.rs
src/librustc/middle/typeck/check/vtable.rs
src/librustc/middle/typeck/check/writeback.rs
src/librustc/middle/typeck/coherence.rs
src/librustc/middle/typeck/collect.rs
src/librustc/middle/typeck/infer/combine.rs
src/librustc/middle/typeck/infer/error_reporting.rs
src/librustc/middle/typeck/infer/test.rs
src/librustc/middle/typeck/variance.rs
src/librustc/util/ppaux.rs
src/librustc_back/svh.rs
src/librustdoc/clean/inline.rs
src/librustdoc/clean/mod.rs
src/librustdoc/doctree.rs
src/librustdoc/fold.rs
src/librustdoc/html/render.rs
src/librustdoc/lib.rs
src/librustdoc/passes.rs
src/librustdoc/stability_summary.rs
src/librustdoc/visit_ast.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/comm/mod.rs
src/libsyntax/ast.rs
src/libsyntax/ast_map/blocks.rs
src/libsyntax/ast_map/mod.rs
src/libsyntax/ast_util.rs
src/libsyntax/crateid.rs
src/libsyntax/ext/build.rs
src/libsyntax/ext/deriving/generic/mod.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/test/auxiliary/macro_crate_test.rs
src/test/auxiliary/privacy_reexport.rs
src/test/auxiliary/reexported_static_methods.rs
src/test/auxiliary/static_priv_by_default.rs
src/test/compile-fail-fulldeps/macro-crate-cannot-read-embedded-ident.rs [new file with mode: 0644]
src/test/compile-fail/borrowck-struct-update-with-dtor.rs
src/test/compile-fail/borrowck-unboxed-closures.rs [new file with mode: 0644]
src/test/compile-fail/glob-resolve1.rs
src/test/compile-fail/import-from-rename.rs
src/test/compile-fail/import-glob-rename.rs
src/test/compile-fail/inaccessible-test-modules.rs
src/test/compile-fail/issue-2937.rs
src/test/compile-fail/lint-dead-code-3.rs
src/test/compile-fail/lint-missing-doc.rs
src/test/compile-fail/lint-unused-imports.rs
src/test/compile-fail/match-static-const-lc.rs
src/test/compile-fail/privacy1.rs
src/test/compile-fail/regionck-unboxed-closure-lifetimes.rs [new file with mode: 0644]
src/test/compile-fail/unboxed-closures-wrong-trait.rs [new file with mode: 0644]
src/test/compile-fail/unresolved-import.rs
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-pass/auto-encode.rs
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/exponential-notation.rs
src/test/run-pass/filter-block-view-items.rs
src/test/run-pass/fsu-moves-and-copies.rs
src/test/run-pass/import.rs
src/test/run-pass/import8.rs
src/test/run-pass/issue-12684.rs
src/test/run-pass/issue-12699.rs
src/test/run-pass/issue-16441.rs [new file with mode: 0644]
src/test/run-pass/issue-5950.rs
src/test/run-pass/issue-9396.rs
src/test/run-pass/match-static-const-rename.rs
src/test/run-pass/tcp-connect-timeouts.rs
src/test/run-pass/tcp-stress.rs
src/test/run-pass/unboxed-closures-all-traits.rs [new file with mode: 0644]
src/test/run-pass/unboxed-closures-drop.rs [new file with mode: 0644]
src/test/run-pass/unboxed-closures-single-word-env.rs [new file with mode: 0644]
src/test/run-pass/use.rs
src/test/run-pass/xcrate-static-addresses.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 fb03d7bc11f5ea9e9b14c8b4f5f3c4f34cc6c6ed..600a9019e6b944478780f0c632e1a3e74297ab69 100644 (file)
@@ -350,9 +350,9 @@ linking to, and in the second case `bar` is the type of native library that the
 compiler is linking to. There are currently three known types of native
 libraries:
 
-* Dynamic - `#[link(name = "readline")]
-* Static - `#[link(name = "my_build_dependency", kind = "static")]
-* Frameworks - `#[link(name = "CoreFoundation", kind = "framework")]
+* Dynamic - `#[link(name = "readline")]`
+* Static - `#[link(name = "my_build_dependency", kind = "static")]`
+* Frameworks - `#[link(name = "CoreFoundation", kind = "framework")]`
 
 Note that frameworks are only available on OSX targets.
 
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 a4f33a5cb2fff6cf6fbc4d1fd4191070849e327d..2593ddc556b433c01845c8a068390d3e84e91ac7 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 9061a623c03f024256c5af2a8fae9cf67f5b0efe..518cd3a9891a347cda99f115337941c94de864b2 100644 (file)
@@ -135,9 +135,9 @@ The `ident` production is any nonempty Unicode string of the following form:
 
 that does _not_ occur in the set of [keywords](#keywords).
 
-Note: `XID_start` and `XID_continue` as character properties cover the
-character ranges used to form the more familiar C and Java language-family
-identifiers.
+> **Note**: `XID_start` and `XID_continue` as character properties cover the
+character ranges used to form the more familiar C and Java language-family
+identifiers.
 
 ### Delimiter-restricted productions
 
@@ -919,7 +919,7 @@ extern crate foo = "some/where/rust-foo#foo:1.0"; // a full crate ID for externa
 ##### Use declarations
 
 ~~~~ {.ebnf .gram}
-use_decl : "pub" ? "use" [ ident '=' path
+use_decl : "pub" ? "use" [ path "as" ident
                           | path_glob ] ;
 
 path_glob : ident [ "::" [ path_glob
@@ -933,13 +933,13 @@ Usually a `use` declaration is used to shorten the path required to refer to a
 module item. These declarations may appear at the top of [modules](#modules) and
 [blocks](#blocks).
 
-*Note*: Unlike in many languages,
-`use` declarations in Rust do *not* declare linkage dependency with external crates.
-Rather, [`extern crate` declarations](#extern-crate-declarations) declare linkage dependencies.
+> **Note**: Unlike in many languages,
+`use` declarations in Rust do *not* declare linkage dependency with external crates.
+Rather, [`extern crate` declarations](#extern-crate-declarations) declare linkage dependencies.
 
 Use declarations support a number of convenient shortcuts:
 
-  * Rebinding the target name as a new local name, using the syntax `use x = p::q::r;`.
+  * Rebinding the target name as a new local name, using the syntax `use p::q::r as x;`.
   * Simultaneously binding a list of paths differing only in their final element,
     using the glob-like brace syntax `use a::b::{c,d,e,f};`
   * Binding all paths matching a given prefix, using the asterisk wildcard syntax `use a::b::*;`
@@ -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.
 
@@ -1535,7 +1538,7 @@ Likewise, supertrait methods may also be called on trait objects.
 # impl Shape for int { fn area(&self) -> f64 { 0.0 } }
 # impl Circle for int { fn radius(&self) -> f64 { 0.0 } }
 # let mycircle = 0;
-let mycircle: Circle = ~mycircle as ~Circle;
+let mycircle = box mycircle as Box<Circle>;
 let nonsense = mycircle.radius() * mycircle.area();
 ~~~~
 
@@ -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
@@ -2538,8 +2573,8 @@ within a statement block is simply a way of restricting its scope to a narrow
 region containing all of its uses; it is otherwise identical in meaning to
 declaring the item outside the statement block.
 
-Note: there is no implicit capture of the function's dynamic environment when
-declaring a function-local item.
+> **Note**: there is no implicit capture of the function's dynamic environment when
+declaring a function-local item.
 
 #### Slot declarations
 
@@ -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 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 ce08f169366dad8fb0937ad13ae460a12210cf3e..354beb56d2dc3cbcf8386a2bdaf8d258e92f9418 100644 (file)
@@ -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;
index 4c7c7e3ea74bb1fa8bbd7171ac840798b1f6c1e5..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);
@@ -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 d911ca6bb14f9824d080449f2729131e6053e8eb..60ee8cc04f74c667e4f05a9479f91915f581930b 100644 (file)
@@ -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 952f28da2af891980a6bafc96d723979fdb39b1f..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,
             };
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 6bda0eed66dd937c66e3b3ff2d221eed6b2d804f..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);
             }
         }
@@ -506,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() }
 }
@@ -702,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));
             }
         }
     }
@@ -720,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,
             })
@@ -911,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
@@ -1502,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
@@ -1515,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());
@@ -1604,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 a2537a1281e918480763f5db85ac022391819eb3..bfd10c835e2061a64b71e5d3bfa13f8172bd894a 100644 (file)
@@ -273,7 +273,7 @@ mod impls {
               Less, Greater, Equal};
     use option::{Option, Some, None};
 
-    macro_rules! eq_impl(
+    macro_rules! partial_eq_impl(
         ($($t:ty)*) => ($(
             #[unstable = "Trait is unstable."]
             impl PartialEq for $t {
@@ -293,18 +293,18 @@ fn eq(&self, _other: &()) -> bool { true }
         fn ne(&self, _other: &()) -> bool { false }
     }
 
-    eq_impl!(bool char uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64)
+    partial_eq_impl!(bool char uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64)
 
-    macro_rules! totaleq_impl(
+    macro_rules! eq_impl(
         ($($t:ty)*) => ($(
             #[unstable = "Trait is unstable."]
             impl Eq for $t {}
         )*)
     )
 
-    totaleq_impl!(() bool char uint u8 u16 u32 u64 int i8 i16 i32 i64)
+    eq_impl!(() bool char uint u8 u16 u32 u64 int i8 i16 i32 i64)
 
-    macro_rules! ord_impl(
+    macro_rules! partial_ord_impl(
         ($($t:ty)*) => ($(
             #[unstable = "Trait is unstable."]
             impl PartialOrd for $t {
@@ -345,9 +345,9 @@ fn partial_cmp(&self, other: &bool) -> Option<Ordering> {
         }
     }
 
-    ord_impl!(char uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64)
+    partial_ord_impl!(char uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64)
 
-    macro_rules! totalord_impl(
+    macro_rules! ord_impl(
         ($($t:ty)*) => ($(
             #[unstable = "Trait is unstable."]
             impl Ord for $t {
@@ -375,7 +375,7 @@ fn cmp(&self, other: &bool) -> Ordering {
         }
     }
 
-    totalord_impl!(char uint u8 u16 u32 u64 int i8 i16 i32 i64)
+    ord_impl!(char uint u8 u16 u32 u64 int i8 i16 i32 i64)
 
     // & pointers
     #[unstable = "Trait is unstable."]
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 9cb64747c91b42ca2e73b144e57b8a80b10f0257..942f7f8b71019f2db0ecdf495b620f86a92caf9b 100644 (file)
@@ -24,7 +24,7 @@
 use ops::Deref;
 use result::{Ok, Err};
 use result;
-use slice::{Vector, ImmutableVector};
+use slice::{Slice, ImmutableSlice};
 use slice;
 use str::StrSlice;
 use str;
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 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 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 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 ab363a88db2d9dfb1cd76d7deb5b2065136e2b97..93320caf5f2819c8f4c115942cb9dc3f899be10d 100644 (file)
@@ -109,10 +109,14 @@ fn fold_foreign_mod(cx: &mut Context, nm: &ast::ForeignMod) -> ast::ForeignMod {
 
 fn fold_item_underscore(cx: &mut Context, item: &ast::Item_) -> ast::Item_ {
     let item = match *item {
-        ast::ItemImpl(ref a, ref b, c, ref methods) => {
-            let methods = methods.iter().filter(|m| method_in_cfg(cx, &***m))
-                .map(|x| *x).collect();
-            ast::ItemImpl((*a).clone(), (*b).clone(), c, methods)
+        ast::ItemImpl(ref a, ref b, c, ref impl_items) => {
+            let impl_items = impl_items.iter()
+                                       .filter(|ii| {
+                                           impl_item_in_cfg(cx, &**ii)
+                                       })
+                                       .map(|x| *x)
+                                       .collect();
+            ast::ItemImpl((*a).clone(), (*b).clone(), c, impl_items)
         }
         ast::ItemTrait(ref a, ref b, ref c, ref methods) => {
             let methods = methods.iter()
@@ -230,14 +234,16 @@ fn view_item_in_cfg(cx: &mut Context, item: &ast::ViewItem) -> bool {
     return (cx.in_cfg)(item.attrs.as_slice());
 }
 
-fn method_in_cfg(cx: &mut Context, meth: &ast::Method) -> bool {
-    return (cx.in_cfg)(meth.attrs.as_slice());
+fn trait_method_in_cfg(cx: &mut Context, meth: &ast::TraitItem) -> bool {
+    match *meth {
+        ast::RequiredMethod(ref meth) => (cx.in_cfg)(meth.attrs.as_slice()),
+        ast::ProvidedMethod(meth) => (cx.in_cfg)(meth.attrs.as_slice())
+    }
 }
 
-fn trait_method_in_cfg(cx: &mut Context, meth: &ast::TraitMethod) -> bool {
-    match *meth {
-        ast::Required(ref meth) => (cx.in_cfg)(meth.attrs.as_slice()),
-        ast::Provided(meth) => (cx.in_cfg)(meth.attrs.as_slice())
+fn impl_item_in_cfg(cx: &mut Context, impl_item: &ast::ImplItem) -> bool {
+    match *impl_item {
+        ast::MethodImplItem(meth) => (cx.in_cfg)(meth.attrs.as_slice()),
     }
 }
 
index 99855c7345cb4e5269a35959944a4edc71e66389..fdfbdea245bb20226ec11b5a8b511e9da02590e1 100644 (file)
@@ -314,7 +314,7 @@ fn visit_ty(&mut self, t: &ast::Ty, _: ()) {
 
             },
             ast::TyBox(_) => { self.gate_box(t.span); }
-            ast::TyUnboxedFn(_) => {
+            ast::TyUnboxedFn(..) => {
                 self.gate_feature("unboxed_closure_sugar",
                                   t.span,
                                   "unboxed closure trait sugar is experimental");
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 f929860c6864bedd969ec832027a7eba64dca114..d08e2ce527f1f60dd73ce03a28c1ee3bcb2f264c 100644 (file)
@@ -801,15 +801,19 @@ fn method_context(cx: &Context, m: &ast::Method) -> MethodContext {
         node: m.id
     };
 
-    match cx.tcx.methods.borrow().find_copy(&did) {
+    match cx.tcx.impl_or_trait_items.borrow().find_copy(&did) {
         None => cx.sess().span_bug(m.span, "missing method descriptor?!"),
         Some(md) => {
-            match md.container {
-                ty::TraitContainer(..) => TraitDefaultImpl,
-                ty::ImplContainer(cid) => {
-                    match ty::impl_trait_ref(cx.tcx, cid) {
-                        Some(..) => TraitImpl,
-                        None => PlainImpl
+            match md {
+                ty::MethodTraitItem(md) => {
+                    match md.container {
+                        ty::TraitContainer(..) => TraitDefaultImpl,
+                        ty::ImplContainer(cid) => {
+                            match ty::impl_trait_ref(cx.tcx, cid) {
+                                Some(..) => TraitImpl,
+                                None => PlainImpl
+                            }
+                        }
                     }
                 }
             }
@@ -1470,7 +1474,15 @@ fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
                                 trait_id: trait_id,
                                 method_num: index,
                                 ..
-                            }) => ty::trait_method(cx.tcx, trait_id, index).def_id
+                            }) => {
+                                match ty::trait_item(cx.tcx,
+                                                     trait_id,
+                                                     index) {
+                                    ty::MethodTraitItem(method) => {
+                                        method.def_id
+                                    }
+                                }
+                            }
                         }
                     }
                     None => return
index 59a6b08638e9170191134f9e469e4ac2aa377500..cf018927f70b460aae25795e75bf91e22387d1a9 100644 (file)
@@ -563,9 +563,9 @@ fn visit_generics(&mut self, g: &ast::Generics, _: ()) {
         visit::walk_generics(self, g, ());
     }
 
-    fn visit_trait_method(&mut self, m: &ast::TraitMethod, _: ()) {
+    fn visit_trait_item(&mut self, m: &ast::TraitItem, _: ()) {
         run_lints!(self, check_trait_method, m);
-        visit::walk_trait_method(self, m, ());
+        visit::walk_trait_item(self, m, ());
     }
 
     fn visit_opt_lifetime_ref(&mut self, sp: Span, lt: &Option<ast::Lifetime>, _: ()) {
index 1bf77b42bec049d0d7259f385036ecd45089f649..dbdda96dcb84fb7f9e1c785309d8f96a01363f35 100644 (file)
@@ -141,7 +141,7 @@ fn check_generics(&mut self, _: &Context, _: &ast::Generics) { }
     fn check_fn(&mut self, _: &Context,
         _: &FnKind, _: &ast::FnDecl, _: &ast::Block, _: Span, _: ast::NodeId) { }
     fn check_ty_method(&mut self, _: &Context, _: &ast::TypeMethod) { }
-    fn check_trait_method(&mut self, _: &Context, _: &ast::TraitMethod) { }
+    fn check_trait_method(&mut self, _: &Context, _: &ast::TraitItem) { }
     fn check_struct_def(&mut self, _: &Context,
         _: &ast::StructDef, _: ast::Ident, _: &ast::Generics, _: ast::NodeId) { }
     fn check_struct_def_post(&mut self, _: &Context,
index 8ed471ec58a5e7da3a805bb7968d690245d0dc4b..6a1c7c6c951c99a507194bbeac344014f98f0815 100644 (file)
@@ -77,7 +77,7 @@
 
 pub static tag_mod_impl: uint = 0x1f;
 
-pub static tag_item_trait_method: uint = 0x20;
+pub static tag_item_trait_item: uint = 0x20;
 
 pub static tag_item_trait_ref: uint = 0x21;
 pub static tag_item_super_trait_ref: uint = 0x22;
 
 pub static tag_item_variances: uint = 0x2a;
 /*
-  trait items contain tag_item_trait_method elements,
-  impl items contain tag_item_impl_method elements, and classes
+  trait items contain tag_item_trait_item elements,
+  impl items contain tag_item_impl_item elements, and classes
   have both. That's because some code treats classes like traits,
   and other code treats them like impls. Because classes can contain
-  both, tag_item_trait_method and tag_item_impl_method have to be two
+  both, tag_item_trait_item and tag_item_impl_item have to be two
   different tags.
  */
-pub static tag_item_impl_method: uint = 0x30;
+pub static tag_item_impl_item: uint = 0x30;
 pub static tag_item_trait_method_explicit_self: uint = 0x31;
 
 
@@ -139,11 +139,12 @@ pub enum astencode_tag { // Reserves 0x40 -- 0x5f
     tag_table_adjustments = 0x51,
     tag_table_moves_map = 0x52,
     tag_table_capture_map = 0x53,
-    tag_table_unboxed_closure_type = 0x54,
+    tag_table_unboxed_closures = 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;
@@ -153,9 +154,11 @@ pub fn from_uint(value : uint) -> Option<astencode_tag> {
     }
 }
 
-pub static tag_item_trait_method_sort: uint = 0x60;
+pub static tag_item_trait_item_sort: uint = 0x60;
 
-pub static tag_item_impl_type_basename: uint = 0x61;
+pub static tag_item_trait_parent_sort: uint = 0x61;
+
+pub static tag_item_impl_type_basename: uint = 0x62;
 
 pub static tag_crate_triple: uint = 0x66;
 
@@ -228,9 +231,11 @@ pub struct LinkMeta {
 pub static tag_unboxed_closures: uint = 0x95;
 pub static tag_unboxed_closure: uint = 0x96;
 pub static tag_unboxed_closure_type: uint = 0x97;
+pub static tag_unboxed_closure_kind: uint = 0x98;
+
+pub static tag_struct_fields: uint = 0x99;
+pub static tag_struct_field: uint = 0x9a;
+pub static tag_struct_field_id: uint = 0x9b;
 
-pub static tag_struct_fields: uint = 0x98;
-pub static tag_struct_field: uint = 0x99;
-pub static tag_struct_field_id: uint = 0x9a;
+pub static tag_attribute_is_sugared_doc: uint = 0x9c;
 
-pub static tag_attribute_is_sugared_doc: uint = 0x9b;
index 252d19bbb237b838cab6db360de0bcc8b1e3c018..ac161ef8bdefefde46dd9cf72e41ad12d7582459 100644 (file)
@@ -16,6 +16,7 @@
 use metadata::cstore;
 use metadata::decoder;
 use middle::lang_items;
+use middle::resolve;
 use middle::ty;
 use middle::typeck;
 use middle::subst::VecPerParamSpace;
@@ -121,30 +122,33 @@ pub fn get_enum_variants(tcx: &ty::ctxt, def: ast::DefId)
 }
 
 /// Returns information about the given implementation.
-pub fn get_impl_methods(cstore: &cstore::CStore, impl_def_id: ast::DefId)
-                        -> Vec<ast::DefId> {
+pub fn get_impl_items(cstore: &cstore::CStore, impl_def_id: ast::DefId)
+                      -> Vec<ty::ImplOrTraitItemId> {
     let cdata = cstore.get_crate_data(impl_def_id.krate);
-    decoder::get_impl_methods(&*cdata, impl_def_id.node)
+    decoder::get_impl_items(&*cdata, impl_def_id.node)
 }
 
-pub fn get_method(tcx: &ty::ctxt, def: ast::DefId) -> ty::Method {
+pub fn get_impl_or_trait_item(tcx: &ty::ctxt, def: ast::DefId)
+                              -> ty::ImplOrTraitItem {
     let cdata = tcx.sess.cstore.get_crate_data(def.krate);
-    decoder::get_method(tcx.sess.cstore.intr.clone(), &*cdata, def.node, tcx)
+    decoder::get_impl_or_trait_item(tcx.sess.cstore.intr.clone(),
+                                    &*cdata,
+                                    def.node,
+                                    tcx)
 }
 
-pub fn get_method_name_and_explicit_self(cstore: &cstore::CStore,
-                                         def: ast::DefId)
-                                         -> (ast::Ident,
-                                             ty::ExplicitSelfCategory)
-{
+pub fn get_trait_item_name_and_kind(cstore: &cstore::CStore, def: ast::DefId)
+                                    -> (ast::Ident, resolve::TraitItemKind) {
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_method_name_and_explicit_self(cstore.intr.clone(), &*cdata, def.node)
+    decoder::get_trait_item_name_and_kind(cstore.intr.clone(),
+                                          &*cdata,
+                                          def.node)
 }
 
-pub fn get_trait_method_def_ids(cstore: &cstore::CStore,
-                                def: ast::DefId) -> Vec<ast::DefId> {
+pub fn get_trait_item_def_ids(cstore: &cstore::CStore, def: ast::DefId)
+                              -> Vec<ty::ImplOrTraitItemId> {
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_trait_method_def_ids(&*cdata, def.node)
+    decoder::get_trait_item_def_ids(&*cdata, def.node)
 }
 
 pub fn get_item_variances(cstore: &cstore::CStore,
@@ -286,15 +290,15 @@ pub fn each_implementation_for_trait(cstore: &cstore::CStore,
     decoder::each_implementation_for_trait(&*cdata, def_id.node, callback)
 }
 
-/// If the given def ID describes a method belonging to a trait (either a
+/// If the given def ID describes an item belonging to a trait (either a
 /// default method or an implementation of a trait method), returns the ID of
 /// the trait that the method belongs to. Otherwise, returns `None`.
-pub fn get_trait_of_method(cstore: &cstore::CStore,
-                           def_id: ast::DefId,
-                           tcx: &ty::ctxt)
-                           -> Option<ast::DefId> {
+pub fn get_trait_of_item(cstore: &cstore::CStore,
+                         def_id: ast::DefId,
+                         tcx: &ty::ctxt)
+                         -> Option<ast::DefId> {
     let cdata = cstore.get_crate_data(def_id.krate);
-    decoder::get_trait_of_method(&*cdata, def_id.node, tcx)
+    decoder::get_trait_of_item(&*cdata, def_id.node, tcx)
 }
 
 pub fn get_tuple_struct_definition_if_ctor(cstore: &cstore::CStore,
index c9807a18383e8ef5bc932222cfb55f306e44b121..74810261d4a750de1bada065dba5e80ec2404376 100644 (file)
 use metadata::csearch::StaticMethodInfo;
 use metadata::csearch;
 use metadata::cstore;
-use metadata::tydecode::{parse_ty_data, parse_def_id,
-                         parse_type_param_def_data,
-                         parse_bare_fn_ty_data, parse_trait_ref_data};
-use middle::lang_items;
+use metadata::tydecode::{parse_ty_data, parse_def_id};
+use metadata::tydecode::{parse_type_param_def_data, parse_bare_fn_ty_data};
+use metadata::tydecode::{parse_trait_ref_data};
 use middle::def;
+use middle::lang_items;
+use middle::resolve::TraitItemKind;
 use middle::subst;
 use middle::ty::{ImplContainer, TraitContainer};
 use middle::ty;
@@ -165,9 +166,9 @@ fn item_visibility(item: rbml::Doc) -> ast::Visibility {
     }
 }
 
-fn item_method_sort(item: rbml::Doc) -> char {
+fn item_sort(item: rbml::Doc) -> char {
     let mut ret = 'r';
-    reader::tagged_docs(item, tag_item_trait_method_sort, |doc| {
+    reader::tagged_docs(item, tag_item_trait_item_sort, |doc| {
         ret = doc.as_str_slice().as_bytes()[0] as char;
         false
     });
@@ -338,15 +339,18 @@ fn item_to_def_like(item: rbml::Doc, did: ast::DefId, cnum: ast::CrateNum)
         UnsafeFn  => DlDef(def::DefFn(did, ast::UnsafeFn)),
         Fn        => DlDef(def::DefFn(did, ast::NormalFn)),
         StaticMethod | UnsafeStaticMethod => {
-            let fn_style = if fam == UnsafeStaticMethod { ast::UnsafeFn } else
-                { ast::NormalFn };
+            let fn_style = if fam == UnsafeStaticMethod {
+                ast::UnsafeFn
+            } else {
+                ast::NormalFn
+            };
             // def_static_method carries an optional field of its enclosing
             // trait or enclosing impl (if this is an inherent static method).
             // So we need to detect whether this is in a trait or not, which
             // we do through the mildly hacky way of checking whether there is
-            // a trait_method_sort.
+            // a trait_parent_sort.
             let provenance = if reader::maybe_get_doc(
-                  item, tag_item_trait_method_sort).is_some() {
+                  item, tag_item_trait_parent_sort).is_some() {
                 def::FromTrait(item_reqd_and_translated_parent_item(cnum,
                                                                     item))
             } else {
@@ -536,14 +540,11 @@ fn each_child_of_item_or_crate(intr: Rc<IdentInterner>,
             None => {}
             Some(inherent_impl_doc) => {
                 let _ = reader::tagged_docs(inherent_impl_doc,
-                                            tag_item_impl_method,
-                                            |impl_method_def_id_doc| {
-                    let impl_method_def_id =
-                        reader::with_doc_data(impl_method_def_id_doc,
-                                              parse_def_id);
-                    let impl_method_def_id =
-                        translate_def_id(cdata, impl_method_def_id);
-                    match maybe_find_item(impl_method_def_id.node, items) {
+                                            tag_item_impl_item,
+                                            |impl_item_def_id_doc| {
+                    let impl_item_def_id = item_def_id(impl_item_def_id_doc,
+                                                       cdata);
+                    match maybe_find_item(impl_item_def_id.node, items) {
                         None => {}
                         Some(impl_method_doc) => {
                             match item_family(impl_method_doc) {
@@ -554,7 +555,7 @@ fn each_child_of_item_or_crate(intr: Rc<IdentInterner>,
                                         item_name(&*intr, impl_method_doc);
                                     let static_method_def_like =
                                         item_to_def_like(impl_method_doc,
-                                                         impl_method_def_id,
+                                                         impl_item_def_id,
                                                          cdata.cnum);
                                     callback(static_method_def_like,
                                              static_method_name,
@@ -752,33 +753,46 @@ fn get_mutability(ch: u8) -> ast::Mutability {
     }
 }
 
-/// Returns information about the given implementation.
-pub fn get_impl_methods(cdata: Cmd, impl_id: ast::NodeId) -> Vec<ast::DefId> {
-    let mut methods = Vec::new();
+/// Returns the def IDs of all the items in the given implementation.
+pub fn get_impl_items(cdata: Cmd, impl_id: ast::NodeId)
+                      -> Vec<ty::ImplOrTraitItemId> {
+    let mut impl_items = Vec::new();
     reader::tagged_docs(lookup_item(impl_id, cdata.data()),
-                        tag_item_impl_method, |doc| {
-        let m_did = reader::with_doc_data(doc, parse_def_id);
-        methods.push(translate_def_id(cdata, m_did));
+                        tag_item_impl_item, |doc| {
+        let def_id = item_def_id(doc, cdata);
+        match item_sort(doc) {
+            'r' | 'p' => impl_items.push(ty::MethodTraitItemId(def_id)),
+            _ => fail!("unknown impl item sort"),
+        }
         true
     });
 
-    methods
+    impl_items
 }
 
-pub fn get_method_name_and_explicit_self(intr: Rc<IdentInterner>,
-                                         cdata: Cmd,
-                                         id: ast::NodeId)
-                                         -> (ast::Ident,
-                                             ty::ExplicitSelfCategory) {
-    let method_doc = lookup_item(id, cdata.data());
-    let name = item_name(&*intr, method_doc);
-    let explicit_self = get_explicit_self(method_doc);
-    (name, explicit_self)
+pub fn get_trait_item_name_and_kind(intr: Rc<IdentInterner>,
+                                    cdata: Cmd,
+                                    id: ast::NodeId)
+                                    -> (ast::Ident, TraitItemKind) {
+    let doc = lookup_item(id, cdata.data());
+    let name = item_name(&*intr, doc);
+    match item_sort(doc) {
+        'r' | 'p' => {
+            let explicit_self = get_explicit_self(doc);
+            (name, TraitItemKind::from_explicit_self_category(explicit_self))
+        }
+        c => {
+            fail!("get_trait_item_name_and_kind(): unknown trait item kind \
+                   in metadata: `{}`", c)
+        }
+    }
 }
 
-pub fn get_method(intr: Rc<IdentInterner>, cdata: Cmd, id: ast::NodeId,
-                  tcx: &ty::ctxt) -> ty::Method
-{
+pub fn get_impl_or_trait_item(intr: Rc<IdentInterner>,
+                              cdata: Cmd,
+                              id: ast::NodeId,
+                              tcx: &ty::ctxt)
+                              -> ty::ImplOrTraitItem {
     let method_doc = lookup_item(id, cdata.data());
     let def_id = item_def_id(method_doc, cdata);
 
@@ -791,36 +805,45 @@ pub fn get_method(intr: Rc<IdentInterner>, cdata: Cmd, id: ast::NodeId,
     };
 
     let name = item_name(&*intr, method_doc);
-    let type_param_defs = item_ty_param_defs(method_doc, tcx, cdata,
-                                             tag_item_method_tps);
-    let rp_defs = item_region_param_defs(method_doc, cdata);
-    let fty = doc_method_fty(method_doc, tcx, cdata);
-    let vis = item_visibility(method_doc);
-    let explicit_self = get_explicit_self(method_doc);
-    let provided_source = get_provided_source(method_doc, cdata);
-
-    ty::Method::new(
-        name,
-        ty::Generics {
-            types: type_param_defs,
-            regions: rp_defs,
-        },
-        fty,
-        explicit_self,
-        vis,
-        def_id,
-        container,
-        provided_source
-    )
-}
-
-pub fn get_trait_method_def_ids(cdata: Cmd,
-                                id: ast::NodeId) -> Vec<ast::DefId> {
+
+    match item_sort(method_doc) {
+        'r' | 'p' => {
+            let type_param_defs = item_ty_param_defs(method_doc, tcx, cdata,
+                                                     tag_item_method_tps);
+            let rp_defs = item_region_param_defs(method_doc, cdata);
+            let fty = doc_method_fty(method_doc, tcx, cdata);
+            let vis = item_visibility(method_doc);
+            let explicit_self = get_explicit_self(method_doc);
+            let provided_source = get_provided_source(method_doc, cdata);
+
+            let generics = ty::Generics {
+                types: type_param_defs,
+                regions: rp_defs,
+            };
+            ty::MethodTraitItem(Rc::new(ty::Method::new(name,
+                                                        generics,
+                                                        fty,
+                                                        explicit_self,
+                                                        vis,
+                                                        def_id,
+                                                        container,
+                                                        provided_source)))
+        }
+        _ => fail!("unknown impl/trait item sort"),
+    }
+}
+
+pub fn get_trait_item_def_ids(cdata: Cmd, id: ast::NodeId)
+                              -> Vec<ty::ImplOrTraitItemId> {
     let data = cdata.data();
     let item = lookup_item(id, data);
     let mut result = Vec::new();
-    reader::tagged_docs(item, tag_item_trait_method, |mth| {
-        result.push(item_def_id(mth, cdata));
+    reader::tagged_docs(item, tag_item_trait_item, |mth| {
+        let def_id = item_def_id(mth, cdata);
+        match item_sort(mth) {
+            'r' | 'p' => result.push(ty::MethodTraitItemId(def_id)),
+            _ => fail!("unknown trait item sort"),
+        }
         true
     });
     result
@@ -834,19 +857,29 @@ pub fn get_item_variances(cdata: Cmd, id: ast::NodeId) -> ty::ItemVariances {
     Decodable::decode(&mut decoder).unwrap()
 }
 
-pub fn get_provided_trait_methods(intr: Rc<IdentInterner>, cdata: Cmd,
-                                  id: ast::NodeId, tcx: &ty::ctxt)
+pub fn get_provided_trait_methods(intr: Rc<IdentInterner>,
+                                  cdata: Cmd,
+                                  id: ast::NodeId,
+                                  tcx: &ty::ctxt)
                                   -> Vec<Rc<ty::Method>> {
     let data = cdata.data();
     let item = lookup_item(id, data);
     let mut result = Vec::new();
 
-    reader::tagged_docs(item, tag_item_trait_method, |mth_id| {
+    reader::tagged_docs(item, tag_item_trait_item, |mth_id| {
         let did = item_def_id(mth_id, cdata);
         let mth = lookup_item(did.node, data);
 
-        if item_method_sort(mth) == 'p' {
-            result.push(Rc::new(get_method(intr.clone(), cdata, did.node, tcx)));
+        if item_sort(mth) == 'p' {
+            let trait_item = get_impl_or_trait_item(intr.clone(),
+                                                    cdata,
+                                                    did.node,
+                                                    tcx);
+            match trait_item {
+                ty::MethodTraitItem(ref method) => {
+                    result.push((*method).clone())
+                }
+            }
         }
         true
     });
@@ -905,8 +938,8 @@ pub fn get_static_methods_if_impl(intr: Rc<IdentInterner>,
     if !ret { return None }
 
     let mut impl_method_ids = Vec::new();
-    reader::tagged_docs(item, tag_item_impl_method, |impl_method_doc| {
-        impl_method_ids.push(reader::with_doc_data(impl_method_doc, parse_def_id));
+    reader::tagged_docs(item, tag_item_impl_item, |impl_method_doc| {
+        impl_method_ids.push(item_def_id(impl_method_doc, cdata));
         true
     });
 
@@ -1230,8 +1263,8 @@ pub fn each_implementation_for_trait(cdata: Cmd,
     });
 }
 
-pub fn get_trait_of_method(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt)
-                           -> Option<ast::DefId> {
+pub fn get_trait_of_item(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt)
+                         -> Option<ast::DefId> {
     let item_doc = lookup_item(id, cdata.data());
     let parent_item_id = match item_parent_item(item_doc) {
         None => return None,
index 9b31d3a1b6460f7fe55a7266268568f0479dfee2..1d426aaaf5c91fdb7c57d2659248c11b3ac2721d 100644 (file)
 use rbml::writer;
 use rbml::io::SeekableMemWriter;
 
-/// A borrowed version of ast::InlinedItem.
+/// A borrowed version of `ast::InlinedItem`.
 pub enum InlinedItemRef<'a> {
     IIItemRef(&'a ast::Item),
-    IIMethodRef(ast::DefId, bool, &'a ast::Method),
+    IITraitItemRef(ast::DefId, InlinedTraitItemRef<'a>),
     IIForeignRef(&'a ast::ForeignItem)
 }
 
+/// A borrowed version of `ast::InlinedTraitItem`.
+pub enum InlinedTraitItemRef<'a> {
+    ProvidedInlinedTraitItemRef(&'a Method),
+    RequiredInlinedTraitItemRef(&'a Method),
+}
+
 pub type Encoder<'a> = writer::Encoder<'a, SeekableMemWriter>;
 
 pub type EncodeInlinedItem<'a> = |ecx: &EncodeContext,
@@ -403,14 +409,24 @@ fn encode_reexported_static_base_methods(ecx: &EncodeContext,
                                          rbml_w: &mut Encoder,
                                          exp: &middle::resolve::Export2)
                                          -> bool {
-    let impl_methods = ecx.tcx.impl_methods.borrow();
+    let impl_items = ecx.tcx.impl_items.borrow();
     match ecx.tcx.inherent_impls.borrow().find(&exp.def_id) {
         Some(implementations) => {
             for base_impl_did in implementations.borrow().iter() {
-                for &method_did in impl_methods.get(base_impl_did).iter() {
-                    let m = ty::method(ecx.tcx, method_did);
-                    if m.explicit_self == ty::StaticExplicitSelfCategory {
-                        encode_reexported_static_method(rbml_w, exp, m.def_id, m.ident);
+                for &method_did in impl_items.get(base_impl_did).iter() {
+                    let impl_item = ty::impl_or_trait_item(
+                        ecx.tcx,
+                        method_did.def_id());
+                    match impl_item {
+                        ty::MethodTraitItem(ref m) => {
+                            if m.explicit_self ==
+                                    ty::StaticExplicitSelfCategory {
+                                encode_reexported_static_method(rbml_w,
+                                                                exp,
+                                                                m.def_id,
+                                                                m.ident);
+                            }
+                        }
                     }
                 }
             }
@@ -425,11 +441,18 @@ fn encode_reexported_static_trait_methods(ecx: &EncodeContext,
                                           rbml_w: &mut Encoder,
                                           exp: &middle::resolve::Export2)
                                           -> bool {
-    match ecx.tcx.trait_methods_cache.borrow().find(&exp.def_id) {
-        Some(methods) => {
-            for m in methods.iter() {
-                if m.explicit_self == ty::StaticExplicitSelfCategory {
-                    encode_reexported_static_method(rbml_w, exp, m.def_id, m.ident);
+    match ecx.tcx.trait_items_cache.borrow().find(&exp.def_id) {
+        Some(trait_items) => {
+            for trait_item in trait_items.iter() {
+                match *trait_item {
+                    ty::MethodTraitItem(ref m) if m.explicit_self ==
+                            ty::StaticExplicitSelfCategory => {
+                        encode_reexported_static_method(rbml_w,
+                                                        exp,
+                                                        m.def_id,
+                                                        m.ident);
+                    }
+                    _ => {}
                 }
             }
 
@@ -630,6 +653,18 @@ fn encode_visibility(rbml_w: &mut Encoder, visibility: Visibility) {
     rbml_w.end_tag();
 }
 
+fn encode_unboxed_closure_kind(rbml_w: &mut Encoder,
+                               kind: ty::UnboxedClosureKind) {
+    rbml_w.start_tag(tag_unboxed_closure_kind);
+    let ch = match kind {
+        ty::FnUnboxedClosureKind => 'f',
+        ty::FnMutUnboxedClosureKind => 'm',
+        ty::FnOnceUnboxedClosureKind => 'o',
+    };
+    rbml_w.wr_str(ch.to_string().as_slice());
+    rbml_w.end_tag();
+}
+
 fn encode_explicit_self(rbml_w: &mut Encoder,
                         explicit_self: &ty::ExplicitSelfCategory) {
     rbml_w.start_tag(tag_item_trait_method_explicit_self);
@@ -663,8 +698,14 @@ fn encode_mutability(rbml_w: &mut Encoder,
     }
 }
 
-fn encode_method_sort(rbml_w: &mut Encoder, sort: char) {
-    rbml_w.start_tag(tag_item_trait_method_sort);
+fn encode_item_sort(rbml_w: &mut Encoder, sort: char) {
+    rbml_w.start_tag(tag_item_trait_item_sort);
+    rbml_w.writer.write(&[ sort as u8 ]);
+    rbml_w.end_tag();
+}
+
+fn encode_parent_sort(rbml_w: &mut Encoder, sort: char) {
+    rbml_w.start_tag(tag_item_trait_parent_sort);
     rbml_w.writer.write(&[ sort as u8 ]);
     rbml_w.end_tag();
 }
@@ -787,6 +828,7 @@ fn encode_info_for_method(ecx: &EncodeContext,
 
     encode_method_ty_fields(ecx, rbml_w, m);
     encode_parent_item(rbml_w, local_def(parent_id));
+    encode_item_sort(rbml_w, 'r');
 
     let stab = stability::lookup(ecx.tcx, m.def_id);
     encode_stability(rbml_w, stab);
@@ -807,9 +849,11 @@ fn encode_info_for_method(ecx: &EncodeContext,
     for &ast_method in ast_method_opt.iter() {
         let any_types = !pty.generics.types.is_empty();
         if any_types || is_default_impl || should_inline(ast_method.attrs.as_slice()) {
-            encode_inlined_item(ecx, rbml_w,
-                                IIMethodRef(local_def(parent_id), false,
-                                            &*ast_method));
+            encode_inlined_item(ecx,
+                                rbml_w,
+                                IITraitItemRef(local_def(parent_id),
+                                               RequiredInlinedTraitItemRef(
+                                                   &*ast_method)));
         } else {
             encode_symbol(ecx, rbml_w, m.def_id.node);
         }
@@ -1094,11 +1138,11 @@ fn add_to_index(item: &Item, rbml_w: &Encoder,
             None => {}
         }
       }
-      ItemImpl(_, ref opt_trait, ty, ref ast_methods) => {
+      ItemImpl(_, ref opt_trait, ty, ref ast_items) => {
         // We need to encode information about the default methods we
         // have inherited, so we drive this based on the impl structure.
-        let impl_methods = tcx.impl_methods.borrow();
-        let methods = impl_methods.get(&def_id);
+        let impl_items = tcx.impl_items.borrow();
+        let items = impl_items.get(&def_id);
 
         add_to_index(item, rbml_w, index);
         rbml_w.start_tag(tag_items_data_item);
@@ -1116,10 +1160,14 @@ fn add_to_index(item: &Item, rbml_w: &Encoder,
             }
             _ => {}
         }
-        for &method_def_id in methods.iter() {
-            rbml_w.start_tag(tag_item_impl_method);
-            let s = def_to_string(method_def_id);
-            rbml_w.writer.write(s.as_bytes());
+        for &item_def_id in items.iter() {
+            rbml_w.start_tag(tag_item_impl_item);
+            match item_def_id {
+                ty::MethodTraitItemId(item_def_id) => {
+                    encode_def_id(rbml_w, item_def_id);
+                    encode_item_sort(rbml_w, 'r');
+                }
+            }
             rbml_w.end_tag();
         }
         for ast_trait_ref in opt_trait.iter() {
@@ -1133,27 +1181,46 @@ fn add_to_index(item: &Item, rbml_w: &Encoder,
         encode_stability(rbml_w, stab);
         rbml_w.end_tag();
 
-        // Iterate down the methods, emitting them. We rely on the
-        // assumption that all of the actually implemented methods
+        // Iterate down the trait items, emitting them. We rely on the
+        // assumption that all of the actually implemented trait items
         // appear first in the impl structure, in the same order they do
         // in the ast. This is a little sketchy.
-        let num_implemented_methods = ast_methods.len();
-        for (i, &method_def_id) in methods.iter().enumerate() {
-            let ast_method = if i < num_implemented_methods {
-                Some(*ast_methods.get(i))
-            } else { None };
+        let num_implemented_methods = ast_items.len();
+        for (i, &trait_item_def_id) in items.iter().enumerate() {
+            let ast_item = if i < num_implemented_methods {
+                Some(*ast_items.get(i))
+            } else {
+                None
+            };
 
             index.push(entry {
-                val: method_def_id.node as i64,
+                val: trait_item_def_id.def_id().node as i64,
                 pos: rbml_w.writer.tell().unwrap(),
             });
-            encode_info_for_method(ecx,
-                                   rbml_w,
-                                   &*ty::method(tcx, method_def_id),
-                                   path.clone(),
-                                   false,
-                                   item.id,
-                                   ast_method)
+
+            let trait_item_type =
+                ty::impl_or_trait_item(tcx, trait_item_def_id.def_id());
+            match (trait_item_type, ast_item) {
+                (ty::MethodTraitItem(method_type),
+                 Some(ast::MethodImplItem(ast_method))) => {
+                    encode_info_for_method(ecx,
+                                           rbml_w,
+                                           &*method_type,
+                                           path.clone(),
+                                           false,
+                                           item.id,
+                                           Some(ast_method))
+                }
+                (ty::MethodTraitItem(method_type), None) => {
+                    encode_info_for_method(ecx,
+                                           rbml_w,
+                                           &*method_type,
+                                           path.clone(),
+                                           false,
+                                           item.id,
+                                           None)
+                }
+            }
         }
       }
       ItemTrait(_, _, ref super_traits, ref ms) => {
@@ -1172,13 +1239,18 @@ fn add_to_index(item: &Item, rbml_w: &Encoder,
         encode_attributes(rbml_w, item.attrs.as_slice());
         encode_visibility(rbml_w, vis);
         encode_stability(rbml_w, stab);
-        for &method_def_id in ty::trait_method_def_ids(tcx, def_id).iter() {
-            rbml_w.start_tag(tag_item_trait_method);
-            encode_def_id(rbml_w, method_def_id);
+        for &method_def_id in ty::trait_item_def_ids(tcx, def_id).iter() {
+            rbml_w.start_tag(tag_item_trait_item);
+            match method_def_id {
+                ty::MethodTraitItemId(method_def_id) => {
+                    encode_def_id(rbml_w, method_def_id);
+                    encode_item_sort(rbml_w, 'r');
+                }
+            }
             rbml_w.end_tag();
 
             rbml_w.start_tag(tag_mod_child);
-            rbml_w.wr_str(def_to_string(method_def_id).as_slice());
+            rbml_w.wr_str(def_to_string(method_def_id.def_id()).as_slice());
             rbml_w.end_tag();
         }
         encode_path(rbml_w, path.clone());
@@ -1195,66 +1267,83 @@ fn add_to_index(item: &Item, rbml_w: &Encoder,
 
         rbml_w.end_tag();
 
-        // Now output the method info for each method.
-        let r = ty::trait_method_def_ids(tcx, def_id);
-        for (i, &method_def_id) in r.iter().enumerate() {
-            assert_eq!(method_def_id.krate, ast::LOCAL_CRATE);
-
-            let method_ty = ty::method(tcx, method_def_id);
+        // Now output the trait item info for each trait item.
+        let r = ty::trait_item_def_ids(tcx, def_id);
+        for (i, &item_def_id) in r.iter().enumerate() {
+            assert_eq!(item_def_id.def_id().krate, ast::LOCAL_CRATE);
 
             index.push(entry {
-                val: method_def_id.node as i64,
+                val: item_def_id.def_id().node as i64,
                 pos: rbml_w.writer.tell().unwrap(),
             });
 
             rbml_w.start_tag(tag_items_data_item);
 
-            encode_method_ty_fields(ecx, rbml_w, &*method_ty);
-            encode_parent_item(rbml_w, def_id);
-
-            let stab = stability::lookup(tcx, method_def_id);
-            encode_stability(rbml_w, stab);
-
-            let elem = ast_map::PathName(method_ty.ident.name);
-            encode_path(rbml_w, path.clone().chain(Some(elem).move_iter()));
-
-            match method_ty.explicit_self {
-                ty::StaticExplicitSelfCategory => {
-                    encode_family(rbml_w,
-                                  fn_style_static_method_family(
-                                      method_ty.fty.fn_style));
-
-                    let pty = ty::lookup_item_type(tcx, method_def_id);
-                    encode_bounds_and_type(rbml_w, ecx, &pty);
-                }
-
-                _ => {
-                    encode_family(rbml_w,
-                                  style_fn_family(
-                                      method_ty.fty.fn_style));
-                }
-            }
-
-            match ms.get(i) {
-                &Required(ref tm) => {
-                    encode_attributes(rbml_w, tm.attrs.as_slice());
-                    encode_method_sort(rbml_w, 'r');
-                    encode_method_argument_names(rbml_w, &*tm.decl);
-                }
+            let trait_item_type =
+                ty::impl_or_trait_item(tcx, item_def_id.def_id());
+            match trait_item_type {
+                 ty::MethodTraitItem(method_ty) => {
+                    let method_def_id = item_def_id.def_id();
+
+                    encode_method_ty_fields(ecx, rbml_w, &*method_ty);
+                    encode_parent_item(rbml_w, def_id);
+
+                    let stab = stability::lookup(tcx, method_def_id);
+                    encode_stability(rbml_w, stab);
+
+                    let elem = ast_map::PathName(method_ty.ident.name);
+                    encode_path(rbml_w,
+                                path.clone().chain(Some(elem).move_iter()));
+
+                    match method_ty.explicit_self {
+                        ty::StaticExplicitSelfCategory => {
+                            encode_family(rbml_w,
+                                          fn_style_static_method_family(
+                                              method_ty.fty.fn_style));
+
+                            let pty = ty::lookup_item_type(tcx,
+                                                           method_def_id);
+                            encode_bounds_and_type(rbml_w, ecx, &pty);
+                        }
+
+                        _ => {
+                            encode_family(rbml_w,
+                                          style_fn_family(
+                                              method_ty.fty.fn_style));
+                        }
+                    }
 
-                &Provided(m) => {
-                    encode_attributes(rbml_w, m.attrs.as_slice());
-                    // If this is a static method, we've already encoded
-                    // this.
-                    if method_ty.explicit_self != ty::StaticExplicitSelfCategory {
-                        // FIXME: I feel like there is something funny going on.
-                        let pty = ty::lookup_item_type(tcx, method_def_id);
-                        encode_bounds_and_type(rbml_w, ecx, &pty);
+                    match ms.get(i) {
+                        &RequiredMethod(ref tm) => {
+                            encode_attributes(rbml_w, tm.attrs.as_slice());
+                            encode_item_sort(rbml_w, 'r');
+                            encode_parent_sort(rbml_w, 't');
+                            encode_method_argument_names(rbml_w, &*tm.decl);
+                        }
+
+                        &ProvidedMethod(m) => {
+                            encode_attributes(rbml_w, m.attrs.as_slice());
+                            // If this is a static method, we've already
+                            // encoded this.
+                            if method_ty.explicit_self !=
+                                    ty::StaticExplicitSelfCategory {
+                                // FIXME: I feel like there is something funny
+                                // going on.
+                                let pty = ty::lookup_item_type(tcx, method_def_id);
+                                encode_bounds_and_type(rbml_w, ecx, &pty);
+                            }
+                            encode_item_sort(rbml_w, 'p');
+                            encode_parent_sort(rbml_w, 't');
+                            encode_inlined_item(
+                                ecx,
+                                rbml_w,
+                                IITraitItemRef(
+                                    def_id,
+                                    ProvidedInlinedTraitItemRef(&*m)));
+                            encode_method_argument_names(rbml_w,
+                                                         &*m.pe_fn_decl());
+                        }
                     }
-                    encode_method_sort(rbml_w, 'p');
-                    encode_inlined_item(ecx, rbml_w,
-                                        IIMethodRef(def_id, true, &*m));
-                    encode_method_argument_names(rbml_w, &*m.pe_fn_decl());
                 }
             }
 
@@ -1629,8 +1718,10 @@ fn encode_unboxed_closures<'a>(
                            ecx: &'a EncodeContext,
                            rbml_w: &'a mut Encoder) {
     rbml_w.start_tag(tag_unboxed_closures);
-    for (unboxed_closure_id, unboxed_closure_type) in
-            ecx.tcx.unboxed_closure_types.borrow().iter() {
+    for (unboxed_closure_id, unboxed_closure) in ecx.tcx
+                                                    .unboxed_closures
+                                                    .borrow()
+                                                    .iter() {
         if unboxed_closure_id.krate != LOCAL_CRATE {
             continue
         }
@@ -1638,8 +1729,9 @@ fn encode_unboxed_closures<'a>(
         rbml_w.start_tag(tag_unboxed_closure);
         encode_def_id(rbml_w, *unboxed_closure_id);
         rbml_w.start_tag(tag_unboxed_closure_type);
-        write_closure_type(ecx, rbml_w, unboxed_closure_type);
+        write_closure_type(ecx, rbml_w, &unboxed_closure.closure_type);
         rbml_w.end_tag();
+        encode_unboxed_closure_kind(rbml_w, unboxed_closure.kind);
         rbml_w.end_tag();
     }
     rbml_w.end_tag();
index fed23185c5d27388fcd58f7723c85f6d60086655..e6e7d8bf8d1a63de55d13de394233fef1cea65fc 100644 (file)
@@ -432,7 +432,8 @@ fn parse_ty(st: &mut PState, conv: conv_did) -> ty::t {
       }
       'k' => {
           let did = parse_def(st, NominalType, |x,y| conv(x,y));
-          return ty::mk_unboxed_closure(st.tcx, did);
+          let region = parse_region(st, conv);
+          return ty::mk_unboxed_closure(st.tcx, did, region);
       }
       'e' => {
           return ty::mk_err();
index ba865c7ab04d01e5e9a019f250c1f568e2eba2e2..fc5e267aa90500fdf16700f92e8642c73464622a 100644 (file)
@@ -285,8 +285,9 @@ fn enc_sty(w: &mut SeekableMemWriter, cx: &ctxt, st: &ty::sty) {
             enc_substs(w, cx, substs);
             mywrite!(w, "]");
         }
-        ty::ty_unboxed_closure(def) => {
+        ty::ty_unboxed_closure(def, region) => {
             mywrite!(w, "k{}", (cx.ds)(def));
+            enc_region(w, cx, region);
         }
         ty::ty_err => {
             mywrite!(w, "e");
index 33b663dea1557b5ea208b4d24b196eb5280de252..26cb2f25129aa61ef02964eedda615a95fa412de 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,
@@ -84,7 +84,8 @@ pub fn encode_inlined_item(ecx: &e::EncodeContext,
     let id = match ii {
         e::IIItemRef(i) => i.id,
         e::IIForeignRef(i) => i.id,
-        e::IIMethodRef(_, _, m) => m.id,
+        e::IITraitItemRef(_, e::ProvidedInlinedTraitItemRef(m)) => m.id,
+        e::IITraitItemRef(_, e::RequiredInlinedTraitItemRef(m)) => m.id,
     };
     debug!("> Encoding inlined item: {} ({})",
            ecx.tcx.map.path_to_string(id),
@@ -137,7 +138,12 @@ pub fn decode_inlined_item(cdata: &cstore::crate_metadata,
         let ident = match ii {
             ast::IIItem(i) => i.ident,
             ast::IIForeign(i) => i.ident,
-            ast::IIMethod(_, _, m) => m.pe_ident(),
+            ast::IITraitItem(_, iti) => {
+                match iti {
+                    ast::ProvidedInlinedTraitItem(m) => m.pe_ident(),
+                    ast::RequiredInlinedTraitItem(m) => m.pe_ident(),
+                }
+            }
         };
         debug!("Fn named: {}", token::get_ident(ident));
         debug!("< Decoded inlined fn: {}::{}",
@@ -344,12 +350,29 @@ fn simplify_ast(ii: e::InlinedItemRef) -> ast::InlinedItem {
 
     match ii {
         // HACK we're not dropping items.
-        e::IIItemRef(i) => ast::IIItem(fold::noop_fold_item(i, &mut fld)
-                                       .expect_one("expected one item")),
-        e::IIMethodRef(d, p, m) => ast::IIMethod(d, p, fold::noop_fold_method(m, &mut fld)
-                                                 .expect_one(
-                "noop_fold_method must produce exactly one method")),
-        e::IIForeignRef(i) => ast::IIForeign(fold::noop_fold_foreign_item(i, &mut fld))
+        e::IIItemRef(i) => {
+            ast::IIItem(fold::noop_fold_item(i, &mut fld)
+                            .expect_one("expected one item"))
+        }
+        e::IITraitItemRef(d, iti) => {
+            ast::IITraitItem(d, match iti {
+                e::ProvidedInlinedTraitItemRef(m) => {
+                    ast::ProvidedInlinedTraitItem(
+                        fold::noop_fold_method(m, &mut fld)
+                            .expect_one("noop_fold_method must produce \
+                                         exactly one method"))
+                }
+                e::RequiredInlinedTraitItemRef(m) => {
+                    ast::RequiredInlinedTraitItem(
+                        fold::noop_fold_method(m, &mut fld)
+                            .expect_one("noop_fold_method must produce \
+                                         exactly one method"))
+                }
+            })
+        }
+        e::IIForeignRef(i) => {
+            ast::IIForeign(fold::noop_fold_foreign_item(i, &mut fld))
+        }
     }
 }
 
@@ -389,9 +412,23 @@ fn renumber_and_map_ast(xcx: &ExtendedDecodeContext,
             ast::IIItem(i) => {
                 ast::IIItem(fld.fold_item(i).expect_one("expected one item"))
             }
-            ast::IIMethod(d, is_provided, m) => {
-                ast::IIMethod(xcx.tr_def_id(d), is_provided, fld.fold_method(m)
-                              .expect_one("expected one method"))
+            ast::IITraitItem(d, iti) => {
+                match iti {
+                    ast::ProvidedInlinedTraitItem(m) => {
+                        ast::IITraitItem(
+                            xcx.tr_def_id(d),
+                            ast::ProvidedInlinedTraitItem(
+                                fld.fold_method(m)
+                                   .expect_one("expected one method")))
+                    }
+                    ast::RequiredInlinedTraitItem(m) => {
+                        ast::IITraitItem(
+                            xcx.tr_def_id(d),
+                            ast::RequiredInlinedTraitItem(
+                                fld.fold_method(m)
+                                   .expect_one("expected one method")))
+                    }
+                }
             }
             ast::IIForeign(i) => ast::IIForeign(fld.fold_foreign_item(i))
         }
@@ -530,9 +567,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 +583,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 {
@@ -679,10 +726,35 @@ pub fn encode_vtable_param_res(ecx: &e::EncodeContext,
     }).unwrap()
 }
 
+pub fn encode_unboxed_closure_kind(ebml_w: &mut Encoder,
+                                   kind: ty::UnboxedClosureKind) {
+    ebml_w.emit_enum("UnboxedClosureKind", |ebml_w| {
+        match kind {
+            ty::FnUnboxedClosureKind => {
+                ebml_w.emit_enum_variant("FnUnboxedClosureKind", 0, 3, |_| {
+                    Ok(())
+                })
+            }
+            ty::FnMutUnboxedClosureKind => {
+                ebml_w.emit_enum_variant("FnMutUnboxedClosureKind", 1, 3, |_| {
+                    Ok(())
+                })
+            }
+            ty::FnOnceUnboxedClosureKind => {
+                ebml_w.emit_enum_variant("FnOnceUnboxedClosureKind",
+                                         2,
+                                         3,
+                                         |_| {
+                    Ok(())
+                })
+            }
+        }
+    }).unwrap()
+}
 
 pub fn encode_vtable_origin(ecx: &e::EncodeContext,
-                        rbml_w: &mut Encoder,
-                        vtable_origin: &typeck::vtable_origin) {
+                            rbml_w: &mut Encoder,
+                            vtable_origin: &typeck::vtable_origin) {
     rbml_w.emit_enum("vtable_origin", |rbml_w| {
         match *vtable_origin {
           typeck::vtable_static(def_id, ref substs, ref vtable_res) => {
@@ -1096,6 +1168,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| {
@@ -1191,14 +1272,15 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
         })
     }
 
-    for unboxed_closure_type in tcx.unboxed_closure_types
-                                   .borrow()
-                                   .find(&ast_util::local_def(id))
-                                   .iter() {
-        rbml_w.tag(c::tag_table_unboxed_closure_type, |rbml_w| {
+    for unboxed_closure in tcx.unboxed_closures
+                              .borrow()
+                              .find(&ast_util::local_def(id))
+                              .iter() {
+        rbml_w.tag(c::tag_table_unboxed_closures, |rbml_w| {
             rbml_w.id(id);
             rbml_w.tag(c::tag_table_val, |rbml_w| {
-                rbml_w.emit_closure_type(ecx, *unboxed_closure_type)
+                rbml_w.emit_closure_type(ecx, &unboxed_closure.closure_type);
+                encode_unboxed_closure_kind(rbml_w, unboxed_closure.kind)
             })
         })
     }
@@ -1225,8 +1307,8 @@ fn read_polytype(&mut self, xcx: &ExtendedDecodeContext)
                      -> ty::Polytype;
     fn read_substs(&mut self, xcx: &ExtendedDecodeContext) -> subst::Substs;
     fn read_auto_adjustment(&mut self, xcx: &ExtendedDecodeContext) -> ty::AutoAdjustment;
-    fn read_unboxed_closure_type(&mut self, xcx: &ExtendedDecodeContext)
-                                 -> ty::ClosureTy;
+    fn read_unboxed_closure(&mut self, xcx: &ExtendedDecodeContext)
+                            -> ty::UnboxedClosure;
     fn convert_def_id(&mut self,
                       xcx: &ExtendedDecodeContext,
                       source: DefIdSource,
@@ -1399,16 +1481,33 @@ fn read_auto_adjustment(&mut self, xcx: &ExtendedDecodeContext) -> ty::AutoAdjus
         }).unwrap()
     }
 
-    fn read_unboxed_closure_type(&mut self, xcx: &ExtendedDecodeContext)
-                                 -> ty::ClosureTy {
-        self.read_opaque(|this, doc| {
+    fn read_unboxed_closure(&mut self, xcx: &ExtendedDecodeContext)
+                            -> ty::UnboxedClosure {
+        let closure_type = self.read_opaque(|this, doc| {
             Ok(tydecode::parse_ty_closure_data(
                 doc.data,
                 xcx.dcx.cdata.cnum,
                 doc.start,
                 xcx.dcx.tcx,
                 |s, a| this.convert_def_id(xcx, s, a)))
-        }).unwrap()
+        }).unwrap();
+        let variants = [
+            "FnUnboxedClosureKind",
+            "FnMutUnboxedClosureKind",
+            "FnOnceUnboxedClosureKind"
+        ];
+        let kind = self.read_enum_variant(variants, |_, i| {
+            Ok(match i {
+                0 => ty::FnUnboxedClosureKind,
+                1 => ty::FnMutUnboxedClosureKind,
+                2 => ty::FnOnceUnboxedClosureKind,
+                _ => fail!("bad enum variant for ty::UnboxedClosureKind"),
+            })
+        }).unwrap();
+        ty::UnboxedClosure {
+            closure_type: closure_type,
+            kind: kind,
+        }
     }
 
     fn convert_def_id(&mut self,
@@ -1509,6 +1608,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 };
@@ -1540,14 +1646,14 @@ fn decode_side_tables(xcx: &ExtendedDecodeContext,
                         let adj: ty::AutoAdjustment = val_dsr.read_auto_adjustment(xcx);
                         dcx.tcx.adjustments.borrow_mut().insert(id, adj);
                     }
-                    c::tag_table_unboxed_closure_type => {
-                        let unboxed_closure_type =
-                            val_dsr.read_unboxed_closure_type(xcx);
+                    c::tag_table_unboxed_closures => {
+                        let unboxed_closure =
+                            val_dsr.read_unboxed_closure(xcx);
                         dcx.tcx
-                           .unboxed_closure_types
+                           .unboxed_closures
                            .borrow_mut()
                            .insert(ast_util::local_def(id),
-                                   unboxed_closure_type);
+                                   unboxed_closure);
                     }
                     _ => {
                         xcx.dcx.tcx.sess.bug(
index 6c5352ed796d689c2e3c76159f22c5ec2d34a8b4..77dd7ed1c4204f1d8d25398a85d84c092d44d630 100644 (file)
@@ -290,8 +290,9 @@ pub fn closure_to_block(closure_id: ast::NodeId,
                     tcx: &ty::ctxt) -> 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::ExprProc(_, block) |
+            ast::ExprFnBlock(_, _, block) |
+            ast::ExprUnboxedFn(_, _, _, block) => { block.id }
             _ => fail!("encountered non-closure id: {}", closure_id)
         },
         _ => fail!("encountered non-expr id: {}", closure_id)
index 61a2e8407303b730c6ae88ac076e5e293720b666..12841fb20d26fdcf4161644f6bb63a538e6a68bf 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 86fe6dc0ddc6c921bd17bd8320b7a3df2c3837d9..9a7bfb0e6dca257cedfca8138e4f6599c1f05d66 100644 (file)
@@ -40,9 +40,9 @@ fn should_explore(tcx: &ty::ctxt, def_id: ast::DefId) -> bool {
 
     match tcx.map.find(def_id.node) {
         Some(ast_map::NodeItem(..))
-        | Some(ast_map::NodeMethod(..))
+        | Some(ast_map::NodeImplItem(..))
         | Some(ast_map::NodeForeignItem(..))
-        | Some(ast_map::NodeTraitMethod(..)) => true,
+        | Some(ast_map::NodeTraitItem(..)) => true,
         _ => false
     }
 }
@@ -114,9 +114,14 @@ fn lookup_and_handle_method(&mut self, id: ast::NodeId,
                         method_num: index,
                         ..
                     }) => {
-                        let def_id = ty::trait_method(self.tcx,
-                                                      trait_id, index).def_id;
-                        self.check_def_id(def_id);
+                        let trait_item = ty::trait_item(self.tcx,
+                                                        trait_id,
+                                                        index);
+                        match trait_item {
+                            ty::MethodTraitItem(method) => {
+                                self.check_def_id(method.def_id);
+                            }
+                        }
                     }
                 }
             }
@@ -208,11 +213,15 @@ fn visit_node(&mut self, node: &ast_map::Node) {
                     _ => ()
                 }
             }
-            ast_map::NodeTraitMethod(trait_method) => {
-                visit::walk_trait_method(self, &*trait_method, ctxt);
+            ast_map::NodeTraitItem(trait_method) => {
+                visit::walk_trait_item(self, &*trait_method, ctxt);
             }
-            ast_map::NodeMethod(method) => {
-                visit::walk_block(self, &*method.pe_body(), ctxt);
+            ast_map::NodeImplItem(impl_item) => {
+                match *impl_item {
+                    ast::MethodImplItem(method) => {
+                        visit::walk_block(self, &*method.pe_body(), ctxt);
+                    }
+                }
             }
             ast_map::NodeForeignItem(foreign_item) => {
                 visit::walk_foreign_item(self, &*foreign_item, ctxt);
@@ -316,9 +325,13 @@ fn visit_item(&mut self, item: &ast::Item, _: ()) {
             self.worklist.push(item.id);
         }
         match item.node {
-            ast::ItemImpl(_, Some(ref _trait_ref), _, ref methods) => {
-                for method in methods.iter() {
-                    self.worklist.push(method.id);
+            ast::ItemImpl(_, Some(ref _trait_ref), _, ref impl_items) => {
+                for impl_item in impl_items.iter() {
+                    match *impl_item {
+                        ast::MethodImplItem(method) => {
+                            self.worklist.push(method.id);
+                        }
+                    }
                 }
             }
             _ => ()
@@ -443,13 +456,14 @@ fn symbol_is_live(&mut self, id: ast::NodeId,
         // This is done to handle the case where, for example, the static
         // method of a private type is used, but the type itself is never
         // called directly.
-        let impl_methods = self.tcx.impl_methods.borrow();
+        let impl_items = self.tcx.impl_items.borrow();
         match self.tcx.inherent_impls.borrow().find(&local_def(id)) {
             None => (),
             Some(impl_list) => {
                 for impl_did in impl_list.borrow().iter() {
-                    for method_did in impl_methods.get(impl_did).iter() {
-                        if self.live_symbols.contains(&method_did.node) {
+                    for item_did in impl_items.get(impl_did).iter() {
+                        if self.live_symbols.contains(&item_did.def_id()
+                                                               .node) {
                             return true;
                         }
                     }
@@ -516,12 +530,12 @@ fn visit_struct_field(&mut self, field: &ast::StructField, _: ()) {
     }
 
     // Overwrite so that we don't warn the trait method itself.
-    fn visit_trait_method(&mut self, trait_method: &ast::TraitMethod, _: ()) {
+    fn visit_trait_item(&mut self, trait_method: &ast::TraitItem, _: ()) {
         match *trait_method {
-            ast::Provided(ref method) => {
+            ast::ProvidedMethod(ref method) => {
                 visit::walk_block(self, &*method.pe_body(), ())
             }
-            ast::Required(_) => ()
+            ast::RequiredMethod(_) => ()
         }
     }
 }
index 7c805b1ac4bcde3917417d0a675376c7db524aed..b76b85e024c447309844607cd789cf384b07c469 100644 (file)
@@ -131,12 +131,14 @@ fn from_trait_id(tcx: &ty::ctxt, trait_id: ast::DefId)
     fn from_method_id(tcx: &ty::ctxt, method_id: ast::DefId)
                       -> OverloadedCallType {
         let method_descriptor =
-            match tcx.methods.borrow_mut().find(&method_id) {
+            match tcx.impl_or_trait_items.borrow_mut().find(&method_id) {
+                Some(&ty::MethodTraitItem(ref method_descriptor)) => {
+                    (*method_descriptor).clone()
+                }
                 None => {
                     tcx.sess.bug("overloaded call method wasn't in method \
                                   map")
                 }
-                Some(ref method_descriptor) => (*method_descriptor).clone(),
             };
         let impl_id = match method_descriptor.container {
             ty::TraitContainer(_) => {
index eda567f7d187c1a33745f52b154601c20eac2c57..1a2d21baa210a20e20a0f103f8dbb597177252a5 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 83f4fbaed67928f21f01ae701bbf27471f4bdbb9..17b2c69f4531629bf9ca6e0260cd6a21585208e6 100644 (file)
@@ -225,7 +225,7 @@ fn check_for_bare(cx: &Context, fv: &freevar_entry) {
             b(check_for_bare)
         }
 
-        ty::ty_unboxed_closure(_) => {}
+        ty::ty_unboxed_closure(..) => {}
 
         ref s => {
             cx.tcx.sess.bug(format!("expect fn type in kind checker, not \
index 1c31b671a947bafe1118999bdafb28b32e937686..baac68904d553308cc69f260806d4b1232018f8a 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..ef1e0515156c038811fc4d6346b486bb049ccb41 100644 (file)
 #![allow(non_camel_case_types)]
 
 use middle::def;
+use middle::freevars;
 use middle::ty;
 use middle::typeck;
-use util::nodemap::NodeMap;
+use util::nodemap::{DefIdMap, NodeMap};
 use util::ppaux::{ty_to_string, Repr};
 
 use syntax::ast::{MutImmutable, MutMutable};
@@ -270,6 +271,10 @@ 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;
+    fn unboxed_closures<'a>(&'a self)
+                        -> &'a RefCell<DefIdMap<ty::UnboxedClosure>>;
 }
 
 impl MutabilityCategory {
@@ -595,13 +600,22 @@ pub fn cat_def(&self,
                           }))
                       }
                   }
-                  ty::ty_unboxed_closure(_) => {
+                  ty::ty_unboxed_closure(closure_id, _) => {
+                      let unboxed_closures = self.typer
+                                                 .unboxed_closures()
+                                                 .borrow();
+                      let kind = unboxed_closures.get(&closure_id).kind;
+                      let onceness = match kind {
+                          ty::FnUnboxedClosureKind |
+                          ty::FnMutUnboxedClosureKind => ast::Many,
+                          ty::FnOnceUnboxedClosureKind => ast::Once,
+                      };
                       Ok(Rc::new(cmt_ {
                           id: id,
                           span: span,
                           cat: cat_copied_upvar(CopiedUpvar {
                               upvar_id: var_id,
-                              onceness: ast::Many,
+                              onceness: onceness,
                               capturing_proc: fn_node_id,
                           }),
                           mutbl: MutabilityCategory::from_def(&def),
index 62b5299f8fbc8619cb0d02319c41f878d8eecc21..61e6debb0864714cbd8d8a41255300e59488eac7 100644 (file)
@@ -83,8 +83,8 @@ fn visit_item(&mut self, item: &ast::Item, _: ()) {
             ast::ItemTrait(_, _, _, ref methods) if item.vis != ast::Public => {
                 for m in methods.iter() {
                     match *m {
-                        ast::Provided(ref m) => self.parents.insert(m.id, item.id),
-                        ast::Required(ref m) => self.parents.insert(m.id, item.id),
+                        ast::ProvidedMethod(ref m) => self.parents.insert(m.id, item.id),
+                        ast::RequiredMethod(ref m) => self.parents.insert(m.id, item.id),
                     };
                 }
             }
@@ -240,7 +240,7 @@ fn visit_item(&mut self, item: &ast::Item, _: ()) {
             //   undefined symbols at linkage time if this case is not handled.
             //
             // * Private trait impls for private types can be completely ignored
-            ast::ItemImpl(_, _, ref ty, ref methods) => {
+            ast::ItemImpl(_, _, ref ty, ref impl_items) => {
                 let public_ty = match ty.node {
                     ast::TyPath(_, _, id) => {
                         match self.tcx.def_map.borrow().get_copy(&id) {
@@ -261,13 +261,18 @@ fn visit_item(&mut self, item: &ast::Item, _: ()) {
                 });
 
                 if public_ty || public_trait {
-                    for method in methods.iter() {
-                        let meth_public = match method.pe_explicit_self().node {
-                            ast::SelfStatic => public_ty,
-                            _ => true,
-                        } && method.pe_vis() == ast::Public;
-                        if meth_public || tr.is_some() {
-                            self.exported_items.insert(method.id);
+                    for impl_item in impl_items.iter() {
+                        match *impl_item {
+                            ast::MethodImplItem(method) => {
+                                let meth_public =
+                                    match method.pe_explicit_self().node {
+                                        ast::SelfStatic => public_ty,
+                                        _ => true,
+                                    } && method.pe_vis() == ast::Public;
+                                if meth_public || tr.is_some() {
+                                    self.exported_items.insert(method.id);
+                                }
+                            }
                         }
                     }
                 }
@@ -278,11 +283,11 @@ fn visit_item(&mut self, item: &ast::Item, _: ()) {
             ast::ItemTrait(_, _, _, ref methods) if public_first => {
                 for method in methods.iter() {
                     match *method {
-                        ast::Provided(ref m) => {
+                        ast::ProvidedMethod(ref m) => {
                             debug!("provided {}", m.id);
                             self.exported_items.insert(m.id);
                         }
-                        ast::Required(ref m) => {
+                        ast::RequiredMethod(ref m) => {
                             debug!("required {}", m.id);
                             self.exported_items.insert(m.id);
                         }
@@ -387,9 +392,10 @@ fn def_privacy(&self, did: ast::DefId) -> PrivacyResult {
             }
             debug!("privacy - is {:?} a public method", did);
 
-            return match self.tcx.methods.borrow().find(&did) {
-                Some(meth) => {
-                    debug!("privacy - well at least it's a method: {:?}", meth);
+            return match self.tcx.impl_or_trait_items.borrow().find(&did) {
+                Some(&ty::MethodTraitItem(ref meth)) => {
+                    debug!("privacy - well at least it's a method: {:?}",
+                           *meth);
                     match meth.container {
                         ty::TraitContainer(id) => {
                             debug!("privacy - recursing on trait {:?}", id);
@@ -451,15 +457,23 @@ fn def_privacy(&self, did: ast::DefId) -> PrivacyResult {
                 // invocation.
                 // FIXME(#10573) is this the right behavior? Why not consider
                 //               where the method was defined?
-                Some(ast_map::NodeMethod(ref m)) => {
-                    let imp = self.tcx.map.get_parent_did(closest_private_id);
-                    match ty::impl_trait_ref(self.tcx, imp) {
-                        Some(..) => return Allowable,
-                        _ if m.pe_vis() == ast::Public => return Allowable,
-                        _ => m.pe_vis()
+                Some(ast_map::NodeImplItem(ref ii)) => {
+                    match **ii {
+                        ast::MethodImplItem(m) => {
+                            let imp = self.tcx
+                                          .map
+                                          .get_parent_did(closest_private_id);
+                            match ty::impl_trait_ref(self.tcx, imp) {
+                                Some(..) => return Allowable,
+                                _ if m.pe_vis() == ast::Public => {
+                                    return Allowable
+                                }
+                                _ => m.pe_vis()
+                            }
+                        }
                     }
                 }
-                Some(ast_map::NodeTraitMethod(_)) => {
+                Some(ast_map::NodeTraitItem(_)) => {
                     return Allowable;
                 }
 
@@ -648,12 +662,17 @@ fn check_field(&mut self,
     }
 
     // Given the ID of a method, checks to ensure it's in scope.
-    fn check_static_method(&mut self, span: Span, method_id: ast::DefId,
+    fn check_static_method(&mut self,
+                           span: Span,
+                           method_id: ast::DefId,
                            name: ast::Ident) {
         // If the method is a default method, we need to use the def_id of
         // the default implementation.
-        let method_id = ty::method(self.tcx, method_id).provided_source
-                                                       .unwrap_or(method_id);
+        let method_id = match ty::impl_or_trait_item(self.tcx, method_id) {
+            ty::MethodTraitItem(method_type) => {
+                method_type.provided_source.unwrap_or(method_id)
+            }
+        };
 
         let string = token::get_ident(name);
         self.report_error(self.ensure_public(span,
@@ -1075,12 +1094,16 @@ fn check_sane_privacy(&self, item: &ast::Item) {
         match item.node {
             // implementations of traits don't need visibility qualifiers because
             // that's controlled by having the trait in scope.
-            ast::ItemImpl(_, Some(..), _, ref methods) => {
+            ast::ItemImpl(_, Some(..), _, ref impl_items) => {
                 check_inherited(item.span, item.vis,
                                 "visibility qualifiers have no effect on trait \
                                  impls");
-                for m in methods.iter() {
-                    check_inherited(m.span, m.pe_vis(), "");
+                for impl_item in impl_items.iter() {
+                    match *impl_item {
+                        ast::MethodImplItem(m) => {
+                            check_inherited(m.span, m.pe_vis(), "");
+                        }
+                    }
                 }
             }
 
@@ -1111,11 +1134,11 @@ fn check_sane_privacy(&self, item: &ast::Item) {
             ast::ItemTrait(_, _, _, ref methods) => {
                 for m in methods.iter() {
                     match *m {
-                        ast::Provided(ref m) => {
+                        ast::ProvidedMethod(ref m) => {
                             check_inherited(m.span, m.pe_vis(),
                                             "unnecessary visibility");
                         }
-                        ast::Required(ref m) => {
+                        ast::RequiredMethod(ref m) => {
                             check_inherited(m.span, m.vis,
                                             "unnecessary visibility");
                         }
@@ -1148,9 +1171,13 @@ fn check_inherited(tcx: &ty::ctxt, sp: Span, vis: ast::Visibility) {
         };
         check_inherited(tcx, item.span, item.vis);
         match item.node {
-            ast::ItemImpl(_, _, _, ref methods) => {
-                for m in methods.iter() {
-                    check_inherited(tcx, m.span, m.pe_vis());
+            ast::ItemImpl(_, _, _, ref impl_items) => {
+                for impl_item in impl_items.iter() {
+                    match *impl_item {
+                        ast::MethodImplItem(m) => {
+                            check_inherited(tcx, m.span, m.pe_vis());
+                        }
+                    }
                 }
             }
             ast::ItemForeignMod(ref fm) => {
@@ -1174,8 +1201,8 @@ fn check_inherited(tcx: &ty::ctxt, sp: Span, vis: ast::Visibility) {
             ast::ItemTrait(_, _, _, ref methods) => {
                 for m in methods.iter() {
                     match *m {
-                        ast::Required(..) => {}
-                        ast::Provided(ref m) => check_inherited(tcx, m.span,
+                        ast::RequiredMethod(..) => {}
+                        ast::ProvidedMethod(ref m) => check_inherited(tcx, m.span,
                                                                 m.pe_vis()),
                     }
                 }
@@ -1270,7 +1297,7 @@ fn visit_item(&mut self, item: &ast::Item, _: ()) {
             // (i.e. we could just return here to not check them at
             // all, or some worse estimation of whether an impl is
             // publicly visible.
-            ast::ItemImpl(ref g, ref trait_ref, self_, ref methods) => {
+            ast::ItemImpl(ref g, ref trait_ref, self_, ref impl_items) => {
                 // `impl [... for] Private` is never visible.
                 let self_contains_private;
                 // impl [... for] Public<...>, but not `impl [... for]
@@ -1311,7 +1338,14 @@ fn visit_item(&mut self, item: &ast::Item, _: ()) {
                 // are private (because `T` won't be visible externally).
                 let trait_or_some_public_method =
                     trait_ref.is_some() ||
-                    methods.iter().any(|m| self.exported_items.contains(&m.id));
+                    impl_items.iter()
+                              .any(|impl_item| {
+                                  match *impl_item {
+                                      ast::MethodImplItem(m) => {
+                                          self.exported_items.contains(&m.id)
+                                      }
+                                  }
+                              });
 
                 if !self_contains_private &&
                         not_private_trait &&
@@ -1321,8 +1355,14 @@ fn visit_item(&mut self, item: &ast::Item, _: ()) {
 
                     match *trait_ref {
                         None => {
-                            for method in methods.iter() {
-                                visit::walk_method_helper(self, &**method, ())
+                            for impl_item in impl_items.iter() {
+                                match *impl_item {
+                                    ast::MethodImplItem(method) => {
+                                        visit::walk_method_helper(self,
+                                                                  &*method,
+                                                                  ())
+                                    }
+                                }
                             }
                         }
                         Some(ref tr) => {
@@ -1345,11 +1385,19 @@ fn visit_item(&mut self, item: &ast::Item, _: ()) {
                     // impl Public<Private> { ... }. Any public static
                     // methods will be visible as `Public::foo`.
                     let mut found_pub_static = false;
-                    for method in methods.iter() {
-                        if method.pe_explicit_self().node == ast::SelfStatic &&
-                            self.exported_items.contains(&method.id) {
-                            found_pub_static = true;
-                            visit::walk_method_helper(self, &**method, ());
+                    for impl_item in impl_items.iter() {
+                        match *impl_item {
+                            ast::MethodImplItem(method) => {
+                                if method.pe_explicit_self().node ==
+                                        ast::SelfStatic &&
+                                        self.exported_items
+                                            .contains(&method.id) {
+                                    found_pub_static = true;
+                                    visit::walk_method_helper(self,
+                                                              &*method,
+                                                              ());
+                                }
+                            }
                         }
                     }
                     if found_pub_static {
index 7ed1209bdf75097485a6f2043565948230e65479..5dfc43daa646f763dcb0c9c835d3d007641a991c 100644 (file)
@@ -193,26 +193,37 @@ fn def_id_represents_local_inlined_item(&self, def_id: ast::DefId) -> bool {
                     _ => false,
                 }
             }
-            Some(ast_map::NodeTraitMethod(trait_method)) => {
+            Some(ast_map::NodeTraitItem(trait_method)) => {
                 match *trait_method {
-                    ast::Required(_) => false,
-                    ast::Provided(_) => true,
+                    ast::RequiredMethod(_) => false,
+                    ast::ProvidedMethod(_) => true,
                 }
             }
-            Some(ast_map::NodeMethod(method)) => {
-                if generics_require_inlining(method.pe_generics()) ||
-                        attributes_specify_inlining(method.attrs.as_slice()) {
-                    true
-                } else {
-                    let impl_did = self.tcx.map.get_parent_did(node_id);
-                    // Check the impl. If the generics on the self type of the
-                    // impl require inlining, this method does too.
-                    assert!(impl_did.krate == ast::LOCAL_CRATE);
-                    match self.tcx.map.expect_item(impl_did.node).node {
-                        ast::ItemImpl(ref generics, _, _, _) => {
-                            generics_require_inlining(generics)
+            Some(ast_map::NodeImplItem(impl_item)) => {
+                match *impl_item {
+                    ast::MethodImplItem(method) => {
+                        if generics_require_inlining(method.pe_generics()) ||
+                                attributes_specify_inlining(
+                                    method.attrs.as_slice()) {
+                            true
+                        } else {
+                            let impl_did = self.tcx
+                                               .map
+                                               .get_parent_did(node_id);
+                            // Check the impl. If the generics on the self
+                            // type of the impl require inlining, this method
+                            // does too.
+                            assert!(impl_did.krate == ast::LOCAL_CRATE);
+                            match self.tcx
+                                      .map
+                                      .expect_item(impl_did.node)
+                                      .node {
+                                ast::ItemImpl(ref generics, _, _, _) => {
+                                    generics_require_inlining(generics)
+                                }
+                                _ => false
+                            }
                         }
-                        _ => false
                     }
                 }
             }
@@ -310,20 +321,24 @@ fn propagate_node(&mut self, node: &ast_map::Node,
                     }
                 }
             }
-            ast_map::NodeTraitMethod(trait_method) => {
+            ast_map::NodeTraitItem(trait_method) => {
                 match *trait_method {
-                    ast::Required(..) => {
+                    ast::RequiredMethod(..) => {
                         // Keep going, nothing to get exported
                     }
-                    ast::Provided(ref method) => {
+                    ast::ProvidedMethod(ref method) => {
                         visit::walk_block(self, &*method.pe_body(), ())
                     }
                 }
             }
-            ast_map::NodeMethod(method) => {
-                let did = self.tcx.map.get_parent_did(search_item);
-                if method_might_be_inlined(self.tcx, &*method, did) {
-                    visit::walk_block(self, &*method.pe_body(), ())
+            ast_map::NodeImplItem(impl_item) => {
+                match *impl_item {
+                    ast::MethodImplItem(method) => {
+                        let did = self.tcx.map.get_parent_did(search_item);
+                        if method_might_be_inlined(self.tcx, &*method, did) {
+                            visit::walk_block(self, &*method.pe_body(), ())
+                        }
+                    }
                 }
             }
             // Nothing to recurse on for these
index 95c04ad6607d66ead0852153c3689e4b233ee014..9edf9fcbdbad62754d8aa973ee65041c3038983c 100644 (file)
@@ -24,7 +24,7 @@
 use syntax::ast::*;
 use syntax::ast;
 use syntax::ast_util::{local_def, PostExpansionMethod};
-use syntax::ast_util::{walk_pat, trait_method_to_ty_method};
+use syntax::ast_util::{walk_pat, trait_item_to_ty_method};
 use syntax::ext::mtwt;
 use syntax::parse::token::special_names;
 use syntax::parse::token::special_idents;
@@ -36,7 +36,7 @@
 
 use std::collections::{HashMap, HashSet};
 use std::cell::{Cell, RefCell};
-use std::gc::{Gc, GC};
+use std::gc::GC;
 use std::mem::replace;
 use std::rc::{Rc, Weak};
 use std::uint;
@@ -225,7 +225,7 @@ enum FallbackSuggestion {
     NoSuggestion,
     Field,
     Method,
-    TraitMethod,
+    TraitItem,
     StaticMethod(String),
     StaticTraitMethod(String),
 }
@@ -272,10 +272,10 @@ enum RibKind {
     ConstantItemRibKind
 }
 
-// Methods can be required or provided. Required methods only occur in traits.
+// Methods can be required or provided. RequiredMethod methods only occur in traits.
 enum MethodSort {
-    Required,
-    Provided(NodeId)
+    RequiredMethod,
+    ProvidedMethod(NodeId)
 }
 
 enum UseLexicalScopeFlag {
@@ -289,19 +289,19 @@ enum ModulePrefixResult {
 }
 
 #[deriving(Clone, Eq, PartialEq)]
-enum MethodIsStaticFlag {
-    MethodIsNotStatic,
-    MethodIsStatic,
+pub enum TraitItemKind {
+    NonstaticMethodTraitItemKind,
+    StaticMethodTraitItemKind,
 }
 
-impl MethodIsStaticFlag {
-    fn from_explicit_self_category(explicit_self_category:
-                                   ExplicitSelfCategory)
-                                   -> MethodIsStaticFlag {
+impl TraitItemKind {
+    pub fn from_explicit_self_category(explicit_self_category:
+                                       ExplicitSelfCategory)
+                                       -> TraitItemKind {
         if explicit_self_category == StaticExplicitSelfCategory {
-            MethodIsStatic
+            StaticMethodTraitItemKind
         } else {
-            MethodIsNotStatic
+            NonstaticMethodTraitItemKind
         }
     }
 }
@@ -824,7 +824,7 @@ struct Resolver<'a> {
 
     graph_root: NameBindings,
 
-    method_map: RefCell<FnvHashMap<(Name, DefId), MethodIsStaticFlag>>,
+    trait_item_map: RefCell<FnvHashMap<(Name, DefId), TraitItemKind>>,
 
     structs: FnvHashMap<DefId, Vec<Name>>,
 
@@ -934,7 +934,7 @@ fn new(session: &'a Session, crate_span: Span) -> Resolver<'a> {
 
             graph_root: graph_root,
 
-            method_map: RefCell::new(FnvHashMap::new()),
+            trait_item_map: RefCell::new(FnvHashMap::new()),
             structs: FnvHashMap::new(),
 
             unresolved_imports: 0,
@@ -1263,7 +1263,7 @@ fn build_reduced_graph_for_item(&mut self,
                 parent
             }
 
-            ItemImpl(_, None, ty, ref methods) => {
+            ItemImpl(_, None, ty, ref impl_items) => {
                 // If this implements an anonymous trait, then add all the
                 // methods within to a new module, if the type was defined
                 // within this module.
@@ -1315,35 +1315,43 @@ fn build_reduced_graph_for_item(&mut self,
                             }
                         };
 
-                        // For each method...
-                        for method in methods.iter() {
-                            // Add the method to the module.
-                            let ident = method.pe_ident();
-                            let method_name_bindings =
-                                self.add_child(ident,
-                                               new_parent.clone(),
-                                               ForbidDuplicateValues,
-                                               method.span);
-                            let def = match method.pe_explicit_self().node {
-                                SelfStatic => {
-                                    // Static methods become
-                                    // `def_static_method`s.
-                                    DefStaticMethod(local_def(method.id),
-                                                      FromImpl(local_def(
-                                                        item.id)),
-                                                      method.pe_fn_style())
-                                }
-                                _ => {
-                                    // Non-static methods become
-                                    // `def_method`s.
-                                    DefMethod(local_def(method.id), None)
-                                }
-                            };
+                        // For each implementation item...
+                        for impl_item in impl_items.iter() {
+                            match *impl_item {
+                                MethodImplItem(method) => {
+                                    // Add the method to the module.
+                                    let ident = method.pe_ident();
+                                    let method_name_bindings =
+                                        self.add_child(ident,
+                                                       new_parent.clone(),
+                                                       ForbidDuplicateValues,
+                                                       method.span);
+                                    let def = match method.pe_explicit_self()
+                                                          .node {
+                                        SelfStatic => {
+                                            // Static methods become
+                                            // `def_static_method`s.
+                                            DefStaticMethod(
+                                                local_def(method.id),
+                                                FromImpl(local_def(item.id)),
+                                                         method.pe_fn_style())
+                                        }
+                                        _ => {
+                                            // Non-static methods become
+                                            // `def_method`s.
+                                            DefMethod(local_def(method.id),
+                                                      None)
+                                        }
+                                    };
 
-                            let is_public = method.pe_vis() == ast::Public;
-                            method_name_bindings.define_value(def,
-                                                              method.span,
-                                                              is_public);
+                                    let is_public =
+                                        method.pe_vis() == ast::Public;
+                                    method_name_bindings.define_value(
+                                        def,
+                                        method.span,
+                                        is_public);
+                                }
+                            }
                         }
                     }
                     _ => {}
@@ -1376,7 +1384,7 @@ fn build_reduced_graph_for_item(&mut self,
 
                 // Add the names of all the methods to the trait info.
                 for method in methods.iter() {
-                    let ty_m = trait_method_to_ty_method(method);
+                    let ty_m = trait_item_to_ty_method(method);
 
                     let ident = ty_m.ident;
 
@@ -1387,13 +1395,13 @@ fn build_reduced_graph_for_item(&mut self,
                             (DefStaticMethod(local_def(ty_m.id),
                                               FromTrait(local_def(item.id)),
                                               ty_m.fn_style),
-                             MethodIsStatic)
+                             StaticMethodTraitItemKind)
                         }
                         _ => {
                             // Non-static methods become `def_method`s.
                             (DefMethod(local_def(ty_m.id),
                                        Some(local_def(item.id))),
-                             MethodIsNotStatic)
+                             NonstaticMethodTraitItemKind)
                         }
                     };
 
@@ -1404,7 +1412,7 @@ fn build_reduced_graph_for_item(&mut self,
                                        ty_m.span);
                     method_name_bindings.define_value(def, ty_m.span, true);
 
-                    self.method_map
+                    self.trait_item_map
                         .borrow_mut()
                         .insert((ident.name, def_id), static_flag);
                 }
@@ -1714,29 +1722,29 @@ fn handle_external_def(&mut self,
               debug!("(building reduced graph for external \
                       crate) building type {}", final_ident);
 
-              // If this is a trait, add all the method names
-              // to the trait info.
+              // If this is a trait, add all the trait item names to the trait
+              // info.
 
-              let method_def_ids =
-                csearch::get_trait_method_def_ids(&self.session.cstore, def_id);
-              for &method_def_id in method_def_ids.iter() {
-                  let (method_name, explicit_self) =
-                      csearch::get_method_name_and_explicit_self(&self.session.cstore,
-                                                                 method_def_id);
+              let trait_item_def_ids =
+                csearch::get_trait_item_def_ids(&self.session.cstore, def_id);
+              for trait_item_def_id in trait_item_def_ids.iter() {
+                  let (trait_item_name, trait_item_kind) =
+                      csearch::get_trait_item_name_and_kind(
+                          &self.session.cstore,
+                          trait_item_def_id.def_id());
 
-                  debug!("(building reduced graph for \
-                          external crate) ... adding \
-                          trait method '{}'",
-                         token::get_ident(method_name));
+                  debug!("(building reduced graph for external crate) ... \
+                          adding trait item '{}'",
+                         token::get_ident(trait_item_name));
 
-                  self.method_map
+                  self.trait_item_map
                       .borrow_mut()
-                      .insert((method_name.name, def_id),
-                              MethodIsStaticFlag::from_explicit_self_category(
-                                  explicit_self));
+                      .insert((trait_item_name.name, def_id),
+                              trait_item_kind);
 
                   if is_exported {
-                      self.external_exports.insert(method_def_id);
+                      self.external_exports
+                          .insert(trait_item_def_id.def_id());
                   }
               }
 
@@ -3680,12 +3688,12 @@ fn resolve_item(&mut self, item: &Item) {
             ItemImpl(ref generics,
                      ref implemented_traits,
                      ref self_type,
-                     ref methods) => {
+                     ref impl_items) => {
                 self.resolve_implementation(item.id,
                                             generics,
                                             implemented_traits,
                                             &**self_type,
-                                            methods.as_slice());
+                                            impl_items.as_slice());
             }
 
             ItemTrait(ref generics, ref unbound, ref traits, ref methods) => {
@@ -3724,12 +3732,12 @@ fn resolve_item(&mut self, item: &Item) {
                         // FIXME #4951: Do we need a node ID here?
 
                         match *method {
-                          ast::Required(ref ty_m) => {
+                          ast::RequiredMethod(ref ty_m) => {
                             this.with_type_parameter_rib
                                 (HasTypeParameters(&ty_m.generics,
                                                    FnSpace,
                                                    item.id,
-                                        MethodRibKind(item.id, Required)),
+                                        MethodRibKind(item.id, RequiredMethod)),
                                  |this| {
 
                                 // Resolve the method-specific type
@@ -3751,9 +3759,9 @@ fn resolve_item(&mut self, item: &Item) {
                                 this.resolve_type(&*ty_m.decl.output);
                             });
                           }
-                          ast::Provided(ref m) => {
+                          ast::ProvidedMethod(ref m) => {
                               this.resolve_method(MethodRibKind(item.id,
-                                                                Provided(m.id)),
+                                                                ProvidedMethod(m.id)),
                                                   &**m)
                           }
                         }
@@ -4129,7 +4137,7 @@ fn resolve_implementation(&mut self,
                               generics: &Generics,
                               opt_trait_reference: &Option<TraitRef>,
                               self_type: &Ty,
-                              methods: &[Gc<Method>]) {
+                              impl_items: &[ImplItem]) {
         // If applicable, create a rib for the type parameters.
         self.with_type_parameter_rib(HasTypeParameters(generics,
                                                        TypeSpace,
@@ -4145,27 +4153,36 @@ fn resolve_implementation(&mut self,
                 this.resolve_type(self_type);
 
                 this.with_current_self_type(self_type, |this| {
-                    for method in methods.iter() {
-                        // If this is a trait impl, ensure the method exists in trait
-                        this.check_trait_method(&**method);
-
-                        // We also need a new scope for the method-specific type parameters.
-                        this.resolve_method(MethodRibKind(id, Provided(method.id)),
-                                            &**method);
+                    for impl_item in impl_items.iter() {
+                        match *impl_item {
+                            MethodImplItem(method) => {
+                                // If this is a trait impl, ensure the method
+                                // exists in trait
+                                this.check_trait_item(method.pe_ident(),
+                                                      method.span);
+
+                                // We also need a new scope for the method-
+                                // specific type parameters.
+                                this.resolve_method(
+                                    MethodRibKind(id,
+                                                  ProvidedMethod(method.id)),
+                                    &*method);
+                            }
+                        }
                     }
                 });
             });
         });
     }
 
-    fn check_trait_method(&self, method: &Method) {
+    fn check_trait_item(&self, ident: Ident, span: Span) {
         // If there is a TraitRef in scope for an impl, then the method must be in the trait.
         for &(did, ref trait_ref) in self.current_trait_ref.iter() {
-            let method_name = method.pe_ident().name;
+            let method_name = ident.name;
 
-            if self.method_map.borrow().find(&(method_name, did)).is_none() {
+            if self.trait_item_map.borrow().find(&(method_name, did)).is_none() {
                 let path_str = self.path_idents_to_string(&trait_ref.path);
-                self.resolve_error(method.span,
+                self.resolve_error(span,
                                     format!("method `{}` is not a member of trait `{}`",
                                             token::get_name(method_name),
                                             path_str).as_slice());
@@ -4845,8 +4862,8 @@ fn resolve_module_relative_path(&mut self,
             TraitModuleKind | ImplModuleKind => {
                 match containing_module.def_id.get() {
                     Some(def_id) => {
-                        match self.method_map.borrow().find(&(ident.name, def_id)) {
-                            Some(&MethodIsStatic) => (),
+                        match self.trait_item_map.borrow().find(&(ident.name, def_id)) {
+                            Some(&StaticMethodTraitItemKind) => (),
                             None => (),
                             _ => {
                                 debug!("containing module was a trait or impl \
@@ -5102,7 +5119,7 @@ fn get_module(this: &mut Resolver, span: Span, ident_path: &[ast::Ident])
                             }
                         }
                         Some(DefMethod(_, None)) if allowed == Everything => return Method,
-                        Some(DefMethod(_, Some(_))) => return TraitMethod,
+                        Some(DefMethod(_, Some(_))) => return TraitItem,
                         _ => ()
                     }
                 }
@@ -5112,14 +5129,14 @@ fn get_module(this: &mut Resolver, span: Span, ident_path: &[ast::Ident])
         }
 
         // Look for a method in the current trait.
-        let method_map = self.method_map.borrow();
+        let trait_item_map = self.trait_item_map.borrow();
         match self.current_trait_ref {
             Some((did, ref trait_ref)) => {
                 let path_str = self.path_idents_to_string(&trait_ref.path);
 
-                match method_map.find(&(name, did)) {
-                    Some(&MethodIsStatic) => return StaticTraitMethod(path_str),
-                    Some(_) => return TraitMethod,
+                match trait_item_map.find(&(name, did)) {
+                    Some(&StaticMethodTraitItemKind) => return StaticTraitMethod(path_str),
+                    Some(_) => return TraitItem,
                     None => {}
                 }
             }
@@ -5262,7 +5279,7 @@ fn resolve_expr(&mut self, expr: &Expr) {
                                         Field =>
                                             format!("`self.{}`", wrong_name),
                                         Method
-                                        | TraitMethod =>
+                                        | TraitItem =>
                                             format!("to call `self.{}`", wrong_name),
                                         StaticTraitMethod(path_str)
                                         | StaticMethod(path_str) =>
@@ -5287,9 +5304,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);
@@ -5437,9 +5454,9 @@ fn add_trait_info(found_traits: &mut Vec<DefId>,
             // Look for the current trait.
             match self.current_trait_ref {
                 Some((trait_def_id, _)) => {
-                    let method_map = self.method_map.borrow();
+                    let trait_item_map = self.trait_item_map.borrow();
 
-                    if method_map.contains_key(&(name, trait_def_id)) {
+                    if trait_item_map.contains_key(&(name, trait_def_id)) {
                         add_trait_info(&mut found_traits, trait_def_id, name);
                     }
                 }
@@ -5450,7 +5467,7 @@ fn add_trait_info(found_traits: &mut Vec<DefId>,
             self.populate_module_if_necessary(&search_module);
 
             {
-                let method_map = self.method_map.borrow();
+                let trait_item_map = self.trait_item_map.borrow();
                 for (_, child_names) in search_module.children.borrow().iter() {
                     let def = match child_names.def_for_namespace(TypeNS) {
                         Some(def) => def,
@@ -5460,7 +5477,7 @@ fn add_trait_info(found_traits: &mut Vec<DefId>,
                         DefTrait(trait_def_id) => trait_def_id,
                         _ => continue,
                     };
-                    if method_map.contains_key(&(name, trait_def_id)) {
+                    if trait_item_map.contains_key(&(name, trait_def_id)) {
                         add_trait_info(&mut found_traits, trait_def_id, name);
                     }
                 }
@@ -5476,7 +5493,7 @@ fn add_trait_info(found_traits: &mut Vec<DefId>,
                     Some(DefTrait(trait_def_id)) => trait_def_id,
                     Some(..) | None => continue,
                 };
-                if self.method_map.borrow().contains_key(&(name, did)) {
+                if self.trait_item_map.borrow().contains_key(&(name, did)) {
                     add_trait_info(&mut found_traits, did, name);
                     self.used_imports.insert((import.type_id, TypeNS));
                 }
index c4373a023ccb24044872da32aacd84c97118e570..11b16f1853379372999919fd9f45379af76bc5a8 100644 (file)
@@ -283,8 +283,8 @@ fn process_method(&mut self, method: &ast::Method, e:DxrVisitorEnv) {
                             let mut result = String::from_str("<");
                             result.push_str(ty_to_string(&*ty).as_slice());
 
-                            match ty::trait_of_method(&self.analysis.ty_cx,
-                                                      ast_util::local_def(method.id)) {
+                            match ty::trait_of_item(&self.analysis.ty_cx,
+                                                    ast_util::local_def(method.id)) {
                                 Some(def_id) => {
                                     result.push_str(" as ");
                                     result.push_str(
@@ -310,8 +310,8 @@ fn process_method(&mut self, method: &ast::Method, e:DxrVisitorEnv) {
                                               ).as_slice());
                 },
             },
-            None => match ty::trait_of_method(&self.analysis.ty_cx,
-                                              ast_util::local_def(method.id)) {
+            None => match ty::trait_of_item(&self.analysis.ty_cx,
+                                            ast_util::local_def(method.id)) {
                 Some(def_id) => {
                     scope_id = def_id.node;
                     match self.analysis.ty_cx.map.get(def_id.node) {
@@ -338,9 +338,19 @@ fn process_method(&mut self, method: &ast::Method, e:DxrVisitorEnv) {
         let qualname = qualname.as_slice();
 
         // record the decl for this def (if it has one)
-        let decl_id = ty::trait_method_of_method(&self.analysis.ty_cx,
-                                                 ast_util::local_def(method.id))
-            .filtered(|def_id| method.id != 0 && def_id.node == 0);
+        let decl_id = ty::trait_item_of_item(&self.analysis.ty_cx,
+                                             ast_util::local_def(method.id))
+            .filtered(|def_id| {
+                match *def_id {
+                    ty::MethodTraitItemId(def_id) => {
+                        method.id != 0 && def_id.node == 0
+                    }
+                }
+            });
+        let decl_id = match decl_id {
+            None => None,
+            Some(ty::MethodTraitItemId(def_id)) => Some(def_id),
+        };
 
         let sub_span = self.span.sub_span_after_keyword(method.span, keywords::Fn);
         self.fmt.method_str(method.span,
@@ -601,7 +611,7 @@ fn process_impl(&mut self,
                     type_parameters: &ast::Generics,
                     trait_ref: &Option<ast::TraitRef>,
                     typ: ast::P<ast::Ty>,
-                    methods: &Vec<Gc<ast::Method>>) {
+                    impl_items: &Vec<ast::ImplItem>) {
         match typ.node {
             ast::TyPath(ref path, _, id) => {
                 match self.lookup_type_ref(id) {
@@ -630,8 +640,12 @@ fn process_impl(&mut self,
         }
 
         self.process_generic_params(type_parameters, item.span, "", item.id, e);
-        for method in methods.iter() {
-            visit::walk_method_helper(self, &**method, e)
+        for impl_item in impl_items.iter() {
+            match *impl_item {
+                ast::MethodImplItem(method) => {
+                    visit::walk_method_helper(self, &*method, e)
+                }
+            }
         }
     }
 
@@ -640,7 +654,7 @@ fn process_trait(&mut self,
                      e: DxrVisitorEnv,
                      generics: &ast::Generics,
                      trait_refs: &Vec<ast::TraitRef>,
-                     methods: &Vec<ast::TraitMethod>) {
+                     methods: &Vec<ast::TraitItem>) {
         let qualname = self.analysis.ty_cx.map.path_to_string(item.id);
 
         let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Trait);
@@ -672,7 +686,7 @@ fn process_trait(&mut self,
         // walk generics and methods
         self.process_generic_params(generics, item.span, qualname.as_slice(), item.id, e);
         for method in methods.iter() {
-            self.visit_trait_method(method, e)
+            self.visit_trait_item(method, e)
         }
     }
 
@@ -735,18 +749,44 @@ fn process_path(&mut self,
             def::DefStaticMethod(declid, provenence, _) => {
                 let sub_span = self.span.sub_span_for_meth_name(ex.span);
                 let defid = if declid.krate == ast::LOCAL_CRATE {
-                    let m = ty::method(&self.analysis.ty_cx, declid);
+                    let ti = ty::impl_or_trait_item(&self.analysis.ty_cx,
+                                                    declid);
                     match provenence {
-                        def::FromTrait(def_id) =>
-                            Some(ty::trait_methods(&self.analysis.ty_cx, def_id)
-                                .iter().find(|mr| mr.ident.name == m.ident.name).unwrap().def_id),
+                        def::FromTrait(def_id) => {
+                            Some(ty::trait_items(&self.analysis.ty_cx,
+                                                 def_id)
+                                    .iter()
+                                    .find(|mr| {
+                                        match **mr {
+                                            ty::MethodTraitItem(ref mr) => {
+                                                mr.ident.name == ti.ident()
+                                                                   .name
+                                            }
+                                        }
+                                    })
+                                    .unwrap()
+                                    .def_id())
+                        }
                         def::FromImpl(def_id) => {
-                            let impl_methods = self.analysis.ty_cx.impl_methods.borrow();
-                            Some(*impl_methods.get(&def_id)
-                                .iter().find(|mr|
-                                    ty::method(
-                                        &self.analysis.ty_cx, **mr).ident.name == m.ident.name)
-                                .unwrap())
+                            let impl_items = self.analysis
+                                                 .ty_cx
+                                                 .impl_items
+                                                 .borrow();
+                            Some(impl_items.get(&def_id)
+                                           .iter()
+                                           .find(|mr| {
+                                            match **mr {
+                                                ty::MethodTraitItemId(mr) => {
+                                                    ty::impl_or_trait_item(
+                                                            &self.analysis
+                                                                 .ty_cx,
+                                                            mr).ident()
+                                                               .name ==
+                                                        ti.ident().name
+                                                    }
+                                                }
+                                            }).unwrap()
+                                              .def_id())
                         }
                     }
                 } else {
@@ -845,27 +885,45 @@ fn process_method_call(&mut self,
             typeck::MethodStatic(def_id) |
             typeck::MethodStaticUnboxedClosure(def_id) => {
                 // method invoked on an object with a concrete type (not a static method)
-                let decl_id = ty::trait_method_of_method(&self.analysis.ty_cx, def_id);
+                let decl_id =
+                    match ty::trait_item_of_item(&self.analysis.ty_cx,
+                                                 def_id) {
+                        None => None,
+                        Some(ty::MethodTraitItemId(decl_id)) => Some(decl_id),
+                    };
 
-                // This incantation is required if the method referenced is a trait's
-                // default implementation.
-                let def_id = ty::method(&self.analysis.ty_cx, def_id).provided_source
-                                    .unwrap_or(def_id);
+                // This incantation is required if the method referenced is a
+                // trait's default implementation.
+                let def_id = match ty::impl_or_trait_item(&self.analysis
+                                                               .ty_cx,
+                                                          def_id) {
+                    ty::MethodTraitItem(method) => {
+                        method.provided_source.unwrap_or(def_id)
+                    }
+                };
                 (Some(def_id), decl_id)
             }
             typeck::MethodParam(mp) => {
                 // method invoked on a type parameter
-                let method = ty::trait_method(&self.analysis.ty_cx,
-                                              mp.trait_id,
-                                              mp.method_num);
-                (None, Some(method.def_id))
+                let trait_item = ty::trait_item(&self.analysis.ty_cx,
+                                                mp.trait_id,
+                                                mp.method_num);
+                match trait_item {
+                    ty::MethodTraitItem(method) => {
+                        (None, Some(method.def_id))
+                    }
+                }
             },
             typeck::MethodObject(mo) => {
                 // method invoked on a trait instance
-                let method = ty::trait_method(&self.analysis.ty_cx,
-                                              mo.trait_id,
-                                              mo.method_num);
-                (None, Some(method.def_id))
+                let trait_item = ty::trait_item(&self.analysis.ty_cx,
+                                                mo.trait_id,
+                                                mo.method_num);
+                match trait_item {
+                    ty::MethodTraitItem(method) => {
+                        (None, Some(method.def_id))
+                    }
+                }
             },
         };
         let sub_span = self.span.sub_span_for_meth_name(ex.span);
@@ -968,8 +1026,17 @@ fn visit_item(&mut self, item:&ast::Item, e: DxrVisitorEnv) {
                 self.process_static(item, e, typ, mt, &*expr),
             ast::ItemStruct(def, ref ty_params) => self.process_struct(item, e, &*def, ty_params),
             ast::ItemEnum(ref def, ref ty_params) => self.process_enum(item, e, def, ty_params),
-            ast::ItemImpl(ref ty_params, ref trait_ref, typ, ref methods) =>
-                self.process_impl(item, e, ty_params, trait_ref, typ, methods),
+            ast::ItemImpl(ref ty_params,
+                          ref trait_ref,
+                          typ,
+                          ref impl_items) => {
+                self.process_impl(item,
+                                  e,
+                                  ty_params,
+                                  trait_ref,
+                                  typ,
+                                  impl_items)
+            }
             ast::ItemTrait(ref generics, _, ref trait_refs, ref methods) =>
                 self.process_trait(item, e, generics, trait_refs, methods),
             ast::ItemMod(ref m) => self.process_mod(item, e, m),
@@ -1027,16 +1094,16 @@ fn visit_fn(&mut self,
         }
     }
 
-    fn visit_trait_method(&mut self, tm: &ast::TraitMethod, e: DxrVisitorEnv) {
+    fn visit_trait_item(&mut self, tm: &ast::TraitItem, e: DxrVisitorEnv) {
         match *tm {
-            ast::Required(ref method_type) => {
+            ast::RequiredMethod(ref method_type) => {
                 if generated_code(method_type.span) {
                     return;
                 }
 
-                let mut scope_id ;
-                let mut qualname = match ty::trait_of_method(&self.analysis.ty_cx,
-                                                             ast_util::local_def(method_type.id)) {
+                let mut scope_id;
+                let mut qualname = match ty::trait_of_item(&self.analysis.ty_cx,
+                                                           ast_util::local_def(method_type.id)) {
                     Some(def_id) => {
                         scope_id = def_id.node;
                         ty::item_path_str(&self.analysis.ty_cx, def_id).append("::")
@@ -1070,7 +1137,7 @@ fn visit_trait_method(&mut self, tm: &ast::TraitMethod, e: DxrVisitorEnv) {
                                             method_type.id,
                                             e);
             }
-            ast::Provided(method) => self.process_method(&*method, e),
+            ast::ProvidedMethod(method) => self.process_method(&*method, e),
         }
     }
 
@@ -1237,7 +1304,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 a3fa5a5f85ba4cd5237d3d43d37ebb49bffbd148..e73d81d9bf5974923a14383547eb37ea6bb37da5 100644 (file)
@@ -16,7 +16,7 @@
 use syntax::{attr, visit};
 use syntax::ast;
 use syntax::ast::{Attribute, Block, Crate, DefId, FnDecl, NodeId, Variant};
-use syntax::ast::{Item, Required, Provided, TraitMethod, TypeMethod, Method};
+use syntax::ast::{Item, RequiredMethod, ProvidedMethod, TraitItem, TypeMethod, Method};
 use syntax::ast::{Generics, StructDef, StructField, Ident};
 use syntax::ast_util::is_local;
 use syntax::attr::Stability;
@@ -68,18 +68,18 @@ fn visit_fn(&mut self, fk: &FnKind, fd: &FnDecl, b: &Block,
         visit::walk_fn(self, fk, fd, b, s, stab)
     }
 
-    fn visit_trait_method(&mut self, t: &TraitMethod, parent: Option<Stability>) {
+    fn visit_trait_item(&mut self, t: &TraitItem, parent: Option<Stability>) {
         let stab = match *t {
-            Required(TypeMethod {attrs: ref attrs, id: id, ..}) =>
+            RequiredMethod(TypeMethod {attrs: ref attrs, id: id, ..}) =>
                 self.annotate(id, attrs.as_slice(), parent),
 
             // work around lack of pattern matching for @ types
-            Provided(method) => match *method {
+            ProvidedMethod(method) => match *method {
                 Method {attrs: ref attrs, id: id, ..} =>
                     self.annotate(id, attrs.as_slice(), parent)
             }
         };
-        visit::walk_trait_method(self, t, stab)
+        visit::walk_trait_item(self, t, stab)
     }
 
     fn visit_variant(&mut self, v: &Variant, g: &Generics, parent: Option<Stability>) {
@@ -116,10 +116,11 @@ pub fn build(krate: &Crate) -> Index {
 
 /// Lookup the stability for a node, loading external crate
 /// metadata as necessary.
-pub fn lookup(tcx: &ty::ctxt,  id: DefId) -> Option<Stability> {
+pub fn lookup(tcx: &ty::ctxt, id: DefId) -> Option<Stability> {
     // is this definition the implementation of a trait method?
-    match ty::trait_method_of_method(tcx, id) {
-        Some(trait_method_id) if trait_method_id != id => {
+    match ty::trait_item_of_item(tcx, id) {
+        Some(ty::MethodTraitItemId(trait_method_id))
+                if trait_method_id != id => {
             lookup(tcx, trait_method_id)
         }
         _ if is_local(id) => {
index 9ec0407b5c3fc48e2c2aa9f39b258dd73f674028..9c68631baa44c6f94a8032e6ebe3d0a2eda8ca26 100644 (file)
@@ -170,7 +170,7 @@ fn represent_type_uncached(cx: &CrateContext, t: ty::t) -> Repr {
 
             return Univariant(mk_struct(cx, ftys.as_slice(), packed), dtor)
         }
-        ty::ty_unboxed_closure(def_id) => {
+        ty::ty_unboxed_closure(def_id, _) => {
             let upvars = ty::unboxed_closure_upvars(cx.tcx(), def_id);
             let upvar_types = upvars.iter().map(|u| u.ty).collect::<Vec<_>>();
             return Univariant(mk_struct(cx, upvar_types.as_slice(), false),
index 35d32d995250645884240321304b06fa972ca31d..9aa4355632cfb3273bb454b05a978819fdbddf36 100644 (file)
@@ -45,8 +45,8 @@
 use middle::trans::build::*;
 use middle::trans::builder::{Builder, noname};
 use middle::trans::callee;
+use middle::trans::cleanup::{CleanupMethods, ScopeId};
 use middle::trans::cleanup;
-use middle::trans::cleanup::CleanupMethods;
 use middle::trans::common::*;
 use middle::trans::consts;
 use middle::trans::controlflow;
@@ -252,6 +252,31 @@ fn get_extern_rust_fn(ccx: &CrateContext, fn_ty: ty::t, name: &str, did: ast::De
     f
 }
 
+pub fn self_type_for_unboxed_closure(ccx: &CrateContext,
+                                     closure_id: ast::DefId)
+                                     -> ty::t {
+    let unboxed_closure_type = ty::mk_unboxed_closure(ccx.tcx(),
+                                                      closure_id,
+                                                      ty::ReStatic);
+    let unboxed_closures = ccx.tcx.unboxed_closures.borrow();
+    let unboxed_closure = unboxed_closures.get(&closure_id);
+    match unboxed_closure.kind {
+        ty::FnUnboxedClosureKind => {
+            ty::mk_imm_rptr(&ccx.tcx, ty::ReStatic, unboxed_closure_type)
+        }
+        ty::FnMutUnboxedClosureKind => {
+            ty::mk_mut_rptr(&ccx.tcx, ty::ReStatic, unboxed_closure_type)
+        }
+        ty::FnOnceUnboxedClosureKind => unboxed_closure_type,
+    }
+}
+
+pub fn kind_for_unboxed_closure(ccx: &CrateContext, closure_id: ast::DefId)
+                                -> ty::UnboxedClosureKind {
+    let unboxed_closures = ccx.tcx.unboxed_closures.borrow();
+    unboxed_closures.get(&closure_id).kind
+}
+
 pub fn decl_rust_fn(ccx: &CrateContext, fn_ty: ty::t, name: &str) -> ValueRef {
     let (inputs, output, abi, env) = match ty::get(fn_ty).sty {
         ty::ty_bare_fn(ref f) => {
@@ -260,12 +285,12 @@ pub fn decl_rust_fn(ccx: &CrateContext, fn_ty: ty::t, name: &str) -> ValueRef {
         ty::ty_closure(ref f) => {
             (f.sig.inputs.clone(), f.sig.output, f.abi, Some(Type::i8p(ccx)))
         }
-        ty::ty_unboxed_closure(closure_did) => {
-            let unboxed_closure_types = ccx.tcx
-                                           .unboxed_closure_types
-                                           .borrow();
-            let function_type = unboxed_closure_types.get(&closure_did);
-            let llenvironment_type = type_of(ccx, fn_ty).ptr_to();
+        ty::ty_unboxed_closure(closure_did, _) => {
+            let unboxed_closures = ccx.tcx.unboxed_closures.borrow();
+            let unboxed_closure = unboxed_closures.get(&closure_did);
+            let function_type = unboxed_closure.closure_type.clone();
+            let self_type = self_type_for_unboxed_closure(ccx, closure_did);
+            let llenvironment_type = type_of_explicit_arg(ccx, self_type);
             (function_type.sig.inputs.clone(),
              function_type.sig.output,
              RustCall,
@@ -691,7 +716,7 @@ fn iter_variant<'r,
               }
           })
       }
-      ty::ty_unboxed_closure(def_id) => {
+      ty::ty_unboxed_closure(def_id, _) => {
           let repr = adt::represent_type(cx.ccx(), t);
           let upvars = ty::unboxed_closure_upvars(cx.tcx(), def_id);
           for (i, upvar) in upvars.iter().enumerate() {
@@ -1274,9 +1299,9 @@ fn has_nested_returns(tcx: &ty::ctxt, id: ast::NodeId) -> bool {
                 _ => tcx.sess.bug("unexpected item variant in has_nested_returns")
             }
         }
-        Some(ast_map::NodeTraitMethod(trait_method)) => {
+        Some(ast_map::NodeTraitItem(trait_method)) => {
             match *trait_method {
-                ast::Provided(m) => {
+                ast::ProvidedMethod(m) => {
                     match m.node {
                         ast::MethDecl(_, _, _, _, _, _, blk, _) => {
                             let mut explicit = CheckForNestedReturnsVisitor { found: false };
@@ -1288,25 +1313,41 @@ fn has_nested_returns(tcx: &ty::ctxt, id: ast::NodeId) -> bool {
                         ast::MethMac(_) => tcx.sess.bug("unexpanded macro")
                     }
                 }
-                ast::Required(_) => tcx.sess.bug("unexpected variant: required trait method in \
-                                                  has_nested_returns")
+                ast::RequiredMethod(_) => {
+                    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
+        Some(ast_map::NodeImplItem(ref ii)) => {
+            match **ii {
+                ast::MethodImplItem(ref 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::MethMac(_) => tcx.sess.bug("unexpanded macro")
             }
         }
         Some(ast_map::NodeExpr(e)) => {
             match e.node {
-                ast::ExprFnBlock(_, blk) | ast::ExprProc(_, blk) | ast::ExprUnboxedFn(_, blk) => {
+                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);
@@ -1458,6 +1499,8 @@ pub fn create_datums_for_fn_args(fcx: &FunctionContext,
 /// Creates rvalue datums for each of the incoming function arguments and
 /// tuples the arguments. These will later be stored into appropriate lvalue
 /// datums.
+///
+/// FIXME(pcwalton): Reduce the amount of code bloat this is responsible for.
 fn create_datums_for_fn_args_under_call_abi<
         'a>(
         mut bcx: &'a Block<'a>,
@@ -1706,7 +1749,8 @@ 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>) {
+                     maybe_load_env: <'a>|&'a Block<'a>, ScopeId|
+                                         -> &'a Block<'a>) {
     ccx.stats.n_closures.set(ccx.stats.n_closures.get() + 1);
 
     let _icx = push_ctxt("trans_closure");
@@ -1771,7 +1815,7 @@ pub fn trans_closure(ccx: &CrateContext,
         }
     };
 
-    bcx = maybe_load_env(bcx);
+    bcx = maybe_load_env(bcx, cleanup::CustomScope(arg_scope));
 
     // Up until here, IR instructions for this function have explicitly not been annotated with
     // source code location, so we don't step into call setup code. From here on, source location
@@ -1852,7 +1896,7 @@ pub fn trans_fn(ccx: &CrateContext,
                   abi,
                   false,
                   NotUnboxedClosure,
-                  |bcx| bcx);
+                  |bcx, _| bcx);
 }
 
 pub fn trans_enum_variant(ccx: &CrateContext,
@@ -2077,8 +2121,12 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) {
         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);
+      ast::ItemImpl(ref generics, _, _, ref impl_items) => {
+        meth::trans_impl(ccx,
+                         item.ident,
+                         impl_items.as_slice(),
+                         generics,
+                         item.id);
       }
       ast::ItemMod(ref m) => {
         trans_mod(ccx, m);
@@ -2186,11 +2234,11 @@ pub fn get_fn_llvm_attributes(ccx: &CrateContext, fn_ty: ty::t)
     let (fn_sig, abi, has_env) = match ty::get(fn_ty).sty {
         ty::ty_closure(ref f) => (f.sig.clone(), f.abi, true),
         ty::ty_bare_fn(ref f) => (f.sig.clone(), f.abi, false),
-        ty::ty_unboxed_closure(closure_did) => {
-            let unboxed_closure_types = ccx.tcx
-                                           .unboxed_closure_types
-                                           .borrow();
-            let function_type = unboxed_closure_types.get(&closure_did);
+        ty::ty_unboxed_closure(closure_did, _) => {
+            let unboxed_closures = ccx.tcx.unboxed_closures.borrow();
+            let function_type = unboxed_closures.get(&closure_did)
+                                                .closure_type
+                                                .clone();
             (function_type.sig.clone(), RustCall, true)
         }
         _ => fail!("expected closure or function.")
@@ -2585,21 +2633,23 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
             v
         }
 
-        ast_map::NodeTraitMethod(trait_method) => {
-            debug!("get_item_val(): processing a NodeTraitMethod");
+        ast_map::NodeTraitItem(trait_method) => {
+            debug!("get_item_val(): processing a NodeTraitItem");
             match *trait_method {
-                ast::Required(_) => {
+                ast::RequiredMethod(_) => {
                     ccx.sess().bug("unexpected variant: required trait method in \
                                    get_item_val()");
                 }
-                ast::Provided(m) => {
+                ast::ProvidedMethod(m) => {
                     register_method(ccx, id, &*m)
                 }
             }
         }
 
-        ast_map::NodeMethod(m) => {
-            register_method(ccx, id, &*m)
+        ast_map::NodeImplItem(ii) => {
+            match *ii {
+                ast::MethodImplItem(m) => register_method(ccx, id, &*m),
+            }
         }
 
         ast_map::NodeForeignItem(ni) => {
index 379b53eebbb4f527cdad7f1d8049c61987e5017b..56c1c66533133c222570fb8f173ca3fe70b88de1 100644 (file)
@@ -77,7 +77,7 @@ pub enum CalleeData {
 
     Intrinsic(ast::NodeId, subst::Substs),
 
-    TraitMethod(MethodData)
+    TraitItem(MethodData)
 }
 
 pub struct Callee<'a> {
@@ -449,7 +449,7 @@ pub fn trans_fn_ref_with_vtables(
     assert!(substs.types.all(|t| !ty::type_needs_infer(*t)));
 
     // Load the info for the appropriate trait if necessary.
-    match ty::trait_of_method(tcx, def_id) {
+    match ty::trait_of_item(tcx, def_id) {
         None => {}
         Some(trait_id) => {
             ty::populate_implementations_for_trait_if_necessary(tcx, trait_id)
@@ -476,35 +476,43 @@ pub fn trans_fn_ref_with_vtables(
             // So, what we need to do is find this substitution and
             // compose it with the one we already have.
 
-            let impl_id = ty::method(tcx, def_id).container_id();
-            let method = ty::method(tcx, source_id);
-            let trait_ref = ty::impl_trait_ref(tcx, impl_id)
-                .expect("could not find trait_ref for impl with \
-                         default methods");
-
-            // Compute the first substitution
-            let first_subst = make_substs_for_receiver_types(
-                tcx, &*trait_ref, &*method);
-
-            // And compose them
-            let new_substs = first_subst.subst(tcx, &substs);
-
-            debug!("trans_fn_with_vtables - default method: \
-                    substs = {}, trait_subst = {}, \
-                    first_subst = {}, new_subst = {}, \
-                    vtables = {}",
-                   substs.repr(tcx), trait_ref.substs.repr(tcx),
-                   first_subst.repr(tcx), new_substs.repr(tcx),
-                   vtables.repr(tcx));
-
-            let param_vtables =
-                resolve_default_method_vtables(bcx, impl_id, &substs, vtables);
-
-            debug!("trans_fn_with_vtables - default method: \
-                    param_vtables = {}",
-                   param_vtables.repr(tcx));
-
-            (true, source_id, new_substs, param_vtables)
+            let impl_id = ty::impl_or_trait_item(tcx, def_id).container()
+                                                             .id();
+            let impl_or_trait_item = ty::impl_or_trait_item(tcx, source_id);
+            match impl_or_trait_item {
+                ty::MethodTraitItem(method) => {
+                    let trait_ref = ty::impl_trait_ref(tcx, impl_id)
+                        .expect("could not find trait_ref for impl with \
+                                 default methods");
+
+                    // Compute the first substitution
+                    let first_subst = make_substs_for_receiver_types(
+                        tcx, &*trait_ref, &*method);
+
+                    // And compose them
+                    let new_substs = first_subst.subst(tcx, &substs);
+
+                    debug!("trans_fn_with_vtables - default method: \
+                            substs = {}, trait_subst = {}, \
+                            first_subst = {}, new_subst = {}, \
+                            vtables = {}",
+                           substs.repr(tcx), trait_ref.substs.repr(tcx),
+                           first_subst.repr(tcx), new_substs.repr(tcx),
+                           vtables.repr(tcx));
+
+                    let param_vtables =
+                        resolve_default_method_vtables(bcx,
+                                                       impl_id,
+                                                       &substs,
+                                                       vtables);
+
+                    debug!("trans_fn_with_vtables - default method: \
+                            param_vtables = {}",
+                           param_vtables.repr(tcx));
+
+                    (true, source_id, new_substs, param_vtables)
+                }
+            }
         }
     };
 
@@ -742,7 +750,7 @@ pub fn trans_call_inner<'a>(
         Fn(llfn) => {
             (llfn, None, None)
         }
-        TraitMethod(d) => {
+        TraitItem(d) => {
             (d.llfn, None, Some(d.llself))
         }
         Closure(d) => {
index 44c52a6739ab4de0c8c51d6e1354d2fe1bf62704..17f1b6ca52669c07dfb0ec39b19358160f6cc48b 100644 (file)
@@ -19,6 +19,7 @@
 use middle::trans::adt;
 use middle::trans::base::*;
 use middle::trans::build::*;
+use middle::trans::cleanup::{CleanupMethods, ScopeId};
 use middle::trans::common::*;
 use middle::trans::datum::{Datum, DatumBlock, Expr, Lvalue, rvalue_scratch_datum};
 use middle::trans::debuginfo;
@@ -306,7 +307,9 @@ fn load_environment<'a>(bcx: &'a Block<'a>,
 
 fn load_unboxed_closure_environment<'a>(
                                     bcx: &'a Block<'a>,
-                                    freevars: &Vec<freevars::freevar_entry>)
+                                    arg_scope_id: ScopeId,
+                                    freevars: &Vec<freevars::freevar_entry>,
+                                    closure_id: ast::DefId)
                                     -> &'a Block<'a> {
     let _icx = push_ctxt("closure::load_environment");
 
@@ -314,11 +317,31 @@ fn load_unboxed_closure_environment<'a>(
         return bcx
     }
 
-    let llenv = bcx.fcx.llenv.unwrap();
+    // Special case for small by-value selfs.
+    let self_type = self_type_for_unboxed_closure(bcx.ccx(), closure_id);
+    let kind = kind_for_unboxed_closure(bcx.ccx(), closure_id);
+    let llenv = if kind == ty::FnOnceUnboxedClosureKind &&
+            !arg_is_indirect(bcx.ccx(), self_type) {
+        let datum = rvalue_scratch_datum(bcx,
+                                         self_type,
+                                         "unboxed_closure_env");
+        store_ty(bcx, bcx.fcx.llenv.unwrap(), datum.val, self_type);
+        assert!(freevars.len() <= 1);
+        datum.val
+    } else {
+        bcx.fcx.llenv.unwrap()
+    };
+
     for (i, freevar) in freevars.iter().enumerate() {
         let upvar_ptr = GEPi(bcx, llenv, [0, i]);
         let def_id = freevar.def.def_id();
         bcx.fcx.llupvars.borrow_mut().insert(def_id.node, upvar_ptr);
+
+        if kind == ty::FnOnceUnboxedClosureKind {
+            bcx.fcx.schedule_drop_mem(arg_scope_id,
+                                      upvar_ptr,
+                                      node_id_type(bcx, def_id.node))
+        }
     }
 
     bcx
@@ -394,7 +417,7 @@ pub fn trans_expr_fn<'a>(
                   ty::ty_fn_abi(fty),
                   true,
                   NotUnboxedClosure,
-                  |bcx| load_environment(bcx, cdata_ty, &freevars, store));
+                  |bcx, _| load_environment(bcx, cdata_ty, &freevars, store));
     fill_fn_pair(bcx, dest_addr, llfn, llbox);
     bcx
 }
@@ -404,7 +427,7 @@ pub fn trans_expr_fn<'a>(
 pub fn get_or_create_declaration_if_unboxed_closure(ccx: &CrateContext,
                                                     closure_id: ast::DefId)
                                                     -> Option<ValueRef> {
-    if !ccx.tcx.unboxed_closure_types.borrow().contains_key(&closure_id) {
+    if !ccx.tcx.unboxed_closures.borrow().contains_key(&closure_id) {
         // Not an unboxed closure.
         return None
     }
@@ -418,7 +441,9 @@ pub fn get_or_create_declaration_if_unboxed_closure(ccx: &CrateContext,
         None => {}
     }
 
-    let function_type = ty::mk_unboxed_closure(&ccx.tcx, closure_id);
+    let function_type = ty::mk_unboxed_closure(&ccx.tcx,
+                                               closure_id,
+                                               ty::ReStatic);
     let symbol = ccx.tcx.map.with_path(closure_id.node, |path| {
         mangle_internal_name_by_path_and_seq(path, "unboxed_closure")
     });
@@ -453,19 +478,10 @@ pub fn trans_unboxed_closure<'a>(
         bcx.ccx(),
         closure_id).unwrap();
 
-    // Untuple the arguments.
-    let unboxed_closure_types = bcx.tcx().unboxed_closure_types.borrow();
-    let /*mut*/ function_type = (*unboxed_closure_types.get(&closure_id)).clone();
-    /*function_type.sig.inputs =
-        match ty::get(*function_type.sig.inputs.get(0)).sty {
-            ty::ty_tup(ref tuple_types) => {
-                tuple_types.iter().map(|x| (*x).clone()).collect()
-            }
-            _ => {
-                bcx.tcx().sess.span_bug(body.span,
-                                        "unboxed closure wasn't a tuple?!")
-            }
-        };*/
+    let unboxed_closures = bcx.tcx().unboxed_closures.borrow();
+    let function_type = unboxed_closures.get(&closure_id)
+                                        .closure_type
+                                        .clone();
     let function_type = ty::mk_closure(bcx.tcx(), function_type);
 
     let freevars: Vec<freevars::freevar_entry> =
@@ -486,7 +502,12 @@ pub fn trans_unboxed_closure<'a>(
                   ty::ty_fn_abi(function_type),
                   true,
                   IsUnboxedClosure,
-                  |bcx| load_unboxed_closure_environment(bcx, freevars_ptr));
+                  |bcx, arg_scope| {
+                      load_unboxed_closure_environment(bcx,
+                                                       arg_scope,
+                                                       freevars_ptr,
+                                                       closure_id)
+                  });
 
     // 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
@@ -502,13 +523,13 @@ pub fn trans_unboxed_closure<'a>(
     let repr = adt::represent_type(bcx.ccx(), node_id_type(bcx, id));
 
     // Create the closure.
-    for freevar in freevars_ptr.iter() {
+    for (i, freevar) in freevars_ptr.iter().enumerate() {
         let datum = expr::trans_local_var(bcx, freevar.def);
         let upvar_slot_dest = adt::trans_field_ptr(bcx,
                                                    &*repr,
                                                    dest_addr,
                                                    0,
-                                                   0);
+                                                   i);
         bcx = datum.store_to(bcx, upvar_slot_dest);
     }
     adt::trans_set_discr(bcx, &*repr, dest_addr, 0);
index 3b89c73b31da8cee0bf4ca5321d03236b4b7cc86..300e7ecf81f43dfaaccd530d006cc65ec0991cce 100644 (file)
@@ -18,6 +18,7 @@
 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;
@@ -31,7 +32,7 @@
 use middle::ty;
 use middle::typeck;
 use util::ppaux::Repr;
-use util::nodemap::NodeMap;
+use util::nodemap::{DefIdMap, NodeMap};
 
 use arena::TypedArena;
 use std::collections::HashMap;
@@ -513,9 +514,19 @@ fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<ast::NodeId> {
         self.tcx().region_maps.temporary_scope(rvalue_id)
     }
 
+    fn unboxed_closures<'a>(&'a self)
+                        -> &'a RefCell<DefIdMap<ty::UnboxedClosure>> {
+        &self.tcx().unboxed_closures
+    }
+
     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 c27b0bb8cb1ebeac5eb625248a57800331d4bcfb..9b78cedd4ac7f7425d5c7090aa0a73a94bf145c1 100644 (file)
@@ -1140,19 +1140,23 @@ pub fn create_function_debug_context(cx: &CrateContext,
                 }
             }
         }
-        ast_map::NodeMethod(ref method) => {
-            (method.pe_ident(),
-             method.pe_fn_decl(),
-             method.pe_generics(),
-             method.pe_body(),
-             method.span,
-             true)
+        ast_map::NodeImplItem(ref item) => {
+            match **item {
+                ast::MethodImplItem(ref method) => {
+                    (method.pe_ident(),
+                     method.pe_fn_decl(),
+                     method.pe_generics(),
+                     method.pe_body(),
+                     method.span,
+                     true)
+                }
+            }
         }
         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,
@@ -1168,9 +1172,9 @@ pub fn create_function_debug_context(cx: &CrateContext,
                         "create_function_debug_context: expected an expr_fn_block here")
             }
         }
-        ast_map::NodeTraitMethod(ref trait_method) => {
+        ast_map::NodeTraitItem(ref trait_method) => {
             match **trait_method {
-                ast::Provided(ref method) => {
+                ast::ProvidedMethod(ref method) => {
                     (method.pe_ident(),
                      method.pe_fn_decl(),
                      method.pe_generics(),
@@ -3618,9 +3622,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,
@@ -3895,7 +3899,7 @@ fn push_debuginfo_type_name(cx: &CrateContext,
                 push_debuginfo_type_name(cx, sig.output, true, output);
             }
         },
-        ty::ty_unboxed_closure(_) => {
+        ty::ty_unboxed_closure(..) => {
             output.push_str("closure");
         }
         ty::ty_err      |
index 1dad6e3cb18439684d0ae3301b2e96a0194657a9..576bdb8b8c0b8ab3278f6d279b2ce33f5866100d 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 88bb88da3f043d31117461ef61ea42e89b283fb0..fe9b593c11c7e1dee174642f0bbf78db75c7dff9 100644 (file)
@@ -741,6 +741,12 @@ unsafe fn build_wrap_fn(ccx: &CrateContext,
             let llforeign_arg_ty = *tys.fn_ty.arg_tys.get(i);
             let foreign_indirect = llforeign_arg_ty.is_indirect();
 
+            if llforeign_arg_ty.is_ignore() {
+                debug!("skipping ignored arg #{}", i);
+                llrust_args.push(C_undef(llrust_ty));
+                continue;
+            }
+
             // skip padding
             let foreign_index = next_foreign_arg(llforeign_arg_ty.pad.is_some());
             let mut llforeign_arg = get_param(llwrapfn, foreign_index);
index bf39f3a6aa385842d1d2a838aafe61dcbffa9648..4b1f37fcdc22afaf6cc1e1c401aab01d1bf6caec 100644 (file)
@@ -115,27 +115,42 @@ pub fn maybe_instantiate_inline(ccx: &CrateContext, fn_id: ast::DefId)
             ccx.sess().bug("maybe_get_item_ast returned a found_parent \
              with a non-item parent");
         }
-        csearch::found(ast::IIMethod(impl_did, is_provided, mth)) => {
-            ccx.external.borrow_mut().insert(fn_id, Some(mth.id));
-            ccx.external_srcs.borrow_mut().insert(mth.id, fn_id);
+        csearch::found(ast::IITraitItem(impl_did, impl_item)) => {
+            match impl_item {
+                ast::ProvidedInlinedTraitItem(mth) |
+                ast::RequiredInlinedTraitItem(mth) => {
+                    ccx.external.borrow_mut().insert(fn_id, Some(mth.id));
+                    ccx.external_srcs.borrow_mut().insert(mth.id, fn_id);
 
-            ccx.stats.n_inlines.set(ccx.stats.n_inlines.get() + 1);
-
-            // If this is a default method, we can't look up the
-            // impl type. But we aren't going to translate anyways, so don't.
-            if is_provided { return local_def(mth.id); }
+                    ccx.stats.n_inlines.set(ccx.stats.n_inlines.get() + 1);
+                }
+            }
 
-            let impl_tpt = ty::lookup_item_type(ccx.tcx(), impl_did);
-            let unparameterized =
-                impl_tpt.generics.types.is_empty() &&
-                mth.pe_generics().ty_params.is_empty();
+            match impl_item {
+                ast::ProvidedInlinedTraitItem(mth) => {
+                    // If this is a default method, we can't look up the
+                    // impl type. But we aren't going to translate anyways, so
+                    // don't.
+                    local_def(mth.id)
+                }
+                ast::RequiredInlinedTraitItem(mth) => {
+                    let impl_tpt = ty::lookup_item_type(ccx.tcx(), impl_did);
+                    let unparameterized = impl_tpt.generics.types.is_empty() &&
+                            mth.pe_generics().ty_params.is_empty();
 
-          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, []);
-          }
-          local_def(mth.id)
+                    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,
+                                 []);
+                    }
+                    local_def(mth.id)
+                }
+            }
         }
     };
 }
index 3578b25c83957edfaade6f1a5a379711255b37d4..31f2a3df6620216a0f34156608fde051ca91c5d1 100644 (file)
@@ -35,7 +35,6 @@
 use util::ppaux::Repr;
 
 use std::c_str::ToCStr;
-use std::gc::Gc;
 use syntax::abi::{Rust, RustCall};
 use syntax::parse::token;
 use syntax::{ast, ast_map, visit};
@@ -49,7 +48,7 @@
 */
 pub fn trans_impl(ccx: &CrateContext,
                   name: ast::Ident,
-                  methods: &[Gc<ast::Method>],
+                  impl_items: &[ast::ImplItem],
                   generics: &ast::Generics,
                   id: ast::NodeId) {
     let _icx = push_ctxt("meth::trans_impl");
@@ -61,24 +60,34 @@ pub fn trans_impl(ccx: &CrateContext,
     // items that we need to translate.
     if !generics.ty_params.is_empty() {
         let mut v = TransItemVisitor{ ccx: ccx };
-        for method in methods.iter() {
-            visit::walk_method_helper(&mut v, &**method, ());
+        for impl_item in impl_items.iter() {
+            match *impl_item {
+                ast::MethodImplItem(method) => {
+                    visit::walk_method_helper(&mut v, &*method, ());
+                }
+            }
         }
         return;
     }
-    for method in methods.iter() {
-        if method.pe_generics().ty_params.len() == 0u {
-            let llfn = get_item_val(ccx, method.id);
-            trans_fn(ccx,
-                     &*method.pe_fn_decl(),
-                     &*method.pe_body(),
-                     llfn,
-                     &param_substs::empty(),
-                     method.id,
-                     []);
+    for impl_item in impl_items.iter() {
+        match *impl_item {
+            ast::MethodImplItem(method) => {
+                if method.pe_generics().ty_params.len() == 0u {
+                    let llfn = get_item_val(ccx, method.id);
+                    trans_fn(ccx,
+                             &*method.pe_fn_decl(),
+                             &*method.pe_body(),
+                             llfn,
+                             &param_substs::empty(),
+                             method.id,
+                             []);
+                }
+                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, ());
     }
 }
 
@@ -165,10 +174,10 @@ pub fn trans_static_method_callee(bcx: &Block,
 
     let mname = if method_id.krate == ast::LOCAL_CRATE {
         match bcx.tcx().map.get(method_id.node) {
-            ast_map::NodeTraitMethod(method) => {
+            ast_map::NodeTraitItem(method) => {
                 let ident = match *method {
-                    ast::Required(ref m) => m.ident,
-                    ast::Provided(ref m) => m.pe_ident()
+                    ast::RequiredMethod(ref m) => m.ident,
+                    ast::ProvidedMethod(ref m) => m.pe_ident()
                 };
                 ident.name
             }
@@ -213,22 +222,33 @@ pub fn trans_static_method_callee(bcx: &Block,
     }
 }
 
-fn method_with_name(ccx: &CrateContext,
-                    impl_id: ast::DefId,
-                    name: ast::Name) -> ast::DefId {
+fn method_with_name(ccx: &CrateContext, impl_id: ast::DefId, name: ast::Name)
+                    -> ast::DefId {
     match ccx.impl_method_cache.borrow().find_copy(&(impl_id, name)) {
         Some(m) => return m,
         None => {}
     }
 
-    let methods = ccx.tcx.impl_methods.borrow();
-    let methods = methods.find(&impl_id)
-                         .expect("could not find impl while translating");
-    let meth_did = methods.iter().find(|&did| ty::method(&ccx.tcx, *did).ident.name == name)
-                                 .expect("could not find method while translating");
-
-    ccx.impl_method_cache.borrow_mut().insert((impl_id, name), *meth_did);
-    *meth_did
+    let impl_items = ccx.tcx.impl_items.borrow();
+    let impl_items =
+        impl_items.find(&impl_id)
+                  .expect("could not find impl while translating");
+    let meth_did = impl_items.iter()
+                             .find(|&did| {
+                                match *did {
+                                    ty::MethodTraitItemId(did) => {
+                                        ty::impl_or_trait_item(&ccx.tcx,
+                                                               did).ident()
+                                                                   .name ==
+                                            name
+                                    }
+                                }
+                             }).expect("could not find method while \
+                                        translating");
+
+    ccx.impl_method_cache.borrow_mut().insert((impl_id, name),
+                                              meth_did.def_id());
+    meth_did.def_id()
 }
 
 fn trans_monomorphized_callee<'a>(
@@ -242,7 +262,9 @@ fn trans_monomorphized_callee<'a>(
     match vtbl {
       typeck::vtable_static(impl_did, rcvr_substs, rcvr_origins) => {
           let ccx = bcx.ccx();
-          let mname = ty::trait_method(ccx.tcx(), trait_id, n_method).ident;
+          let mname = match ty::trait_item(ccx.tcx(), trait_id, n_method) {
+              ty::MethodTraitItem(method) => method.ident,
+          };
           let mth_id = method_with_name(bcx.ccx(), impl_did, mname.name);
 
           // create a concatenated set of substitutions which includes
@@ -433,7 +455,7 @@ pub fn trans_trait_callee_from_llval<'a>(bcx: &'a Block<'a>,
 
     return Callee {
         bcx: bcx,
-        data: TraitMethod(MethodData {
+        data: TraitItem(MethodData {
             llfn: mptr,
             llself: llself,
         })
@@ -446,7 +468,7 @@ pub fn trans_trait_callee_from_llval<'a>(bcx: &'a Block<'a>,
 fn get_callee_substitutions_for_unboxed_closure(bcx: &Block,
                                                 def_id: ast::DefId)
                                                 -> subst::Substs {
-    let self_ty = ty::mk_unboxed_closure(bcx.tcx(), def_id);
+    let self_ty = ty::mk_unboxed_closure(bcx.tcx(), def_id, ty::ReStatic);
     subst::Substs::erased(
         VecPerParamSpace::new(Vec::new(),
                               vec![
@@ -552,35 +574,42 @@ fn emit_vtable_methods(bcx: &Block,
 
     ty::populate_implementations_for_trait_if_necessary(bcx.tcx(), trt_id);
 
-    let trait_method_def_ids = ty::trait_method_def_ids(tcx, trt_id);
-    trait_method_def_ids.iter().map(|method_def_id| {
-        let ident = ty::method(tcx, *method_def_id).ident;
+    let trait_item_def_ids = ty::trait_item_def_ids(tcx, trt_id);
+    trait_item_def_ids.iter().map(|method_def_id| {
+        let method_def_id = method_def_id.def_id();
+        let ident = ty::impl_or_trait_item(tcx, method_def_id).ident();
         // The substitutions we have are on the impl, so we grab
         // the method type from the impl to substitute into.
         let m_id = method_with_name(ccx, impl_id, ident.name);
-        let m = ty::method(tcx, m_id);
-        debug!("(making impl vtable) emitting method {} at subst {}",
-               m.repr(tcx),
-               substs.repr(tcx));
-        if m.generics.has_type_params(subst::FnSpace) ||
-           ty::type_has_self(ty::mk_bare_fn(tcx, m.fty.clone())) {
-            debug!("(making impl vtable) method has self or type params: {}",
-                   token::get_ident(ident));
-            C_null(Type::nil(ccx).ptr_to())
-        } else {
-            let mut fn_ref = trans_fn_ref_with_vtables(bcx,
-                                                       m_id,
-                                                       ExprId(0),
-                                                       substs.clone(),
-                                                       vtables.clone());
-            if m.explicit_self == ty::ByValueExplicitSelfCategory {
-                fn_ref = trans_unboxing_shim(bcx,
-                                             fn_ref,
-                                             &*m,
-                                             m_id,
-                                             substs.clone());
+        let ti = ty::impl_or_trait_item(tcx, m_id);
+        match ti {
+            ty::MethodTraitItem(m) => {
+                debug!("(making impl vtable) emitting method {} at subst {}",
+                       m.repr(tcx),
+                       substs.repr(tcx));
+                if m.generics.has_type_params(subst::FnSpace) ||
+                   ty::type_has_self(ty::mk_bare_fn(tcx, m.fty.clone())) {
+                    debug!("(making impl vtable) method has self or type \
+                            params: {}",
+                           token::get_ident(ident));
+                    C_null(Type::nil(ccx).ptr_to())
+                } else {
+                    let mut fn_ref = trans_fn_ref_with_vtables(
+                        bcx,
+                        m_id,
+                        ExprId(0),
+                        substs.clone(),
+                        vtables.clone());
+                    if m.explicit_self == ty::ByValueExplicitSelfCategory {
+                        fn_ref = trans_unboxing_shim(bcx,
+                                                     fn_ref,
+                                                     &*m,
+                                                     m_id,
+                                                     substs.clone());
+                    }
+                    fn_ref
+                }
             }
-            fn_ref
         }
     }).collect()
 }
index 6d705c7d914e39118788d7d8cad768bb7b1028cf..e19ee035a781e3a02169232b68c70b17caaa5783 100644 (file)
@@ -197,15 +197,25 @@ pub fn monomorphic_fn(ccx: &CrateContext,
             }
             d
         }
-        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, []);
-            d
+        ast_map::NodeImplItem(ii) => {
+            match *ii {
+                ast::MethodImplItem(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,
+                             []);
+                    d
+                }
+            }
         }
-        ast_map::NodeTraitMethod(method) => {
+        ast_map::NodeTraitItem(method) => {
             match *method {
-                ast::Provided(mth) => {
+                ast::ProvidedMethod(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,
index 9caa9f681aadffe42beb6d8b8a03261a45cda3b6..2aff12c2b68c5010a262a596a21942b3697fbf92 100644 (file)
@@ -25,7 +25,6 @@
 use middle::ty;
 use util::ppaux::ty_to_string;
 
-use std::rc::Rc;
 use arena::TypedArena;
 use libc::c_uint;
 use syntax::ast::DefId;
@@ -36,7 +35,7 @@
 
 pub struct Reflector<'a, 'b> {
     visitor_val: ValueRef,
-    visitor_methods: &'a [Rc<ty::Method>],
+    visitor_items: &'a [ty::ImplOrTraitItem],
     final_bcx: &'b Block<'b>,
     tydesc_ty: Type,
     bcx: &'b Block<'b>
@@ -87,13 +86,14 @@ pub fn c_mt(&mut self, mt: &ty::mt) -> Vec<ValueRef> {
     pub fn visit(&mut self, ty_name: &str, args: &[ValueRef]) {
         let fcx = self.bcx.fcx;
         let tcx = self.bcx.tcx();
-        let mth_idx = ty::method_idx(token::str_to_ident(format!(
+        let mth_idx = ty::impl_or_trait_item_idx(token::str_to_ident(format!(
                         "visit_{}", ty_name).as_slice()),
-                                     self.visitor_methods.as_slice()).expect(
+                                     self.visitor_items.as_slice()).expect(
                 format!("couldn't find visit method for {}", ty_name).as_slice());
-        let mth_ty =
-            ty::mk_bare_fn(tcx,
-                           self.visitor_methods[mth_idx].fty.clone());
+        let method = match self.visitor_items[mth_idx] {
+            ty::MethodTraitItem(ref method) => (*method).clone(),
+        };
+        let mth_ty = ty::mk_bare_fn(tcx, method.fty.clone());
         let v = self.visitor_val;
         debug!("passing {} args:", args.len());
         let mut bcx = self.bcx;
@@ -397,10 +397,10 @@ pub fn emit_calls_to_trait_visit_ty<'a>(
     let final = fcx.new_temp_block("final");
     let tydesc_ty = ty::get_tydesc_ty(bcx.tcx()).unwrap();
     let tydesc_ty = type_of(bcx.ccx(), tydesc_ty);
-    let visitor_methods = ty::trait_methods(bcx.tcx(), visitor_trait_id);
+    let visitor_items = ty::trait_items(bcx.tcx(), visitor_trait_id);
     let mut r = Reflector {
         visitor_val: visitor_val,
-        visitor_methods: visitor_methods.as_slice(),
+        visitor_items: visitor_items.as_slice(),
         final_bcx: final,
         tydesc_ty: tydesc_ty,
         bcx: bcx
index 94c376c09c86a66a3257c0c455e1cfd11cea39db..8a445fc48398ee21feeb051de4e2ca587e33af0b 100644 (file)
@@ -273,7 +273,7 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type {
         let name = llvm_type_name(cx, an_enum, did, tps);
         adt::incomplete_type_of(cx, &*repr, name.as_slice())
       }
-      ty::ty_unboxed_closure(did) => {
+      ty::ty_unboxed_closure(did, _) => {
         // Only create the named struct, but don't fill it in. We
         // fill it in *after* placing it into the type cache.
         let repr = adt::represent_type(cx, t);
index a4588da1bd7dd7361a22669e54bfd057b0036f61..40c4d9682c4a3e8bf504bbcf63c9193e49543132 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;
@@ -75,11 +76,64 @@ pub struct field {
 }
 
 #[deriving(Clone)]
-pub enum MethodContainer {
+pub enum ImplOrTraitItemContainer {
     TraitContainer(ast::DefId),
     ImplContainer(ast::DefId),
 }
 
+impl ImplOrTraitItemContainer {
+    pub fn id(&self) -> ast::DefId {
+        match *self {
+            TraitContainer(id) => id,
+            ImplContainer(id) => id,
+        }
+    }
+}
+
+#[deriving(Clone)]
+pub enum ImplOrTraitItem {
+    MethodTraitItem(Rc<Method>),
+}
+
+impl ImplOrTraitItem {
+    fn id(&self) -> ImplOrTraitItemId {
+        match *self {
+            MethodTraitItem(ref method) => MethodTraitItemId(method.def_id),
+        }
+    }
+
+    pub fn def_id(&self) -> ast::DefId {
+        match *self {
+            MethodTraitItem(ref method) => method.def_id,
+        }
+    }
+
+    pub fn ident(&self) -> ast::Ident {
+        match *self {
+            MethodTraitItem(ref method) => method.ident,
+        }
+    }
+
+    pub fn container(&self) -> ImplOrTraitItemContainer {
+        match *self {
+            MethodTraitItem(ref method) => method.container,
+        }
+    }
+}
+
+#[deriving(Clone)]
+pub enum ImplOrTraitItemId {
+    MethodTraitItemId(ast::DefId),
+}
+
+impl ImplOrTraitItemId {
+    pub fn def_id(&self) -> ast::DefId {
+        match *self {
+            MethodTraitItemId(def_id) => def_id,
+        }
+    }
+}
+
 #[deriving(Clone)]
 pub struct Method {
     pub ident: ast::Ident,
@@ -88,7 +142,7 @@ pub struct Method {
     pub explicit_self: ExplicitSelfCategory,
     pub vis: ast::Visibility,
     pub def_id: ast::DefId,
-    pub container: MethodContainer,
+    pub container: ImplOrTraitItemContainer,
 
     // If this method is provided, we need to know where it came from
     pub provided_source: Option<ast::DefId>
@@ -101,7 +155,7 @@ pub fn new(ident: ast::Ident,
                explicit_self: ExplicitSelfCategory,
                vis: ast::Visibility,
                def_id: ast::DefId,
-               container: MethodContainer,
+               container: ImplOrTraitItemContainer,
                provided_source: Option<ast::DefId>)
                -> Method {
        Method {
@@ -273,14 +327,14 @@ pub struct ctxt {
     /// other items.
     pub item_substs: RefCell<NodeMap<ItemSubsts>>,
 
-    /// Maps from a method to the method "descriptor"
-    pub methods: RefCell<DefIdMap<Rc<Method>>>,
+    /// Maps from a trait item to the trait item "descriptor"
+    pub impl_or_trait_items: RefCell<DefIdMap<ImplOrTraitItem>>,
 
-    /// Maps from a trait def-id to a list of the def-ids of its methods
-    pub trait_method_def_ids: RefCell<DefIdMap<Rc<Vec<DefId>>>>,
+    /// Maps from a trait def-id to a list of the def-ids of its trait items
+    pub trait_item_def_ids: RefCell<DefIdMap<Rc<Vec<ImplOrTraitItemId>>>>,
 
-    /// A cache for the trait_methods() routine
-    pub trait_methods_cache: RefCell<DefIdMap<Rc<Vec<Rc<Method>>>>>,
+    /// A cache for the trait_items() routine
+    pub trait_items_cache: RefCell<DefIdMap<Rc<Vec<ImplOrTraitItem>>>>,
 
     pub impl_trait_cache: RefCell<DefIdMap<Option<Rc<ty::TraitRef>>>>,
 
@@ -331,11 +385,11 @@ pub struct ctxt {
     /// Methods in these implementations don't need to be exported.
     pub inherent_impls: RefCell<DefIdMap<Rc<RefCell<Vec<ast::DefId>>>>>,
 
-    /// Maps a DefId of an impl to a list of its methods.
+    /// Maps a DefId of an impl to a list of its items.
     /// Note that this contains all of the impls that we know about,
     /// including ones in other crates. It's not clear that this is the best
     /// way to do it.
-    pub impl_methods: RefCell<DefIdMap<Vec<ast::DefId>>>,
+    pub impl_items: RefCell<DefIdMap<Vec<ImplOrTraitItemId>>>,
 
     /// Set of used unsafe nodes (functions or blocks). Unsafe nodes not
     /// present in this set can be warned about.
@@ -372,7 +426,7 @@ pub struct ctxt {
 
     /// Records the type of each unboxed closure. The def ID is the ID of the
     /// expression defining the unboxed closure.
-    pub unboxed_closure_types: RefCell<DefIdMap<ClosureTy>>,
+    pub unboxed_closures: RefCell<DefIdMap<UnboxedClosure>>,
 
     pub node_lint_levels: RefCell<HashMap<(ast::NodeId, lint::LintId),
                                           lint::LevelSource>>,
@@ -384,6 +438,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 {
@@ -741,7 +798,7 @@ pub enum sty {
     ty_closure(Box<ClosureTy>),
     ty_trait(Box<TyTrait>),
     ty_struct(DefId, Substs),
-    ty_unboxed_closure(DefId),
+    ty_unboxed_closure(DefId, Region),
     ty_tup(Vec<t>),
 
     ty_param(ParamTy), // type parameter
@@ -1052,11 +1109,27 @@ pub struct ItemSubsts {
 
 pub type node_type_table = RefCell<HashMap<uint,t>>;
 
+/// Records information about each unboxed closure.
+pub struct UnboxedClosure {
+    /// The type of the unboxed closure.
+    pub closure_type: ClosureTy,
+    /// The kind of unboxed closure this is.
+    pub kind: UnboxedClosureKind,
+}
+
+#[deriving(PartialEq, Eq)]
+pub enum UnboxedClosureKind {
+    FnUnboxedClosureKind,
+    FnMutUnboxedClosureKind,
+    FnOnceUnboxedClosureKind,
+}
+
 pub fn mk_ctxt(s: Session,
                dm: resolve::DefMap,
                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)
@@ -1084,9 +1157,9 @@ pub fn mk_ctxt(s: Session,
         tc_cache: RefCell::new(HashMap::new()),
         ast_ty_to_ty_cache: RefCell::new(NodeMap::new()),
         enum_var_cache: RefCell::new(DefIdMap::new()),
-        methods: RefCell::new(DefIdMap::new()),
-        trait_method_def_ids: RefCell::new(DefIdMap::new()),
-        trait_methods_cache: RefCell::new(DefIdMap::new()),
+        impl_or_trait_items: RefCell::new(DefIdMap::new()),
+        trait_item_def_ids: RefCell::new(DefIdMap::new()),
+        trait_items_cache: RefCell::new(DefIdMap::new()),
         impl_trait_cache: RefCell::new(DefIdMap::new()),
         ty_param_defs: RefCell::new(NodeMap::new()),
         adjustments: RefCell::new(NodeMap::new()),
@@ -1100,7 +1173,7 @@ pub fn mk_ctxt(s: Session,
         destructors: RefCell::new(DefIdSet::new()),
         trait_impls: RefCell::new(DefIdMap::new()),
         inherent_impls: RefCell::new(DefIdMap::new()),
-        impl_methods: RefCell::new(DefIdMap::new()),
+        impl_items: RefCell::new(DefIdMap::new()),
         used_unsafe: RefCell::new(NodeSet::new()),
         used_mut_nodes: RefCell::new(NodeSet::new()),
         impl_vtables: RefCell::new(DefIdMap::new()),
@@ -1112,10 +1185,11 @@ pub fn mk_ctxt(s: Session,
         method_map: RefCell::new(FnvHashMap::new()),
         vtable_map: RefCell::new(FnvHashMap::new()),
         dependency_formats: RefCell::new(HashMap::new()),
-        unboxed_closure_types: RefCell::new(DefIdMap::new()),
+        unboxed_closures: 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),
     }
 }
 
@@ -1171,7 +1245,7 @@ fn sflags(substs: &Substs) -> uint {
     }
     match &st {
       &ty_nil | &ty_bool | &ty_char | &ty_int(_) | &ty_float(_) | &ty_uint(_) |
-      &ty_str | &ty_unboxed_closure(_) => {}
+      &ty_str => {}
       // You might think that we could just return ty_err for
       // any type containing ty_err as a component, and get
       // rid of the has_ty_err flag -- likewise for ty_bot (with
@@ -1188,6 +1262,7 @@ fn sflags(substs: &Substs) -> uint {
               flags |= has_params as uint;
           }
       }
+      &ty_unboxed_closure(_, ref region) => flags |= rflags(*region),
       &ty_infer(_) => flags |= needs_infer as uint,
       &ty_enum(_, ref substs) | &ty_struct(_, ref substs) => {
           flags |= sflags(substs);
@@ -1436,8 +1511,9 @@ pub fn mk_struct(cx: &ctxt, struct_id: ast::DefId, substs: Substs) -> t {
     mk_t(cx, ty_struct(struct_id, substs))
 }
 
-pub fn mk_unboxed_closure(cx: &ctxt, closure_id: ast::DefId) -> t {
-    mk_t(cx, ty_unboxed_closure(closure_id))
+pub fn mk_unboxed_closure(cx: &ctxt, closure_id: ast::DefId, region: Region)
+                          -> t {
+    mk_t(cx, ty_unboxed_closure(closure_id, region))
 }
 
 pub fn mk_var(cx: &ctxt, v: TyVid) -> t { mk_infer(cx, TyVar(v)) }
@@ -1470,8 +1546,8 @@ pub fn maybe_walk_ty(ty: t, f: |t| -> bool) {
     }
     match get(ty).sty {
         ty_nil | ty_bot | ty_bool | ty_char | ty_int(_) | ty_uint(_) | ty_float(_) |
-        ty_str | ty_infer(_) | ty_param(_) | ty_unboxed_closure(_) | ty_err => {
-        }
+        ty_str | ty_infer(_) | ty_param(_) | ty_unboxed_closure(..) |
+        ty_err => {}
         ty_box(ty) | ty_uniq(ty) => maybe_walk_ty(ty, f),
         ty_ptr(ref tm) | ty_rptr(_, ref tm) | ty_vec(ref tm, _) => {
             maybe_walk_ty(tm.ty, f);
@@ -1578,7 +1654,7 @@ pub fn type_is_vec(ty: t) -> bool {
 pub fn type_is_structural(ty: t) -> bool {
     match get(ty).sty {
       ty_struct(..) | ty_tup(_) | ty_enum(..) | ty_closure(_) |
-      ty_vec(_, Some(_)) | ty_unboxed_closure(_) => true,
+      ty_vec(_, Some(_)) | ty_unboxed_closure(..) => true,
       _ => type_is_slice(ty) | type_is_trait(ty)
     }
 }
@@ -2093,10 +2169,13 @@ fn tc_ty(cx: &ctxt,
                 apply_lang_items(cx, did, res)
             }
 
-            ty_unboxed_closure(did) => {
+            ty_unboxed_closure(did, r) => {
+                // FIXME(#14449): `borrowed_contents` below assumes `&mut`
+                // unboxed closure.
                 let upvars = unboxed_closure_upvars(cx, did);
                 TypeContents::union(upvars.as_slice(),
-                                    |f| tc_ty(cx, f.ty, cache))
+                                    |f| tc_ty(cx, f.ty, cache)) |
+                    borrowed_contents(r, MutMutable)
             }
 
             ty_tup(ref tys) => {
@@ -2343,7 +2422,7 @@ fn subtypes_require(cx: &ctxt, seen: &mut Vec<DefId>,
                 r
             }
 
-            ty_unboxed_closure(did) => {
+            ty_unboxed_closure(did, _) => {
                 let upvars = unboxed_closure_upvars(cx, did);
                 upvars.iter().any(|f| type_requires(cx, seen, r_ty, f.ty))
             }
@@ -2471,7 +2550,7 @@ fn type_structurally_recursive(cx: &ctxt, sp: Span, seen: &mut Vec<DefId>,
                 r
             }
 
-            ty_unboxed_closure(did) => {
+            ty_unboxed_closure(did, _) => {
                 let upvars = unboxed_closure_upvars(cx, did);
                 find_nonrepresentable(cx,
                                       sp,
@@ -2712,7 +2791,7 @@ pub fn ty_fn_args(fty: t) -> Vec<t> {
 pub fn ty_closure_store(fty: t) -> TraitStore {
     match get(fty).sty {
         ty_closure(ref f) => f.store,
-        ty_unboxed_closure(_) => {
+        ty_unboxed_closure(..) => {
             // Close enough for the purposes of all the callers of this
             // function (which is soon to be deprecated anyhow).
             UniqTraitStore
@@ -3049,11 +3128,19 @@ pub fn method_call_type_param_defs(tcx: &ctxt, origin: typeck::MethodOrigin)
                 Err(s) => tcx.sess.fatal(s.as_slice()),
             }
         }
-        typeck::MethodParam(typeck::MethodParam{trait_id: trt_id,
-                                                method_num: n_mth, ..}) |
-        typeck::MethodObject(typeck::MethodObject{trait_id: trt_id,
-                                                  method_num: n_mth, ..}) => {
-            ty::trait_method(tcx, trt_id, n_mth).generics.types.clone()
+        typeck::MethodParam(typeck::MethodParam{
+            trait_id: trt_id,
+            method_num: n_mth,
+            ..
+        }) |
+        typeck::MethodObject(typeck::MethodObject{
+                trait_id: trt_id,
+                method_num: n_mth,
+                ..
+        }) => {
+            match ty::trait_item(tcx, trt_id, n_mth) {
+                ty::MethodTraitItem(method) => method.generics.types.clone(),
+            }
         }
     }
 }
@@ -3271,8 +3358,9 @@ pub fn field_idx_strict(tcx: &ctxt, name: ast::Name, fields: &[field])
               .collect::<Vec<String>>()).as_slice());
 }
 
-pub fn method_idx(id: ast::Ident, meths: &[Rc<Method>]) -> Option<uint> {
-    meths.iter().position(|m| m.ident == id)
+pub fn impl_or_trait_item_idx(id: ast::Ident, trait_items: &[ImplOrTraitItem])
+                              -> Option<uint> {
+    trait_items.iter().position(|m| m.ident() == id)
 }
 
 /// Returns a vector containing the indices of all type parameters that appear
@@ -3312,7 +3400,7 @@ pub fn ty_sort_string(cx: &ctxt, t: t) -> String {
         ty_struct(id, _) => {
             format!("struct {}", item_path_str(cx, id))
         }
-        ty_unboxed_closure(_) => "closure".to_string(),
+        ty_unboxed_closure(..) => "closure".to_string(),
         ty_tup(_) => "tuple".to_string(),
         ty_infer(TyVar(_)) => "inferred type".to_string(),
         ty_infer(IntVar(_)) => "integral variable".to_string(),
@@ -3514,7 +3602,15 @@ pub fn provided_trait_methods(cx: &ctxt, id: ast::DefId) -> Vec<Rc<Method>> {
                 match item.node {
                     ItemTrait(_, _, _, ref ms) => {
                         let (_, p) = ast_util::split_trait_methods(ms.as_slice());
-                        p.iter().map(|m| method(cx, ast_util::local_def(m.id))).collect()
+                        p.iter()
+                         .map(|m| {
+                            match impl_or_trait_item(
+                                    cx,
+                                    ast_util::local_def(m.id)) {
+                                MethodTraitItem(m) => m,
+                            }
+                         })
+                         .collect()
                     }
                     _ => {
                         cx.sess.bug(format!("provided_trait_methods: `{}` is \
@@ -3566,7 +3662,7 @@ fn lookup_locally_or_in_crate_store<V:Clone>(
     /*!
      * Helper for looking things up in the various maps
      * that are populated during typeck::collect (e.g.,
-     * `cx.methods`, `cx.tcache`, etc).  All of these share
+     * `cx.impl_or_trait_items`, `cx.tcache`, etc).  All of these share
      * the pattern that if the id is local, it should have
      * been loaded into the map by the `typeck::collect` phase.
      * If the def-id is external, then we have to go consult
@@ -3586,40 +3682,47 @@ fn lookup_locally_or_in_crate_store<V:Clone>(
     v
 }
 
-pub fn trait_method(cx: &ctxt, trait_did: ast::DefId, idx: uint) -> Rc<Method> {
-    let method_def_id = *ty::trait_method_def_ids(cx, trait_did).get(idx);
-    ty::method(cx, method_def_id)
+pub fn trait_item(cx: &ctxt, trait_did: ast::DefId, idx: uint)
+                  -> ImplOrTraitItem {
+    let method_def_id = ty::trait_item_def_ids(cx, trait_did).get(idx)
+                                                             .def_id();
+    impl_or_trait_item(cx, method_def_id)
 }
 
-
-pub fn trait_methods(cx: &ctxt, trait_did: ast::DefId) -> Rc<Vec<Rc<Method>>> {
-    let mut trait_methods = cx.trait_methods_cache.borrow_mut();
-    match trait_methods.find_copy(&trait_did) {
-        Some(methods) => methods,
+pub fn trait_items(cx: &ctxt, trait_did: ast::DefId)
+                   -> Rc<Vec<ImplOrTraitItem>> {
+    let mut trait_items = cx.trait_items_cache.borrow_mut();
+    match trait_items.find_copy(&trait_did) {
+        Some(trait_items) => trait_items,
         None => {
-            let def_ids = ty::trait_method_def_ids(cx, trait_did);
-            let methods: Rc<Vec<Rc<Method>>> = Rc::new(def_ids.iter().map(|d| {
-                ty::method(cx, *d)
-            }).collect());
-            trait_methods.insert(trait_did, methods.clone());
-            methods
+            let def_ids = ty::trait_item_def_ids(cx, trait_did);
+            let items: Rc<Vec<ImplOrTraitItem>> =
+                Rc::new(def_ids.iter()
+                               .map(|d| impl_or_trait_item(cx, d.def_id()))
+                               .collect());
+            trait_items.insert(trait_did, items.clone());
+            items
         }
     }
 }
 
-pub fn method(cx: &ctxt, id: ast::DefId) -> Rc<Method> {
-    lookup_locally_or_in_crate_store("methods", id,
-                                     &mut *cx.methods.borrow_mut(), || {
-        Rc::new(csearch::get_method(cx, id))
+pub fn impl_or_trait_item(cx: &ctxt, id: ast::DefId) -> ImplOrTraitItem {
+    lookup_locally_or_in_crate_store("impl_or_trait_items",
+                                     id,
+                                     &mut *cx.impl_or_trait_items
+                                             .borrow_mut(),
+                                     || {
+        csearch::get_impl_or_trait_item(cx, id)
     })
 }
 
-pub fn trait_method_def_ids(cx: &ctxt, id: ast::DefId) -> Rc<Vec<DefId>> {
-    lookup_locally_or_in_crate_store("trait_method_def_ids",
+pub fn trait_item_def_ids(cx: &ctxt, id: ast::DefId)
+                          -> Rc<Vec<ImplOrTraitItemId>> {
+    lookup_locally_or_in_crate_store("trait_item_def_ids",
                                      id,
-                                     &mut *cx.trait_method_def_ids.borrow_mut(),
+                                     &mut *cx.trait_item_def_ids.borrow_mut(),
                                      || {
-        Rc::new(csearch::get_trait_method_def_ids(&cx.sess.cstore, id))
+        Rc::new(csearch::get_trait_item_def_ids(&cx.sess.cstore, id))
     })
 }
 
@@ -3681,7 +3784,7 @@ pub fn ty_to_def_id(ty: t) -> Option<ast::DefId> {
         ty_trait(box TyTrait { def_id: id, .. }) |
         ty_struct(id, _) |
         ty_enum(id, _) |
-        ty_unboxed_closure(id) => Some(id),
+        ty_unboxed_closure(id, _) => Some(id),
         _ => None
     }
 }
@@ -4433,7 +4536,8 @@ pub fn populate_implementations_for_type_if_necessary(tcx: &ctxt,
 
     csearch::each_implementation_for_type(&tcx.sess.cstore, type_id,
             |impl_def_id| {
-        let methods = csearch::get_impl_methods(&tcx.sess.cstore, impl_def_id);
+        let impl_items = csearch::get_impl_items(&tcx.sess.cstore,
+                                                 impl_def_id);
 
         // Record the trait->implementation mappings, if applicable.
         let associated_traits = csearch::get_impl_trait(tcx, impl_def_id);
@@ -4443,14 +4547,21 @@ pub fn populate_implementations_for_type_if_necessary(tcx: &ctxt,
 
         // For any methods that use a default implementation, add them to
         // the map. This is a bit unfortunate.
-        for &method_def_id in methods.iter() {
-            for &source in ty::method(tcx, method_def_id).provided_source.iter() {
-                tcx.provided_method_sources.borrow_mut().insert(method_def_id, source);
+        for impl_item_def_id in impl_items.iter() {
+            let method_def_id = impl_item_def_id.def_id();
+            match impl_or_trait_item(tcx, method_def_id) {
+                MethodTraitItem(method) => {
+                    for &source in method.provided_source.iter() {
+                        tcx.provided_method_sources
+                           .borrow_mut()
+                           .insert(method_def_id, source);
+                    }
+                }
             }
         }
 
         // Store the implementation info.
-        tcx.impl_methods.borrow_mut().insert(impl_def_id, methods);
+        tcx.impl_items.borrow_mut().insert(impl_def_id, impl_items);
 
         // If this is an inherent implementation, record it.
         if associated_traits.is_none() {
@@ -4483,21 +4594,28 @@ pub fn populate_implementations_for_trait_if_necessary(
 
     csearch::each_implementation_for_trait(&tcx.sess.cstore, trait_id,
             |implementation_def_id| {
-        let methods = csearch::get_impl_methods(&tcx.sess.cstore, implementation_def_id);
+        let impl_items = csearch::get_impl_items(&tcx.sess.cstore, implementation_def_id);
 
         // Record the trait->implementation mapping.
         record_trait_implementation(tcx, trait_id, implementation_def_id);
 
         // For any methods that use a default implementation, add them to
         // the map. This is a bit unfortunate.
-        for &method_def_id in methods.iter() {
-            for &source in ty::method(tcx, method_def_id).provided_source.iter() {
-                tcx.provided_method_sources.borrow_mut().insert(method_def_id, source);
+        for impl_item_def_id in impl_items.iter() {
+            let method_def_id = impl_item_def_id.def_id();
+            match impl_or_trait_item(tcx, method_def_id) {
+                MethodTraitItem(method) => {
+                    for &source in method.provided_source.iter() {
+                        tcx.provided_method_sources
+                           .borrow_mut()
+                           .insert(method_def_id, source);
+                    }
+                }
             }
         }
 
         // Store the implementation info.
-        tcx.impl_methods.borrow_mut().insert(implementation_def_id, methods);
+        tcx.impl_items.borrow_mut().insert(implementation_def_id, impl_items);
     });
 
     tcx.populated_external_traits.borrow_mut().insert(trait_id);
@@ -4529,14 +4647,15 @@ pub fn trait_id_of_impl(tcx: &ctxt,
 pub fn impl_of_method(tcx: &ctxt, def_id: ast::DefId)
                        -> Option<ast::DefId> {
     if def_id.krate != LOCAL_CRATE {
-        return match csearch::get_method(tcx, def_id).container {
+        return match csearch::get_impl_or_trait_item(tcx,
+                                                     def_id).container() {
             TraitContainer(_) => None,
             ImplContainer(def_id) => Some(def_id),
         };
     }
-    match tcx.methods.borrow().find_copy(&def_id) {
-        Some(method) => {
-            match method.container {
+    match tcx.impl_or_trait_items.borrow().find_copy(&def_id) {
+        Some(trait_item) => {
+            match trait_item.container() {
                 TraitContainer(_) => None,
                 ImplContainer(def_id) => Some(def_id),
             }
@@ -4545,17 +4664,16 @@ pub fn impl_of_method(tcx: &ctxt, def_id: ast::DefId)
     }
 }
 
-/// If the given def ID describes a method belonging to a trait (either a
+/// If the given def ID describes an item belonging to a trait (either a
 /// default method or an implementation of a trait method), return the ID of
 /// the trait that the method belongs to. Otherwise, return `None`.
-pub fn trait_of_method(tcx: &ctxt, def_id: ast::DefId)
-                       -> Option<ast::DefId> {
+pub fn trait_of_item(tcx: &ctxt, def_id: ast::DefId) -> Option<ast::DefId> {
     if def_id.krate != LOCAL_CRATE {
-        return csearch::get_trait_of_method(&tcx.sess.cstore, def_id, tcx);
+        return csearch::get_trait_of_item(&tcx.sess.cstore, def_id, tcx);
     }
-    match tcx.methods.borrow().find_copy(&def_id) {
-        Some(method) => {
-            match method.container {
+    match tcx.impl_or_trait_items.borrow().find_copy(&def_id) {
+        Some(impl_or_trait_item) => {
+            match impl_or_trait_item.container() {
                 TraitContainer(def_id) => Some(def_id),
                 ImplContainer(def_id) => trait_id_of_impl(tcx, def_id),
             }
@@ -4564,25 +4682,27 @@ pub fn trait_of_method(tcx: &ctxt, def_id: ast::DefId)
     }
 }
 
-/// If the given def ID describes a method belonging to a trait, (either a
+/// If the given def ID describes an item belonging to a trait, (either a
 /// default method or an implementation of a trait method), return the ID of
 /// the method inside trait definition (this means that if the given def ID
 /// is already that of the original trait method, then the return value is
 /// the same).
 /// Otherwise, return `None`.
-pub fn trait_method_of_method(tcx: &ctxt,
-                              def_id: ast::DefId) -> Option<ast::DefId> {
-    let method = match tcx.methods.borrow().find(&def_id) {
+pub fn trait_item_of_item(tcx: &ctxt, def_id: ast::DefId)
+                          -> Option<ImplOrTraitItemId> {
+    let impl_item = match tcx.impl_or_trait_items.borrow().find(&def_id) {
         Some(m) => m.clone(),
         None => return None,
     };
-    let name = method.ident.name;
-    match trait_of_method(tcx, def_id) {
+    let name = match impl_item {
+        MethodTraitItem(method) => method.ident.name,
+    };
+    match trait_of_item(tcx, def_id) {
         Some(trait_did) => {
-            let trait_methods = ty::trait_methods(tcx, trait_did);
-            trait_methods.iter()
-                .position(|m| m.ident.name == name)
-                .map(|idx| ty::trait_method(tcx, trait_did, idx).def_id)
+            let trait_items = ty::trait_items(tcx, trait_did);
+            trait_items.iter()
+                .position(|m| m.ident().name == name)
+                .map(|idx| ty::trait_item(tcx, trait_did, idx).id())
         }
         None => None
     }
@@ -4711,9 +4831,10 @@ pub fn hash_crate_independent(tcx: &ctxt, t: t, svh: &Svh) -> u64 {
             }
             ty_infer(_) => unreachable!(),
             ty_err => byte!(23),
-            ty_unboxed_closure(d) => {
+            ty_unboxed_closure(d, r) => {
                 byte!(24);
                 did(&mut state, d);
+                region(&mut state, r);
             }
         }
     });
@@ -4862,6 +4983,16 @@ 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)
+    }
+
+    fn unboxed_closures<'a>(&'a self)
+                        -> &'a RefCell<DefIdMap<UnboxedClosure>> {
+        &self.unboxed_closures
+    }
 }
 
 /// The category of explicit self.
@@ -4903,6 +5034,7 @@ pub fn accumulate_lifetimes_in_type(accumulator: &mut Vec<ty::Region>,
                     UniqTraitStore => {}
                 }
             }
+            ty_unboxed_closure(_, ref region) => accumulator.push(*region),
             ty_nil |
             ty_bot |
             ty_bool |
@@ -4919,7 +5051,6 @@ pub fn accumulate_lifetimes_in_type(accumulator: &mut Vec<ty::Region>,
             ty_tup(_) |
             ty_param(_) |
             ty_infer(_) |
-            ty_unboxed_closure(_) |
             ty_err => {}
         }
     })
index e2b984959060c2b270e9536b509fbcaaa67e512b..9f475bfd9d5d06dbba4ec703350517e0311ecba5 100644 (file)
@@ -392,8 +392,8 @@ pub fn super_fold_sty<T:TypeFolder>(this: &mut T,
         ty::ty_struct(did, ref substs) => {
             ty::ty_struct(did, substs.fold_with(this))
         }
-        ty::ty_unboxed_closure(did) => {
-            ty::ty_unboxed_closure(did)
+        ty::ty_unboxed_closure(did, ref region) => {
+            ty::ty_unboxed_closure(did, region.fold_with(this))
         }
         ty::ty_nil | ty::ty_bot | ty::ty_bool | ty::ty_char | ty::ty_str |
         ty::ty_int(_) | ty::ty_uint(_) | ty::ty_float(_) |
index 5e7426f3ae749ccddeba3f06a56c000c71409e5b..c317f98a25afef408b00a99abf6d67227d4851c0 100644 (file)
@@ -51,7 +51,8 @@
 
 use middle::const_eval;
 use middle::def;
-use middle::lang_items::FnMutTraitLangItem;
+use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem};
+use middle::lang_items::{FnOnceTraitLangItem};
 use middle::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs};
 use middle::subst::{VecPerParamSpace};
 use middle::ty;
@@ -544,16 +545,17 @@ fn ast_ty_to_mt<AC:AstConv, RS:RegionScope>(this: &AC,
 
 pub fn trait_ref_for_unboxed_function<AC:AstConv,
                                       RS:RegionScope>(
-                                          this: &AC,
-                                          rscope: &RS,
-                                          unboxed_function: &ast::UnboxedFnTy,
-                                          self_ty: Option<ty::t>)
-    -> ty::TraitRef
-{
-    let fn_mut_trait_did = this.tcx()
-                               .lang_items
-                               .require(FnMutTraitLangItem)
-                               .unwrap();
+                                      this: &AC,
+                                      rscope: &RS,
+                                      unboxed_function: &ast::UnboxedFnTy,
+                                      self_ty: Option<ty::t>)
+                                      -> ty::TraitRef {
+    let lang_item = match unboxed_function.kind {
+        ast::FnUnboxedClosureKind => FnTraitLangItem,
+        ast::FnMutUnboxedClosureKind => FnMutTraitLangItem,
+        ast::FnOnceUnboxedClosureKind => FnOnceTraitLangItem,
+    };
+    let trait_did = this.tcx().lang_items.require(lang_item).unwrap();
     let input_types =
         unboxed_function.decl
                         .inputs
@@ -574,7 +576,7 @@ pub fn trait_ref_for_unboxed_function<AC:AstConv,
     }
 
     ty::TraitRef {
-        def_id: fn_mut_trait_did,
+        def_id: trait_did,
         substs: substs,
     }
 }
@@ -810,7 +812,7 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:RegionScope>(
                                             None);
                 ty::mk_closure(tcx, fn_decl)
             }
-            ast::TyUnboxedFn(_) => {
+            ast::TyUnboxedFn(..) => {
                 tcx.sess.span_err(ast_ty.span,
                                   "cannot use unboxed functions here");
                 ty::mk_err()
index 1805c18eaf10c9771011e12430b51e488b52e210..1e3ea095704bf167057eccb365205b7c4fee6015 100644 (file)
@@ -220,9 +220,15 @@ fn get_method_index(tcx: &ty::ctxt,
     // methods from them.
     let mut method_count = 0;
     ty::each_bound_trait_and_supertraits(tcx, &[subtrait], |bound_ref| {
-        if bound_ref.def_id == trait_ref.def_id { false }
-            else {
-            method_count += ty::trait_methods(tcx, bound_ref.def_id).len();
+        if bound_ref.def_id == trait_ref.def_id {
+            false
+        } else {
+            let trait_items = ty::trait_items(tcx, bound_ref.def_id);
+            for trait_item in trait_items.iter() {
+                match *trait_item {
+                    ty::MethodTraitItem(_) => method_count += 1,
+                }
+            }
             true
         }
     });
@@ -444,7 +450,7 @@ fn push_inherent_candidates(&mut self, self_ty: ty::t) {
                 },
                 ty_enum(did, _) |
                 ty_struct(did, _) |
-                ty_unboxed_closure(did) => {
+                ty_unboxed_closure(did, _) => {
                     if self.check_traits == CheckTraitsAndInherentMethods {
                         self.push_inherent_impl_candidates_for_type(did);
                     }
@@ -468,7 +474,7 @@ fn push_bound_candidates(&mut self, self_ty: ty::t, restrict_to: Option<DefId>)
                 ty_param(p) => {
                     self.push_inherent_candidates_from_param(self_ty, restrict_to, p);
                 }
-                ty_unboxed_closure(closure_did) => {
+                ty_unboxed_closure(closure_did, _) => {
                     self.push_unboxed_closure_call_candidates_if_applicable(
                         closure_did);
                 }
@@ -488,11 +494,13 @@ fn push_extension_candidate(&mut self, trait_did: DefId) {
         ty::populate_implementations_for_trait_if_necessary(self.tcx(), trait_did);
 
         // Look for explicit implementations.
-        let impl_methods = self.tcx().impl_methods.borrow();
+        let impl_items = self.tcx().impl_items.borrow();
         for impl_infos in self.tcx().trait_impls.borrow().find(&trait_did).iter() {
             for impl_did in impl_infos.borrow().iter() {
-                let methods = impl_methods.get(impl_did);
-                self.push_candidates_from_impl(*impl_did, methods.as_slice(), true);
+                let items = impl_items.get(impl_did);
+                self.push_candidates_from_impl(*impl_did,
+                                               items.as_slice(),
+                                               true);
             }
         }
     }
@@ -520,8 +528,11 @@ fn push_unboxed_closure_call_candidate_if_applicable(
             trait_did: DefId,
             closure_did: DefId,
             closure_function_type: &ClosureTy) {
-        let method =
-            ty::trait_methods(self.tcx(), trait_did).get(0).clone();
+        let trait_item = ty::trait_items(self.tcx(), trait_did).get(0)
+                                                               .clone();
+        let method = match trait_item {
+            ty::MethodTraitItem(method) => method,
+        };
 
         let vcx = self.fcx.vtable_context();
         let region_params =
@@ -531,8 +542,11 @@ fn push_unboxed_closure_call_candidate_if_applicable(
         let arguments_type = *closure_function_type.sig.inputs.get(0);
         let return_type = closure_function_type.sig.output;
 
+        let closure_region =
+            vcx.infcx.next_region_var(MiscVariable(self.span));
         let unboxed_closure_type = ty::mk_unboxed_closure(self.tcx(),
-                                                          closure_did);
+                                                          closure_did,
+                                                          closure_region);
         self.extension_candidates.push(Candidate {
             rcvr_match_condition:
                 RcvrMatchesIfSubtype(unboxed_closure_type),
@@ -548,39 +562,38 @@ fn push_unboxed_closure_call_candidate_if_applicable(
     fn push_unboxed_closure_call_candidates_if_applicable(
             &mut self,
             closure_did: DefId) {
-        // FIXME(pcwalton): Try `Fn` and `FnOnce` too.
-        let trait_did = match self.tcx().lang_items.fn_mut_trait() {
-            Some(trait_did) => trait_did,
-            None => return,
-        };
-
-        match self.tcx()
-                  .unboxed_closure_types
-                  .borrow()
-                  .find(&closure_did) {
-            None => {}  // Fall through to try inherited.
-            Some(closure_function_type) => {
-                self.push_unboxed_closure_call_candidate_if_applicable(
-                    trait_did,
-                    closure_did,
-                    closure_function_type);
-                return
+        let trait_dids = [
+            self.tcx().lang_items.fn_trait(),
+            self.tcx().lang_items.fn_mut_trait(),
+            self.tcx().lang_items.fn_once_trait()
+        ];
+        for optional_trait_did in trait_dids.iter() {
+            let trait_did = match *optional_trait_did {
+                Some(trait_did) => trait_did,
+                None => continue,
+            };
+
+            match self.tcx().unboxed_closures.borrow().find(&closure_did) {
+                None => {}  // Fall through to try inherited.
+                Some(closure) => {
+                    self.push_unboxed_closure_call_candidate_if_applicable(
+                        trait_did,
+                        closure_did,
+                        &closure.closure_type);
+                    return
+                }
             }
-        }
 
-        match self.fcx
-                  .inh
-                  .unboxed_closure_types
-                  .borrow()
-                  .find(&closure_did) {
-            Some(closure_function_type) => {
-                self.push_unboxed_closure_call_candidate_if_applicable(
-                    trait_did,
-                    closure_did,
-                    closure_function_type);
-                return
+            match self.fcx.inh.unboxed_closures.borrow().find(&closure_did) {
+                Some(closure) => {
+                    self.push_unboxed_closure_call_candidate_if_applicable(
+                        trait_did,
+                        closure_did,
+                        &closure.closure_type);
+                    return
+                }
+                None => {}
             }
-            None => {}
         }
 
         self.tcx().sess.bug("didn't find unboxed closure type in tcx map or \
@@ -699,14 +712,24 @@ fn push_inherent_candidates_from_bounds_inner(&mut self,
             let this_bound_idx = next_bound_idx;
             next_bound_idx += 1;
 
-            let trait_methods = ty::trait_methods(tcx, bound_trait_ref.def_id);
-            match trait_methods.iter().position(|m| {
-                m.explicit_self != ty::StaticExplicitSelfCategory &&
-                m.ident.name == self.m_name }) {
+            let trait_items = ty::trait_items(tcx, bound_trait_ref.def_id);
+            match trait_items.iter().position(|ti| {
+                match *ti {
+                    ty::MethodTraitItem(ref m) => {
+                        m.explicit_self != ty::StaticExplicitSelfCategory &&
+                        m.ident.name == self.m_name
+                    }
+                }
+            }) {
                 Some(pos) => {
-                    let method = trait_methods.get(pos).clone();
-
-                    match mk_cand(bound_trait_ref, method, pos, this_bound_idx) {
+                    let method = match *trait_items.get(pos) {
+                        ty::MethodTraitItem(ref method) => (*method).clone(),
+                    };
+
+                    match mk_cand(bound_trait_ref,
+                                  method,
+                                  pos,
+                                  this_bound_idx) {
                         Some(cand) => {
                             debug!("pushing inherent candidate for param: {}",
                                    cand.repr(self.tcx()));
@@ -731,18 +754,20 @@ fn push_inherent_impl_candidates_for_type(&mut self, did: DefId) {
         // metadata if necessary.
         ty::populate_implementations_for_type_if_necessary(self.tcx(), did);
 
-        let impl_methods = self.tcx().impl_methods.borrow();
+        let impl_items = self.tcx().impl_items.borrow();
         for impl_infos in self.tcx().inherent_impls.borrow().find(&did).iter() {
             for impl_did in impl_infos.borrow().iter() {
-                let methods = impl_methods.get(impl_did);
-                self.push_candidates_from_impl(*impl_did, methods.as_slice(), false);
+                let items = impl_items.get(impl_did);
+                self.push_candidates_from_impl(*impl_did,
+                                               items.as_slice(),
+                                               false);
             }
         }
     }
 
     fn push_candidates_from_impl(&mut self,
                                  impl_did: DefId,
-                                 impl_methods: &[DefId],
+                                 impl_items: &[ImplOrTraitItemId],
                                  is_extension: bool) {
         let did = if self.report_statics == ReportStaticMethods {
             // we only want to report each base trait once
@@ -760,13 +785,23 @@ fn push_candidates_from_impl(&mut self,
 
         debug!("push_candidates_from_impl: {} {}",
                token::get_name(self.m_name),
-               impl_methods.iter().map(|&did| ty::method(self.tcx(), did).ident)
-                                 .collect::<Vec<ast::Ident>>()
-                                 .repr(self.tcx()));
-
-        let method = match impl_methods.iter().map(|&did| ty::method(self.tcx(), did))
-                                              .find(|m| m.ident.name == self.m_name) {
-            Some(method) => method,
+               impl_items.iter()
+                         .map(|&did| {
+                             ty::impl_or_trait_item(self.tcx(),
+                                                    did.def_id()).ident()
+                         })
+                         .collect::<Vec<ast::Ident>>()
+                         .repr(self.tcx()));
+
+        let method = match impl_items.iter()
+                                     .map(|&did| {
+                                         ty::impl_or_trait_item(self.tcx(),
+                                                                did.def_id())
+                                     })
+                                     .find(|m| {
+                                         m.ident().name == self.m_name
+                                     }) {
+            Some(ty::MethodTraitItem(method)) => method,
             None => { return; } // No method with the right name.
         };
 
@@ -1484,9 +1519,16 @@ fn report_candidate(&self, idx: uint, origin: &MethodOrigin) {
                 let did = if self.report_statics == ReportStaticMethods {
                     // If we're reporting statics, we want to report the trait
                     // definition if possible, rather than an impl
-                    match ty::trait_method_of_method(self.tcx(), impl_did) {
-                        None => {debug!("(report candidate) No trait method found"); impl_did},
-                        Some(trait_did) => {debug!("(report candidate) Found trait ref"); trait_did}
+                    match ty::trait_item_of_item(self.tcx(), impl_did) {
+                        None => {
+                            debug!("(report candidate) No trait method \
+                                    found");
+                            impl_did
+                        }
+                        Some(MethodTraitItemId(trait_did)) => {
+                            debug!("(report candidate) Found trait ref");
+                            trait_did
+                        }
                     }
                 } else {
                     // If it is an instantiated default method, use the original
index aa38ff68f24e6c901ed3510b14dbf1a7a7fe824f..3403a51610cff082d618de0e22d5c566e020178e 100644 (file)
 use std::rc::Rc;
 use std::gc::Gc;
 use syntax::abi;
-use syntax::ast::{Provided, Required};
+use syntax::ast::{ProvidedMethod, RequiredMethod};
 use syntax::ast;
 use syntax::ast_map;
 use syntax::ast_util::{local_def, PostExpansionMethod};
@@ -168,7 +168,7 @@ pub struct Inherited<'a> {
     method_map: MethodMap,
     vtable_map: vtable_map,
     upvar_borrow_map: RefCell<ty::UpvarBorrowMap>,
-    unboxed_closure_types: RefCell<DefIdMap<ty::ClosureTy>>,
+    unboxed_closures: RefCell<DefIdMap<ty::UnboxedClosure>>,
 }
 
 /// When type-checking an expression, we propagate downward
@@ -275,7 +275,7 @@ fn new(tcx: &'a ty::ctxt,
             method_map: RefCell::new(FnvHashMap::new()),
             vtable_map: RefCell::new(FnvHashMap::new()),
             upvar_borrow_map: RefCell::new(HashMap::new()),
-            unboxed_closure_types: RefCell::new(DefIdMap::new()),
+            unboxed_closures: RefCell::new(DefIdMap::new()),
         }
     }
 }
@@ -680,23 +680,27 @@ pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
 
         check_bare_fn(ccx, &**decl, &**body, it.id, fn_pty.ty, param_env);
       }
-      ast::ItemImpl(_, ref opt_trait_ref, _, ref ms) => {
+      ast::ItemImpl(_, ref opt_trait_ref, _, ref impl_items) => {
         debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id);
 
         let impl_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
-        for m in ms.iter() {
-            check_method_body(ccx, &impl_pty.generics, &**m);
+        for impl_item in impl_items.iter() {
+            match *impl_item {
+                ast::MethodImplItem(m) => {
+                    check_method_body(ccx, &impl_pty.generics, &*m);
+                }
+            }
         }
 
         match *opt_trait_ref {
             Some(ref ast_trait_ref) => {
                 let impl_trait_ref =
                     ty::node_id_to_trait_ref(ccx.tcx, ast_trait_ref.ref_id);
-                check_impl_methods_against_trait(ccx,
-                                             it.span,
-                                             ast_trait_ref,
-                                             &*impl_trait_ref,
-                                             ms.as_slice());
+                check_impl_items_against_trait(ccx,
+                                               it.span,
+                                               ast_trait_ref,
+                                               &*impl_trait_ref,
+                                               impl_items.as_slice());
                 vtable::resolve_impl(ccx.tcx, it, &impl_pty.generics, &*impl_trait_ref);
             }
             None => { }
@@ -707,11 +711,11 @@ pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
         let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id));
         for trait_method in (*trait_methods).iter() {
             match *trait_method {
-                Required(..) => {
+                RequiredMethod(..) => {
                     // Nothing to do, since required methods don't have
                     // bodies to check.
                 }
-                Provided(m) => {
+                ProvidedMethod(m) => {
                     check_method_body(ccx, &trait_def.generics, &*m);
                 }
             }
@@ -770,7 +774,9 @@ fn check_method_body(ccx: &CrateCtxt,
             item_generics.repr(ccx.tcx),
             method.id);
     let method_def_id = local_def(method.id);
-    let method_ty = ty::method(ccx.tcx, method_def_id);
+    let method_ty = match ty::impl_or_trait_item(ccx.tcx, method_def_id) {
+        ty::MethodTraitItem(ref method_ty) => (*method_ty).clone(),
+    };
     let method_generics = &method_ty.generics;
 
     let param_env = ty::construct_parameter_environment(ccx.tcx,
@@ -787,43 +793,58 @@ fn check_method_body(ccx: &CrateCtxt,
                   param_env);
 }
 
-fn check_impl_methods_against_trait(ccx: &CrateCtxt,
-                                    impl_span: Span,
-                                    ast_trait_ref: &ast::TraitRef,
-                                    impl_trait_ref: &ty::TraitRef,
-                                    impl_methods: &[Gc<ast::Method>]) {
+fn check_impl_items_against_trait(ccx: &CrateCtxt,
+                                  impl_span: Span,
+                                  ast_trait_ref: &ast::TraitRef,
+                                  impl_trait_ref: &ty::TraitRef,
+                                  impl_items: &[ast::ImplItem]) {
     // Locate trait methods
     let tcx = ccx.tcx;
-    let trait_methods = ty::trait_methods(tcx, impl_trait_ref.def_id);
+    let trait_items = ty::trait_items(tcx, impl_trait_ref.def_id);
 
     // Check existing impl methods to see if they are both present in trait
     // and compatible with trait signature
-    for impl_method in impl_methods.iter() {
-        let impl_method_def_id = local_def(impl_method.id);
-        let impl_method_ty = ty::method(ccx.tcx, impl_method_def_id);
-
-        // If this is an impl of a trait method, find the corresponding
-        // method definition in the trait.
-        let opt_trait_method_ty =
-            trait_methods.iter().
-            find(|tm| tm.ident.name == impl_method_ty.ident.name);
-        match opt_trait_method_ty {
-            Some(trait_method_ty) => {
-                compare_impl_method(ccx.tcx,
-                                    &*impl_method_ty,
-                                    impl_method.span,
-                                    impl_method.pe_body().id,
-                                    &**trait_method_ty,
-                                    &impl_trait_ref.substs);
-            }
-            None => {
-                // This is span_bug as it should have already been caught in resolve.
-                tcx.sess.span_bug(
-                    impl_method.span,
-                    format!(
-                        "method `{}` is not a member of trait `{}`",
-                        token::get_ident(impl_method_ty.ident),
-                        pprust::path_to_string(&ast_trait_ref.path)).as_slice());
+    for impl_item in impl_items.iter() {
+        match *impl_item {
+            ast::MethodImplItem(impl_method) => {
+                let impl_method_def_id = local_def(impl_method.id);
+                let impl_item_ty = ty::impl_or_trait_item(ccx.tcx,
+                                                          impl_method_def_id);
+
+                // If this is an impl of a trait method, find the
+                // corresponding method definition in the trait.
+                let opt_trait_method_ty =
+                    trait_items.iter()
+                               .find(|ti| {
+                                   ti.ident().name == impl_item_ty.ident()
+                                                                  .name
+                               });
+                match opt_trait_method_ty {
+                    Some(trait_method_ty) => {
+                        match (trait_method_ty, &impl_item_ty) {
+                            (&ty::MethodTraitItem(ref trait_method_ty),
+                             &ty::MethodTraitItem(ref impl_method_ty)) => {
+                                compare_impl_method(ccx.tcx,
+                                                    &**impl_method_ty,
+                                                    impl_method.span,
+                                                    impl_method.pe_body().id,
+                                                    &**trait_method_ty,
+                                                    &impl_trait_ref.substs);
+                            }
+                        }
+                    }
+                    None => {
+                        // This is span_bug as it should have already been
+                        // caught in resolve.
+                        tcx.sess.span_bug(
+                            impl_method.span,
+                            format!(
+                                "method `{}` is not a member of trait `{}`",
+                                token::get_ident(impl_item_ty.ident()),
+                                pprust::path_to_string(
+                                    &ast_trait_ref.path)).as_slice());
+                    }
+                }
             }
         }
     }
@@ -832,16 +853,26 @@ fn check_impl_methods_against_trait(ccx: &CrateCtxt,
     let provided_methods = ty::provided_trait_methods(tcx,
                                                       impl_trait_ref.def_id);
     let mut missing_methods = Vec::new();
-    for trait_method in trait_methods.iter() {
-        let is_implemented =
-            impl_methods.iter().any(
-                |m| m.pe_ident().name == trait_method.ident.name);
-        let is_provided =
-            provided_methods.iter().any(
-                |m| m.ident.name == trait_method.ident.name);
-        if !is_implemented && !is_provided {
-            missing_methods.push(
-                format!("`{}`", token::get_ident(trait_method.ident)));
+    for trait_item in trait_items.iter() {
+        match *trait_item {
+            ty::MethodTraitItem(ref trait_method) => {
+                let is_implemented =
+                    impl_items.iter().any(|ii| {
+                        match *ii {
+                            ast::MethodImplItem(m) => {
+                                m.pe_ident().name == trait_method.ident.name
+                            }
+                        }
+                    });
+                let is_provided =
+                    provided_methods.iter().any(
+                        |m| m.ident.name == trait_method.ident.name);
+                if !is_implemented && !is_provided {
+                    missing_methods.push(
+                        format!("`{}`",
+                                token::get_ident(trait_method.ident)));
+                }
+            }
         }
     }
 
@@ -853,7 +884,7 @@ fn check_impl_methods_against_trait(ccx: &CrateCtxt,
 }
 
 /**
- * Checks that a method from an impl/class conforms to the signature of
+ * Checks that a method from an impl conforms to the signature of
  * the same method as declared in the trait.
  *
  * # Parameters
@@ -1271,7 +1302,7 @@ pub fn vtable_context<'a>(&'a self) -> VtableContext<'a> {
         VtableContext {
             infcx: self.infcx(),
             param_env: &self.inh.param_env,
-            unboxed_closure_types: &self.inh.unboxed_closure_types,
+            unboxed_closures: &self.inh.unboxed_closures,
         }
     }
 }
@@ -2618,6 +2649,7 @@ fn check_user_unop(fcx: &FnCtxt,
 
     fn check_unboxed_closure(fcx: &FnCtxt,
                              expr: &ast::Expr,
+                             kind: ast::UnboxedClosureKind,
                              decl: &ast::FnDecl,
                              body: ast::P<ast::Block>) {
         // The `RegionTraitStore` is a lie, but we ignore it so it doesn't
@@ -2635,8 +2667,16 @@ fn check_unboxed_closure(fcx: &FnCtxt,
             abi::RustCall,
             None);
 
+        let region = match fcx.infcx().anon_regions(expr.span, 1) {
+            Err(_) => {
+                fcx.ccx.tcx.sess.span_bug(expr.span,
+                                          "can't make anon regions here?!")
+            }
+            Ok(regions) => *regions.get(0),
+        };
         let closure_type = ty::mk_unboxed_closure(fcx.ccx.tcx,
-                                                  local_def(expr.id));
+                                                  local_def(expr.id),
+                                                  region);
         fcx.write_ty(expr.id, closure_type);
 
         check_fn(fcx.ccx,
@@ -2648,13 +2688,24 @@ fn check_unboxed_closure(fcx: &FnCtxt,
                  fcx.inh);
 
         // Tuple up the arguments and insert the resulting function type into
-        // the `unboxed_closure_types` table.
+        // the `unboxed_closures` table.
         fn_ty.sig.inputs = vec![ty::mk_tup(fcx.tcx(), fn_ty.sig.inputs)];
 
+        let kind = match kind {
+            ast::FnUnboxedClosureKind => ty::FnUnboxedClosureKind,
+            ast::FnMutUnboxedClosureKind => ty::FnMutUnboxedClosureKind,
+            ast::FnOnceUnboxedClosureKind => ty::FnOnceUnboxedClosureKind,
+        };
+
+        let unboxed_closure = ty::UnboxedClosure {
+            closure_type: fn_ty,
+            kind: kind,
+        };
+
         fcx.inh
-           .unboxed_closure_types
+           .unboxed_closures
            .borrow_mut()
-           .insert(local_def(expr.id), fn_ty);
+           .insert(local_def(expr.id), unboxed_closure);
     }
 
     fn check_expr_fn(fcx: &FnCtxt,
@@ -3390,7 +3441,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,9 +3453,10 @@ fn check_fn_for_vec_elements_expected(fcx: &FnCtxt,
                       body.clone(),
                       expected);
       }
-      ast::ExprUnboxedFn(ref decl, ref body) => {
+      ast::ExprUnboxedFn(_, kind, ref decl, ref body) => {
         check_unboxed_closure(fcx,
                               expr,
+                              kind,
                               &**decl,
                               *body);
       }
index d0431de81a359543d4daa30baca6952bacd0024d..0acf6e91831641a71bfa10e095e3c2189992e0d8 100644 (file)
@@ -132,7 +132,7 @@ fn get_i(x: &'a Bar) -> &'a int {
 use middle::typeck::infer;
 use middle::typeck::MethodCall;
 use middle::pat_util;
-use util::nodemap::NodeMap;
+use util::nodemap::{DefIdMap, NodeMap};
 use util::ppaux::{ty_to_string, region_to_string, Repr};
 
 use syntax::ast;
@@ -290,6 +290,16 @@ 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)
+    }
+
+    fn unboxed_closures<'a>(&'a self)
+                        -> &'a RefCell<DefIdMap<ty::UnboxedClosure>> {
+        &self.fcx.inh.unboxed_closures
+    }
 }
 
 pub fn regionck_expr(fcx: &FnCtxt, e: &ast::Expr) {
@@ -587,9 +597,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);
         }
 
@@ -655,6 +665,17 @@ fn check_expr_fn_block(rcx: &mut Rcx,
                 }
             });
         }
+        ty::ty_unboxed_closure(_, region) => {
+            freevars::with_freevars(tcx, expr.id, |freevars| {
+                // No free variables means that there is no environment and
+                // hence the closure has static lifetime. Otherwise, the
+                // closure must not outlive the variables it closes over
+                // by-reference.
+                if !freevars.is_empty() {
+                    constrain_free_variables(rcx, region, expr, freevars);
+                }
+            })
+        }
         _ => ()
     }
 
index 565b88b74939b9505e6f42a02a6bf9f30684e7a4..850d5c5a8f07d03a110608fdd7db132f8fd5abcd 100644 (file)
@@ -71,7 +71,7 @@
 pub struct VtableContext<'a> {
     pub infcx: &'a infer::InferCtxt<'a>,
     pub param_env: &'a ty::ParameterEnvironment,
-    pub unboxed_closure_types: &'a RefCell<DefIdMap<ty::ClosureTy>>,
+    pub unboxed_closures: &'a RefCell<DefIdMap<ty::UnboxedClosure>>,
 }
 
 impl<'a> VtableContext<'a> {
@@ -309,31 +309,42 @@ fn search_for_unboxed_closure_vtable(vcx: &VtableContext,
                                      -> Option<vtable_origin> {
     let tcx = vcx.tcx();
     let closure_def_id = match ty::get(ty).sty {
-        ty::ty_unboxed_closure(closure_def_id) => closure_def_id,
+        ty::ty_unboxed_closure(closure_def_id, _) => closure_def_id,
         _ => return None,
     };
 
     let fn_traits = [
-        tcx.lang_items.fn_trait(),
-        tcx.lang_items.fn_mut_trait(),
-        tcx.lang_items.fn_once_trait()
+        (ty::FnUnboxedClosureKind, tcx.lang_items.fn_trait()),
+        (ty::FnMutUnboxedClosureKind, tcx.lang_items.fn_mut_trait()),
+        (ty::FnOnceUnboxedClosureKind, tcx.lang_items.fn_once_trait()),
     ];
-    for fn_trait in fn_traits.iter() {
-        match *fn_trait {
-            Some(ref fn_trait) if *fn_trait == trait_ref.def_id => {}
+    for tuple in fn_traits.iter() {
+        let kind = match tuple {
+            &(kind, Some(ref fn_trait)) if *fn_trait == trait_ref.def_id => {
+                kind
+            }
             _ => continue,
         };
 
         // Check to see whether the argument and return types match.
-        let unboxed_closure_types = tcx.unboxed_closure_types.borrow();
-        let closure_type = match unboxed_closure_types.find(&closure_def_id) {
-            Some(closure_type) => (*closure_type).clone(),
+        let unboxed_closures = tcx.unboxed_closures.borrow();
+        let closure_type = match unboxed_closures.find(&closure_def_id) {
+            Some(closure) => {
+                if closure.kind != kind {
+                    continue
+                }
+                closure.closure_type.clone()
+            }
             None => {
                 // Try the inherited unboxed closure type map.
-                let unboxed_closure_types = vcx.unboxed_closure_types
-                                               .borrow();
-                match unboxed_closure_types.find(&closure_def_id) {
-                    Some(closure_type) => (*closure_type).clone(),
+                let unboxed_closures = vcx.unboxed_closures.borrow();
+                match unboxed_closures.find(&closure_def_id) {
+                    Some(closure) => {
+                        if closure.kind != kind {
+                            continue
+                        }
+                        closure.closure_type.clone()
+                    }
                     None => {
                         tcx.sess.span_bug(span,
                                           "didn't find unboxed closure type \
@@ -881,11 +892,11 @@ pub fn resolve_impl(tcx: &ty::ctxt,
     debug!("impl_trait_ref={}", impl_trait_ref.repr(tcx));
 
     let infcx = &infer::new_infer_ctxt(tcx);
-    let unboxed_closure_types = RefCell::new(DefIdMap::new());
+    let unboxed_closures = RefCell::new(DefIdMap::new());
     let vcx = VtableContext {
         infcx: infcx,
         param_env: &param_env,
-        unboxed_closure_types: &unboxed_closure_types,
+        unboxed_closures: &unboxed_closures,
     };
 
     // Resolve the vtables for the trait reference on the impl.  This
@@ -934,11 +945,11 @@ pub fn resolve_impl(tcx: &ty::ctxt,
 pub fn trans_resolve_method(tcx: &ty::ctxt, id: ast::NodeId,
                             substs: &subst::Substs) -> vtable_res {
     let generics = ty::lookup_item_type(tcx, ast_util::local_def(id)).generics;
-    let unboxed_closure_types = RefCell::new(DefIdMap::new());
+    let unboxed_closures = RefCell::new(DefIdMap::new());
     let vcx = VtableContext {
         infcx: &infer::new_infer_ctxt(tcx),
         param_env: &ty::construct_parameter_environment(tcx, &ty::Generics::empty(), id),
-        unboxed_closure_types: &unboxed_closure_types,
+        unboxed_closures: &unboxed_closures,
     };
 
     lookup_vtables(&vcx,
index d94ac103ceb731ed37f18d15a5e80f5c5c68fcfb..892a62249ac3b5aa47b8e4778aca710783a3ca96 100644 (file)
@@ -43,7 +43,7 @@ pub fn resolve_type_vars_in_expr(fcx: &FnCtxt, e: &ast::Expr) {
     let mut wbcx = WritebackCx::new(fcx);
     wbcx.visit_expr(e, ());
     wbcx.visit_upvar_borrow_map();
-    wbcx.visit_unboxed_closure_types();
+    wbcx.visit_unboxed_closures();
 }
 
 pub fn resolve_type_vars_in_fn(fcx: &FnCtxt,
@@ -62,7 +62,7 @@ pub fn resolve_type_vars_in_fn(fcx: &FnCtxt,
         }
     }
     wbcx.visit_upvar_borrow_map();
-    wbcx.visit_unboxed_closure_types();
+    wbcx.visit_unboxed_closures();
 }
 
 pub fn resolve_impl_res(infcx: &infer::InferCtxt,
@@ -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);
@@ -211,23 +211,27 @@ fn visit_upvar_borrow_map(&self) {
         }
     }
 
-    fn visit_unboxed_closure_types(&self) {
+    fn visit_unboxed_closures(&self) {
         if self.fcx.writeback_errors.get() {
             return
         }
 
-        for (def_id, closure_ty) in self.fcx
-                                        .inh
-                                        .unboxed_closure_types
-                                        .borrow()
-                                        .iter() {
-            let closure_ty = self.resolve(closure_ty,
+        for (def_id, unboxed_closure) in self.fcx
+                                             .inh
+                                             .unboxed_closures
+                                             .borrow()
+                                             .iter() {
+            let closure_ty = self.resolve(&unboxed_closure.closure_type,
                                           ResolvingUnboxedClosure(*def_id));
+            let unboxed_closure = ty::UnboxedClosure {
+                closure_type: closure_ty,
+                kind: unboxed_closure.kind,
+            };
             self.fcx
                 .tcx()
-                .unboxed_closure_types
+                .unboxed_closures
                 .borrow_mut()
-                .insert(*def_id, closure_ty);
+                .insert(*def_id, unboxed_closure);
         }
     }
 
index fdf9125e6e14d2cca5a46993ff394bf9d93569c8..3dee787b6c9064edea7f3507a25dd933427dcf7e 100644 (file)
@@ -20,7 +20,8 @@
 use middle::subst;
 use middle::subst::{Substs};
 use middle::ty::get;
-use middle::ty::{ImplContainer, lookup_item_type};
+use middle::ty::{ImplContainer, ImplOrTraitItemId, MethodTraitItemId};
+use middle::ty::{lookup_item_type};
 use middle::ty::{t, ty_bool, ty_char, ty_bot, ty_box, ty_enum, ty_err};
 use middle::ty::{ty_str, ty_vec, ty_float, ty_infer, ty_int, ty_nil};
 use middle::ty::{ty_param, Polytype, ty_ptr};
@@ -109,7 +110,7 @@ fn type_is_defined_in_local_crate(tcx: &ty::ctxt, original_type: t) -> bool {
         match get(t).sty {
             ty_enum(def_id, _) |
             ty_struct(def_id, _) |
-            ty_unboxed_closure(def_id) => {
+            ty_unboxed_closure(def_id, _) => {
                 if def_id.krate == ast::LOCAL_CRATE {
                     found_nominal = true;
                 }
@@ -153,7 +154,7 @@ fn get_base_type_def_id(inference_context: &InferCtxt,
             match get(base_type).sty {
                 ty_enum(def_id, _) |
                 ty_struct(def_id, _) |
-                ty_unboxed_closure(def_id) => {
+                ty_unboxed_closure(def_id, _) => {
                     Some(def_id)
                 }
                 ty_rptr(_, ty::mt {ty, ..}) | ty_uniq(ty) => match ty::get(ty).sty {
@@ -308,7 +309,7 @@ fn check_implementation(&self, item: &Item,
             }
         }
 
-        let impl_methods = self.create_impl_from_item(item);
+        let impl_items = self.create_impl_from_item(item);
 
         for associated_trait in associated_traits.iter() {
             let trait_ref = ty::node_id_to_trait_ref(
@@ -337,16 +338,17 @@ fn check_implementation(&self, item: &Item,
             }
         }
 
-        tcx.impl_methods.borrow_mut().insert(impl_did, impl_methods);
+        tcx.impl_items.borrow_mut().insert(impl_did, impl_items);
     }
 
     // Creates default method IDs and performs type substitutions for an impl
     // and trait pair. Then, for each provided method in the trait, inserts a
     // `ProvidedMethodInfo` instance into the `provided_method_sources` map.
-    fn instantiate_default_methods(&self,
-                                   impl_id: DefId,
-                                   trait_ref: &ty::TraitRef,
-                                   all_methods: &mut Vec<DefId>) {
+    fn instantiate_default_methods(
+            &self,
+            impl_id: DefId,
+            trait_ref: &ty::TraitRef,
+            all_impl_items: &mut Vec<ImplOrTraitItemId>) {
         let tcx = self.crate_context.tcx;
         debug!("instantiate_default_methods(impl_id={:?}, trait_ref={})",
                impl_id, trait_ref.repr(tcx));
@@ -373,7 +375,7 @@ fn instantiate_default_methods(&self,
                     Some(trait_method.def_id)));
 
             debug!("new_method_ty={}", new_method_ty.repr(tcx));
-            all_methods.push(new_did);
+            all_impl_items.push(MethodTraitItemId(new_did));
 
             // construct the polytype for the method based on the
             // method_ty.  it will have all the generics from the
@@ -385,7 +387,9 @@ fn instantiate_default_methods(&self,
             debug!("new_polytype={}", new_polytype.repr(tcx));
 
             tcx.tcache.borrow_mut().insert(new_did, new_polytype);
-            tcx.methods.borrow_mut().insert(new_did, new_method_ty);
+            tcx.impl_or_trait_items
+               .borrow_mut()
+               .insert(new_did, ty::MethodTraitItem(new_method_ty));
 
             // Pair the new synthesized ID up with the
             // ID of the method.
@@ -576,13 +580,20 @@ fn ast_type_is_defined_in_local_crate(&self, original_type: &ast::Ty) -> bool {
         }
     }
 
-    // Converts an implementation in the AST to a vector of methods.
-    fn create_impl_from_item(&self, item: &Item) -> Vec<DefId> {
+    // Converts an implementation in the AST to a vector of items.
+    fn create_impl_from_item(&self, item: &Item) -> Vec<ImplOrTraitItemId> {
         match item.node {
-            ItemImpl(_, ref trait_refs, _, ref ast_methods) => {
-                let mut methods: Vec<DefId> = ast_methods.iter().map(|ast_method| {
-                    local_def(ast_method.id)
-                }).collect();
+            ItemImpl(_, ref trait_refs, _, ref ast_items) => {
+                let mut items: Vec<ImplOrTraitItemId> =
+                        ast_items.iter()
+                                 .map(|ast_item| {
+                            match *ast_item {
+                                ast::MethodImplItem(ast_method) => {
+                                    MethodTraitItemId(
+                                        local_def(ast_method.id))
+                                }
+                            }
+                        }).collect();
 
                 for trait_ref in trait_refs.iter() {
                     let ty_trait_ref = ty::node_id_to_trait_ref(
@@ -591,10 +602,10 @@ fn create_impl_from_item(&self, item: &Item) -> Vec<DefId> {
 
                     self.instantiate_default_methods(local_def(item.id),
                                                      &*ty_trait_ref,
-                                                     &mut methods);
+                                                     &mut items);
                 }
 
-                methods
+                items
             }
             _ => {
                 self.crate_context.tcx.sess.span_bug(item.span,
@@ -614,7 +625,8 @@ fn add_external_impl(&self,
                          impls_seen: &mut HashSet<DefId>,
                          impl_def_id: DefId) {
         let tcx = self.crate_context.tcx;
-        let methods = csearch::get_impl_methods(&tcx.sess.cstore, impl_def_id);
+        let impl_items = csearch::get_impl_items(&tcx.sess.cstore,
+                                                 impl_def_id);
 
         // Make sure we don't visit the same implementation multiple times.
         if !impls_seen.insert(impl_def_id) {
@@ -629,20 +641,27 @@ fn add_external_impl(&self,
         // Do a sanity check.
         assert!(associated_traits.is_some());
 
-        // Record all the trait methods.
+        // Record all the trait items.
         for trait_ref in associated_traits.iter() {
             self.add_trait_impl(trait_ref.def_id, impl_def_id);
         }
 
         // For any methods that use a default implementation, add them to
         // the map. This is a bit unfortunate.
-        for &method_def_id in methods.iter() {
-            for &source in ty::method(tcx, method_def_id).provided_source.iter() {
-                tcx.provided_method_sources.borrow_mut().insert(method_def_id, source);
+        for item_def_id in impl_items.iter() {
+            let impl_item = ty::impl_or_trait_item(tcx, item_def_id.def_id());
+            match impl_item {
+                ty::MethodTraitItem(ref method) => {
+                    for &source in method.provided_source.iter() {
+                        tcx.provided_method_sources
+                           .borrow_mut()
+                           .insert(item_def_id.def_id(), source);
+                    }
+                }
             }
         }
 
-        tcx.impl_methods.borrow_mut().insert(impl_def_id, methods);
+        tcx.impl_items.borrow_mut().insert(impl_def_id, impl_items);
     }
 
     // Adds implementations and traits from external crates to the coherence
@@ -669,28 +688,31 @@ fn populate_destructor_table(&self) {
             Some(id) => id, None => { return }
         };
 
-        let impl_methods = tcx.impl_methods.borrow();
+        let impl_items = tcx.impl_items.borrow();
         let trait_impls = match tcx.trait_impls.borrow().find_copy(&drop_trait) {
             None => return, // No types with (new-style) dtors present.
             Some(found_impls) => found_impls
         };
 
         for &impl_did in trait_impls.borrow().iter() {
-            let methods = impl_methods.get(&impl_did);
-            if methods.len() < 1 {
+            let items = impl_items.get(&impl_did);
+            if items.len() < 1 {
                 // We'll error out later. For now, just don't ICE.
                 continue;
             }
-            let method_def_id = *methods.get(0);
+            let method_def_id = *items.get(0);
 
             let self_type = self.get_self_type_for_implementation(impl_did);
             match ty::get(self_type.ty).sty {
                 ty::ty_enum(type_def_id, _) |
                 ty::ty_struct(type_def_id, _) |
-                ty::ty_unboxed_closure(type_def_id) => {
-                    tcx.destructor_for_type.borrow_mut().insert(type_def_id,
-                                                                method_def_id);
-                    tcx.destructors.borrow_mut().insert(method_def_id);
+                ty::ty_unboxed_closure(type_def_id, _) => {
+                    tcx.destructor_for_type
+                       .borrow_mut()
+                       .insert(type_def_id, method_def_id.def_id());
+                    tcx.destructors
+                       .borrow_mut()
+                       .insert(method_def_id.def_id());
                 }
                 _ => {
                     // Destructors only work on nominal types.
index a81c6344cc9c6014002af35656940c1511cbd1d6..284330c51c86a963e7c269703644f7b1e7bc84de 100644 (file)
@@ -37,7 +37,7 @@
 use middle::resolve_lifetime;
 use middle::subst;
 use middle::subst::{Substs};
-use middle::ty::{ImplContainer, MethodContainer, TraitContainer};
+use middle::ty::{ImplContainer, ImplOrTraitItemContainer, TraitContainer};
 use middle::ty::{Polytype};
 use middle::ty;
 use middle::ty_fold::TypeFolder;
@@ -200,64 +200,74 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt,
     match tcx.map.get(trait_id) {
         ast_map::NodeItem(item) => {
             match item.node {
-                ast::ItemTrait(_, _, _, ref ms) => {
+                ast::ItemTrait(_, _, _, ref trait_items) => {
                     // For each method, construct a suitable ty::Method and
-                    // store it into the `tcx.methods` table:
-                    for m in ms.iter() {
-                        let ty_method = Rc::new(match m {
-                            &ast::Required(ref m) => {
-                                ty_method_of_trait_method(
-                                    ccx,
-                                    trait_id,
-                                    &trait_def.generics,
-                                    &m.id,
-                                    &m.ident,
-                                    &m.explicit_self,
-                                    m.abi,
-                                    &m.generics,
-                                    &m.fn_style,
-                                    &*m.decl)
-                            }
+                    // store it into the `tcx.impl_or_trait_items` table:
+                    for trait_item in trait_items.iter() {
+                        match *trait_item {
+                            ast::RequiredMethod(_) |
+                            ast::ProvidedMethod(_) => {
+                                let ty_method = Rc::new(match *trait_item {
+                                    ast::RequiredMethod(ref m) => {
+                                        ty_method_of_trait_method(
+                                            ccx,
+                                            trait_id,
+                                            &trait_def.generics,
+                                            &m.id,
+                                            &m.ident,
+                                            &m.explicit_self,
+                                            m.abi,
+                                            &m.generics,
+                                            &m.fn_style,
+                                            &*m.decl)
+                                    }
+                                    ast::ProvidedMethod(ref m) => {
+                                        ty_method_of_trait_method(
+                                            ccx,
+                                            trait_id,
+                                            &trait_def.generics,
+                                            &m.id,
+                                            &m.pe_ident(),
+                                            m.pe_explicit_self(),
+                                            m.pe_abi(),
+                                            m.pe_generics(),
+                                            &m.pe_fn_style(),
+                                            &*m.pe_fn_decl())
+                                    }
+                                });
 
-                            &ast::Provided(ref m) => {
-                                ty_method_of_trait_method(
-                                    ccx,
-                                    trait_id,
-                                    &trait_def.generics,
-                                    &m.id,
-                                    &m.pe_ident(),
-                                    m.pe_explicit_self(),
-                                    m.pe_abi(),
-                                    m.pe_generics(),
-                                    &m.pe_fn_style(),
-                                    &*m.pe_fn_decl())
-                            }
-                        });
+                                if ty_method.explicit_self ==
+                                        ty::StaticExplicitSelfCategory {
+                                    make_static_method_ty(ccx, &*ty_method);
+                                }
 
-                        if ty_method.explicit_self ==
-                                ty::StaticExplicitSelfCategory {
-                            make_static_method_ty(ccx, &*ty_method);
+                                tcx.impl_or_trait_items
+                                   .borrow_mut()
+                                   .insert(ty_method.def_id,
+                                           ty::MethodTraitItem(ty_method));
+                            }
                         }
-
-                        tcx.methods.borrow_mut().insert(ty_method.def_id,
-                                                        ty_method);
                     }
 
                     // Add an entry mapping
-                    let method_def_ids = Rc::new(ms.iter().map(|m| {
-                        match m {
-                            &ast::Required(ref ty_method) => {
-                                local_def(ty_method.id)
-                            }
-                            &ast::Provided(ref method) => {
-                                local_def(method.id)
+                    let trait_item_def_ids =
+                        Rc::new(trait_items.iter()
+                                           .map(|ti| {
+                            match *ti {
+                                ast::RequiredMethod(ref ty_method) => {
+                                    ty::MethodTraitItemId(local_def(
+                                            ty_method.id))
+                                }
+                                ast::ProvidedMethod(ref method) => {
+                                    ty::MethodTraitItemId(local_def(
+                                            method.id))
+                                }
                             }
-                        }
-                    }).collect());
+                        }).collect());
 
                     let trait_def_id = local_def(trait_id);
-                    tcx.trait_method_def_ids.borrow_mut()
-                        .insert(trait_def_id, method_def_ids);
+                    tcx.trait_item_def_ids.borrow_mut()
+                        .insert(trait_def_id, trait_item_def_ids);
                 }
                 _ => {} // Ignore things that aren't traits.
             }
@@ -346,12 +356,11 @@ pub fn convert_field(ccx: &CrateCtxt,
 }
 
 fn convert_methods(ccx: &CrateCtxt,
-                   container: MethodContainer,
+                   container: ImplOrTraitItemContainer,
                    ms: &[Gc<ast::Method>],
                    untransformed_rcvr_ty: ty::t,
                    rcvr_ty_generics: &ty::Generics,
-                   rcvr_visibility: ast::Visibility)
-{
+                   rcvr_visibility: ast::Visibility) {
     let tcx = ccx.tcx;
     let mut seen_methods = HashSet::new();
     for m in ms.iter() {
@@ -379,11 +388,13 @@ fn convert_methods(ccx: &CrateCtxt,
 
         write_ty_to_tcx(tcx, m.id, fty);
 
-        tcx.methods.borrow_mut().insert(mty.def_id, mty);
+        tcx.impl_or_trait_items
+           .borrow_mut()
+           .insert(mty.def_id, ty::MethodTraitItem(mty));
     }
 
     fn ty_of_method(ccx: &CrateCtxt,
-                    container: MethodContainer,
+                    container: ImplOrTraitItemContainer,
                     m: &ast::Method,
                     untransformed_rcvr_ty: ty::t,
                     rcvr_ty_generics: &ty::Generics,
@@ -459,7 +470,10 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
                                    enum_definition.variants.as_slice(),
                                    generics);
         },
-        ast::ItemImpl(ref generics, ref opt_trait_ref, selfty, ref ms) => {
+        ast::ItemImpl(ref generics,
+                      ref opt_trait_ref,
+                      selfty,
+                      ref impl_items) => {
             let ty_generics = ty_generics_for_type(ccx, generics);
             let selfty = ccx.to_ty(&ExplicitRscope, &*selfty);
             write_ty_to_tcx(tcx, it.id, selfty);
@@ -480,16 +494,22 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
                 it.vis
             };
 
-            for method in ms.iter() {
-                check_method_self_type(ccx,
-                                       &BindingRscope::new(method.id),
-                                       selfty,
-                                       method.pe_explicit_self())
+            let mut methods = Vec::new();
+            for impl_item in impl_items.iter() {
+                match *impl_item {
+                    ast::MethodImplItem(ref method) => {
+                        check_method_self_type(ccx,
+                                               &BindingRscope::new(method.id),
+                                               selfty,
+                                               method.pe_explicit_self());
+                        methods.push(*method);
+                    }
+                }
             }
 
             convert_methods(ccx,
                             ImplContainer(local_def(it.id)),
-                            ms.as_slice(),
+                            methods.as_slice(),
                             selfty,
                             &ty_generics,
                             parent_visibility);
@@ -507,14 +527,14 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
                                              0,
                                              local_def(it.id));
                 match *trait_method {
-                    ast::Required(ref type_method) => {
+                    ast::RequiredMethod(ref type_method) => {
                         let rscope = BindingRscope::new(type_method.id);
                         check_method_self_type(ccx,
                                                &rscope,
                                                self_type,
                                                &type_method.explicit_self)
                     }
-                    ast::Provided(ref method) => {
+                    ast::ProvidedMethod(ref method) => {
                         check_method_self_type(ccx,
                                                &BindingRscope::new(method.id),
                                                self_type,
index 1aae97d3d83e9266a68d0b2a536dbcdb77772829..d99d55d4d873dfba386a001b099dd1092af61b74 100644 (file)
@@ -492,9 +492,11 @@ fn check_ptr_to_unsized<C:Combine>(this: &C,
             Ok(ty::mk_struct(tcx, a_id, substs))
       }
 
-      (&ty::ty_unboxed_closure(a_id), &ty::ty_unboxed_closure(b_id))
+      (&ty::ty_unboxed_closure(a_id, a_region),
+       &ty::ty_unboxed_closure(b_id, b_region))
       if a_id == b_id => {
-          Ok(ty::mk_unboxed_closure(tcx, a_id))
+          let region = if_ok!(this.regions(a_region, b_region));
+          Ok(ty::mk_unboxed_closure(tcx, a_id, region))
       }
 
       (&ty::ty_box(a_inner), &ty::ty_box(b_inner)) => {
index e191fb343b53a3dce42980c527ec3891c2590da1..a4e7f28b45063b7d0f4e93545c98ba3358c97b5b 100644 (file)
@@ -305,7 +305,8 @@ fn free_regions_from_same_fn(tcx: &ty::ctxt,
                         },
                         _ => None
                     },
-                    ast_map::NodeMethod(..) => {
+                    ast_map::NodeImplItem(..) |
+                    ast_map::NodeTraitItem(..) => {
                         Some(FreeRegionsFromSameFn::new(fr1, fr2, scope_id))
                     },
                     _ => None
@@ -699,9 +700,17 @@ fn give_suggestion(&self, same_regions: &[SameRegions]) {
                         _ => None
                     }
                 }
-                ast_map::NodeMethod(ref m) => {
-                    Some((m.pe_fn_decl(), m.pe_generics(), m.pe_fn_style(),
-                          m.pe_ident(), Some(m.pe_explicit_self().node), m.span))
+                ast_map::NodeImplItem(ref item) => {
+                    match **item {
+                        ast::MethodImplItem(ref m) => {
+                            Some((m.pe_fn_decl(),
+                                  m.pe_generics(),
+                                  m.pe_fn_style(),
+                                  m.pe_ident(),
+                                  Some(m.pe_explicit_self().node),
+                                  m.span))
+                        }
+                    }
                 },
                 _ => None
             },
@@ -1454,10 +1463,14 @@ fn lifetimes_in_scope(tcx: &ty::ctxt,
                 },
                 _ => None
             },
-            ast_map::NodeMethod(m) => {
-                taken.push_all(m.pe_generics().lifetimes.as_slice());
-                Some(m.id)
-            },
+            ast_map::NodeImplItem(ii) => {
+                match *ii {
+                    ast::MethodImplItem(m) => {
+                        taken.push_all(m.pe_generics().lifetimes.as_slice());
+                        Some(m.id)
+                    }
+                }
+            }
             _ => None
         },
         None => None
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 be9ae0cc719f2966bacae5be17c17c04cbcf463c..e0fab95a04529435a9c039aceeba218e3bf073b5 100644 (file)
@@ -515,10 +515,14 @@ fn visit_item(&mut self, item: &ast::Item, _: ()) {
             }
 
             ast::ItemTrait(..) => {
-                let methods = ty::trait_methods(tcx, did);
-                for method in methods.iter() {
-                    self.add_constraints_from_sig(
-                        &method.fty.sig, self.covariant);
+                let trait_items = ty::trait_items(tcx, did);
+                for trait_item in trait_items.iter() {
+                    match *trait_item {
+                        ty::MethodTraitItem(ref method) => {
+                            self.add_constraints_from_sig(&method.fty.sig,
+                                                          self.covariant);
+                        }
+                    }
                 }
             }
 
@@ -609,8 +613,8 @@ macro_rules! cannot_happen { () => { {
                         _                    => cannot_happen!(),
                     }
                 }
-                ast_map::NodeTraitMethod(..) => is_inferred = false,
-                ast_map::NodeMethod(_)       => is_inferred = false,
+                ast_map::NodeTraitItem(..)   => is_inferred = false,
+                ast_map::NodeImplItem(..)    => is_inferred = false,
                 _                            => cannot_happen!(),
             }
 
@@ -722,10 +726,15 @@ fn add_constraints_from_ty(&mut self,
         match ty::get(ty).sty {
             ty::ty_nil | ty::ty_bot | ty::ty_bool |
             ty::ty_char | ty::ty_int(_) | ty::ty_uint(_) |
-            ty::ty_float(_) | ty::ty_str | ty::ty_unboxed_closure(..) => {
+            ty::ty_float(_) | ty::ty_str => {
                 /* leaf type -- noop */
             }
 
+            ty::ty_unboxed_closure(_, region) => {
+                let contra = self.contravariant(variance);
+                self.add_constraints_from_region(region, contra);
+            }
+
             ty::ty_rptr(region, ref mt) => {
                 let contra = self.contravariant(variance);
                 self.add_constraints_from_region(region, contra);
index 4e193f0f1d952f816ce290d7a97883fe0c2b733f..301143e5045509c941b3bfc2320a8fcc5a2a50c2 100644 (file)
@@ -762,8 +762,8 @@ fn repr(&self, tcx: &ctxt) -> String {
                 match tcx.map.find(self.node) {
                     Some(ast_map::NodeItem(..)) |
                     Some(ast_map::NodeForeignItem(..)) |
-                    Some(ast_map::NodeMethod(..)) |
-                    Some(ast_map::NodeTraitMethod(..)) |
+                    Some(ast_map::NodeImplItem(..)) |
+                    Some(ast_map::NodeTraitItem(..)) |
                     Some(ast_map::NodeVariant(..)) |
                     Some(ast_map::NodeStructCtor(..)) => {
                         return format!(
index d45ebb3858e9f703ed2671563535f59570e9fe06..29668795ed7ba429e3d30c42c60fedb976237218 100644 (file)
@@ -480,8 +480,8 @@ fn visit_ty_method(&mut self, t: &TypeMethod, e: E) {
             SawTyMethod.hash(self.st); visit::walk_ty_method(self, t, e)
         }
 
-        fn visit_trait_method(&mut self, t: &TraitMethod, e: E) {
-            SawTraitMethod.hash(self.st); visit::walk_trait_method(self, t, e)
+        fn visit_trait_item(&mut self, t: &TraitItem, e: E) {
+            SawTraitMethod.hash(self.st); visit::walk_trait_item(self, t, e)
         }
 
         fn visit_struct_field(&mut self, s: &StructField, e: E) {
index 3c942d0791e77fb6e5db6ff7cb36c21d1d584c4c..0e87be1c241b91a1e02de8ab1a4456f042fc30cb 100644 (file)
@@ -157,13 +157,13 @@ pub fn record_extern_fqn(cx: &core::DocContext,
 
 pub fn build_external_trait(tcx: &ty::ctxt, did: ast::DefId) -> clean::Trait {
     let def = ty::lookup_trait_def(tcx, did);
-    let methods = ty::trait_methods(tcx, did).clean();
+    let trait_items = ty::trait_items(tcx, did).clean();
     let provided = ty::provided_trait_methods(tcx, did);
-    let mut methods = methods.move_iter().map(|meth| {
-        if provided.iter().any(|a| a.def_id == meth.def_id) {
-            clean::Provided(meth)
+    let mut items = trait_items.move_iter().map(|trait_item| {
+        if provided.iter().any(|a| a.def_id == trait_item.def_id) {
+            clean::ProvidedMethod(trait_item)
         } else {
-            clean::Required(meth)
+            clean::RequiredMethod(trait_item)
         }
     });
     let supertraits = ty::trait_supertraits(tcx, did);
@@ -176,7 +176,7 @@ pub fn build_external_trait(tcx: &ty::ctxt, did: ast::DefId) -> clean::Trait {
 
     clean::Trait {
         generics: (&def.generics, subst::TypeSpace).clean(),
-        methods: methods.collect(),
+        items: items.collect(),
         parents: parents.collect()
     }
 }
@@ -303,27 +303,33 @@ fn build_impl(cx: &core::DocContext,
 
     let attrs = load_attrs(tcx, did);
     let ty = ty::lookup_item_type(tcx, did);
-    let methods = csearch::get_impl_methods(&tcx.sess.cstore,
-                                            did).iter().filter_map(|did| {
-        let method = ty::method(tcx, *did);
-        if method.vis != ast::Public && associated_trait.is_none() {
-            return None
-        }
-        let mut item = ty::method(tcx, *did).clean();
-        item.inner = match item.inner.clone() {
-            clean::TyMethodItem(clean::TyMethod {
-                fn_style, decl, self_, generics
-            }) => {
-                clean::MethodItem(clean::Method {
-                    fn_style: fn_style,
-                    decl: decl,
-                    self_: self_,
-                    generics: generics,
-                })
+    let trait_items = csearch::get_impl_items(&tcx.sess.cstore, did)
+            .iter()
+            .filter_map(|did| {
+        let did = did.def_id();
+        let impl_item = ty::impl_or_trait_item(tcx, did);
+        match impl_item {
+            ty::MethodTraitItem(method) => {
+                if method.vis != ast::Public && associated_trait.is_none() {
+                    return None
+                }
+                let mut item = method.clean();
+                item.inner = match item.inner.clone() {
+                    clean::TyMethodItem(clean::TyMethod {
+                        fn_style, decl, self_, generics
+                    }) => {
+                        clean::MethodItem(clean::Method {
+                            fn_style: fn_style,
+                            decl: decl,
+                            self_: self_,
+                            generics: generics,
+                        })
+                    }
+                    _ => fail!("not a tymethod"),
+                };
+                Some(item)
             }
-            _ => fail!("not a tymethod"),
-        };
-        Some(item)
+        }
     }).collect();
     return Some(clean::Item {
         inner: clean::ImplItem(clean::Impl {
@@ -336,7 +342,7 @@ fn build_impl(cx: &core::DocContext,
             }),
             for_: ty.ty.clean(),
             generics: (&ty.generics, subst::TypeSpace).clean(),
-            methods: methods,
+            items: trait_items,
         }),
         source: clean::Span::empty(),
         name: None,
index a1f486b3b31b81a92f14fabccda514d6c0632a9f..c5d3c73c9bcf7b5d00fdebda6386b7cab9339bca 100644 (file)
@@ -907,7 +907,7 @@ fn clean(&self) -> RetStyle {
 
 #[deriving(Clone, Encodable, Decodable)]
 pub struct Trait {
-    pub methods: Vec<TraitMethod>,
+    pub items: Vec<TraitItem>,
     pub generics: Generics,
     pub parents: Vec<Type>,
 }
@@ -922,7 +922,7 @@ fn clean(&self) -> Item {
             visibility: self.vis.clean(),
             stability: self.stab.clean(),
             inner: TraitItem(Trait {
-                methods: self.methods.clean(),
+                items: self.items.clean(),
                 generics: self.generics.clean(),
                 parents: self.parents.clean(),
             }),
@@ -937,37 +937,50 @@ fn clean(&self) -> Type {
 }
 
 #[deriving(Clone, Encodable, Decodable)]
-pub enum TraitMethod {
-    Required(Item),
-    Provided(Item),
+pub enum TraitItem {
+    RequiredMethod(Item),
+    ProvidedMethod(Item),
 }
 
-impl TraitMethod {
+impl TraitItem {
     pub fn is_req(&self) -> bool {
         match self {
-            &Required(..) => true,
+            &RequiredMethod(..) => true,
             _ => false,
         }
     }
     pub fn is_def(&self) -> bool {
         match self {
-            &Provided(..) => true,
+            &ProvidedMethod(..) => true,
             _ => false,
         }
     }
     pub fn item<'a>(&'a self) -> &'a Item {
         match *self {
-            Required(ref item) => item,
-            Provided(ref item) => item,
+            RequiredMethod(ref item) => item,
+            ProvidedMethod(ref item) => item,
         }
     }
 }
 
-impl Clean<TraitMethod> for ast::TraitMethod {
-    fn clean(&self) -> TraitMethod {
+impl Clean<TraitItem> for ast::TraitItem {
+    fn clean(&self) -> TraitItem {
         match self {
-            &ast::Required(ref t) => Required(t.clean()),
-            &ast::Provided(ref t) => Provided(t.clean()),
+            &ast::RequiredMethod(ref t) => RequiredMethod(t.clean()),
+            &ast::ProvidedMethod(ref t) => ProvidedMethod(t.clean()),
+        }
+    }
+}
+
+#[deriving(Clone, Encodable, Decodable)]
+pub enum ImplItem {
+    MethodImplItem(Item),
+}
+
+impl Clean<ImplItem> for ast::ImplItem {
+    fn clean(&self) -> ImplItem {
+        match self {
+            &ast::MethodImplItem(ref t) => MethodImplItem(t.clean()),
         }
     }
 }
@@ -1019,6 +1032,14 @@ fn clean(&self) -> Item {
     }
 }
 
+impl Clean<Item> for ty::ImplOrTraitItem {
+    fn clean(&self) -> Item {
+        match *self {
+            ty::MethodTraitItem(ref mti) => mti.clean(),
+        }
+    }
+}
+
 /// A representation of a Type suitable for hyperlinking purposes. Ideally one can get the original
 /// type out of the AST/ty::ctxt given one of these, if more information is needed. Most importantly
 /// it does not preserve mutability or boxes.
@@ -1714,7 +1735,7 @@ pub struct Impl {
     pub generics: Generics,
     pub trait_: Option<Type>,
     pub for_: Type,
-    pub methods: Vec<Item>,
+    pub items: Vec<Item>,
     pub derived: bool,
 }
 
@@ -1735,7 +1756,11 @@ fn clean(&self) -> Item {
                 generics: self.generics.clean(),
                 trait_: self.trait_.clean(),
                 for_: self.for_.clean(),
-                methods: self.methods.clean(),
+                items: self.items.clean().move_iter().map(|ti| {
+                        match ti {
+                            MethodImplItem(i) => i,
+                        }
+                    }).collect(),
                 derived: detect_derived(self.attrs.as_slice()),
             }),
         }
index 313f1c81c79e81ba8df55f0d5af5fb24b11cd01a..a5ead46384a0056dda7e0a6eb52b8be3c381042c 100644 (file)
@@ -154,7 +154,7 @@ pub struct Static {
 
 pub struct Trait {
     pub name: Ident,
-    pub methods: Vec<ast::TraitMethod>, //should be TraitMethod
+    pub items: Vec<ast::TraitItem>, //should be TraitItem
     pub generics: ast::Generics,
     pub parents: Vec<ast::TraitRef>,
     pub attrs: Vec<ast::Attribute>,
@@ -168,7 +168,7 @@ pub struct Impl {
     pub generics: ast::Generics,
     pub trait_: Option<ast::TraitRef>,
     pub for_: ast::P<ast::Ty>,
-    pub methods: Vec<Gc<ast::Method>>,
+    pub items: Vec<ast::ImplItem>,
     pub attrs: Vec<ast::Attribute>,
     pub where: Span,
     pub vis: ast::Visibility,
index 60853f450ab329dcb0a5d3ad5a5bedaf5d33a509..f0082f8900e6ae3414a92b802490d06786c8f33c 100644 (file)
@@ -40,29 +40,31 @@ fn fold_item_recur(&mut self, item: Item) -> Option<Item> {
                 EnumItem(i)
             },
             TraitItem(mut i) => {
-                fn vtrm<T: DocFolder>(this: &mut T, trm: TraitMethod) -> Option<TraitMethod> {
+                fn vtrm<T: DocFolder>(this: &mut T, trm: TraitItem)
+                        -> Option<TraitItem> {
                     match trm {
-                        Required(it) => {
+                        RequiredMethod(it) => {
                             match this.fold_item(it) {
-                                Some(x) => return Some(Required(x)),
+                                Some(x) => return Some(RequiredMethod(x)),
                                 None => return None,
                             }
                         },
-                        Provided(it) => {
+                        ProvidedMethod(it) => {
                             match this.fold_item(it) {
-                                Some(x) => return Some(Provided(x)),
+                                Some(x) => return Some(ProvidedMethod(x)),
                                 None => return None,
                             }
                         },
                     }
                 }
-                let mut foo = Vec::new(); swap(&mut foo, &mut i.methods);
-                i.methods.extend(foo.move_iter().filter_map(|x| vtrm(self, x)));
+                let mut foo = Vec::new(); swap(&mut foo, &mut i.items);
+                i.items.extend(foo.move_iter().filter_map(|x| vtrm(self, x)));
                 TraitItem(i)
             },
             ImplItem(mut i) => {
-                let mut foo = Vec::new(); swap(&mut foo, &mut i.methods);
-                i.methods.extend(foo.move_iter().filter_map(|x| self.fold_item(x)));
+                let mut foo = Vec::new(); swap(&mut foo, &mut i.items);
+                i.items.extend(foo.move_iter()
+                                  .filter_map(|x| self.fold_item(x)));
                 ImplItem(i)
             },
             VariantItem(i) => {
index 4f511e390ff98650100a3ae13a56c833fda05f49..bb68c6536a00d3ab676b3c506de65b87be9ad5df 100644 (file)
@@ -1624,10 +1624,24 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
                   it.name.get_ref().as_slice(),
                   t.generics,
                   parents));
-    let required = t.methods.iter().filter(|m| m.is_req()).collect::<Vec<&clean::TraitMethod>>();
-    let provided = t.methods.iter().filter(|m| !m.is_req()).collect::<Vec<&clean::TraitMethod>>();
-
-    if t.methods.len() == 0 {
+    let required = t.items.iter()
+                          .filter(|m| {
+                              match **m {
+                                  clean::RequiredMethod(_) => true,
+                                  _ => false,
+                              }
+                          })
+                          .collect::<Vec<&clean::TraitItem>>();
+    let provided = t.items.iter()
+                          .filter(|m| {
+                              match **m {
+                                  clean::ProvidedMethod(_) => true,
+                                  _ => false,
+                              }
+                          })
+                          .collect::<Vec<&clean::TraitItem>>();
+
+    if t.items.len() == 0 {
         try!(write!(w, "{{ }}"));
     } else {
         try!(write!(w, "{{\n"));
@@ -1651,7 +1665,8 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
     // Trait documentation
     try!(document(w, it));
 
-    fn meth(w: &mut fmt::Formatter, m: &clean::TraitMethod) -> fmt::Result {
+    fn trait_item(w: &mut fmt::Formatter, m: &clean::TraitItem)
+                  -> fmt::Result {
         try!(write!(w, "<h3 id='{}.{}' class='method'>{}<code>",
                     shortty(m.item()),
                     *m.item().name.get_ref(),
@@ -1669,7 +1684,7 @@ fn meth(w: &mut fmt::Formatter, m: &clean::TraitMethod) -> fmt::Result {
             <div class='methods'>
         "));
         for m in required.iter() {
-            try!(meth(w, *m));
+            try!(trait_item(w, *m));
         }
         try!(write!(w, "</div>"));
     }
@@ -1679,7 +1694,7 @@ fn meth(w: &mut fmt::Formatter, m: &clean::TraitMethod) -> fmt::Result {
             <div class='methods'>
         "));
         for m in provided.iter() {
-            try!(meth(w, *m));
+            try!(trait_item(w, *m));
         }
         try!(write!(w, "</div>"));
     }
@@ -1991,8 +2006,8 @@ fn render_impl(w: &mut fmt::Formatter, i: &Impl) -> fmt::Result {
         None => {}
     }
 
-    fn docmeth(w: &mut fmt::Formatter, item: &clean::Item,
-               dox: bool) -> fmt::Result {
+    fn doctraititem(w: &mut fmt::Formatter, item: &clean::Item, dox: bool)
+                    -> fmt::Result {
         try!(write!(w, "<h4 id='method.{}' class='method'>{}<code>",
                     *item.name.get_ref(),
                     ConciseStability(&item.stability)));
@@ -2008,21 +2023,21 @@ fn docmeth(w: &mut fmt::Formatter, item: &clean::Item,
     }
 
     try!(write!(w, "<div class='impl-methods'>"));
-    for meth in i.impl_.methods.iter() {
-        try!(docmeth(w, meth, true));
+    for trait_item in i.impl_.items.iter() {
+        try!(doctraititem(w, trait_item, true));
     }
 
     fn render_default_methods(w: &mut fmt::Formatter,
                               t: &clean::Trait,
                               i: &clean::Impl) -> fmt::Result {
-        for method in t.methods.iter() {
-            let n = method.item().name.clone();
-            match i.methods.iter().find(|m| { m.name == n }) {
+        for trait_item in t.items.iter() {
+            let n = trait_item.item().name.clone();
+            match i.items.iter().find(|m| { m.name == n }) {
                 Some(..) => continue,
                 None => {}
             }
 
-            try!(docmeth(w, method.item(), false));
+            try!(doctraititem(w, trait_item.item(), false));
         }
         Ok(())
     }
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 cc5bc5cb7c170de7265e18f3ab14bc8ad234e937..eeccc3303ebfec7e000f307dc9c6744e65288062 100644 (file)
@@ -202,7 +202,7 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
                     clean::ModuleItem(ref m)
                         if m.items.len() == 0 &&
                            i.doc_value().is_none() => None,
-                    clean::ImplItem(ref i) if i.methods.len() == 0 => None,
+                    clean::ImplItem(ref i) if i.items.len() == 0 => None,
                     _ => {
                         self.retained.insert(i.def_id.node);
                         Some(i)
index 60db4fda05190098046ed477101d521a98276680..bbcf38f4955715604cb30f0bab593c41f09d5a52 100644 (file)
@@ -21,7 +21,7 @@
 use syntax::ast::Public;
 
 use clean::{Crate, Item, ModuleItem, Module, StructItem, Struct, EnumItem, Enum};
-use clean::{ImplItem, Impl, TraitItem, Trait, TraitMethod, Provided, Required};
+use clean::{ImplItem, Impl, Trait, TraitItem, ProvidedMethod, RequiredMethod};
 use clean::{ViewItemItem, PrimitiveItem};
 
 #[deriving(Zero, Encodable, Decodable, PartialEq, Eq)]
@@ -110,7 +110,7 @@ fn summarize_item(item: &Item) -> (Counts, Option<ModuleSummary>) {
     match item.inner {
         // Require explicit `pub` to be visible
         StructItem(Struct { fields: ref subitems, .. }) |
-        ImplItem(Impl { methods: ref subitems, trait_: None, .. }) => {
+        ImplItem(Impl { items: ref subitems, trait_: None, .. }) => {
             let subcounts = subitems.iter().filter(|i| visible(*i))
                                            .map(summarize_item)
                                            .map(|s| s.val0())
@@ -124,16 +124,21 @@ fn summarize_item(item: &Item) -> (Counts, Option<ModuleSummary>) {
                                            .sum();
             (item_counts + subcounts, None)
         }
-        TraitItem(Trait { methods: ref methods, .. }) => {
-            fn extract_item<'a>(meth: &'a TraitMethod) -> &'a Item {
-                match *meth {
-                    Provided(ref item) | Required(ref item) => item
+        TraitItem(Trait {
+            items: ref trait_items,
+            ..
+        }) => {
+            fn extract_item<'a>(trait_item: &'a TraitItem) -> &'a Item {
+                match *trait_item {
+                    ProvidedMethod(ref item) |
+                    RequiredMethod(ref item) => item
                 }
             }
-            let subcounts = methods.iter().map(extract_item)
-                                          .map(summarize_item)
-                                          .map(|s| s.val0())
-                                          .sum();
+            let subcounts = trait_items.iter()
+                                       .map(extract_item)
+                                       .map(summarize_item)
+                                       .map(|s| s.val0())
+                                       .sum();
             (item_counts + subcounts, None)
         }
         ModuleItem(Module { items: ref items, .. }) => {
index 5b2a542ca9664b308ab707eef25c843438e36c7f..f7ccad79fdacca21363733e102b0ecf8b4c5cbfe 100644 (file)
@@ -317,10 +317,10 @@ pub fn visit_item(&mut self, item: &ast::Item, om: &mut Module) {
                 };
                 om.statics.push(s);
             },
-            ast::ItemTrait(ref gen, _, ref tr, ref met) => {
+            ast::ItemTrait(ref gen, _, ref tr, ref items) => {
                 let t = Trait {
                     name: item.ident,
-                    methods: met.iter().map(|x| (*x).clone()).collect(),
+                    items: items.iter().map(|x| (*x).clone()).collect(),
                     generics: gen.clone(),
                     parents: tr.iter().map(|x| (*x).clone()).collect(),
                     id: item.id,
@@ -331,12 +331,12 @@ pub fn visit_item(&mut self, item: &ast::Item, om: &mut Module) {
                 };
                 om.traits.push(t);
             },
-            ast::ItemImpl(ref gen, ref tr, ty, ref meths) => {
+            ast::ItemImpl(ref gen, ref tr, ty, ref items) => {
                 let i = Impl {
                     generics: gen.clone(),
                     trait_: tr.clone(),
                     for_: ty,
-                    methods: meths.iter().map(|x| *x).collect(),
+                    items: items.iter().map(|x| *x).collect(),
                     attrs: item.attrs.iter().map(|x| *x).collect(),
                     id: item.id,
                     where: item.span,
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 c82b4831341ef05f785ba83fed563383a2a35a88..3dd4343c5f4fcd4070f05f720ec91f45ac0fc468 100644 (file)
@@ -976,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");
     })
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 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..e14fb8e3f5b0459f42e4d4cd8c6e06df5e788edc 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, UnboxedClosureKind, 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
@@ -755,9 +767,14 @@ pub struct TypeMethod {
 /// doesn't have an implementation, just a signature) or provided (meaning it
 /// has a default implementation).
 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
-pub enum TraitMethod {
-    Required(TypeMethod),
-    Provided(Gc<Method>),
+pub enum TraitItem {
+    RequiredMethod(TypeMethod),
+    ProvidedMethod(Gc<Method>),
+}
+
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
+pub enum ImplItem {
+    MethodImplItem(Gc<Method>),
 }
 
 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
@@ -888,6 +905,7 @@ pub struct BareFnTy {
 
 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub struct UnboxedFnTy {
+    pub kind: UnboxedClosureKind,
     pub decl: P<FnDecl>,
 }
 
@@ -1101,11 +1119,11 @@ pub fn id(&self) -> NodeId {
 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub enum ViewPath_ {
 
-    /// `quux = foo::bar::baz`
+    /// `foo::bar::baz as quux`
     ///
     /// or just
     ///
-    /// `foo::bar::baz ` (with 'baz =' implicitly on the left)
+    /// `foo::bar::baz` (with `as baz` implicitly on the right)
     ViewPathSimple(Ident, Path, NodeId),
 
     /// `foo::bar::*`
@@ -1260,11 +1278,11 @@ pub enum Item_ {
               Option<TyParamBound>, // (optional) default bound not required for Self.
                                     // Currently, only Sized makes sense here.
               Vec<TraitRef> ,
-              Vec<TraitMethod>),
+              Vec<TraitItem>),
     ItemImpl(Generics,
              Option<TraitRef>, // (optional) trait this impl implements
              P<Ty>, // self
-             Vec<Gc<Method>>),
+             Vec<ImplItem>),
     /// A macro invocation (which includes macro definition)
     ItemMac(Mac),
 }
@@ -1285,16 +1303,29 @@ pub enum ForeignItem_ {
     ForeignItemStatic(P<Ty>, /* is_mutbl */ bool),
 }
 
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
+pub enum UnboxedClosureKind {
+    FnUnboxedClosureKind,
+    FnMutUnboxedClosureKind,
+    FnOnceUnboxedClosureKind,
+}
+
 /// The data we save and restore about an inlined item or method.  This is not
 /// part of the AST that we parse from a file, but it becomes part of the tree
 /// that we trans.
 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub enum InlinedItem {
     IIItem(Gc<Item>),
-    IIMethod(DefId /* impl id */, bool /* is provided */, Gc<Method>),
+    IITraitItem(DefId /* impl id */, InlinedTraitItem),
     IIForeign(Gc<ForeignItem>),
 }
 
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
+pub enum InlinedTraitItem {
+    ProvidedInlinedTraitItem(Gc<Method>),
+    RequiredInlinedTraitItem(Gc<Method>),
+}
+
 #[cfg(test)]
 mod test {
     use serialize::json;
index a522f80554327f89a297c2c6107c821923cad6bb..b00c6ce14b5b85f58dfdc9d225b4e8b0c34e89a5 100644 (file)
@@ -60,9 +60,9 @@ fn is_fn_like(&self) -> bool {
     }
 }
 
-impl MaybeFnLike for ast::TraitMethod {
+impl MaybeFnLike for ast::TraitItem {
     fn is_fn_like(&self) -> bool {
-        match *self { ast::Provided(_) => true, _ => false, }
+        match *self { ast::ProvidedMethod(_) => true, _ => false, }
     }
 }
 
@@ -97,9 +97,9 @@ fn new(node: Node) -> FnLikeNode { FnLikeNode { node: node } }
         match node {
             ast_map::NodeItem(item) if item.is_fn_like() =>
                 Some(FnLikeCode(new(node))),
-            ast_map::NodeTraitMethod(tm) if tm.is_fn_like() =>
+            ast_map::NodeTraitItem(tm) if tm.is_fn_like() =>
                 Some(FnLikeCode(new(node))),
-            ast_map::NodeMethod(_) =>
+            ast_map::NodeImplItem(_) =>
                 Some(FnLikeCode(new(node))),
             ast_map::NodeExpr(e) if e.is_fn_like() =>
                 Some(FnLikeCode(new(node))),
@@ -200,13 +200,17 @@ fn handle<'a, A>(&'a self,
                     }),
                 _ => fail!("item FnLikeNode that is not fn-like"),
             },
-            ast_map::NodeTraitMethod(ref t) => match **t {
-                ast::Provided(ref m) => method(&**m),
+            ast_map::NodeTraitItem(ref t) => match **t {
+                ast::ProvidedMethod(ref m) => method(&**m),
                 _ => fail!("trait method FnLikeNode that is not fn-like"),
             },
-            ast_map::NodeMethod(ref m) => method(&**m),
+            ast_map::NodeImplItem(ref ii) => {
+                match **ii {
+                    ast::MethodImplItem(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 881ee4fd8d13e664d5ebbfcaa317fb4fcd4f56c9..78afa8441c5f3e265cbb9268f48ac1aecf1757b9 100644 (file)
@@ -99,8 +99,8 @@ pub fn path_to_string<PI: Iterator<PathElem>>(mut path: PI) -> String {
 pub enum Node {
     NodeItem(Gc<Item>),
     NodeForeignItem(Gc<ForeignItem>),
-    NodeTraitMethod(Gc<TraitMethod>),
-    NodeMethod(Gc<Method>),
+    NodeTraitItem(Gc<TraitItem>),
+    NodeImplItem(Gc<ImplItem>),
     NodeVariant(P<Variant>),
     NodeExpr(Gc<Expr>),
     NodeStmt(Gc<Stmt>),
@@ -125,8 +125,8 @@ enum MapEntry {
     /// All the node types, with a parent ID.
     EntryItem(NodeId, Gc<Item>),
     EntryForeignItem(NodeId, Gc<ForeignItem>),
-    EntryTraitMethod(NodeId, Gc<TraitMethod>),
-    EntryMethod(NodeId, Gc<Method>),
+    EntryTraitItem(NodeId, Gc<TraitItem>),
+    EntryImplItem(NodeId, Gc<ImplItem>),
     EntryVariant(NodeId, P<Variant>),
     EntryExpr(NodeId, Gc<Expr>),
     EntryStmt(NodeId, Gc<Stmt>),
@@ -144,7 +144,7 @@ enum MapEntry {
 
 struct InlinedParent {
     path: Vec<PathElem> ,
-    /// Required by NodeTraitMethod and NodeMethod.
+    /// RequiredMethod by NodeTraitItem and NodeImplItem.
     def_id: DefId
 }
 
@@ -153,8 +153,8 @@ fn parent(&self) -> Option<NodeId> {
         Some(match *self {
             EntryItem(id, _) => id,
             EntryForeignItem(id, _) => id,
-            EntryTraitMethod(id, _) => id,
-            EntryMethod(id, _) => id,
+            EntryTraitItem(id, _) => id,
+            EntryImplItem(id, _) => id,
             EntryVariant(id, _) => id,
             EntryExpr(id, _) => id,
             EntryStmt(id, _) => id,
@@ -172,8 +172,8 @@ fn to_node(&self) -> Option<Node> {
         Some(match *self {
             EntryItem(_, p) => NodeItem(p),
             EntryForeignItem(_, p) => NodeForeignItem(p),
-            EntryTraitMethod(_, p) => NodeTraitMethod(p),
-            EntryMethod(_, p) => NodeMethod(p),
+            EntryTraitItem(_, p) => NodeTraitItem(p),
+            EntryImplItem(_, p) => NodeImplItem(p),
             EntryVariant(_, p) => NodeVariant(p),
             EntryExpr(_, p) => NodeExpr(p),
             EntryStmt(_, p) => NodeStmt(p),
@@ -324,13 +324,23 @@ pub fn get_path_elem(&self, id: NodeId) -> PathElem {
                 }
             }
             NodeForeignItem(i) => PathName(i.ident.name),
-            NodeMethod(m) => match m.node {
-                MethDecl(ident, _, _, _, _, _, _, _) => PathName(ident.name),
-                MethMac(_) => fail!("no path elem for {:?}", node)
+            NodeImplItem(ii) => {
+                match *ii {
+                    MethodImplItem(ref m) => {
+                        match m.node {
+                            MethDecl(ident, _, _, _, _, _, _, _) => {
+                                PathName(ident.name)
+                            }
+                            MethMac(_) => {
+                                fail!("no path elem for {:?}", node)
+                            }
+                        }
+                    }
+                }
             },
-            NodeTraitMethod(tm) => match *tm {
-                Required(ref m) => PathName(m.ident.name),
-                Provided(m) => match m.node {
+            NodeTraitItem(tm) => match *tm {
+                RequiredMethod(ref m) => PathName(m.ident.name),
+                ProvidedMethod(m) => match m.node {
                     MethDecl(ident, _, _, _, _, _, _, _) => {
                         PathName(ident.name)
                     }
@@ -393,11 +403,15 @@ pub fn with_attrs<T>(&self, id: NodeId, f: |Option<&[Attribute]>| -> T) -> T {
         let attrs = match node {
             NodeItem(ref i) => Some(i.attrs.as_slice()),
             NodeForeignItem(ref fi) => Some(fi.attrs.as_slice()),
-            NodeTraitMethod(ref tm) => match **tm {
-                Required(ref type_m) => Some(type_m.attrs.as_slice()),
-                Provided(ref m) => Some(m.attrs.as_slice())
+            NodeTraitItem(ref tm) => match **tm {
+                RequiredMethod(ref type_m) => Some(type_m.attrs.as_slice()),
+                ProvidedMethod(ref m) => Some(m.attrs.as_slice())
             },
-            NodeMethod(ref m) => Some(m.attrs.as_slice()),
+            NodeImplItem(ref ii) => {
+                match **ii {
+                    MethodImplItem(ref m) => Some(m.attrs.as_slice()),
+                }
+            }
             NodeVariant(ref v) => Some(v.node.attrs.as_slice()),
             // unit/tuple structs take the attributes straight from
             // the struct definition.
@@ -428,13 +442,17 @@ pub fn opt_span(&self, id: NodeId) -> Option<Span> {
         let sp = match self.find(id) {
             Some(NodeItem(item)) => item.span,
             Some(NodeForeignItem(foreign_item)) => foreign_item.span,
-            Some(NodeTraitMethod(trait_method)) => {
+            Some(NodeTraitItem(trait_method)) => {
                 match *trait_method {
-                    Required(ref type_method) => type_method.span,
-                    Provided(ref method) => method.span,
+                    RequiredMethod(ref type_method) => type_method.span,
+                    ProvidedMethod(ref method) => method.span,
+                }
+            }
+            Some(NodeImplItem(ref impl_item)) => {
+                match **impl_item {
+                    MethodImplItem(ref method) => method.span,
                 }
             }
-            Some(NodeMethod(method)) => method.span,
             Some(NodeVariant(variant)) => variant.span,
             Some(NodeExpr(expr)) => expr.span,
             Some(NodeStmt(stmt)) => stmt.span,
@@ -532,8 +550,8 @@ fn next(&mut self) -> Option<NodeId> {
             let (p, name) = match self.map.find_entry(idx) {
                 Some(EntryItem(p, n))        => (p, n.name()),
                 Some(EntryForeignItem(p, n)) => (p, n.name()),
-                Some(EntryTraitMethod(p, n)) => (p, n.name()),
-                Some(EntryMethod(p, n))      => (p, n.name()),
+                Some(EntryTraitItem(p, n))   => (p, n.name()),
+                Some(EntryImplItem(p, n))    => (p, n.name()),
                 Some(EntryVariant(p, n))     => (p, n.name()),
                 _ => continue,
             };
@@ -553,11 +571,18 @@ impl<T:Named> Named for Spanned<T> { fn name(&self) -> Name { self.node.name() }
 impl Named for Item { fn name(&self) -> Name { self.ident.name } }
 impl Named for ForeignItem { fn name(&self) -> Name { self.ident.name } }
 impl Named for Variant_ { fn name(&self) -> Name { self.name.name } }
-impl Named for TraitMethod {
+impl Named for TraitItem {
+    fn name(&self) -> Name {
+        match *self {
+            RequiredMethod(ref tm) => tm.ident.name,
+            ProvidedMethod(m) => m.name(),
+        }
+    }
+}
+impl Named for ImplItem {
     fn name(&self) -> Name {
         match *self {
-            Required(ref tm) => tm.ident.name,
-            Provided(m) => m.name(),
+            MethodImplItem(ref m) => m.name(),
         }
     }
 }
@@ -616,9 +641,15 @@ fn fold_item(&mut self, i: Gc<Item>) -> SmallVector<Gc<Item>> {
         assert_eq!(self.parent, i.id);
 
         match i.node {
-            ItemImpl(_, _, _, ref ms) => {
-                for &m in ms.iter() {
-                    self.insert(m.id, EntryMethod(self.parent, m));
+            ItemImpl(_, _, _, ref impl_items) => {
+                for impl_item in impl_items.iter() {
+                    match *impl_item {
+                        MethodImplItem(m) => {
+                            self.insert(m.id,
+                                        EntryImplItem(self.parent,
+                                                      box(GC) *impl_item));
+                        }
+                    }
                 }
             }
             ItemEnum(ref enum_definition, _) => {
@@ -649,13 +680,13 @@ fn fold_item(&mut self, i: Gc<Item>) -> SmallVector<Gc<Item>> {
 
                 for tm in methods.iter() {
                     match *tm {
-                        Required(ref m) => {
-                            self.insert(m.id, EntryTraitMethod(self.parent,
+                        RequiredMethod(ref m) => {
+                            self.insert(m.id, EntryTraitItem(self.parent,
                                                                box(GC) (*tm).clone()));
                         }
-                        Provided(m) => {
-                            self.insert(m.id, EntryTraitMethod(self.parent,
-                                                               box(GC) Provided(m)));
+                        ProvidedMethod(m) => {
+                            self.insert(m.id, EntryTraitItem(self.parent,
+                                                               box(GC) ProvidedMethod(m)));
                         }
                     }
                 }
@@ -798,13 +829,18 @@ pub fn map_decoded_item<F: FoldOps>(map: &Map,
     let ii = fold(&mut cx);
     match ii {
         IIItem(_) => {}
-        IIMethod(impl_did, is_provided, m) => {
-            let entry = if is_provided {
-                EntryTraitMethod(cx.parent, box(GC) Provided(m))
-            } else {
-                EntryMethod(cx.parent, m)
+        IITraitItem(impl_did, inlined_trait_item) => {
+            let (trait_item_id, entry) = match inlined_trait_item {
+                ProvidedInlinedTraitItem(m) => {
+                    (m.id,
+                     EntryTraitItem(cx.parent, box(GC) ProvidedMethod(m)))
+                }
+                RequiredInlinedTraitItem(m) => {
+                    (m.id,
+                     EntryImplItem(cx.parent, box(GC) MethodImplItem(m)))
+                }
             };
-            cx.insert(m.id, entry);
+            cx.insert(trait_item_id, entry);
             def_id = impl_did;
         }
         IIForeign(i) => {
@@ -829,8 +865,8 @@ fn print_node(&mut self, node: &Node) -> IoResult<()> {
         match *node {
             NodeItem(a)        => self.print_item(&*a),
             NodeForeignItem(a) => self.print_foreign_item(&*a),
-            NodeTraitMethod(a) => self.print_trait_method(&*a),
-            NodeMethod(a)      => self.print_method(&*a),
+            NodeTraitItem(a)   => self.print_trait_method(&*a),
+            NodeImplItem(a)    => self.print_impl_item(&*a),
             NodeVariant(a)     => self.print_variant(&*a),
             NodeExpr(a)        => self.print_expr(&*a),
             NodeStmt(a)        => self.print_stmt(&*a),
@@ -870,17 +906,23 @@ fn node_id_to_string(map: &Map, id: NodeId) -> String {
             let path_str = map.path_to_str_with_ident(id, item.ident);
             format!("foreign item {} (id={})", path_str, id)
         }
-        Some(NodeMethod(m)) => match m.node {
-            MethDecl(ident, _, _, _, _, _, _, _) =>
-                format!("method {} in {} (id={})",
-                        token::get_ident(ident),
-                        map.path_to_string(id), id),
-            MethMac(ref mac) =>
-                format!("method macro {} (id={})",
-                        pprust::mac_to_string(mac), id)
-        },
-        Some(NodeTraitMethod(ref tm)) => {
-            let m = ast_util::trait_method_to_ty_method(&**tm);
+        Some(NodeImplItem(ref ii)) => {
+            match **ii {
+                MethodImplItem(ref m) => {
+                    match m.node {
+                        MethDecl(ident, _, _, _, _, _, _, _) =>
+                            format!("method {} in {} (id={})",
+                                    token::get_ident(ident),
+                                    map.path_to_string(id), id),
+                        MethMac(ref mac) =>
+                            format!("method macro {} (id={})",
+                                    pprust::mac_to_string(mac), id)
+                    }
+                }
+            }
+        }
+        Some(NodeTraitItem(ref tm)) => {
+            let m = ast_util::trait_item_to_ty_method(&**tm);
             format!("method {} in {} (id={})",
                     token::get_ident(m.ident),
                     map.path_to_string(id), id)
index cf2b5bc406373759a5376b8cb71668cb8f89b587..7689646d373c4027de875a3f901c775ea6f84f65 100644 (file)
@@ -241,51 +241,52 @@ pub fn impl_pretty_name(trait_ref: &Option<TraitRef>, ty: &Ty) -> Ident {
     token::gensym_ident(pretty.as_slice())
 }
 
-/// extract a TypeMethod from a TraitMethod. if the TraitMethod is
+pub fn trait_method_to_ty_method(method: &Method) -> TypeMethod {
+    match method.node {
+        MethDecl(ident,
+                 ref generics,
+                 abi,
+                 explicit_self,
+                 fn_style,
+                 decl,
+                 _,
+                 vis) => {
+            TypeMethod {
+                ident: ident,
+                attrs: method.attrs.clone(),
+                fn_style: fn_style,
+                decl: decl,
+                generics: generics.clone(),
+                explicit_self: explicit_self,
+                id: method.id,
+                span: method.span,
+                vis: vis,
+                abi: abi,
+            }
+        },
+        MethMac(_) => fail!("expected non-macro method declaration")
+    }
+}
+
+/// extract a TypeMethod from a TraitItem. if the TraitItem is
 /// a default, pull out the useful fields to make a TypeMethod
 //
 // NB: to be used only after expansion is complete, and macros are gone.
-pub fn trait_method_to_ty_method(method: &TraitMethod) -> TypeMethod {
+pub fn trait_item_to_ty_method(method: &TraitItem) -> TypeMethod {
     match *method {
-        Required(ref m) => (*m).clone(),
-        Provided(m) => {
-            match m.node {
-                MethDecl(ident,
-                         ref generics,
-                         abi,
-                         explicit_self,
-                         fn_style,
-                         decl,
-                         _,
-                         vis) => {
-                    TypeMethod {
-                        ident: ident,
-                        attrs: m.attrs.clone(),
-                        fn_style: fn_style,
-                        decl: decl,
-                        generics: generics.clone(),
-                        explicit_self: explicit_self,
-                        id: m.id,
-                        span: m.span,
-                        vis: vis,
-                        abi: abi,
-                    }
-                },
-                MethMac(_) => fail!("expected non-macro method declaration")
-            }
-
-        }
+        RequiredMethod(ref m) => (*m).clone(),
+        ProvidedMethod(ref m) => trait_method_to_ty_method(&**m),
     }
 }
 
-pub fn split_trait_methods(trait_methods: &[TraitMethod])
+pub fn split_trait_methods(trait_methods: &[TraitItem])
     -> (Vec<TypeMethod> , Vec<Gc<Method>> ) {
     let mut reqd = Vec::new();
     let mut provd = Vec::new();
     for trt_method in trait_methods.iter() {
         match *trt_method {
-            Required(ref tm) => reqd.push((*tm).clone()),
-            Provided(m) => provd.push(m)
+            RequiredMethod(ref tm) => reqd.push((*tm).clone()),
+            ProvidedMethod(m) => provd.push(m)
         }
     };
     (reqd, provd)
@@ -543,12 +544,12 @@ fn visit_struct_def(&mut self,
         visit::walk_struct_def(self, struct_def, ());
     }
 
-    fn visit_trait_method(&mut self, tm: &ast::TraitMethod, _: ()) {
+    fn visit_trait_item(&mut self, tm: &ast::TraitItem, _: ()) {
         match *tm {
-            ast::Required(ref m) => self.operation.visit_id(m.id),
-            ast::Provided(ref m) => self.operation.visit_id(m.id),
+            ast::RequiredMethod(ref m) => self.operation.visit_id(m.id),
+            ast::ProvidedMethod(ref m) => self.operation.visit_id(m.id),
         }
-        visit::walk_trait_method(self, tm, ());
+        visit::walk_trait_item(self, tm, ());
     }
 }
 
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 5842ca4a0d54d05ecb22af4396f22771aa16e260..7a8ee6d1416834b2be06f6045af0d86cb163f3a9 100644 (file)
@@ -452,8 +452,13 @@ fn create_derived_impl(&self,
             self.span,
             ident,
             (vec!(attr)).append(self.attributes.as_slice()),
-            ast::ItemImpl(trait_generics, opt_trait_ref,
-                          self_type, methods))
+            ast::ItemImpl(trait_generics,
+                          opt_trait_ref,
+                          self_type,
+                          methods.move_iter()
+                                 .map(|method| {
+                                     ast::MethodImplItem(method)
+                                 }).collect()))
     }
 
     fn expand_struct_def(&self,
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..4ed2a3ed4c2b0cd8304c059daabb28810a3a2e47 100644 (file)
@@ -368,6 +368,7 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
         TyUnboxedFn(ref f) => {
             TyUnboxedFn(box(GC) UnboxedFnTy {
                 decl: fld.fold_fn_decl(&*f.decl),
+                kind: f.kind,
             })
         }
         TyTup(ref tys) => TyTup(tys.iter().map(|&ty| fld.fold_ty(ty)).collect()),
@@ -641,6 +642,7 @@ pub fn noop_fold_ty_param_bound<T: Folder>(tpb: &TyParamBound, fld: &mut T)
         UnboxedFnTyParamBound(ref unboxed_function_type) => {
             UnboxedFnTyParamBound(UnboxedFnTy {
                 decl: fld.fold_fn_decl(&*unboxed_function_type.decl),
+                kind: unboxed_function_type.kind,
             })
         }
         OtherRegionTyParamBound(s) => OtherRegionTyParamBound(s)
@@ -832,26 +834,37 @@ pub fn noop_fold_item_underscore<T: Folder>(i: &Item_, folder: &mut T) -> Item_
             let struct_def = folder.fold_struct_def(*struct_def);
             ItemStruct(struct_def, folder.fold_generics(generics))
         }
-        ItemImpl(ref generics, ref ifce, ty, ref methods) => {
+        ItemImpl(ref generics, ref ifce, ty, ref impl_items) => {
             ItemImpl(folder.fold_generics(generics),
                      ifce.as_ref().map(|p| folder.fold_trait_ref(p)),
                      folder.fold_ty(ty),
-                     methods.iter().flat_map(|x| folder.fold_method(*x).move_iter()).collect()
+                     impl_items.iter()
+                               .flat_map(|impl_item| {
+                                    match *impl_item {
+                                        MethodImplItem(x) => {
+                                            folder.fold_method(x)
+                                                  .move_iter()
+                                                  .map(|x| MethodImplItem(x))
+                                        }
+                                    }
+                               }).collect()
             )
         }
         ItemTrait(ref generics, ref unbound, ref traits, ref methods) => {
             let methods = methods.iter().flat_map(|method| {
                 let r = match *method {
-                    Required(ref m) =>
-                            SmallVector::one(Required(folder.fold_type_method(m))).move_iter(),
-                    Provided(method) => {
+                    RequiredMethod(ref m) => {
+                            SmallVector::one(RequiredMethod(
+                                    folder.fold_type_method(m))).move_iter()
+                    }
+                    ProvidedMethod(method) => {
                             // the awkward collect/iter idiom here is because
                             // even though an iter and a map satisfy the same trait bound,
                             // they're not actually the same type, so the method arms
                             // don't unify.
-                            let methods : SmallVector<ast::TraitMethod> =
+                            let methods : SmallVector<ast::TraitItem> =
                                 folder.fold_method(method).move_iter()
-                                .map(|m| Provided(m)).collect();
+                                .map(|m| ProvidedMethod(m)).collect();
                             methods.move_iter()
                         }
                 };
@@ -1094,16 +1107,19 @@ 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, kind, ref decl, ref body) => {
+            ExprUnboxedFn(capture_clause,
+                          kind,
+                          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 08d96f5b0086d590dd2b0aae2999df4d35a987a1..8c448b5a0b0f4555ba4e607baf7d04e31dd7185a 100644 (file)
 use abi;
 use ast::{BareFnTy, ClosureTy};
 use ast::{StaticRegionTyParamBound, OtherRegionTyParamBound, TraitTyParamBound};
-use ast::{Provided, Public, FnStyle};
+use ast::{ProvidedMethod, Public, FnStyle};
 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};
 use ast::{ExprVec, ExprVstore, ExprVstoreSlice};
 use ast::{ExprVstoreMutSlice, ExprWhile, ExprForLoop, Field, FnDecl};
 use ast::{ExprVstoreUniq, Once, Many};
+use ast::{FnUnboxedClosureKind, FnMutUnboxedClosureKind};
+use ast::{FnOnceUnboxedClosureKind};
 use ast::{ForeignItem, ForeignItemStatic, ForeignItemFn, ForeignMod};
-use ast::{Ident, NormalFn, Inherited, Item, Item_, ItemStatic};
+use ast::{Ident, NormalFn, Inherited, ImplItem, Item, Item_, ItemStatic};
 use ast::{ItemEnum, ItemFn, ItemForeignMod, ItemImpl};
 use ast::{ItemMac, ItemMod, ItemStruct, ItemTrait, ItemTy, Lit, Lit_};
 use ast::{LitBool, LitChar, LitByte, LitBinary};
 use ast::{LitNil, LitStr, LitInt, Local, LocalLet};
 use ast::{MutImmutable, MutMutable, Mac_, MacInvocTT, Matcher, MatchNonterminal};
 use ast::{MatchSeq, MatchTok, Method, MutTy, BiMul, Mutability};
+use ast::{MethodImplItem};
 use ast::{NamedField, UnNeg, NoReturn, UnNot, P, Pat, PatEnum};
 use ast::{PatIdent, PatLit, PatRange, PatRegion, PatStruct};
 use ast::{PatTup, PatBox, PatWild, PatWildMulti, PatWildSingle};
-use ast::{BiRem, Required};
+use ast::{BiRem, RequiredMethod};
 use ast::{RetStyle, Return, BiShl, BiShr, Stmt, StmtDecl};
 use ast::{StmtExpr, StmtSemi, StmtMac, StructDef, StructField};
 use ast::{StructVariantKind, BiSub};
 use ast::StrStyle;
 use ast::{SelfExplicit, SelfRegion, SelfStatic, SelfValue};
-use ast::{TokenTree, TraitMethod, TraitRef, TTDelim, TTSeq, TTTok};
+use ast::{TokenTree, TraitItem, TraitRef, TTDelim, TTSeq, TTTok};
 use ast::{TTNonterminal, TupleVariantKind, Ty, Ty_, TyBot, TyBox};
 use ast::{TypeField, TyFixedLengthVec, TyClosure, TyProc, TyBareFn};
 use ast::{TyTypeof, TyInfer, TypeMethod};
 use ast::{TyNil, TyParam, TyParamBound, TyParen, TyPath, TyPtr, TyRptr};
 use ast::{TyTup, TyU32, TyUnboxedFn, TyUniq, TyVec, UnUniq};
-use ast::{UnboxedFnTy, UnboxedFnTyParamBound, UnnamedField, UnsafeBlock};
+use ast::{UnboxedClosureKind, UnboxedFnTy, UnboxedFnTyParamBound};
+use ast::{UnnamedField, UnsafeBlock};
 use ast::{UnsafeFn, ViewItem, ViewItem_, ViewItemExternCrate, ViewItemUse};
 use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple};
 use ast::Visibility;
@@ -1086,6 +1091,34 @@ pub fn parse_proc_type(&mut self) -> Ty_ {
         })
     }
 
+    /// Parses an optional unboxed closure kind (`&:`, `&mut:`, or `:`).
+    pub fn parse_optional_unboxed_closure_kind(&mut self)
+                                               -> Option<UnboxedClosureKind> {
+        if self.token == token::BINOP(token::AND) &&
+                    self.look_ahead(1, |t| {
+                        token::is_keyword(keywords::Mut, t)
+                    }) &&
+                    self.look_ahead(2, |t| *t == token::COLON) {
+            self.bump();
+            self.bump();
+            self.bump();
+            return Some(FnMutUnboxedClosureKind)
+        }
+
+        if self.token == token::BINOP(token::AND) &&
+                    self.look_ahead(1, |t| *t == token::COLON) {
+            self.bump();
+            self.bump();
+            return Some(FnUnboxedClosureKind)
+        }
+
+        if self.eat(&token::COLON) {
+            return Some(FnOnceUnboxedClosureKind)
+        }
+
+        return None
+    }
+
     /// Parse a TyClosure type
     pub fn parse_ty_closure(&mut self) -> Ty_ {
         /*
@@ -1114,27 +1147,19 @@ pub fn parse_ty_closure(&mut self) -> Ty_ {
             Vec::new()
         };
 
-        let (is_unboxed, inputs) = if self.eat(&token::OROR) {
-            (false, Vec::new())
+        let (optional_unboxed_closure_kind, inputs) = if self.eat(&token::OROR) {
+            (None, Vec::new())
         } else {
             self.expect_or();
 
-            let is_unboxed = self.token == token::BINOP(token::AND) &&
-                self.look_ahead(1, |t| {
-                    token::is_keyword(keywords::Mut, t)
-                }) &&
-                self.look_ahead(2, |t| *t == token::COLON);
-            if is_unboxed {
-                self.bump();
-                self.bump();
-                self.bump();
-            }
+            let optional_unboxed_closure_kind =
+                self.parse_optional_unboxed_closure_kind();
 
             let inputs = self.parse_seq_to_before_or(
                 &token::COMMA,
                 |p| p.parse_arg_general(false));
             self.expect_or();
-            (is_unboxed, inputs)
+            (optional_unboxed_closure_kind, inputs)
         };
 
         let (region, bounds) = {
@@ -1154,18 +1179,22 @@ pub fn parse_ty_closure(&mut self) -> Ty_ {
             variadic: false
         });
 
-        if is_unboxed {
-            TyUnboxedFn(box(GC) UnboxedFnTy {
-                decl: decl,
-            })
-        } else {
-            TyClosure(box(GC) ClosureTy {
-                fn_style: fn_style,
-                onceness: onceness,
-                bounds: bounds,
-                decl: decl,
-                lifetimes: lifetime_defs,
-            }, region)
+        match optional_unboxed_closure_kind {
+            Some(unboxed_closure_kind) => {
+                TyUnboxedFn(box(GC) UnboxedFnTy {
+                    kind: unboxed_closure_kind,
+                    decl: decl,
+                })
+            }
+            None => {
+                TyClosure(box(GC) ClosureTy {
+                    fn_style: fn_style,
+                    onceness: onceness,
+                    bounds: bounds,
+                    decl: decl,
+                    lifetimes: lifetime_defs,
+                }, region)
+            }
         }
     }
 
@@ -1210,7 +1239,7 @@ pub fn parse_ty_fn_decl(&mut self, allow_variadic: bool)
     }
 
     /// Parse the methods in a trait declaration
-    pub fn parse_trait_methods(&mut self) -> Vec<TraitMethod> {
+    pub fn parse_trait_methods(&mut self) -> Vec<TraitItem> {
         self.parse_unspanned_seq(
             &token::LBRACE,
             &token::RBRACE,
@@ -1248,7 +1277,7 @@ pub fn parse_trait_methods(&mut self) -> Vec<TraitMethod> {
               token::SEMI => {
                 p.bump();
                 debug!("parse_trait_methods(): parsing required method");
-                Required(TypeMethod {
+                RequiredMethod(TypeMethod {
                     ident: ident,
                     attrs: attrs,
                     fn_style: style,
@@ -1266,7 +1295,7 @@ pub fn parse_trait_methods(&mut self) -> Vec<TraitMethod> {
                 let (inner_attrs, body) =
                     p.parse_inner_attrs_and_block();
                 let attrs = attrs.append(inner_attrs.as_slice());
-                Provided(box(GC) ast::Method {
+                ProvidedMethod(box(GC) ast::Method {
                     attrs: attrs,
                     id: ast::DUMMY_NODE_ID,
                     span: mk_sp(lo, hi),
@@ -1985,7 +2014,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 +2065,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,9 +2728,11 @@ 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 (decl, optional_unboxed_closure_kind) =
+            self.parse_fn_block_decl();
         let body = self.parse_expr();
         let fakeblock = P(ast::Block {
             view_items: Vec::new(),
@@ -2709,10 +2743,20 @@ pub fn parse_lambda_expr(&mut self) -> Gc<Expr> {
             span: body.span,
         });
 
-        if is_unboxed {
-            self.mk_expr(lo, body.span.hi, ExprUnboxedFn(decl, fakeblock))
-        } else {
-            self.mk_expr(lo, body.span.hi, ExprFnBlock(decl, fakeblock))
+        match optional_unboxed_closure_kind {
+            Some(unboxed_closure_kind) => {
+                self.mk_expr(lo,
+                             body.span.hi,
+                             ExprUnboxedFn(capture_clause,
+                                           unboxed_closure_kind,
+                                           decl,
+                                           fakeblock))
+            }
+            None => {
+                self.mk_expr(lo,
+                             body.span.hi,
+                             ExprFnBlock(capture_clause, decl, fakeblock))
+            }
         }
     }
 
@@ -3544,28 +3588,22 @@ fn parse_block_tail_(&mut self, lo: BytePos, s: BlockCheckMode,
     }
 
     fn parse_unboxed_function_type(&mut self) -> UnboxedFnTy {
-        let inputs = if self.eat(&token::OROR) {
-            Vec::new()
-        } else {
-            self.expect_or();
+        let (optional_unboxed_closure_kind, inputs) =
+            if self.eat(&token::OROR) {
+                (None, Vec::new())
+            } else {
+                self.expect_or();
 
-            if self.token == token::BINOP(token::AND) &&
-                    self.look_ahead(1, |t| {
-                        token::is_keyword(keywords::Mut, t)
-                    }) &&
-                    self.look_ahead(2, |t| *t == token::COLON) {
-                self.bump();
-                self.bump();
-                self.bump();
-            }
+                let optional_unboxed_closure_kind =
+                    self.parse_optional_unboxed_closure_kind();
 
-            let inputs = self.parse_seq_to_before_or(&token::COMMA,
-                                                     |p| {
-                p.parse_arg_general(false)
-            });
-            self.expect_or();
-            inputs
-        };
+                let inputs = self.parse_seq_to_before_or(&token::COMMA,
+                                                         |p| {
+                    p.parse_arg_general(false)
+                });
+                self.expect_or();
+                (optional_unboxed_closure_kind, inputs)
+            };
 
         let (return_style, output) = self.parse_ret_ty();
         UnboxedFnTy {
@@ -3574,7 +3612,11 @@ fn parse_unboxed_function_type(&mut self) -> UnboxedFnTy {
                 output: output,
                 cf: return_style,
                 variadic: false,
-            })
+            }),
+            kind: match optional_unboxed_closure_kind {
+                Some(kind) => kind,
+                None => FnMutUnboxedClosureKind,
+            },
         }
     }
 
@@ -4017,29 +4059,22 @@ macro_rules! parse_remaining_arguments {
     }
 
     // parse the |arg, arg| header on a lambda
-    fn parse_fn_block_decl(&mut self) -> (P<FnDecl>, bool) {
-        let (is_unboxed, inputs_captures) = {
+    fn parse_fn_block_decl(&mut self)
+                           -> (P<FnDecl>, Option<UnboxedClosureKind>) {
+        let (optional_unboxed_closure_kind, inputs_captures) = {
             if self.eat(&token::OROR) {
-                (false, Vec::new())
+                (None, Vec::new())
             } else {
                 self.expect(&token::BINOP(token::OR));
-                let is_unboxed = self.token == token::BINOP(token::AND) &&
-                    self.look_ahead(1, |t| {
-                        token::is_keyword(keywords::Mut, t)
-                    }) &&
-                    self.look_ahead(2, |t| *t == token::COLON);
-                if is_unboxed {
-                    self.bump();
-                    self.bump();
-                    self.bump();
-                }
+                let optional_unboxed_closure_kind =
+                    self.parse_optional_unboxed_closure_kind();
                 let args = self.parse_seq_to_before_end(
                     &token::BINOP(token::OR),
                     seq_sep_trailing_disallowed(token::COMMA),
                     |p| p.parse_fn_block_arg()
                 );
                 self.bump();
-                (is_unboxed, args)
+                (optional_unboxed_closure_kind, args)
             }
         };
         let output = if self.eat(&token::RARROW) {
@@ -4057,7 +4092,7 @@ fn parse_fn_block_decl(&mut self) -> (P<FnDecl>, bool) {
             output: output,
             cf: Return,
             variadic: false
-        }), is_unboxed)
+        }), optional_unboxed_closure_kind)
     }
 
     /// Parses the `(arg, arg) -> return_type` header on a procedure.
@@ -4209,6 +4244,18 @@ fn parse_item_trait(&mut self) -> ItemInfo {
         (ident, ItemTrait(tps, sized, traits, meths), None)
     }
 
+    fn parse_impl_items(&mut self) -> (Vec<ImplItem>, Vec<Attribute>) {
+        let mut impl_items = Vec::new();
+        self.expect(&token::LBRACE);
+        let (inner_attrs, next) = self.parse_inner_attrs_and_next();
+        let mut method_attrs = Some(next);
+        while !self.eat(&token::RBRACE) {
+            impl_items.push(MethodImplItem(self.parse_method(method_attrs)));
+            method_attrs = None;
+        }
+        (impl_items, inner_attrs)
+    }
+
     /// Parses two variants (with the region/type params always optional):
     ///    impl<T> Foo { ... }
     ///    impl<T> ToString for ~[T] { ... }
@@ -4250,18 +4297,13 @@ fn parse_item_impl(&mut self) -> ItemInfo {
             None
         };
 
-        let mut meths = Vec::new();
-        self.expect(&token::LBRACE);
-        let (inner_attrs, next) = self.parse_inner_attrs_and_next();
-        let mut method_attrs = Some(next);
-        while !self.eat(&token::RBRACE) {
-            meths.push(self.parse_method(method_attrs));
-            method_attrs = None;
-        }
+        let (impl_items, attrs) = self.parse_impl_items();
 
         let ident = ast_util::impl_pretty_name(&opt_trait, &*ty);
 
-        (ident, ItemImpl(generics, opt_trait, ty, meths), Some(inner_attrs))
+        (ident,
+         ItemImpl(generics, opt_trait, ty, impl_items),
+         Some(attrs))
     }
 
     /// Parse a::B<String,int>
@@ -5275,6 +5317,7 @@ fn parse_view_path(&mut self) -> Gc<ViewPath> {
         match self.token {
           token::EQ => {
             // x = foo::bar
+            // NOTE(stage0, #16461, pcwalton): Deprecate after snapshot.
             self.bump();
             let path_lo = self.span.lo;
             path = vec!(self.parse_ident());
@@ -5357,7 +5400,7 @@ fn parse_view_path(&mut self) -> Gc<ViewPath> {
           }
           _ => ()
         }
-        let last = *path.get(path.len() - 1u);
+        let mut rename_to = *path.get(path.len() - 1u);
         let path = ast::Path {
             span: mk_sp(lo, self.span.hi),
             global: false,
@@ -5369,9 +5412,12 @@ fn parse_view_path(&mut self) -> Gc<ViewPath> {
                 }
             }).collect()
         };
+        if self.eat_keyword(keywords::As) {
+            rename_to = self.parse_ident()
+        }
         return box(GC) spanned(lo,
                         self.last_span.hi,
-                        ViewPathSimple(last, path, ast::DUMMY_NODE_ID));
+                        ViewPathSimple(rename_to, path, ast::DUMMY_NODE_ID));
     }
 
     /// Parses a sequence of items. Stops when it finds program
index 9d4b7343c8a156fa63e039549773934a59199a8e..be2467d588ccbc9b028ece32cd11405abf752b87 100644 (file)
@@ -9,8 +9,10 @@
 // except according to those terms.
 
 use abi;
-use ast::{P, StaticRegionTyParamBound, OtherRegionTyParamBound};
-use ast::{TraitTyParamBound, UnboxedFnTyParamBound, Required, Provided};
+use ast::{FnMutUnboxedClosureKind, FnOnceUnboxedClosureKind};
+use ast::{FnUnboxedClosureKind, MethodImplItem, P, OtherRegionTyParamBound};
+use ast::{StaticRegionTyParamBound, TraitTyParamBound, UnboxedClosureKind};
+use ast::{UnboxedFnTyParamBound, RequiredMethod, ProvidedMethod};
 use ast;
 use ast_util;
 use owned_slice::OwnedSlice;
@@ -58,7 +60,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 +81,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 +152,8 @@ pub fn new(cm: &'a CodeMap,
                 cur_lit: 0
             },
             boxes: Vec::new(),
-            ann: ann
+            ann: ann,
+            encode_idents_with_hygiene: false,
         }
     }
 }
@@ -169,70 +174,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, None))
 }
 
 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 +253,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 +263,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 {
@@ -558,7 +596,7 @@ pub fn print_type(&mut self, ty: &ast::Ty) -> IoResult<()> {
                                       &None,
                                       Some(&generics),
                                       None,
-                                      false));
+                                      None));
             }
             ast::TyClosure(f, ref region) => {
                 let generics = ast::Generics {
@@ -575,7 +613,7 @@ pub fn print_type(&mut self, ty: &ast::Ty) -> IoResult<()> {
                                       &f.bounds,
                                       Some(&generics),
                                       None,
-                                      false));
+                                      None));
             }
             ast::TyProc(ref f) => {
                 let generics = ast::Generics {
@@ -592,7 +630,7 @@ pub fn print_type(&mut self, ty: &ast::Ty) -> IoResult<()> {
                                       &f.bounds,
                                       Some(&generics),
                                       None,
-                                      false));
+                                      None));
             }
             ast::TyUnboxedFn(f) => {
                 try!(self.print_ty_fn(None,
@@ -605,7 +643,7 @@ pub fn print_type(&mut self, ty: &ast::Ty) -> IoResult<()> {
                                       &None,
                                       None,
                                       None,
-                                      true));
+                                      Some(f.kind)));
             }
             ast::TyPath(ref path, ref bounds, _) => {
                 try!(self.print_bounded_path(path, bounds));
@@ -749,7 +787,10 @@ pub fn print_item(&mut self, item: &ast::Item) -> IoResult<()> {
                                        item.span));
             }
 
-            ast::ItemImpl(ref generics, ref opt_trait, ref ty, ref methods) => {
+            ast::ItemImpl(ref generics,
+                          ref opt_trait,
+                          ref ty,
+                          ref impl_items) => {
                 try!(self.head(visibility_qualified(item.vis,
                                                     "impl").as_slice()));
                 if generics.is_parameterized() {
@@ -771,8 +812,12 @@ pub fn print_item(&mut self, item: &ast::Item) -> IoResult<()> {
                 try!(space(&mut self.s));
                 try!(self.bopen());
                 try!(self.print_inner_attributes(item.attrs.as_slice()));
-                for meth in methods.iter() {
-                    try!(self.print_method(&**meth));
+                for impl_item in impl_items.iter() {
+                    match *impl_item {
+                        ast::MethodImplItem(meth) => {
+                            try!(self.print_method(&*meth));
+                        }
+                    }
                 }
                 try!(self.bclose(item.span));
             }
@@ -1018,15 +1063,21 @@ pub fn print_ty_method(&mut self, m: &ast::TypeMethod) -> IoResult<()> {
                               &None,
                               Some(&m.generics),
                               Some(m.explicit_self.node),
-                              false));
+                              None));
         word(&mut self.s, ";")
     }
 
     pub fn print_trait_method(&mut self,
-                              m: &ast::TraitMethod) -> IoResult<()> {
+                              m: &ast::TraitItem) -> IoResult<()> {
         match *m {
-            Required(ref ty_m) => self.print_ty_method(ty_m),
-            Provided(ref m) => self.print_method(&**m)
+            RequiredMethod(ref ty_m) => self.print_ty_method(ty_m),
+            ProvidedMethod(ref m) => self.print_method(&**m)
+        }
+    }
+
+    pub fn print_impl_item(&mut self, ii: &ast::ImplItem) -> IoResult<()> {
+        match *ii {
+            MethodImplItem(ref m) => self.print_method(&**m),
         }
     }
 
@@ -1437,13 +1488,15 @@ 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.
                 //
                 // if !decl.inputs.is_empty() {
-                try!(self.print_fn_block_args(&**decl, false));
+                try!(self.print_fn_block_args(&**decl, None));
                 try!(space(&mut self.s));
                 // }
 
@@ -1467,13 +1520,15 @@ 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, kind, 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.
                 //
                 // if !decl.inputs.is_empty() {
-                try!(self.print_fn_block_args(&**decl, true));
+                try!(self.print_fn_block_args(&**decl, Some(kind)));
                 try!(space(&mut self.s));
                 // }
 
@@ -1672,7 +1727,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<()> {
@@ -2007,13 +2067,17 @@ pub fn print_fn_args_and_ret(&mut self, decl: &ast::FnDecl,
         }
     }
 
-    pub fn print_fn_block_args(&mut self,
-                               decl: &ast::FnDecl,
-                               is_unboxed: bool)
-                               -> IoResult<()> {
+    pub fn print_fn_block_args(
+            &mut self,
+            decl: &ast::FnDecl,
+            unboxed_closure_kind: Option<UnboxedClosureKind>)
+            -> IoResult<()> {
         try!(word(&mut self.s, "|"));
-        if is_unboxed {
-            try!(self.word_space("&mut:"));
+        match unboxed_closure_kind {
+            None => {}
+            Some(FnUnboxedClosureKind) => try!(self.word_space("&:")),
+            Some(FnMutUnboxedClosureKind) => try!(self.word_space("&mut:")),
+            Some(FnOnceUnboxedClosureKind) => try!(self.word_space(":")),
         }
         try!(self.print_fn_args(decl, None));
         try!(word(&mut self.s, "|"));
@@ -2030,6 +2094,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, "("));
@@ -2095,7 +2167,7 @@ pub fn print_bounds(&mut self,
                                          &None,
                                          None,
                                          None,
-                                         true)
+                                         Some(unboxed_function_type.kind))
                     }
                     OtherRegionTyParamBound(_) => Ok(())
                 })
@@ -2203,13 +2275,17 @@ pub fn print_meta_item(&mut self, item: &ast::MetaItem) -> IoResult<()> {
     pub fn print_view_path(&mut self, vp: &ast::ViewPath) -> IoResult<()> {
         match vp.node {
             ast::ViewPathSimple(ident, ref path, _) => {
+                try!(self.print_path(path, false));
+
                 // FIXME(#6993) can't compare identifiers directly here
-                if path.segments.last().unwrap().identifier.name != ident.name {
-                    try!(self.print_ident(ident));
+                if path.segments.last().unwrap().identifier.name !=
+                        ident.name {
                     try!(space(&mut self.s));
-                    try!(self.word_space("="));
+                    try!(self.word_space("as"));
+                    try!(self.print_ident(ident));
                 }
-                self.print_path(path, false)
+
+                Ok(())
             }
 
             ast::ViewPathGlob(ref path, _) => {
@@ -2313,7 +2389,8 @@ pub fn print_ty_fn(&mut self,
                        opt_bounds: &Option<OwnedSlice<ast::TyParamBound>>,
                        generics: Option<&ast::Generics>,
                        opt_explicit_self: Option<ast::ExplicitSelf_>,
-                       is_unboxed: bool)
+                       opt_unboxed_closure_kind:
+                        Option<ast::UnboxedClosureKind>)
                        -> IoResult<()> {
         try!(self.ibox(indent_unit));
 
@@ -2330,7 +2407,7 @@ pub fn print_ty_fn(&mut self,
             try!(self.print_fn_style(fn_style));
             try!(self.print_opt_abi_and_extern_if_nondefault(opt_abi));
             try!(self.print_onceness(onceness));
-            if !is_unboxed {
+            if opt_unboxed_closure_kind.is_none() {
                 try!(word(&mut self.s, "fn"));
             }
         }
@@ -2346,20 +2423,30 @@ pub fn print_ty_fn(&mut self,
         match generics { Some(g) => try!(self.print_generics(g)), _ => () }
         try!(zerobreak(&mut self.s));
 
-        if is_unboxed || opt_sigil == Some('&') {
+        if opt_unboxed_closure_kind.is_some() || opt_sigil == Some('&') {
             try!(word(&mut self.s, "|"));
         } else {
             try!(self.popen());
         }
 
-        if is_unboxed {
-            try!(word(&mut self.s, "&mut"));
-            try!(self.word_space(":"));
+        match opt_unboxed_closure_kind {
+            Some(ast::FnUnboxedClosureKind) => {
+                try!(word(&mut self.s, "&"));
+                try!(self.word_space(":"));
+            }
+            Some(ast::FnMutUnboxedClosureKind) => {
+                try!(word(&mut self.s, "&mut"));
+                try!(self.word_space(":"));
+            }
+            Some(ast::FnOnceUnboxedClosureKind) => {
+                try!(self.word_space(":"));
+            }
+            None => {}
         }
 
         try!(self.print_fn_args(decl, opt_explicit_self));
 
-        if is_unboxed || opt_sigil == Some('&') {
+        if opt_unboxed_closure_kind.is_some() || opt_sigil == Some('&') {
             try!(word(&mut self.s, "|"));
         } else {
             if decl.variadic {
index 647e81db1f1c03a28be271fd542a6c8b6c0eabff..18cbf797d03c441f91de5e47119c43f7d5651c79 100644 (file)
@@ -99,7 +99,7 @@ fn visit_fn(&mut self, fk: &FnKind, fd: &FnDecl, b: &Block, s: Span, _: NodeId,
         walk_fn(self, fk, fd, b, s, e)
     }
     fn visit_ty_method(&mut self, t: &TypeMethod, e: E) { walk_ty_method(self, t, e) }
-    fn visit_trait_method(&mut self, t: &TraitMethod, e: E) { walk_trait_method(self, t, e) }
+    fn visit_trait_item(&mut self, t: &TraitItem, e: E) { walk_trait_item(self, t, e) }
     fn visit_struct_def(&mut self, s: &StructDef, _: Ident, _: &Generics, _: NodeId, e: E) {
         walk_struct_def(self, s, e)
     }
@@ -148,7 +148,16 @@ pub fn walk_inlined_item<E: Clone, V: Visitor<E>>(visitor: &mut V,
     match *item {
         IIItem(i) => visitor.visit_item(&*i, env),
         IIForeign(i) => visitor.visit_foreign_item(&*i, env),
-        IIMethod(_, _, m) => walk_method_helper(visitor, &*m, env),
+        IITraitItem(_, iti) => {
+            match iti {
+                ProvidedInlinedTraitItem(m) => {
+                    walk_method_helper(visitor, &*m, env)
+                }
+                RequiredInlinedTraitItem(m) => {
+                    walk_method_helper(visitor, &*m, env)
+                }
+            }
+        }
     }
 }
 
@@ -269,7 +278,7 @@ pub fn walk_item<E: Clone, V: Visitor<E>>(visitor: &mut V, item: &Item, env: E)
         ItemImpl(ref type_parameters,
                  ref trait_reference,
                  typ,
-                 ref methods) => {
+                 ref impl_items) => {
             visitor.visit_generics(type_parameters, env.clone());
             match *trait_reference {
                 Some(ref trait_reference) => walk_trait_ref_helper(visitor,
@@ -277,8 +286,12 @@ pub fn walk_item<E: Clone, V: Visitor<E>>(visitor: &mut V, item: &Item, env: E)
                 None => ()
             }
             visitor.visit_ty(&*typ, env.clone());
-            for method in methods.iter() {
-                walk_method_helper(visitor, &**method, env.clone())
+            for impl_item in impl_items.iter() {
+                match *impl_item {
+                    MethodImplItem(method) => {
+                        walk_method_helper(visitor, &*method, env.clone())
+                    }
+                }
             }
         }
         ItemStruct(ref struct_definition, ref generics) => {
@@ -297,7 +310,7 @@ pub fn walk_item<E: Clone, V: Visitor<E>>(visitor: &mut V, item: &Item, env: E)
                                    env.clone())
             }
             for method in methods.iter() {
-                visitor.visit_trait_method(method, env.clone())
+                visitor.visit_trait_item(method, env.clone())
             }
         }
         ItemMac(ref macro) => visitor.visit_mac(macro, env.clone()),
@@ -626,14 +639,14 @@ pub fn walk_ty_method<E: Clone, V: Visitor<E>>(visitor: &mut V,
     }
 }
 
-pub fn walk_trait_method<E: Clone, V: Visitor<E>>(visitor: &mut V,
-                                                  trait_method: &TraitMethod,
+pub fn walk_trait_item<E: Clone, V: Visitor<E>>(visitor: &mut V,
+                                                  trait_method: &TraitItem,
                                                   env: E) {
     match *trait_method {
-        Required(ref method_type) => {
+        RequiredMethod(ref method_type) => {
             visitor.visit_ty_method(method_type, env)
         }
-        Provided(ref method) => walk_method_helper(visitor, &**method, env),
+        ProvidedMethod(ref method) => walk_method_helper(visitor, &**method, env),
     }
 }
 
@@ -787,7 +800,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 +808,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 8c35424d394f4c357fb15d0d1726b72d4fb2daf8..9ced6cb62af00f0c310167f6720f498782f9db30 100644 (file)
@@ -396,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 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() {}
index 7e0f7f3abfe227d3ff88188f997c5d51ba3ef797..266903169c7b07f373ced546cf85f392a7dd498f 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-pub use bar = foo;
+pub use foo as bar;
 
 mod foo {
     pub fn frob() {}
index 882442f5e00906203b5e24a135ecd75da98f809d..3bad76f0e703e62919f7ea9622bf32ffbe438fd8 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 pub use sub_foo::Foo;
-pub use Baz = self::Bar;
+pub use self::Bar as Baz;
 pub use sub_foo::Boz;
 pub use sub_foo::Bort;
 
index 0216e7c5854b8fcd531c3e7646531fea4583609f..b756eb2b582f70076b6dfb7f6189437e23a228d1 100644 (file)
@@ -39,10 +39,10 @@ pub enum reexported_d {}
 }
 
 pub mod bar {
-    pub use e = foo::reexported_a;
-    pub use f = foo::reexported_b;
-    pub use g = foo::reexported_c;
-    pub use h = foo::reexported_d;
+    pub use foo::reexported_a as e;
+    pub use foo::reexported_b as f;
+    pub use foo::reexported_c as g;
+    pub use foo::reexported_d as h;
 }
 
 pub static a: int = 0;
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!());
+}
index b5d274a5584ab13ba42228e3608f88661827b25c..23cd4d80724e0c5523b25cf3cf763b6af56c51ca 100644 (file)
@@ -12,7 +12,7 @@
 // move, when the struct implements Drop.
 
 // NoCopy
-use NP = std::kinds::marker::NoCopy;
+use std::kinds::marker::NoCopy as NP;
 
 
 struct S { a: int, np: NP }
diff --git a/src/test/compile-fail/borrowck-unboxed-closures.rs b/src/test/compile-fail/borrowck-unboxed-closures.rs
new file mode 100644 (file)
index 0000000..d822bb2
--- /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.
+
+#![feature(overloaded_calls)]
+
+fn a<F:|&: int, int| -> int>(mut f: F) {
+    let g = &mut f;
+    f(1, 2);    //~ ERROR cannot borrow `f` as immutable
+    //~^ ERROR cannot borrow `f` as immutable
+}
+
+fn b<F:|&mut: int, int| -> int>(f: F) {
+    f(1, 2);    //~ ERROR cannot borrow immutable argument
+}
+
+fn c<F:|: int, int| -> int>(f: F) {
+    f(1, 2);
+    f(1, 2);    //~ ERROR use of moved value
+}
+
+fn main() {}
+
index aae5e0194a1d1d025a7add145aed42afeb5ecbd3..c522ecc4817f821c482ab9e0fe789b74ef99d593 100644 (file)
@@ -15,7 +15,7 @@
 use bar::*;
 
 mod bar {
-    use import = self::fpriv;
+    use self::fpriv as import;
     fn fpriv() {}
     extern {
         fn epriv();
index f7212779263117e0cfd6e6ba900a6a161d93ff76..ebd897a0611392efbf8117d092df35f2947137e8 100644 (file)
@@ -10,7 +10,7 @@
 
 // error-pattern:expected
 
-use baz = foo::{bar};
+use foo::{bar} as baz;
 
 mod foo {
     pub fn bar() {}
index 5016cab77233c8f1318c0294e582311f4342b3f9..fb400b6c2bb1e9465aacd8052909e046a2294996 100644 (file)
@@ -10,7 +10,7 @@
 
 // error-pattern:expected
 
-use baz = foo::*;
+use foo::* as baz;
 
 mod foo {
     pub fn bar() {}
index b646f8083b8d5590286cf99672a9fb1db7d5a060..bfc1ac2daef41d01c0c50e855fa7fb20a77f7dbf 100644 (file)
@@ -12,8 +12,8 @@
 
 // the `--test` harness creates modules with these textual names, but
 // they should be inaccessible from normal code.
-use x = __test; //~ ERROR unresolved import `__test`
-use y = __test_reexports; //~ ERROR unresolved import `__test_reexports`
+use __test as x; //~ ERROR unresolved import `__test`
+use __test_reexports as y; //~ ERROR unresolved import `__test_reexports`
 
 #[test]
 fn baz() {}
index 335012cedb84c1335e1e1136cfddbf41cdda44fb..e4fae73b18991293ee9c9a7a1ada252ca7e276c5 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use x = m::f; //~ ERROR unresolved import `m::f`. There is no `f` in `m`
+use m::f as x; //~ ERROR unresolved import `m::f`. There is no `f` in `m`
 
 mod m {}
 
index e34bfb10a719b9700da5595fd74d44bb5f82bbdb..41e6f24d79c79fcfdf3ead05be80f860fd232eeb 100644 (file)
@@ -16,7 +16,7 @@
 
 extern crate libc;
 
-pub use x = extern_foo;
+pub use extern_foo as x;
 extern {
     fn extern_foo();
 }
index db145be6ebd24b9a1f8b49503aaadb0677b39e1b..a63a3a61f68a0923d75b55e2d998e2c1f8b49e20 100644 (file)
@@ -148,8 +148,8 @@ fn also_undocumented2() {}
 }
 /// dox
 pub mod public_interface {
-    pub use foo = internal_impl::documented;
-    pub use bar = internal_impl::undocumented1;
+    pub use internal_impl::documented as foo;
+    pub use internal_impl::undocumented1 as bar;
     pub use internal_impl::{documented, undocumented2};
     pub use internal_impl::globbed::*;
 }
index f03e748e4176d5f495371816474818d307038ed4..d9bf722f73e4230f9a4e63df29f874006cc3b7db 100644 (file)
@@ -12,7 +12,7 @@
 #![deny(unused_imports)]
 #![allow(dead_code)]
 
-use cal = bar::c::cc;
+use bar::c::cc as cal;
 
 use std::mem::*;            // shouldn't get errors for not using
                             // everything imported
index a409ae60ccaa1e8077b68253907fb4a63f37423a..b5ffa3546c19d02cbbaefc8810762a19aa4a94d3 100644 (file)
@@ -43,7 +43,7 @@ mod n {
 }
 
 fn h() {
-    use not_okay = self::n::OKAY;
+    use self::n::OKAY as not_okay;
     let r = match (0,0) {
         (0, not_okay) => 0,
 //~^ ERROR static constant in pattern `not_okay` should have an uppercase name such as `NOT_OKAY`
index 52be07b463d8dd189ac1e35dfa09e6fd72623cbc..e52a4da13528799cbbe5a02df36253a17f4f681f 100644 (file)
@@ -176,7 +176,7 @@ pub mod mytest {
                          //~^ NOTE: module `i` is private
 
     pub mod foo {
-        pub use foo = self::i::A;
+        pub use self::i::A as foo;
 
         mod i {
             pub struct A;
diff --git a/src/test/compile-fail/regionck-unboxed-closure-lifetimes.rs b/src/test/compile-fail/regionck-unboxed-closure-lifetimes.rs
new file mode 100644 (file)
index 0000000..1c590db
--- /dev/null
@@ -0,0 +1,24 @@
+// 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.
+
+#![feature(unboxed_closure_sugar, unboxed_closures, overloaded_calls)]
+
+use std::ops::FnMut;
+
+fn main() {
+    let mut f;
+    {
+        let c = 1;
+        let c_ref = &c;
+        f = |&mut: a: int, b: int| { a + b + *c_ref };
+        //~^ ERROR cannot infer an appropriate lifetime
+    }
+}
+
diff --git a/src/test/compile-fail/unboxed-closures-wrong-trait.rs b/src/test/compile-fail/unboxed-closures-wrong-trait.rs
new file mode 100644 (file)
index 0000000..50d90c6
--- /dev/null
@@ -0,0 +1,22 @@
+// 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.
+
+#![feature(lang_items, overloaded_calls, unboxed_closures)]
+
+fn c<F:|: int, int| -> int>(f: F) -> int {
+    f(5, 6)
+}
+
+fn main() {
+    let z: int = 7;
+    assert_eq!(c(|&: x: int, y| x + y + z), 10);
+    //~^ ERROR failed to find an implementation
+}
+
index b5dcd5d165d4c0477cf0caab38b284569f636db7..7da7b364bda3658f16d07a4cece551e42530d460 100644 (file)
@@ -10,7 +10,7 @@
 
 use foo::bar; //~ ERROR unresolved import `foo::bar`. Maybe a missing `extern crate foo`?
 
-use x = bar::baz; //~ ERROR unresolved import `bar::baz`. There is no `baz` in `bar`
+use bar::baz as x; //~ ERROR unresolved import `bar::baz`. There is no `baz` in `bar`
 
 mod bar {
     struct bar;
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 b03feb8fc224b050c2e822a23fcad972ad6bc618..10c3df9388a011f05c105ed4bf8f7f7e7cfd31ba 100644 (file)
@@ -19,8 +19,8 @@
 
 use std::hashmap::{HashMap, HashSet};
 
-use EBReader = rbml::reader;
-use EBWriter = rbml::writer;
+use rbml::reader as EBReader;
+use rbml::writer as EBWriter;
 use std::cmp::Eq;
 use std::cmp;
 use std::io;
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) },
index 7e71be4114836c30a441552d24dd19f13e717c35..318305b7ec38eda17b592b262f70767ab7391543 100644 (file)
@@ -10,8 +10,8 @@
 
 #![feature(macro_rules)]
 
-use s = std::num::strconv;
-use to_string = std::num::strconv::float_to_str_common;
+use std::num::strconv as s;
+use std::num::strconv::float_to_str_common as to_string;
 
 macro_rules! t(($a:expr, $b:expr) => { { let (r, _) = $a; assert_eq!(r, $b.to_string()) } })
 
index 34272b145a29ddcecdb55e1219802ef23aa50dfa..37f7d84aaf1e42a46742267fed395d0fc10b1d4e 100644 (file)
@@ -11,5 +11,5 @@
 pub fn main() {
     // Make sure that this view item is filtered out because otherwise it would
     // trigger a compilation error
-    #[cfg(not_present)] use foo = bar;
+    #[cfg(not_present)] use bar as foo;
 }
index 0e6b857d7cf52b292534843bac5da33bd90a927f..14843b30e1c41a3b5a0a7ad46fa9e927e472f42c 100644 (file)
@@ -11,7 +11,7 @@
 // Issue 4691: Ensure that functional-struct-updates operates
 // correctly and moves rather than copy when appropriate.
 
-use NP = std::kinds::marker::NoCopy;
+use std::kinds::marker::NoCopy as NP;
 
 struct ncint { np: NP, v: int }
 fn ncint(v: int) -> ncint { ncint { np: NP, v: v } }
index 5d404909bf229b54655a97cbb95ffa2e978c353d..cf825bbbcea76c8c4eb747604bbd7c16b82488af 100644 (file)
@@ -16,7 +16,7 @@ mod foo {
 
 mod bar {
     use foo::x;
-    use z = foo::x;
+    use foo::x as z;
     pub fn thing() { x(10); z(10); }
 }
 
index 58ccf3aaa1e3d9b651150f7a5d4fff09cd0e1350..119107404d74d60096f186b2627108ec766f5e6a 100644 (file)
@@ -11,7 +11,7 @@
 
 
 use foo::x;
-use z = foo::x;
+use foo::x as z;
 
 mod foo {
     pub fn x(y: int) { println!("{}", y); }
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-16441.rs b/src/test/run-pass/issue-16441.rs
new file mode 100644 (file)
index 0000000..62c36e1
--- /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.
+
+struct Empty;
+
+// This used to cause an ICE
+extern "C" fn ice(_a: Empty) {}
+
+fn main() {
+}
index fd852f7fd516da81ebe60a7ea9d861c306766fd2..c9413258e0fb8d82442e3b8b76955124eb931cd2 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 
-pub use local_alias = local;
+pub use local as local_alias;
 
 mod local { }
 
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 06f6be8265414f38289e3db717ff110e62e688c9..92f57f34c947d15b3ec641991ffb45f38515811c 100644 (file)
@@ -38,7 +38,7 @@ mod m {
 }
 
 fn g() {
-    use AHA = self::m::aha;
+    use self::m::aha as AHA;
     let r = match (0,0) {
         (0, AHA) => 0,
         (x, y)   => 1 + x + y,
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) }
     });
diff --git a/src/test/run-pass/unboxed-closures-all-traits.rs b/src/test/run-pass/unboxed-closures-all-traits.rs
new file mode 100644 (file)
index 0000000..c362a83
--- /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.
+
+#![feature(lang_items, overloaded_calls, unboxed_closures)]
+
+fn a<F:|&: int, int| -> int>(f: F) -> int {
+    f(1, 2)
+}
+
+fn b<F:|&mut: int, int| -> int>(mut f: F) -> int {
+    f(3, 4)
+}
+
+fn c<F:|: int, int| -> int>(f: F) -> int {
+    f(5, 6)
+}
+
+fn main() {
+    let z: int = 7;
+    assert_eq!(a(|&: x: int, y| x + y + z), 10);
+    assert_eq!(b(|&mut: x: int, y| x + y + z), 14);
+    assert_eq!(c(|: x: int, y| x + y + z), 18);
+}
+
diff --git a/src/test/run-pass/unboxed-closures-drop.rs b/src/test/run-pass/unboxed-closures-drop.rs
new file mode 100644 (file)
index 0000000..f20dddc
--- /dev/null
@@ -0,0 +1,127 @@
+// 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.
+
+// A battery of tests to ensure destructors of unboxed closure environments
+// run at the right times.
+
+#![feature(overloaded_calls, unboxed_closures)]
+
+static mut DROP_COUNT: uint = 0;
+
+fn drop_count() -> uint {
+    unsafe {
+        DROP_COUNT
+    }
+}
+
+struct Droppable {
+    x: int,
+}
+
+impl Droppable {
+    fn new() -> Droppable {
+        Droppable {
+            x: 1
+        }
+    }
+}
+
+impl Drop for Droppable {
+    fn drop(&mut self) {
+        unsafe {
+            DROP_COUNT += 1
+        }
+    }
+}
+
+fn a<F:|&: int, int| -> int>(f: F) -> int {
+    f(1, 2)
+}
+
+fn b<F:|&mut: int, int| -> int>(mut f: F) -> int {
+    f(3, 4)
+}
+
+fn c<F:|: int, int| -> int>(f: F) -> int {
+    f(5, 6)
+}
+
+fn test_fn() {
+    {
+        a(|&: a: int, b| { a + b });
+    }
+    assert_eq!(drop_count(), 0);
+
+    {
+        let z = &Droppable::new();
+        a(|&: a: int, b| { z; a + b });
+        assert_eq!(drop_count(), 0);
+    }
+    assert_eq!(drop_count(), 1);
+
+    {
+        let z = &Droppable::new();
+        let zz = &Droppable::new();
+        a(|&: a: int, b| { z; zz; a + b });
+        assert_eq!(drop_count(), 1);
+    }
+    assert_eq!(drop_count(), 3);
+}
+
+fn test_fn_mut() {
+    {
+        b(|&mut: a: int, b| { a + b });
+    }
+    assert_eq!(drop_count(), 3);
+
+    {
+        let z = &Droppable::new();
+        b(|&mut: a: int, b| { z; a + b });
+        assert_eq!(drop_count(), 3);
+    }
+    assert_eq!(drop_count(), 4);
+
+    {
+        let z = &Droppable::new();
+        let zz = &Droppable::new();
+        b(|&mut: a: int, b| { z; zz; a + b });
+        assert_eq!(drop_count(), 4);
+    }
+    assert_eq!(drop_count(), 6);
+}
+
+fn test_fn_once() {
+    {
+        c(|: a: int, b| { a + b });
+    }
+    assert_eq!(drop_count(), 6);
+
+    {
+        let z = Droppable::new();
+        c(|: a: int, b| { z; a + b });
+        assert_eq!(drop_count(), 7);
+    }
+    assert_eq!(drop_count(), 7);
+
+    {
+        let z = Droppable::new();
+        let zz = Droppable::new();
+        c(|: a: int, b| { z; zz; a + b });
+        assert_eq!(drop_count(), 9);
+    }
+    assert_eq!(drop_count(), 9);
+}
+
+fn main() {
+    test_fn();
+    test_fn_mut();
+    test_fn_once();
+}
+
diff --git a/src/test/run-pass/unboxed-closures-single-word-env.rs b/src/test/run-pass/unboxed-closures-single-word-env.rs
new file mode 100644 (file)
index 0000000..754b1f7
--- /dev/null
@@ -0,0 +1,34 @@
+// 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.
+
+// Ensures that single-word environments work right in unboxed closures.
+// These take a different path in codegen.
+
+#![feature(overloaded_calls, unboxed_closures)]
+
+fn a<F:|&: int, int| -> int>(f: F) -> int {
+    f(1, 2)
+}
+
+fn b<F:|&mut: int, int| -> int>(mut f: F) -> int {
+    f(3, 4)
+}
+
+fn c<F:|: int, int| -> int>(f: F) -> int {
+    f(5, 6)
+}
+
+fn main() {
+    let z = 10;
+    assert_eq!(a(|&: x: int, y| x + y + z), 13);
+    assert_eq!(b(|&mut: x: int, y| x + y + z), 17);
+    assert_eq!(c(|: x: int, y| x + y + z), 21);
+}
+
index dfed391640516d0cf6e6b90e4d65d5c0d685b2f7..cdc0ffed7a1cb11f0b100959970d69ba3bf7b45e 100644 (file)
@@ -18,9 +18,9 @@
 
 
 use std::str;
-use x = zed::str;
+use zed::str as x;
 mod baz {
-    pub use x = std::str;
+    pub use std::str as x;
 }
 
 #[start]
index 634c9623e8468e1d7c354c82dc456087b3f6de68..6afa02fce55149a45552a0953c317d684b9fe5d4 100644 (file)
@@ -12,7 +12,7 @@
 
 extern crate xcrate_static_addresses;
 
-use other = xcrate_static_addresses;
+use xcrate_static_addresses as other;
 
 pub fn main() {
     other::verify_same(&other::global);