]> git.lizzy.rs Git - rust.git/commitdiff
rollup merge of #16828 : steveklabnik/more_pointer_guide
authorAlex Crichton <alex@alexcrichton.com>
Sun, 31 Aug 2014 06:46:46 +0000 (23:46 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Sun, 31 Aug 2014 06:46:46 +0000 (23:46 -0700)
244 files changed:
configure
mk/crates.mk
mk/tests.mk
src/compiletest/common.rs
src/compiletest/compiletest.rs
src/compiletest/header.rs
src/compiletest/procsrv.rs
src/compiletest/runtest.rs
src/doc/guide-ffi.md
src/doc/guide.md
src/doc/rust.md
src/etc/gdb_rust_pretty_printing.py [new file with mode: 0644]
src/etc/unicode.py
src/libarena/lib.rs
src/libcollections/dlist.rs
src/libcollections/hash/mod.rs
src/libcollections/lib.rs
src/libcollections/priority_queue.rs
src/libcollections/ringbuf.rs
src/libcollections/smallintmap.rs
src/libcollections/str.rs
src/libcollections/treemap.rs
src/libcollections/trie.rs
src/libcore/cell.rs
src/libcore/char.rs
src/libcore/finally.rs
src/libcore/fmt/mod.rs
src/libcore/intrinsics.rs
src/libcore/iter.rs
src/libcore/lib.rs
src/libcore/num/mod.rs
src/libcore/ops.rs
src/libcore/option.rs
src/libcore/raw.rs
src/libcore/result.rs
src/libcore/slice.rs
src/libcore/str.rs
src/libcoretest/option.rs
src/libdebug/lib.rs
src/libdebug/reflect.rs
src/libdebug/repr.rs
src/libfmt_macros/lib.rs
src/libgetopts/lib.rs
src/libglob/lib.rs
src/libgraphviz/lib.rs
src/libgraphviz/maybe_owned_vec.rs
src/libgreen/lib.rs
src/libgreen/sched.rs
src/libgreen/task.rs
src/liblibc/lib.rs
src/liblog/directive.rs
src/liblog/lib.rs
src/libnative/io/mod.rs
src/libnative/io/process.rs
src/libnative/io/timer_unix.rs
src/libnative/lib.rs
src/libnative/task.rs
src/libnum/bigint.rs
src/libnum/rational.rs
src/librand/distributions/mod.rs
src/librand/lib.rs
src/librbml/lib.rs
src/libregex/test/bench.rs
src/librlibc/lib.rs
src/librustc/diagnostics.rs
src/librustc/driver/driver.rs
src/librustc/driver/mod.rs
src/librustc/driver/pretty.rs [new file with mode: 0644]
src/librustc/lib.rs
src/librustc/lint/builtin.rs
src/librustc/lint/context.rs
src/librustc/middle/cfg/construct.rs
src/librustc/middle/check_loop.rs
src/librustc/middle/dataflow.rs
src/librustc/middle/expr_use_visitor.rs
src/librustc/middle/liveness.rs
src/librustc/middle/mem_categorization.rs
src/librustc/middle/region.rs
src/librustc/middle/resolve.rs
src/librustc/middle/trans/_match.rs
src/librustc/middle/trans/base.rs
src/librustc/middle/trans/build.rs
src/librustc/middle/trans/cabi_arm.rs
src/librustc/middle/trans/cabi_mips.rs
src/librustc/middle/trans/cabi_x86_64.rs
src/librustc/middle/trans/common.rs
src/librustc/middle/trans/debuginfo.rs
src/librustc/middle/trans/expr.rs
src/librustc/middle/trans/glue.rs
src/librustc/middle/trans/intrinsic.rs
src/librustc/middle/trans/monomorphize.rs
src/librustc/middle/trans/tvec.rs
src/librustc/middle/trans/type_.rs
src/librustc/middle/ty.rs
src/librustc/middle/typeck/check/mod.rs
src/librustc/middle/typeck/check/regionck.rs
src/librustc/middle/typeck/infer/coercion.rs
src/librustc/middle/typeck/infer/combine.rs
src/librustc/middle/typeck/infer/equate.rs [new file with mode: 0644]
src/librustc/middle/typeck/infer/error_reporting.rs
src/librustc/middle/typeck/infer/glb.rs
src/librustc/middle/typeck/infer/lattice.rs
src/librustc/middle/typeck/infer/lub.rs
src/librustc/middle/typeck/infer/macros.rs [deleted file]
src/librustc/middle/typeck/infer/mod.rs
src/librustc/middle/typeck/infer/region_inference/mod.rs
src/librustc/middle/typeck/infer/resolve.rs
src/librustc/middle/typeck/infer/sub.rs
src/librustc/middle/typeck/infer/type_variable.rs [new file with mode: 0644]
src/librustc/middle/typeck/infer/unify.rs
src/librustc/plugin/registry.rs
src/librustc/util/nodemap.rs
src/librustc/util/snapshot_vec.rs [new file with mode: 0644]
src/librustc_llvm/lib.rs
src/librustdoc/clean/inline.rs
src/librustdoc/clean/mod.rs
src/librustdoc/flock.rs
src/librustdoc/html/render.rs
src/librustdoc/lib.rs
src/librustrt/exclusive.rs
src/librustrt/lib.rs
src/librustrt/libunwind.rs
src/librustrt/local_data.rs
src/librustrt/mutex.rs
src/librustrt/task.rs
src/librustrt/thread.rs
src/librustrt/thread_local_storage.rs
src/librustuv/access.rs
src/librustuv/addrinfo.rs
src/librustuv/async.rs
src/librustuv/lib.rs
src/librustuv/net.rs
src/librustuv/process.rs
src/librustuv/stream.rs
src/librustuv/timeout.rs
src/librustuv/timer.rs
src/librustuv/uvio.rs
src/libserialize/json.rs
src/libserialize/lib.rs
src/libserialize/serialize.rs
src/libstd/collections/hashmap.rs
src/libstd/dynamic_lib.rs
src/libstd/io/buffered.rs
src/libstd/io/extensions.rs
src/libstd/io/mod.rs
src/libstd/io/net/tcp.rs
src/libstd/io/net/unix.rs
src/libstd/io/process.rs
src/libstd/io/tempfile.rs
src/libstd/lib.rs
src/libstd/os.rs
src/libstd/path/mod.rs
src/libstd/rand/os.rs
src/libstd/rt/backtrace.rs
src/libstd/time/duration.rs
src/libsync/comm/mod.rs
src/libsync/comm/oneshot.rs
src/libsync/comm/select.rs
src/libsync/comm/sync.rs
src/libsync/lib.rs
src/libsync/lock.rs
src/libsync/mpsc_queue.rs
src/libsync/raw.rs
src/libsyntax/abi.rs
src/libsyntax/ast.rs
src/libsyntax/ast_map/mod.rs
src/libsyntax/ast_util.rs
src/libsyntax/ext/expand.rs
src/libsyntax/fold.rs
src/libsyntax/lib.rs
src/libsyntax/parse/parser.rs
src/libsyntax/print/pprust.rs
src/libsyntax/visit.rs
src/libterm/win.rs
src/libunicode/tables.rs
src/libunicode/u_char.rs
src/libunicode/u_str.rs
src/snapshots.txt
src/test/auxiliary/lint_group_plugin_test.rs [new file with mode: 0644]
src/test/bench/msgsend-ring-mutex-arcs.rs
src/test/bench/msgsend-ring-rw-arcs.rs
src/test/bench/shootout-spectralnorm.rs
src/test/bench/sudoku.rs
src/test/compile-fail-fulldeps/lint-group-plugin-deny-cmdline.rs [new file with mode: 0644]
src/test/compile-fail/borrowck-closures-mut-of-imm.rs
src/test/compile-fail/borrowck-reborrow-from-shorter-lived-andmut.rs
src/test/compile-fail/for-loop-bogosity.rs
src/test/compile-fail/for-loop-type-error.rs [new file with mode: 0644]
src/test/compile-fail/issue-10291.rs
src/test/compile-fail/issue-13482.rs
src/test/compile-fail/issue-16338.rs
src/test/compile-fail/issue-2149.rs
src/test/compile-fail/kindck-inherited-copy-bound.rs [new file with mode: 0644]
src/test/compile-fail/kindck-send-object1.rs [new file with mode: 0644]
src/test/compile-fail/kindck-send-object2.rs [new file with mode: 0644]
src/test/compile-fail/kindck-send-owned.rs [new file with mode: 0644]
src/test/compile-fail/kindck-send-region-pointers.rs [new file with mode: 0644]
src/test/compile-fail/kindck-send-unsafe.rs [new file with mode: 0644]
src/test/compile-fail/lint-group-style.rs [new file with mode: 0644]
src/test/compile-fail/lint-non-camel-case-types.rs
src/test/compile-fail/lint-non-snake-case-functions.rs
src/test/compile-fail/lint-non-snake-case-lifetimes.rs [new file with mode: 0644]
src/test/compile-fail/lint-non-snake-case-modules.rs [new file with mode: 0644]
src/test/compile-fail/lint-uppercase-variables.rs
src/test/compile-fail/match-static-const-lc.rs
src/test/compile-fail/regions-bounds.rs
src/test/compile-fail/regions-escape-bound-fn-2.rs
src/test/compile-fail/regions-escape-bound-fn.rs
src/test/compile-fail/regions-escape-via-trait-or-not.rs
src/test/compile-fail/regions-infer-at-fn-not-param.rs
src/test/compile-fail/regions-infer-contravariance-due-to-decl.rs
src/test/compile-fail/regions-infer-covariance-due-to-decl.rs
src/test/compile-fail/regions-infer-not-param.rs
src/test/compile-fail/regions-infer-paramd-indirect.rs
src/test/compile-fail/regions-infer-proc-static-upvar.rs [new file with mode: 0644]
src/test/compile-fail/regions-reborrow-from-shorter-mut-ref-mut-ref.rs
src/test/compile-fail/regions-reborrow-from-shorter-mut-ref.rs
src/test/compile-fail/regions-ret-borrowed-1.rs
src/test/compile-fail/regions-ret-borrowed.rs
src/test/compile-fail/regions-variance-contravariant-use-covariant-in-second-position.rs
src/test/compile-fail/regions-variance-contravariant-use-covariant.rs
src/test/compile-fail/regions-variance-covariant-use-contravariant.rs
src/test/compile-fail/resolve-conflict-import-vs-extern-crate.rs
src/test/compile-fail/resolve-conflict-item-vs-import.rs
src/test/compile-fail/resolve-conflict-type-vs-import.rs [new file with mode: 0644]
src/test/debuginfo/gdb-pretty-struct-and-enums-pre-gdb-7-7.rs [new file with mode: 0644]
src/test/debuginfo/gdb-pretty-struct-and-enums.rs [new file with mode: 0644]
src/test/run-make/pretty-expanded-hygiene/Makefile [new file with mode: 0644]
src/test/run-make/pretty-expanded-hygiene/input.pp.rs [new file with mode: 0755]
src/test/run-make/pretty-expanded-hygiene/input.rs [new file with mode: 0755]
src/test/run-make/rustdoc-search-index/Makefile [new file with mode: 0644]
src/test/run-make/rustdoc-search-index/index.rs [new file with mode: 0644]
src/test/run-make/rustdoc-search-index/verify.sh [new file with mode: 0755]
src/test/run-pass-fulldeps/lint-group-plugin.rs [new file with mode: 0644]
src/test/run-pass/hygienic-labels-in-let.rs
src/test/run-pass/hygienic-labels.rs
src/test/run-pass/labeled-break.rs
src/test/run-pass/match-static-const-rename.rs
src/test/run-pass/reflect-visit-type.rs
src/test/run-pass/regions-infer-reborrow-ref-mut-recurse.rs [new file with mode: 0644]
src/test/run-pass/regions-infer-static-from-proc.rs [new file with mode: 0644]
src/test/run-pass/regions-scope-chain-example.rs [new file with mode: 0644]
src/test/run-pass/tcp-accept-stress.rs
src/test/run-pass/while-label.rs [new file with mode: 0644]

index 5a2f9b5f20c763d01cffad1a880ef4251764a470..1d6c387caa7c669811a7fa936bd4dd3b2840728d 100755 (executable)
--- a/configure
+++ b/configure
@@ -515,6 +515,13 @@ probe CFG_LUALATEX         lualatex
 probe CFG_GDB              gdb
 probe CFG_LLDB             lldb
 
+if [ ! -z "$CFG_GDB" ]
+then
+    # Extract the version
+    CFG_GDB_VERSION=$($CFG_GDB --version 2>/dev/null | head -1)
+    putvar CFG_GDB_VERSION
+fi
+
 if [ ! -z "$CFG_LLDB" ]
 then
     # If CFG_LLDB_PYTHON_DIR is not already set from the outside and valid, try to read it from
index 5bc4505fb05c742bf92f22bf21d65320820112d2..f830e1a9d958519f1de323e4096dff5fe6fb2efb 100644 (file)
@@ -96,7 +96,7 @@ DEPS_test := std getopts serialize rbml term time regex native:rust_test_helpers
 DEPS_time := std serialize
 DEPS_rand := core
 DEPS_url := std
-DEPS_log := std
+DEPS_log := std regex
 DEPS_regex := std
 DEPS_regex_macros = rustc syntax std regex
 DEPS_fmt_macros = std
index f78243046801d6defaa9e560def866776fe575ff..d95f886e078896cb4649f3905883310401bcbe62 100644 (file)
@@ -623,6 +623,7 @@ CTEST_COMMON_ARGS$(1)-T-$(2)-H-$(3) := \
         --stage-id stage$(1)-$(2) \
         --target $(2) \
         --host $(3) \
+        --gdb-version="$(CFG_GDB_VERSION)" \
         --android-cross-path=$(CFG_ANDROID_CROSS_PATH) \
         --adb-path=$(CFG_ADB) \
         --adb-test-dir=$(CFG_ADB_TEST_DIR) \
index ba201a4a633c62708d2902513cb499de800974e0..afe2d071461a0317356c811f443b8f803e5bb8a8 100644 (file)
@@ -130,6 +130,9 @@ pub struct Config {
     // Host triple for the compiler being invoked
     pub host: String,
 
+    // Version of GDB
+    pub gdb_version: Option<String>,
+
     // Path to the android tools
     pub android_cross_path: Path,
 
index 583d9249b35476a72f59346dac2e8f544e94f1e5..6c6cd6f610f5be970f07e4f7faa8c58c6df52b5f 100644 (file)
@@ -81,6 +81,7 @@ pub fn parse_config(args: Vec<String> ) -> Config {
           optflag("", "jit", "run tests under the JIT"),
           optopt("", "target", "the target to build for", "TARGET"),
           optopt("", "host", "the host to build for", "HOST"),
+          optopt("", "gdb-version", "the version of GDB used", "MAJOR.MINOR"),
           optopt("", "android-cross-path", "Android NDK standalone path", "PATH"),
           optopt("", "adb-path", "path to the android debugger", "PATH"),
           optopt("", "adb-test-dir", "path to tests for the android debugger", "PATH"),
@@ -157,6 +158,7 @@ fn opt_path(m: &getopts::Matches, nm: &str) -> Path {
         jit: matches.opt_present("jit"),
         target: opt_str2(matches.opt_str("target")),
         host: opt_str2(matches.opt_str("host")),
+        gdb_version: extract_gdb_version(matches.opt_str("gdb-version")),
         android_cross_path: opt_path(matches, "android-cross-path"),
         adb_path: opt_str2(matches.opt_str("adb-path")),
         adb_test_dir: opt_str2(matches.opt_str("adb-test-dir")),
@@ -376,3 +378,26 @@ pub fn make_metrics_test_closure(config: &Config, testfile: &Path) -> test::Test
         runtest::run_metrics(config, testfile, mm)
     })
 }
+
+fn extract_gdb_version(full_version_line: Option<String>) -> Option<String> {
+    match full_version_line {
+        Some(ref full_version_line)
+          if full_version_line.as_slice().trim().len() > 0 => {
+            let full_version_line = full_version_line.as_slice().trim();
+
+            let re = Regex::new(r"(^|[^0-9])([0-9]\.[0-9])([^0-9]|$)").unwrap();
+
+            match re.captures(full_version_line) {
+                Some(captures) => {
+                    Some(captures.at(2).to_string())
+                }
+                None => {
+                    println!("Could not extract GDB version from line '{}'",
+                             full_version_line);
+                    None
+                }
+            }
+        },
+        _ => None
+    }
+}
\ No newline at end of file
index f6cd217b580cd24be78747dc23cca861906771ef..9ad2582dec8456d60c6d52d4aaf2534a6f6f1e8e 100644 (file)
@@ -12,6 +12,8 @@
 use common;
 use util;
 
+use std::from_str::FromStr;
+
 pub struct TestProps {
     // Lines that should be expected, in order, on standard out
     pub error_patterns: Vec<String> ,
@@ -142,23 +144,42 @@ fn ignore_stage(config: &Config) -> String {
         format!("ignore-{}",
                 config.stage_id.as_slice().split('-').next().unwrap())
     }
+    fn ignore_gdb(config: &Config, line: &str) -> bool {
+        if config.mode != common::DebugInfoGdb {
+            return false;
+        }
 
-    let val = iter_header(testfile, |ln| {
-        if parse_name_directive(ln, "ignore-test") {
-            false
-        } else if parse_name_directive(ln, ignore_target(config).as_slice()) {
-            false
-        } else if parse_name_directive(ln, ignore_stage(config).as_slice()) {
-            false
-        } else if config.mode == common::Pretty &&
-                parse_name_directive(ln, "ignore-pretty") {
-            false
-        } else if config.target != config.host &&
-                parse_name_directive(ln, "ignore-cross-compile") {
-            false
-        } else {
-            true
+        if parse_name_directive(line, "ignore-gdb") {
+            return true;
         }
+
+        match config.gdb_version {
+            Some(ref actual_version) => {
+                if line.contains("min-gdb-version") {
+                    let min_version = line.trim()
+                                          .split(' ')
+                                          .last()
+                                          .expect("Malformed GDB version directive");
+                    // Ignore if actual version is smaller the minimum required
+                    // version
+                    gdb_version_to_int(actual_version.as_slice()) <
+                        gdb_version_to_int(min_version.as_slice())
+                } else {
+                    false
+                }
+            }
+            None => false
+        }
+    }
+
+    let val = iter_header(testfile, |ln| {
+        !parse_name_directive(ln, "ignore-test") &&
+        !parse_name_directive(ln, ignore_target(config).as_slice()) &&
+        !parse_name_directive(ln, ignore_stage(config).as_slice()) &&
+        !(config.mode == common::Pretty && parse_name_directive(ln, "ignore-pretty")) &&
+        !(config.target != config.host && parse_name_directive(ln, "ignore-cross-compile")) &&
+        !ignore_gdb(config, ln) &&
+        !(config.mode == common::DebugInfoLldb && parse_name_directive(ln, "ignore-lldb"))
     });
 
     !val
@@ -278,3 +299,21 @@ pub fn parse_name_value_directive(line: &str, directive: &str)
         None => None
     }
 }
+
+pub fn gdb_version_to_int(version_string: &str) -> int {
+    let error_string = format!(
+        "Encountered GDB version string with unexpected format: {}",
+        version_string);
+    let error_string = error_string.as_slice();
+
+    let components: Vec<&str> = version_string.trim().split('.').collect();
+
+    if components.len() != 2 {
+        fail!("{}", error_string);
+    }
+
+    let major: int = FromStr::from_str(components[0]).expect(error_string);
+    let minor: int = FromStr::from_str(components[1]).expect(error_string);
+
+    return major * 1000 + minor;
+}
index 28ff2c18ad3baf5fb9af65d0c272e768aa5ca252..2c3aa88a680833ddf75f94ad95b5a7f84892de6c 100644 (file)
@@ -47,7 +47,7 @@ pub fn run(lib_path: &str,
     match cmd.spawn() {
         Ok(mut process) => {
             for input in input.iter() {
-                process.stdin.get_mut_ref().write(input.as_bytes()).unwrap();
+                process.stdin.as_mut().unwrap().write(input.as_bytes()).unwrap();
             }
             let ProcessOutput { status, output, error } =
                 process.wait_with_output().unwrap();
@@ -79,7 +79,7 @@ pub fn run_background(lib_path: &str,
     match cmd.spawn() {
         Ok(mut process) => {
             for input in input.iter() {
-                process.stdin.get_mut_ref().write(input.as_bytes()).unwrap();
+                process.stdin.as_mut().unwrap().write(input.as_bytes()).unwrap();
             }
 
             Some(process)
index b36bc96cd351cd6098fad4675770e6d4be8baa11..ee787a5f0a9bf223e62ea6bb2e3c0d838369b07a 100644 (file)
@@ -323,7 +323,12 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) {
     };
 
     let config = &mut config;
-    let DebuggerCommands { commands, check_lines, .. } = parse_debugger_commands(testfile, "gdb");
+    let DebuggerCommands {
+        commands,
+        check_lines,
+        use_gdb_pretty_printer,
+        ..
+    } = parse_debugger_commands(testfile, "gdb");
     let mut cmds = commands.connect("\n");
 
     // compile test file (it should have 'compile-flags:-g' in the header)
@@ -334,7 +339,6 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) {
 
     let exe_file = make_exe_name(config, testfile);
 
-    let mut proc_args;
     let debugger_run_result;
     match config.target.as_slice() {
         "arm-linux-androideabi" => {
@@ -454,18 +458,65 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) {
         }
 
         _=> {
+            let rust_src_root = find_rust_src_root(config)
+                .expect("Could not find Rust source root");
+            let rust_pp_module_rel_path = Path::new("./src/etc");
+            let rust_pp_module_abs_path = rust_src_root.join(rust_pp_module_rel_path)
+                                                       .as_str()
+                                                       .unwrap()
+                                                       .to_string();
             // write debugger script
-            let script_str = [
-                "set charset UTF-8".to_string(),
-                cmds,
-                "quit\n".to_string()
-            ].connect("\n");
+            let mut script_str = String::with_capacity(2048);
+
+            script_str.push_str("set charset UTF-8\n");
+            script_str.push_str("show version\n");
+
+            match config.gdb_version {
+                Some(ref version) => {
+                    println!("NOTE: compiletest thinks it is using GDB version {}",
+                             version.as_slice());
+
+                    if header::gdb_version_to_int(version.as_slice()) >
+                        header::gdb_version_to_int("7.4") {
+                        // Add the directory containing the pretty printers to
+                        // GDB's script auto loading safe path ...
+                        script_str.push_str(
+                            format!("add-auto-load-safe-path {}\n",
+                                    rust_pp_module_abs_path.as_slice())
+                                .as_slice());
+                        // ... and also the test directory
+                        script_str.push_str(
+                            format!("add-auto-load-safe-path {}\n",
+                                    config.build_base.as_str().unwrap())
+                                .as_slice());
+                    }
+                }
+                _ => {
+                    println!("NOTE: compiletest does not know which version of \
+                              GDB it is using");
+                }
+            }
+
+            // Load the target executable
+            script_str.push_str(format!("file {}\n",
+                                        exe_file.as_str().unwrap())
+                                    .as_slice());
+
+            script_str.push_str(cmds.as_slice());
+            script_str.push_str("quit\n");
+
             debug!("script_str = {}", script_str);
             dump_output_file(config,
                              testfile,
                              script_str.as_slice(),
                              "debugger.script");
 
+            if use_gdb_pretty_printer {
+                // Only emit the gdb auto-loading script if pretty printers
+                // should actually be loaded
+                dump_gdb_autoload_script(config, testfile);
+            }
+
             // run debugger script with gdb
             #[cfg(windows)]
             fn debugger() -> String {
@@ -483,16 +534,19 @@ fn debugger() -> String {
                 vec!("-quiet".to_string(),
                      "-batch".to_string(),
                      "-nx".to_string(),
-                     format!("-command={}", debugger_script.as_str().unwrap()),
-                     exe_file.as_str().unwrap().to_string());
-            proc_args = ProcArgs {
+                     format!("-command={}", debugger_script.as_str().unwrap()));
+
+            let proc_args = ProcArgs {
                 prog: debugger(),
                 args: debugger_opts,
             };
+
+            let environment = vec![("PYTHONPATH".to_string(), rust_pp_module_abs_path)];
+
             debugger_run_result = compose_and_run(config,
                                                   testfile,
                                                   proc_args,
-                                                  Vec::new(),
+                                                  environment,
                                                   config.run_lib_path.as_slice(),
                                                   None,
                                                   None);
@@ -504,6 +558,32 @@ fn debugger() -> String {
     }
 
     check_debugger_output(&debugger_run_result, check_lines.as_slice());
+
+    fn dump_gdb_autoload_script(config: &Config, testfile: &Path) {
+        let mut script_path = output_base_name(config, testfile);
+        let mut script_file_name = script_path.filename().unwrap().to_vec();
+        script_file_name.push_all("-gdb.py".as_bytes());
+        script_path.set_filename(script_file_name.as_slice());
+
+        let script_content = "import gdb_rust_pretty_printing\n\
+                              gdb_rust_pretty_printing.register_printers(gdb.current_objfile())\n"
+                             .as_bytes();
+
+        File::create(&script_path).write(script_content).unwrap();
+    }
+}
+
+fn find_rust_src_root(config: &Config) -> Option<Path> {
+    let mut path = config.src_base.clone();
+    let path_postfix = Path::new("src/etc/lldb_batchmode.py");
+
+    while path.pop() {
+        if path.join(path_postfix.clone()).is_file() {
+            return Some(path);
+        }
+    }
+
+    return None;
 }
 
 fn run_debuginfo_lldb_test(config: &Config, props: &TestProps, testfile: &Path) {
@@ -533,7 +613,8 @@ fn run_debuginfo_lldb_test(config: &Config, props: &TestProps, testfile: &Path)
     let DebuggerCommands {
         commands,
         check_lines,
-        breakpoint_lines
+        breakpoint_lines,
+        ..
     } = parse_debugger_commands(testfile, "lldb");
 
     // Write debugger script:
@@ -619,6 +700,7 @@ struct DebuggerCommands {
     commands: Vec<String>,
     check_lines: Vec<String>,
     breakpoint_lines: Vec<uint>,
+    use_gdb_pretty_printer: bool
 }
 
 fn parse_debugger_commands(file_path: &Path, debugger_prefix: &str)
@@ -631,6 +713,7 @@ fn parse_debugger_commands(file_path: &Path, debugger_prefix: &str)
     let mut breakpoint_lines = vec!();
     let mut commands = vec!();
     let mut check_lines = vec!();
+    let mut use_gdb_pretty_printer = false;
     let mut counter = 1;
     let mut reader = BufferedReader::new(File::open(file_path).unwrap());
     for line in reader.lines() {
@@ -640,6 +723,10 @@ fn parse_debugger_commands(file_path: &Path, debugger_prefix: &str)
                     breakpoint_lines.push(counter);
                 }
 
+                if line.as_slice().contains("gdb-use-pretty-printer") {
+                    use_gdb_pretty_printer = true;
+                }
+
                 header::parse_name_value_directive(
                         line.as_slice(),
                         command_directive.as_slice()).map(|cmd| {
@@ -663,7 +750,8 @@ fn parse_debugger_commands(file_path: &Path, debugger_prefix: &str)
     DebuggerCommands {
         commands: commands,
         check_lines: check_lines,
-        breakpoint_lines: breakpoint_lines
+        breakpoint_lines: breakpoint_lines,
+        use_gdb_pretty_printer: use_gdb_pretty_printer,
     }
 }
 
@@ -1526,7 +1614,7 @@ fn compile_cc_with_clang_and_save_bitcode(config: &Config, _props: &TestProps,
     let testcc = testfile.with_extension("cc");
     let proc_args = ProcArgs {
         // FIXME (#9639): This needs to handle non-utf8 paths
-        prog: config.clang_path.get_ref().as_str().unwrap().to_string(),
+        prog: config.clang_path.as_ref().unwrap().as_str().unwrap().to_string(),
         args: vec!("-c".to_string(),
                    "-emit-llvm".to_string(),
                    "-o".to_string(),
@@ -1542,7 +1630,7 @@ fn extract_function_from_bitcode(config: &Config, _props: &TestProps,
     let bitcodefile = output_base_name(config, testfile).with_extension("bc");
     let bitcodefile = append_suffix_to_stem(&bitcodefile, suffix);
     let extracted_bc = append_suffix_to_stem(&bitcodefile, "extract");
-    let prog = config.llvm_bin_path.get_ref().join("llvm-extract");
+    let prog = config.llvm_bin_path.as_ref().unwrap().join("llvm-extract");
     let proc_args = ProcArgs {
         // FIXME (#9639): This needs to handle non-utf8 paths
         prog: prog.as_str().unwrap().to_string(),
@@ -1559,7 +1647,7 @@ fn disassemble_extract(config: &Config, _props: &TestProps,
     let bitcodefile = append_suffix_to_stem(&bitcodefile, suffix);
     let extracted_bc = append_suffix_to_stem(&bitcodefile, "extract");
     let extracted_ll = extracted_bc.with_extension("ll");
-    let prog = config.llvm_bin_path.get_ref().join("llvm-dis");
+    let prog = config.llvm_bin_path.as_ref().unwrap().join("llvm-dis");
     let proc_args = ProcArgs {
         // FIXME (#9639): This needs to handle non-utf8 paths
         prog: prog.as_str().unwrap().to_string(),
index 0ded9db3ad08b4aea9c0c81951c4e1068f5e9548..dd35a610e15e8e109b2963614ebb08ec5efbe0ca 100644 (file)
@@ -477,7 +477,7 @@ extern crate libc;
 
 #[cfg(target_os = "win32", target_arch = "x86")]
 #[link(name = "kernel32")]
-#[allow(non_snake_case_functions)]
+#[allow(non_snake_case)]
 extern "stdcall" {
     fn SetEnvironmentVariableA(n: *const u8, v: *const u8) -> libc::c_int;
 }
@@ -528,8 +528,8 @@ the `libc` module, and Rust links against `libc` and `libm` by default.
 # The "nullable pointer optimization"
 
 Certain types are defined to not be `null`. This includes references (`&T`,
-`&mut T`), owning pointers (`~T`), and function pointers (`extern "abi"
-fn()`). When interfacing with C, pointers that might be null are often used.
+`&mut T`), boxes (`Box<T>`), and function pointers (`extern "abi" fn()`).
+When interfacing with C, pointers that might be null are often used.
 As a special case, a generic `enum` that contains exactly two variants, one of
 which contains no data and the other containing a single field, is eligible
 for the "nullable pointer optimization". When such an enum is instantiated
index 8a634a083e8ad49974ba171d6118b88be0a160f1..ba5ac0921ed8a1277658db879262285ce1874e40 100644 (file)
@@ -2670,10 +2670,10 @@ $ cargo new modules --bin
 
 Let's double check our work by compiling:
 
-```{bash,ignore}
-$ cargo build
+```{bash,notrust}
+$ cargo run
    Compiling modules v0.0.1 (file:///home/you/projects/modules)
-$ ./target/modules
+     Running `target/modules`
 Hello, world!
 ```
 
@@ -3011,7 +3011,7 @@ markers.
 Rust provides six attributes to indicate the stability level of various
 parts of your library. The six levels are:
 
-* deprecated: this item should no longer be used. No guarantee of backwards
+* deprecated: This item should no longer be used. No guarantee of backwards
   compatibility.
 * experimental: This item was only recently introduced or is otherwise in a
   state of flux. It may change significantly, or even be removed. No guarantee
@@ -3668,15 +3668,20 @@ because it's easy. And if you need precise control over when something is
 deallocated, leaving it up to your runtime can make this difficult.
 
 Rust chooses a different path, and that path is called **ownership**. Any
-binding that creates a resource is the **owner** of that resource.  Being an
-owner gives you three privileges, with two restrictions:
+binding that creates a resource is the **owner** of that resource.
+
+Being an owner affords you some privileges:
 
 1. You control when that resource is deallocated.
 2. You may lend that resource, immutably, to as many borrowers as you'd like.
-3. You may lend that resource, mutably, to a single borrower. **BUT**
-4. Once you've done so, you may not also lend it out otherwise, mutably or
-   immutably.
-5. You may not lend it out mutably if you're currently lending it to someone.
+3. You may lend that resource, mutably, to a single borrower.
+
+But it also comes with some restrictions:
+
+1. If someone is borrowing your resource (either mutably or immutably), you may
+   not mutate the resource or mutably lend it to someone.
+2. If someone is mutably borrowing your resource, you may not lend it out at
+   all (mutably or immutably) or access it in any way.
 
 What's up with all this 'lending' and 'borrowing'? When you allocate memory,
 you get a pointer to that memory. This pointer allows you to manipulate said
@@ -5510,7 +5515,7 @@ Guide can help you if you want to write your own.
 
 # Unsafe
 
-Finally, there's one more concept that you should be aware in Rust: `unsafe`.
+Finally, there's one more Rust concept that you should be aware of: `unsafe`.
 There are two circumstances where Rust's safety provisions don't work well.
 The first is when interfacing with C code, and the second is when building
 certain kinds of abstractions.
index 88c22024a60a11324ea74ce4f20c2df0221291ed..ba5a01f899f850dc8be00b22b6cde1f2dd808a6d 100644 (file)
@@ -2215,14 +2215,14 @@ These types help drive the compiler's analysis
 
 * `begin_unwind`
   : ___Needs filling in___
+* `managed_bound`
+  : This type implements "managed"
 * `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"
+* `no_share_bound`
+  : This type does not implement "share", even if eligible
 * `eh_personality`
   : ___Needs filling in___
 * `exchange_free`
diff --git a/src/etc/gdb_rust_pretty_printing.py b/src/etc/gdb_rust_pretty_printing.py
new file mode 100644 (file)
index 0000000..e8a6427
--- /dev/null
@@ -0,0 +1,231 @@
+# Copyright 2013-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.
+
+import gdb
+
+#===============================================================================
+# GDB Pretty Printing Module for Rust
+#===============================================================================
+
+def register_printers(objfile):
+  "Registers Rust pretty printers for the given objfile"
+  objfile.pretty_printers.append(rust_pretty_printer_lookup_function)
+
+def rust_pretty_printer_lookup_function(val):
+  "Returns the correct Rust pretty printer for the given value if there is one"
+  type_code = val.type.code
+
+  if type_code == gdb.TYPE_CODE_STRUCT:
+    struct_kind = classify_struct(val.type)
+
+    if struct_kind == STRUCT_KIND_STR_SLICE:
+      return RustStringSlicePrinter(val)
+
+    if struct_kind == STRUCT_KIND_TUPLE:
+      return RustTuplePrinter(val)
+
+    if struct_kind == STRUCT_KIND_TUPLE_STRUCT:
+      return RustTupleStructPrinter(val, False)
+
+    if struct_kind == STRUCT_KIND_CSTYLE_VARIANT:
+      return RustCStyleEnumPrinter(val[get_field_at_index(val, 0)])
+
+    if struct_kind == STRUCT_KIND_TUPLE_VARIANT:
+      return RustTupleStructPrinter(val, True)
+
+    if struct_kind == STRUCT_KIND_STRUCT_VARIANT:
+      return RustStructPrinter(val, True)
+
+    return RustStructPrinter(val, False)
+
+  # Enum handling
+  if type_code == gdb.TYPE_CODE_UNION:
+    enum_members = list(val.type.fields())
+    enum_member_count = len(enum_members)
+
+    if enum_member_count == 0:
+      return RustStructPrinter(val, false)
+
+    if enum_member_count == 1:
+      if enum_members[0].name == None:
+        # This is a singleton enum
+        return rust_pretty_printer_lookup_function(val[enum_members[0]])
+      else:
+        assert enum_members[0].name.startswith("RUST$ENCODED$ENUM$")
+        # This is a space-optimized enum
+        last_separator_index = enum_members[0].name.rfind("$")
+        second_last_separator_index = first_variant_name.rfind("$", 0, last_separator_index)
+        disr_field_index = first_variant_name[second_last_separator_index + 1 :
+                                              last_separator_index]
+        disr_field_index = int(disr_field_index)
+
+        sole_variant_val = val[enum_members[0]]
+        disr_field = get_field_at_index(sole_variant_val, disr_field_index)
+        discriminant = int(sole_variant_val[disr_field])
+
+        if discriminant == 0:
+          null_variant_name = first_variant_name[last_separator_index + 1:]
+          return IdentityPrinter(null_variant_name)
+
+        return rust_pretty_printer_lookup_function(sole_variant_val)
+
+    # This is a regular enum, extract the discriminant
+    discriminant_name, discriminant_val = extract_discriminant_value(val)
+    return rust_pretty_printer_lookup_function(val[enum_members[discriminant_val]])
+
+  # No pretty printer has been found
+  return None
+
+#=------------------------------------------------------------------------------
+# Pretty Printer Classes
+#=------------------------------------------------------------------------------
+
+class RustStructPrinter:
+  def __init__(self, val, hide_first_field):
+    self.val = val
+    self.hide_first_field = hide_first_field
+
+  def to_string(self):
+    return self.val.type.tag
+
+  def children(self):
+    cs = []
+    for field in self.val.type.fields():
+      field_name = field.name
+      # Normally the field name is used as a key to access the field value,
+      # because that's also supported in older versions of GDB...
+      field_key = field_name
+      if field_name == None:
+        field_name = ""
+        # ... but for fields without a name (as in tuples), we have to fall back
+        # to the newer method of using the field object directly as key. In
+        # older versions of GDB, this will just fail.
+        field_key = field
+      name_value_tuple = ( field_name, self.val[field_key] )
+      cs.append( name_value_tuple )
+
+    if self.hide_first_field:
+      cs = cs[1:]
+
+    return cs
+
+class RustTuplePrinter:
+  def __init__(self, val):
+    self.val = val
+
+  def to_string(self):
+    return None
+
+  def children(self):
+    cs = []
+    for field in self.val.type.fields():
+      cs.append( ("", self.val[field]) )
+
+    return cs
+
+  def display_hint(self):
+    return "array"
+
+class RustTupleStructPrinter:
+  def __init__(self, val, hide_first_field):
+    self.val = val
+    self.hide_first_field = hide_first_field
+
+  def to_string(self):
+    return self.val.type.tag
+
+  def children(self):
+    cs = []
+    for field in self.val.type.fields():
+      cs.append( ("", self.val[field]) )
+
+    if self.hide_first_field:
+      cs = cs[1:]
+
+    return cs
+
+  def display_hint(self):
+    return "array"
+
+class RustStringSlicePrinter:
+  def __init__(self, val):
+    self.val = val
+
+  def to_string(self):
+    slice_byte_len = self.val["length"]
+    return '"%s"' % self.val["data_ptr"].string(encoding = "utf-8",
+                                                length = slice_byte_len)
+
+class RustCStyleEnumPrinter:
+  def __init__(self, val):
+    assert val.type.code == gdb.TYPE_CODE_ENUM
+    self.val = val
+
+  def to_string(self):
+    return str(self.val)
+
+class IdentityPrinter:
+  def __init__(self, string):
+    self.string
+
+  def to_string(self):
+    return self.string
+
+STRUCT_KIND_REGULAR_STRUCT  = 0
+STRUCT_KIND_TUPLE_STRUCT    = 1
+STRUCT_KIND_TUPLE           = 2
+STRUCT_KIND_TUPLE_VARIANT   = 3
+STRUCT_KIND_STRUCT_VARIANT  = 4
+STRUCT_KIND_CSTYLE_VARIANT  = 5
+STRUCT_KIND_STR_SLICE       = 6
+
+def classify_struct(type):
+  if type.tag == "&str":
+    return STRUCT_KIND_STR_SLICE
+
+  fields = list(type.fields())
+  field_count = len(fields)
+
+  if field_count == 0:
+    return STRUCT_KIND_REGULAR_STRUCT
+
+  if fields[0].artificial:
+    if field_count == 1:
+      return STRUCT_KIND_CSTYLE_VARIANT
+    elif fields[1].name == None:
+      return STRUCT_KIND_TUPLE_VARIANT
+    else:
+      return STRUCT_KIND_STRUCT_VARIANT
+
+  if fields[0].name == None:
+    if type.tag.startswith("("):
+      return STRUCT_KIND_TUPLE
+    else:
+      return STRUCT_KIND_TUPLE_STRUCT
+
+  return STRUCT_KIND_REGULAR_STRUCT
+
+def extract_discriminant_value(enum_val):
+  assert enum_val.type.code == gdb.TYPE_CODE_UNION
+  for variant_descriptor in enum_val.type.fields():
+    variant_val = enum_val[variant_descriptor]
+    for field in variant_val.type.fields():
+      return (field.name, int(variant_val[field]))
+
+def first_field(val):
+  for field in val.type.fields():
+    return field
+
+def get_field_at_index(val, index):
+  i = 0
+  for field in val.type.fields():
+    if i == index:
+      return field
+  return None
index 7663cd1e3466abb3d0bfb1ff5d67d455e8aa86f7..a74bb748971356a24de6de0122245d7712b09242 100755 (executable)
@@ -34,7 +34,7 @@ preamble = '''// Copyright 2012-2014 The Rust Project Developers. See the COPYRI
 
 // NOTE: The following code was generated by "src/etc/unicode.py", do not edit directly
 
-#![allow(missing_doc, non_uppercase_statics, non_snake_case_functions)]
+#![allow(missing_doc, non_uppercase_statics, non_snake_case)]
 '''
 
 # Mapping taken from Table 12 from:
index f212cdd46380767e4ab6dafa396ed0840b739320..73464047319886d53d2990bddc636b13d980881c 100644 (file)
@@ -476,7 +476,7 @@ pub fn alloc(&self, object: T) -> &T {
     /// Grows the arena.
     #[inline(never)]
     fn grow(&self) {
-        let chunk = self.first.borrow_mut().take_unwrap();
+        let chunk = self.first.borrow_mut().take().unwrap();
         let new_capacity = chunk.capacity.checked_mul(&2).unwrap();
         let chunk = TypedArenaChunk::<T>::new(Some(chunk), new_capacity);
         self.ptr.set(chunk.start() as *const T);
@@ -489,13 +489,13 @@ fn grow(&self) {
 impl<T> Drop for TypedArena<T> {
     fn drop(&mut self) {
         // Determine how much was filled.
-        let start = self.first.borrow().get_ref().start() as uint;
+        let start = self.first.borrow().as_ref().unwrap().start() as uint;
         let end = self.ptr.get() as uint;
         let diff = (end - start) / mem::size_of::<T>();
 
         // Pass that to the `destroy` method.
         unsafe {
-            self.first.borrow_mut().get_mut_ref().destroy(diff)
+            self.first.borrow_mut().as_mut().unwrap().destroy(diff)
         }
     }
 }
index 47c56375ada180770cff843bd4a847a0964cd46e..643da9703648f5fbdc841b1369d85137aecd4df2 100644 (file)
@@ -49,16 +49,7 @@ struct Node<T> {
     value: T,
 }
 
-/// Note: stage0-specific version that lacks bound on A.
-#[cfg(stage0)]
-pub struct Items<'a, T> {
-    head: &'a Link<T>,
-    tail: Rawlink<Node<T>>,
-    nelem: uint,
-}
-
 /// An iterator over references to the items of a `DList`.
-#[cfg(not(stage0))]
 pub struct Items<'a, T:'a> {
     head: &'a Link<T>,
     tail: Rawlink<Node<T>>,
@@ -70,17 +61,7 @@ impl<'a, T> Clone for Items<'a, T> {
     fn clone(&self) -> Items<'a, T> { *self }
 }
 
-/// Note: stage0-specific version that lacks bound on A.
-#[cfg(stage0)]
-pub struct MutItems<'a, T> {
-    list: &'a mut DList<T>,
-    head: Rawlink<Node<T>>,
-    tail: Rawlink<Node<T>>,
-    nelem: uint,
-}
-
 /// An iterator over mutable references to the items of a `DList`.
-#[cfg(not(stage0))]
 pub struct MutItems<'a, T:'a> {
     list: &'a mut DList<T>,
     head: Rawlink<Node<T>>,
@@ -649,7 +630,7 @@ fn insert_next_node(&mut self, mut ins_node: Box<Node<A>>) {
                     None => return self.list.push_front_node(ins_node),
                     Some(prev) => prev,
                 };
-                let node_own = prev_node.next.take_unwrap();
+                let node_own = prev_node.next.take().unwrap();
                 ins_node.next = link_with_prev(node_own, Rawlink::some(&mut *ins_node));
                 prev_node.next = link_with_prev(ins_node, Rawlink::some(prev_node));
                 self.list.length += 1;
@@ -805,21 +786,21 @@ pub fn check_links<T>(list: &DList<T>) {
     fn test_basic() {
         let mut m: DList<Box<int>> = DList::new();
         assert_eq!(m.pop_front(), None);
-        assert_eq!(m.pop_back(), None);
+        assert_eq!(m.pop(), None);
         assert_eq!(m.pop_front(), None);
         m.push_front(box 1);
         assert_eq!(m.pop_front(), Some(box 1));
-        m.push_back(box 2);
-        m.push_back(box 3);
+        m.push(box 2);
+        m.push(box 3);
         assert_eq!(m.len(), 2);
         assert_eq!(m.pop_front(), Some(box 2));
         assert_eq!(m.pop_front(), Some(box 3));
         assert_eq!(m.len(), 0);
         assert_eq!(m.pop_front(), None);
-        m.push_back(box 1);
-        m.push_back(box 3);
-        m.push_back(box 5);
-        m.push_back(box 7);
+        m.push(box 1);
+        m.push(box 3);
+        m.push(box 5);
+        m.push(box 7);
         assert_eq!(m.pop_front(), Some(box 1));
 
         let mut n = DList::new();
@@ -856,19 +837,19 @@ fn test_append() {
         {
             let mut m = DList::new();
             let mut n = DList::new();
-            n.push_back(2i);
+            n.push(2i);
             m.append(n);
             assert_eq!(m.len(), 1);
-            assert_eq!(m.pop_back(), Some(2));
+            assert_eq!(m.pop(), Some(2));
             check_links(&m);
         }
         {
             let mut m = DList::new();
             let n = DList::new();
-            m.push_back(2i);
+            m.push(2i);
             m.append(n);
             assert_eq!(m.len(), 1);
-            assert_eq!(m.pop_back(), Some(2));
+            assert_eq!(m.pop(), Some(2));
             check_links(&m);
         }
 
@@ -889,10 +870,10 @@ fn test_prepend() {
         {
             let mut m = DList::new();
             let mut n = DList::new();
-            n.push_back(2i);
+            n.push(2i);
             m.prepend(n);
             assert_eq!(m.len(), 1);
-            assert_eq!(m.pop_back(), Some(2));
+            assert_eq!(m.pop(), Some(2));
             check_links(&m);
         }
 
@@ -950,9 +931,9 @@ fn test_iterator() {
     #[test]
     fn test_iterator_clone() {
         let mut n = DList::new();
-        n.push_back(2i);
-        n.push_back(3);
-        n.push_back(4);
+        n.push(2i);
+        n.push(3);
+        n.push(4);
         let mut it = n.iter();
         it.next();
         let mut jt = it.clone();
@@ -1007,7 +988,7 @@ fn test_mut_iter() {
         let mut n = DList::new();
         assert!(n.mut_iter().next().is_none());
         n.push_front(4i);
-        n.push_back(5);
+        n.push(5);
         let mut it = n.mut_iter();
         assert_eq!(it.size_hint(), (2, Some(2)));
         assert!(it.next().is_some());
@@ -1081,8 +1062,8 @@ fn test_insert_ordered() {
         assert_eq!(n.pop_front(), Some(1));
 
         let mut m = DList::new();
-        m.push_back(2i);
-        m.push_back(4);
+        m.push(2i);
+        m.push(4);
         m.insert_ordered(3);
         check_links(&m);
         assert_eq!(vec![2,3,4], m.move_iter().collect::<Vec<int>>());
@@ -1119,7 +1100,7 @@ fn test_eq() {
         assert!(n == m);
         n.push_front(1);
         assert!(n != m);
-        m.push_back(1);
+        m.push(1);
         assert!(n == m);
 
         let n = list_from([2i,3,4]);
@@ -1134,9 +1115,9 @@ fn test_hash() {
 
       assert!(hash::hash(&x) == hash::hash(&y));
 
-      x.push_back(1i);
-      x.push_back(2);
-      x.push_back(3);
+      x.push(1i);
+      x.push(2);
+      x.push(3);
 
       y.push_front(3i);
       y.push_front(2);
@@ -1216,19 +1197,19 @@ fn fuzz_test(sz: int) {
             let r: u8 = rand::random();
             match r % 6 {
                 0 => {
-                    m.pop_back();
+                    m.pop();
                     v.pop();
                 }
                 1 => {
                     m.pop_front();
-                    v.shift();
+                    v.remove(0);
                 }
                 2 | 4 =>  {
                     m.push_front(-i);
-                    v.unshift(-i);
+                    v.insert(0, -i);
                 }
                 3 | 5 | _ => {
-                    m.push_back(i);
+                    m.push(i);
                     v.push(i);
                 }
             }
@@ -1264,7 +1245,7 @@ fn bench_push_front(b: &mut test::Bencher) {
     fn bench_push_back(b: &mut test::Bencher) {
         let mut m: DList<int> = DList::new();
         b.iter(|| {
-            m.push_back(0);
+            m.push(0);
         })
     }
 
@@ -1272,8 +1253,8 @@ fn bench_push_back(b: &mut test::Bencher) {
     fn bench_push_back_pop_back(b: &mut test::Bencher) {
         let mut m: DList<int> = DList::new();
         b.iter(|| {
-            m.push_back(0);
-            m.pop_back();
+            m.push(0);
+            m.pop();
         })
     }
 
index ef26452a52902e8fd22d0d53edccb4af161c26ac..c59de19e822cc518dd1240bdc04ef8c0ce596741 100644 (file)
@@ -157,8 +157,8 @@ fn hash(&self, state: &mut S) {
 
     ( $($name:ident)+) => (
         impl<S: Writer, $($name: Hash<S>),*> Hash<S> for ($($name,)*) {
-            #[allow(uppercase_variables)]
             #[inline]
+            #[allow(non_snake_case)]
             fn hash(&self, state: &mut S) {
                 match *self {
                     ($(ref $name,)*) => {
@@ -293,7 +293,6 @@ fn hash(&self, state: &mut S) {
 
 #[cfg(test)]
 mod tests {
-    use std::prelude::*;
     use std::mem;
 
     use slice::ImmutableSlice;
index a98d9ddb9db027fab877948812d27bdef78774d3..175597c77f61ab52665f650a464adbb66cf4df73 100644 (file)
@@ -23,9 +23,6 @@
 #![feature(unsafe_destructor, import_shadowing)]
 #![no_std]
 
-// NOTE(stage0, pcwalton): Remove after snapshot.
-#![allow(unknown_features)]
-
 #[phase(plugin, link)] extern crate core;
 extern crate unicode;
 extern crate alloc;
index 905078ccc3c8c424c3a792b85fa0009725cb3d57..da8cf085218f453bef6fd53f3303ed64825e8e86 100644 (file)
@@ -515,14 +515,7 @@ fn siftdown(&mut self, pos: uint) {
     }
 }
 
-/// Note: stage0-specific version that lacks bound on A.
-#[cfg(stage0)]
-pub struct Items <'a, T> {
-    iter: slice::Items<'a, T>,
-}
-
 /// `PriorityQueue` iterator.
-#[cfg(not(stage0))]
 pub struct Items <'a, T:'a> {
     iter: slice::Items<'a, T>,
 }
index 6b293c9f4d8b248f6dfbb46e932b9e0e94964fb8..c71367265db02ec01de49acdcb2c578e4b7bf333 100644 (file)
@@ -293,17 +293,7 @@ pub fn mut_iter<'a>(&'a mut self) -> MutItems<'a, T> {
     }
 }
 
-/// Note: stage0-specific version that lacks bound on A.
-#[cfg(stage0)]
-pub struct Items<'a, T> {
-    lo: uint,
-    index: uint,
-    rindex: uint,
-    elts: &'a [Option<T>],
-}
-
 /// `RingBuf` iterator.
-#[cfg(not(stage0))]
 pub struct Items<'a, T:'a> {
     lo: uint,
     index: uint,
@@ -319,7 +309,7 @@ fn next(&mut self) -> Option<&'a T> {
         }
         let raw_index = raw_index(self.lo, self.elts.len(), self.index);
         self.index += 1;
-        Some(self.elts[raw_index].get_ref())
+        Some(self.elts[raw_index].as_ref().unwrap())
     }
 
     #[inline]
@@ -337,7 +327,7 @@ fn next_back(&mut self) -> Option<&'a T> {
         }
         self.rindex -= 1;
         let raw_index = raw_index(self.lo, self.elts.len(), self.rindex);
-        Some(self.elts[raw_index].get_ref())
+        Some(self.elts[raw_index].as_ref().unwrap())
     }
 }
 
@@ -353,21 +343,12 @@ fn idx(&mut self, j: uint) -> Option<&'a T> {
             None
         } else {
             let raw_index = raw_index(self.lo, self.elts.len(), self.index + j);
-            Some(self.elts[raw_index].get_ref())
+            Some(self.elts[raw_index].as_ref().unwrap())
         }
     }
 }
 
-/// Note: stage0-specific version that lacks bound on A.
-#[cfg(stage0)]
-pub struct MutItems<'a, T> {
-    remaining1: &'a mut [Option<T>],
-    remaining2: &'a mut [Option<T>],
-    nelts: uint,
-}
-
 /// `RingBuf` mutable iterator.
-#[cfg(not(stage0))]
 pub struct MutItems<'a, T:'a> {
     remaining1: &'a mut [Option<T>],
     remaining2: &'a mut [Option<T>],
@@ -560,9 +541,9 @@ fn test_simple() {
         assert_eq!(d.len(), 0u);
         d.push_front(17i);
         d.push_front(42i);
-        d.push_back(137);
+        d.push(137);
         assert_eq!(d.len(), 3u);
-        d.push_back(137);
+        d.push(137);
         assert_eq!(d.len(), 4u);
         debug!("{:?}", d.front());
         assert_eq!(*d.front().unwrap(), 42);
@@ -571,21 +552,21 @@ fn test_simple() {
         let mut i = d.pop_front();
         debug!("{:?}", i);
         assert_eq!(i, Some(42));
-        i = d.pop_back();
+        i = d.pop();
         debug!("{:?}", i);
         assert_eq!(i, Some(137));
-        i = d.pop_back();
+        i = d.pop();
         debug!("{:?}", i);
         assert_eq!(i, Some(137));
-        i = d.pop_back();
+        i = d.pop();
         debug!("{:?}", i);
         assert_eq!(i, Some(17));
         assert_eq!(d.len(), 0u);
-        d.push_back(3);
+        d.push(3);
         assert_eq!(d.len(), 1u);
         d.push_front(2);
         assert_eq!(d.len(), 2u);
-        d.push_back(4);
+        d.push(4);
         assert_eq!(d.len(), 3u);
         d.push_front(1);
         assert_eq!(d.len(), 4u);
@@ -610,22 +591,22 @@ fn test_boxes() {
         assert_eq!(deq.len(), 0);
         deq.push_front(a);
         deq.push_front(b);
-        deq.push_back(c);
+        deq.push(c);
         assert_eq!(deq.len(), 3);
-        deq.push_back(d);
+        deq.push(d);
         assert_eq!(deq.len(), 4);
         assert_eq!(deq.front(), Some(&b));
         assert_eq!(deq.back(), Some(&d));
         assert_eq!(deq.pop_front(), Some(b));
-        assert_eq!(deq.pop_back(), Some(d));
-        assert_eq!(deq.pop_back(), Some(c));
-        assert_eq!(deq.pop_back(), Some(a));
+        assert_eq!(deq.pop(), Some(d));
+        assert_eq!(deq.pop(), Some(c));
+        assert_eq!(deq.pop(), Some(a));
         assert_eq!(deq.len(), 0);
-        deq.push_back(c);
+        deq.push(c);
         assert_eq!(deq.len(), 1);
         deq.push_front(b);
         assert_eq!(deq.len(), 2);
-        deq.push_back(d);
+        deq.push(d);
         assert_eq!(deq.len(), 3);
         deq.push_front(a);
         assert_eq!(deq.len(), 4);
@@ -641,22 +622,22 @@ fn test_parameterized<T:Clone + PartialEq + Show>(a: T, b: T, c: T, d: T) {
         assert_eq!(deq.len(), 0);
         deq.push_front(a.clone());
         deq.push_front(b.clone());
-        deq.push_back(c.clone());
+        deq.push(c.clone());
         assert_eq!(deq.len(), 3);
-        deq.push_back(d.clone());
+        deq.push(d.clone());
         assert_eq!(deq.len(), 4);
         assert_eq!((*deq.front().unwrap()).clone(), b.clone());
         assert_eq!((*deq.back().unwrap()).clone(), d.clone());
         assert_eq!(deq.pop_front().unwrap(), b.clone());
-        assert_eq!(deq.pop_back().unwrap(), d.clone());
-        assert_eq!(deq.pop_back().unwrap(), c.clone());
-        assert_eq!(deq.pop_back().unwrap(), a.clone());
+        assert_eq!(deq.pop().unwrap(), d.clone());
+        assert_eq!(deq.pop().unwrap(), c.clone());
+        assert_eq!(deq.pop().unwrap(), a.clone());
         assert_eq!(deq.len(), 0);
-        deq.push_back(c.clone());
+        deq.push(c.clone());
         assert_eq!(deq.len(), 1);
         deq.push_front(b.clone());
         assert_eq!(deq.len(), 2);
-        deq.push_back(d.clone());
+        deq.push(d.clone());
         assert_eq!(deq.len(), 3);
         deq.push_front(a.clone());
         assert_eq!(deq.len(), 4);
@@ -680,7 +661,7 @@ fn test_push_front_grow() {
 
         let mut deq = RingBuf::new();
         for i in range(0u, 66) {
-            deq.push_back(i);
+            deq.push(i);
         }
 
         for i in range(0u, 66) {
@@ -718,7 +699,7 @@ fn bench_new(b: &mut test::Bencher) {
     fn bench_push_back(b: &mut test::Bencher) {
         let mut deq = RingBuf::new();
         b.iter(|| {
-            deq.push_back(0i);
+            deq.push(0i);
         })
     }
 
@@ -797,10 +778,10 @@ fn test_param_reccy() {
     #[test]
     fn test_with_capacity() {
         let mut d = RingBuf::with_capacity(0);
-        d.push_back(1i);
+        d.push(1i);
         assert_eq!(d.len(), 1);
         let mut d = RingBuf::with_capacity(50);
-        d.push_back(1i);
+        d.push(1i);
         assert_eq!(d.len(), 1);
     }
 
@@ -848,11 +829,11 @@ fn test_with_capacity_non_power_two() {
     #[test]
     fn test_reserve_exact() {
         let mut d = RingBuf::new();
-        d.push_back(0u64);
+        d.push(0u64);
         d.reserve_exact(50);
         assert_eq!(d.elts.capacity(), 50);
         let mut d = RingBuf::new();
-        d.push_back(0u32);
+        d.push(0u32);
         d.reserve_exact(50);
         assert_eq!(d.elts.capacity(), 50);
     }
@@ -860,11 +841,11 @@ fn test_reserve_exact() {
     #[test]
     fn test_reserve() {
         let mut d = RingBuf::new();
-        d.push_back(0u64);
+        d.push(0u64);
         d.reserve(50);
         assert_eq!(d.elts.capacity(), 64);
         let mut d = RingBuf::new();
-        d.push_back(0u32);
+        d.push(0u32);
         d.reserve(50);
         assert_eq!(d.elts.capacity(), 64);
     }
@@ -884,7 +865,7 @@ fn test_iter() {
         assert_eq!(d.iter().size_hint(), (0, Some(0)));
 
         for i in range(0i, 5) {
-            d.push_back(i);
+            d.push(i);
         }
         {
             let b: &[_] = &[&0,&1,&2,&3,&4];
@@ -915,7 +896,7 @@ fn test_rev_iter() {
         assert_eq!(d.iter().rev().next(), None);
 
         for i in range(0i, 5) {
-            d.push_back(i);
+            d.push(i);
         }
         {
             let b: &[_] = &[&4,&3,&2,&1,&0];
@@ -934,11 +915,11 @@ fn test_mut_rev_iter_wrap() {
         let mut d = RingBuf::with_capacity(3);
         assert!(d.mut_iter().rev().next().is_none());
 
-        d.push_back(1i);
-        d.push_back(2);
-        d.push_back(3);
+        d.push(1i);
+        d.push(2);
+        d.push(3);
         assert_eq!(d.pop_front(), Some(1));
-        d.push_back(4);
+        d.push(4);
 
         assert_eq!(d.mut_iter().rev().map(|x| *x).collect::<Vec<int>>(),
                    vec!(4, 3, 2));
@@ -1011,13 +992,13 @@ fn test_clone() {
         let mut d = RingBuf::new();
         d.push_front(17i);
         d.push_front(42);
-        d.push_back(137);
-        d.push_back(137);
+        d.push(137);
+        d.push(137);
         assert_eq!(d.len(), 4u);
         let mut e = d.clone();
         assert_eq!(e.len(), 4u);
         while !d.is_empty() {
-            assert_eq!(d.pop_back(), e.pop_back());
+            assert_eq!(d.pop(), e.pop());
         }
         assert_eq!(d.len(), 0u);
         assert_eq!(e.len(), 0u);
@@ -1030,15 +1011,15 @@ fn test_eq() {
         d.push_front(137i);
         d.push_front(17);
         d.push_front(42);
-        d.push_back(137);
+        d.push(137);
         let mut e = RingBuf::with_capacity(0);
-        e.push_back(42);
-        e.push_back(17);
-        e.push_back(137);
-        e.push_back(137);
+        e.push(42);
+        e.push(17);
+        e.push(137);
+        e.push(137);
         assert!(&e == &d);
-        e.pop_back();
-        e.push_back(0);
+        e.pop();
+        e.push(0);
         assert!(e != d);
         e.clear();
         assert!(e == RingBuf::new());
index 5ef1dd2ab2277e6bf773c889a29e044a751d66b0..b3b3bb1ea22434ba8086842742d621c30c20d906 100644 (file)
@@ -489,16 +489,7 @@ fn next_back(&mut self) -> Option<$elem> {
     }
 }
 
-/// Note: stage0-specific version that lacks bound on A.
-#[cfg(stage0)]
-pub struct Entries<'a, T> {
-    front: uint,
-    back: uint,
-    iter: slice::Items<'a, Option<T>>
-}
-
 /// Forward iterator over a map.
-#[cfg(not(stage0))]
 pub struct Entries<'a, T:'a> {
     front: uint,
     back: uint,
@@ -508,17 +499,8 @@ pub struct Entries<'a, T:'a> {
 iterator!(impl Entries -> (uint, &'a T), get_ref)
 double_ended_iterator!(impl Entries -> (uint, &'a T), get_ref)
 
-/// Note: stage0-specific version that lacks bound on A.
-#[cfg(stage0)]
-pub struct MutEntries<'a, T> {
-    front: uint,
-    back: uint,
-    iter: slice::MutItems<'a, Option<T>>
-}
-
 /// Forward iterator over the key-value pairs of a map, with the
 /// values being mutable.
-#[cfg(not(stage0))]
 pub struct MutEntries<'a, T:'a> {
     front: uint,
     back: uint,
index 3f9a179872e147725f6a9c4687a8197a8d899245..c13695e2b84ce4929102c8b88cdb8ceeea49affa 100644 (file)
@@ -2374,7 +2374,6 @@ mod bench {
     use test::Bencher;
     use test::black_box;
     use super::*;
-    use std::option::{None, Some};
     use std::iter::{Iterator, DoubleEndedIterator};
     use std::collections::Collection;
 
index 6bb1e4a5ad09cd967ee3453af3324d9deff1fb9f..80a7c6d4bad1dc5f90ae2f3342ffa46227512e8c 100644 (file)
@@ -668,20 +668,7 @@ pub fn mut_upper_bound<'a>(&'a mut self, k: &K) -> MutEntries<'a, K, V> {
     }
 }
 
-/// Note: stage0-specific version that lacks bound on A.
-#[cfg(stage0)]
-pub struct Entries<'a, K, V> {
-    stack: Vec<&'a TreeNode<K, V>>,
-    // See the comment on MutEntries; this is just to allow
-    // code-sharing (for this immutable-values iterator it *could* very
-    // well be Option<&'a TreeNode<K,V>>).
-    node: *const TreeNode<K, V>,
-    remaining_min: uint,
-    remaining_max: uint
-}
-
 /// Lazy forward iterator over a map
-#[cfg(not(stage0))]
 pub struct Entries<'a, K:'a, V:'a> {
     stack: Vec<&'a TreeNode<K, V>>,
     // See the comment on MutEntries; this is just to allow
@@ -692,49 +679,13 @@ pub struct Entries<'a, K:'a, V:'a> {
     remaining_max: uint
 }
 
-/// Note: stage0-specific version that lacks bound on A.
-#[cfg(stage0)]
-pub struct RevEntries<'a, K, V> {
-    iter: Entries<'a, K, V>,
-}
-
 /// Lazy backward iterator over a map
-#[cfg(not(stage0))]
 pub struct RevEntries<'a, K:'a, V:'a> {
     iter: Entries<'a, K, V>,
 }
 
-/// Note: stage0-specific version that lacks bound on A.
-#[cfg(stage0)]
-pub struct MutEntries<'a, K, V> {
-    stack: Vec<&'a mut TreeNode<K, V>>,
-    // Unfortunately, we require some unsafe-ness to get around the
-    // fact that we would be storing a reference *into* one of the
-    // nodes in the stack.
-    //
-    // As far as the compiler knows, this would let us invalidate the
-    // reference by assigning a new value to this node's position in
-    // its parent, which would cause this current one to be
-    // deallocated so this reference would be invalid. (i.e. the
-    // compilers complaints are 100% correct.)
-    //
-    // However, as far as you humans reading this code know (or are
-    // about to know, if you haven't read far enough down yet), we are
-    // only reading from the TreeNode.{left,right} fields. the only
-    // thing that is ever mutated is the .value field (although any
-    // actual mutation that happens is done externally, by the
-    // iterator consumer). So, don't be so concerned, rustc, we've got
-    // it under control.
-    //
-    // (This field can legitimately be null.)
-    node: *mut TreeNode<K, V>,
-    remaining_min: uint,
-    remaining_max: uint
-}
-
 /// Lazy forward iterator over a map that allows for the mutation of
 /// the values.
-#[cfg(not(stage0))]
 pub struct MutEntries<'a, K:'a, V:'a> {
     stack: Vec<&'a mut TreeNode<K, V>>,
     // Unfortunately, we require some unsafe-ness to get around the
@@ -761,14 +712,7 @@ pub struct MutEntries<'a, K:'a, V:'a> {
     remaining_max: uint
 }
 
-/// Note: stage0-specific version that lacks bound on A.
-#[cfg(stage0)]
-pub struct RevMutEntries<'a, K, V> {
-    iter: MutEntries<'a, K, V>,
-}
-
 /// Lazy backward iterator over a map
-#[cfg(not(stage0))]
 pub struct RevMutEntries<'a, K:'a, V:'a> {
     iter: MutEntries<'a, K, V>,
 }
@@ -1375,26 +1319,12 @@ pub fn union<'a>(&'a self, other: &'a TreeSet<T>) -> UnionItems<'a, T> {
     }
 }
 
-/// Note: stage0-specific version that lacks bound on A.
-#[cfg(stage0)]
-pub struct SetItems<'a, T> {
-    iter: Entries<'a, T, ()>
-}
-
 /// A lazy forward iterator over a set.
-#[cfg(not(stage0))]
 pub struct SetItems<'a, T:'a> {
     iter: Entries<'a, T, ()>
 }
 
-/// Note: stage0-specific version that lacks bound on A.
-#[cfg(stage0)]
-pub struct RevSetItems<'a, T> {
-    iter: RevEntries<'a, T, ()>
-}
-
 /// A lazy backward iterator over a set.
-#[cfg(not(stage0))]
 pub struct RevSetItems<'a, T:'a> {
     iter: RevEntries<'a, T, ()>
 }
@@ -1402,57 +1332,25 @@ pub struct RevSetItems<'a, T:'a> {
 /// A lazy forward iterator over a set that consumes the set while iterating.
 pub type MoveSetItems<T> = iter::Map<'static, (T, ()), T, MoveEntries<T, ()>>;
 
-/// Note: stage0-specific version that lacks bound on A.
-#[cfg(stage0)]
-pub struct DifferenceItems<'a, T> {
-    a: Peekable<&'a T, SetItems<'a, T>>,
-    b: Peekable<&'a T, SetItems<'a, T>>,
-}
-
 /// A lazy iterator producing elements in the set difference (in-order).
-#[cfg(not(stage0))]
 pub struct DifferenceItems<'a, T:'a> {
     a: Peekable<&'a T, SetItems<'a, T>>,
     b: Peekable<&'a T, SetItems<'a, T>>,
 }
 
-/// Note: stage0-specific version that lacks bound on A.
-#[cfg(stage0)]
-pub struct SymDifferenceItems<'a, T> {
-    a: Peekable<&'a T, SetItems<'a, T>>,
-    b: Peekable<&'a T, SetItems<'a, T>>,
-}
-
 /// A lazy iterator producing elements in the set symmetric difference (in-order).
-#[cfg(not(stage0))]
 pub struct SymDifferenceItems<'a, T:'a> {
     a: Peekable<&'a T, SetItems<'a, T>>,
     b: Peekable<&'a T, SetItems<'a, T>>,
 }
 
-/// Note: stage0-specific version that lacks bound on A.
-#[cfg(stage0)]
-pub struct IntersectionItems<'a, T> {
-    a: Peekable<&'a T, SetItems<'a, T>>,
-    b: Peekable<&'a T, SetItems<'a, T>>,
-}
-
 /// A lazy iterator producing elements in the set intersection (in-order).
-#[cfg(not(stage0))]
 pub struct IntersectionItems<'a, T:'a> {
     a: Peekable<&'a T, SetItems<'a, T>>,
     b: Peekable<&'a T, SetItems<'a, T>>,
 }
 
-/// Note: stage0-specific version that lacks bound on A.
-#[cfg(stage0)]
-pub struct UnionItems<'a, T> {
-    a: Peekable<&'a T, SetItems<'a, T>>,
-    b: Peekable<&'a T, SetItems<'a, T>>,
-}
-
 /// A lazy iterator producing elements in the set union (in-order).
-#[cfg(not(stage0))]
 pub struct UnionItems<'a, T:'a> {
     a: Peekable<&'a T, SetItems<'a, T>>,
     b: Peekable<&'a T, SetItems<'a, T>>,
@@ -1545,7 +1443,7 @@ pub fn new(key: K, value: V) -> TreeNode<K, V> {
 // Remove left horizontal link by rotating right
 fn skew<K: Ord, V>(node: &mut Box<TreeNode<K, V>>) {
     if node.left.as_ref().map_or(false, |x| x.level == node.level) {
-        let mut save = node.left.take_unwrap();
+        let mut save = node.left.take().unwrap();
         swap(&mut node.left, &mut save.right); // save.right now None
         swap(node, &mut save);
         node.right = Some(save);
@@ -1557,7 +1455,7 @@ fn skew<K: Ord, V>(node: &mut Box<TreeNode<K, V>>) {
 fn split<K: Ord, V>(node: &mut Box<TreeNode<K, V>>) {
     if node.right.as_ref().map_or(false,
       |x| x.right.as_ref().map_or(false, |y| y.level == node.level)) {
-        let mut save = node.right.take_unwrap();
+        let mut save = node.right.take().unwrap();
         swap(&mut node.right, &mut save.left); // save.left now None
         save.level += 1;
         swap(node, &mut save);
@@ -1661,7 +1559,7 @@ fn heir_swap<K: Ord, V>(node: &mut Box<TreeNode<K, V>>,
           Equal => {
             if save.left.is_some() {
                 if save.right.is_some() {
-                    let mut left = save.left.take_unwrap();
+                    let mut left = save.left.take().unwrap();
                     if left.right.is_some() {
                         heir_swap(save, &mut left.right);
                     } else {
@@ -1671,13 +1569,13 @@ fn heir_swap<K: Ord, V>(node: &mut Box<TreeNode<K, V>>,
                     save.left = Some(left);
                     (remove(&mut save.left, key), true)
                 } else {
-                    let new = save.left.take_unwrap();
+                    let new = save.left.take().unwrap();
                     let box TreeNode{value, ..} = replace(save, new);
-                    *save = save.left.take_unwrap();
+                    *save = save.left.take().unwrap();
                     (Some(value), true)
                 }
             } else if save.right.is_some() {
-                let new = save.right.take_unwrap();
+                let new = save.right.take().unwrap();
                 let box TreeNode{value, ..} = replace(save, new);
                 (Some(value), true)
             } else {
index e79ec67cba0ba2ce2e3371f19c28bf450313fe5d..fa8bcf94de1cd6fbfff2b2b06f6e32b1f817f39b 100644 (file)
@@ -857,17 +857,7 @@ fn remove<T>(count: &mut uint, child: &mut Child<T>, key: uint,
     return ret;
 }
 
-/// Note: stage0-specific version that lacks bound on A.
-#[cfg(stage0)]
-pub struct Entries<'a, T> {
-    stack: [slice::Items<'a, Child<T>>, .. NUM_CHUNKS],
-    length: uint,
-    remaining_min: uint,
-    remaining_max: uint
-}
-
 /// A forward iterator over a map.
-#[cfg(not(stage0))]
 pub struct Entries<'a, T:'a> {
     stack: [slice::Items<'a, Child<T>>, .. NUM_CHUNKS],
     length: uint,
@@ -875,18 +865,8 @@ pub struct Entries<'a, T:'a> {
     remaining_max: uint
 }
 
-/// Note: stage0-specific version that lacks bound on A.
-#[cfg(stage0)]
-pub struct MutEntries<'a, T> {
-    stack: [slice::MutItems<'a, Child<T>>, .. NUM_CHUNKS],
-    length: uint,
-    remaining_min: uint,
-    remaining_max: uint
-}
-
 /// A forward iterator over the key-value pairs of a map, with the
 /// values being mutable.
-#[cfg(not(stage0))]
 pub struct MutEntries<'a, T:'a> {
     stack: [slice::MutItems<'a, Child<T>>, .. NUM_CHUNKS],
     length: uint,
index 4cbe7d6d963fc5004730914972e9360f79bfa2a7..1cad9a3f8ca22e6b7e1941f18a403a0755a1b613 100644 (file)
@@ -99,7 +99,7 @@
 //!             // Take a reference to the inside of cache cell
 //!             let mut cache = self.span_tree_cache.borrow_mut();
 //!             if cache.is_some() {
-//!                 return cache.get_ref().clone();
+//!                 return cache.as_ref().unwrap().clone();
 //!             }
 //!
 //!             let span_tree = self.calc_span_tree();
@@ -324,22 +324,12 @@ fn eq(&self, other: &RefCell<T>) -> bool {
 
 /// Wraps a borrowed reference to a value in a `RefCell` box.
 #[unstable]
-#[cfg(not(stage0))]
 pub struct Ref<'b, T:'b> {
     // FIXME #12808: strange name to try to avoid interfering with
     // field accesses of the contained type via Deref
     _parent: &'b RefCell<T>
 }
 
-/// Dox.
-#[unstable]
-#[cfg(stage0)]
-pub struct Ref<'b, T> {
-    // FIXME #12808: strange name to try to avoid interfering with
-    // field accesses of the contained type via Deref
-    _parent: &'b RefCell<T>
-}
-
 #[unsafe_destructor]
 #[unstable]
 impl<'b, T> Drop for Ref<'b, T> {
@@ -379,22 +369,12 @@ pub fn clone_ref<'b, T>(orig: &Ref<'b, T>) -> Ref<'b, T> {
 
 /// Wraps a mutable borrowed reference to a value in a `RefCell` box.
 #[unstable]
-#[cfg(not(stage0))]
 pub struct RefMut<'b, T:'b> {
     // FIXME #12808: strange name to try to avoid interfering with
     // field accesses of the contained type via Deref
     _parent: &'b RefCell<T>
 }
 
-/// Dox.
-#[unstable]
-#[cfg(stage0)]
-pub struct RefMut<'b, T> {
-    // FIXME #12808: strange name to try to avoid interfering with
-    // field accesses of the contained type via Deref
-    _parent: &'b RefCell<T>
-}
-
 #[unsafe_destructor]
 #[unstable]
 impl<'b, T> Drop for RefMut<'b, T> {
index 4e9a72c6af544c95974646b77c9420bdae10640c..95267a8f9e5fab92d78e9b4a54a29c50678bd0f5 100644 (file)
@@ -12,7 +12,7 @@
 //!
 //! For more details, see ::unicode::char (a.k.a. std::char)
 
-#![allow(non_snake_case_functions)]
+#![allow(non_snake_case)]
 #![doc(primitive = "char")]
 
 use mem::transmute;
index c36150eb964e509dc1807244b29c62b4d3a1a9cd..9b59b410e7cc450022c10031e83dd50859068f96 100644 (file)
@@ -102,18 +102,11 @@ pub fn try_finally<T,U,R>(mutate: &mut T,
     try_fn(&mut *f.mutate, drop)
 }
 
-#[cfg(not(stage0))]
 struct Finallyalizer<'a,A:'a> {
     mutate: &'a mut A,
     dtor: |&mut A|: 'a
 }
 
-#[cfg(stage0)]
-struct Finallyalizer<'a,A> {
-    mutate: &'a mut A,
-    dtor: |&mut A|: 'a
-}
-
 #[unsafe_destructor]
 impl<'a,A> Drop for Finallyalizer<'a,A> {
     #[inline]
index f7ff92f5ce39bc669225d9e1c02e4407666bb8b9..32663e5eb0fe2b6c9bb4cca88f1213be9b4fe606 100644 (file)
@@ -668,7 +668,7 @@ macro_rules! tuple (
     () => ();
     ( $($name:ident,)+ ) => (
         impl<$($name:Show),*> Show for ($($name,)*) {
-            #[allow(uppercase_variables, dead_assignment)]
+            #[allow(non_snake_case, dead_assignment)]
             fn fmt(&self, f: &mut Formatter) -> Result {
                 try!(write!(f, "("));
                 let ($(ref $name,)*) = *self;
index 4ecc1b8f45fc09f0db753a96ae41894b589084ed..9636ce6a736daa86cbbe42a9c8cc360b600c13dc 100644 (file)
@@ -93,9 +93,6 @@ pub trait TyVisitor {
     fn visit_char(&mut self) -> bool;
 
     fn visit_estr_slice(&mut self) -> bool;
-    // NOTE: remove after snapshot
-    #[cfg(stage0)]
-    fn visit_estr_fixed(&mut self, n: uint, sz: uint, align: uint) -> bool;
 
     fn visit_box(&mut self, mtbl: uint, inner: *const TyDesc) -> bool;
     fn visit_uniq(&mut self, mtbl: uint, inner: *const TyDesc) -> bool;
@@ -103,11 +100,6 @@ pub trait TyVisitor {
     fn visit_rptr(&mut self, mtbl: uint, inner: *const TyDesc) -> bool;
 
     fn visit_evec_slice(&mut self, mtbl: uint, inner: *const TyDesc) -> bool;
-    // NOTE: remove after snapshot
-    #[cfg(stage0)]
-    fn visit_evec_fixed(&mut self, n: uint, sz: uint, align: uint,
-                        mtbl: uint, inner: *const TyDesc) -> bool;
-    #[cfg(not(stage0))]
     fn visit_evec_fixed(&mut self, n: uint, sz: uint, align: uint,
                         inner: *const TyDesc) -> bool;
 
index 7df8a7864d93a34bc1ddc90f1b533f8135e3dd28..da7f026aed4f5fd33c4fd03dc76724efd66f3700 100644 (file)
@@ -777,18 +777,10 @@ fn idx(&mut self, index: uint) -> Option<A> {
 
 /// A mutable reference to an iterator
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
-#[cfg(not(stage0))]
 pub struct ByRef<'a, T:'a> {
     iter: &'a mut T
 }
 
-/// Dox
-#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
-#[cfg(stage0)]
-pub struct ByRef<'a, T> {
-    iter: &'a mut T
-}
-
 impl<'a, A, T: Iterator<A>+'a> Iterator<A> for ByRef<'a, T> {
     #[inline]
     fn next(&mut self) -> Option<A> { self.iter.next() }
@@ -2199,7 +2191,12 @@ pub fn iterate<'a, T: Clone>(f: |T|: 'a -> T, seed: T) -> Iterate<'a, T> {
         if *first {
             *first = false;
         } else {
-            val.mutate(|x| (*f)(x));
+            match val.take() {
+                Some(x) => {
+                    *val = Some((*f)(x))
+                }
+                None => {}
+            }
         }
         val.clone()
     })
index 050e23481116317cf7a349eb3de260261b50828c..7e2ea492d4ccfc77e1506374adae623b38809270 100644 (file)
@@ -58,7 +58,7 @@
 
 #![no_std]
 #![feature(globs, intrinsics, lang_items, macro_rules, managed_boxes, phase)]
-#![feature(simd, unsafe_destructor, issue_5723_bootstrap)]
+#![feature(simd, unsafe_destructor)]
 #![deny(missing_doc)]
 
 mod macros;
index 42f74ab429a6f92bc53ab11e1c6bfd36de854daa..6d6ca59ce01eda067a5d8e5b70c51510543c9a83 100644 (file)
@@ -160,6 +160,8 @@ pub trait Signed: Num + Neg<Self> {
     /// Computes the absolute value.
     ///
     /// For `f32` and `f64`, `NaN` will be returned if the number is `NaN`.
+    ///
+    /// For signed integers, `::MIN` will be returned if the number is `::MIN`.
     fn abs(&self) -> Self;
 
     /// The positive difference of two numbers.
@@ -176,7 +178,7 @@ pub trait Signed: Num + Neg<Self> {
     /// * `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
     /// * `NaN` if the number is `NaN`
     ///
-    /// For `int`:
+    /// For signed integers:
     ///
     /// * `0` if the number is zero
     /// * `1` if the number is positive
@@ -272,6 +274,8 @@ fn is_negative(&self) -> bool { *self < 0.0 || (1.0 / *self) == $neg_inf }
 /// Computes the absolute value.
 ///
 /// For `f32` and `f64`, `NaN` will be returned if the number is `NaN`
+///
+/// For signed integers, `::MIN` will be returned if the number is `::MIN`.
 #[inline(always)]
 pub fn abs<T: Signed>(value: T) -> T {
     value.abs()
@@ -294,7 +298,7 @@ pub fn abs_sub<T: Signed>(x: T, y: T) -> T {
 /// * `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
 /// * `NaN` if the number is `NaN`
 ///
-/// For int:
+/// For signed integers:
 ///
 /// * `0` if the number is zero
 /// * `1` if the number is positive
index 23577dd29e0af0c75ee24a463e9ae5ba16e458e2..836285bc3135ad8e0bbd1dac18695439d2b89a5b 100644 (file)
@@ -775,7 +775,7 @@ impl<Result$(,$args)*>
         FnMut<($($args,)*),Result>
         for extern "Rust" fn($($args: $args,)*) -> Result {
             #[rust_call_abi_hack]
-            #[allow(uppercase_variables)]
+            #[allow(non_snake_case)]
             fn call_mut(&mut self, args: ($($args,)*)) -> Result {
                 let ($($args,)*) = args;
                 (*self)($($args,)*)
index 7773e03416e9e61bfda18d4dab35963421c81f00..537d78a67feb2230188246c1d81d9a0f47e95f46 100644 (file)
 //! }
 //! ```
 
+#![stable]
+
 use cmp::{PartialEq, Eq, Ord};
 use default::Default;
 use slice::Slice;
 
 /// The `Option` type.
 #[deriving(Clone, PartialEq, PartialOrd, Eq, Ord, Show)]
+#[stable]
 pub enum Option<T> {
     /// No value
     None,
@@ -173,6 +176,7 @@ impl<T> Option<T> {
 
     /// Returns `true` if the option is a `Some` value
     #[inline]
+    #[stable]
     pub fn is_some(&self) -> bool {
         match *self {
             Some(_) => true,
@@ -182,6 +186,7 @@ pub fn is_some(&self) -> bool {
 
     /// Returns `true` if the option is a `None` value
     #[inline]
+    #[stable]
     pub fn is_none(&self) -> bool {
         !self.is_some()
     }
@@ -207,18 +212,21 @@ pub fn is_none(&self) -> bool {
     /// println!("still can print num_as_str: {}", num_as_str);
     /// ```
     #[inline]
+    #[stable]
     pub fn as_ref<'r>(&'r self) -> Option<&'r T> {
         match *self { Some(ref x) => Some(x), None => None }
     }
 
     /// Convert from `Option<T>` to `Option<&mut T>`
     #[inline]
+    #[unstable = "waiting for mut conventions"]
     pub fn as_mut<'r>(&'r mut self) -> Option<&'r mut T> {
         match *self { Some(ref mut x) => Some(x), None => None }
     }
 
     /// Convert from `Option<T>` to `&mut [T]` (without copying)
     #[inline]
+    #[unstable = "waiting for mut conventions"]
     pub fn as_mut_slice<'r>(&'r mut self) -> &'r mut [T] {
         match *self {
             Some(ref mut x) => {
@@ -243,6 +251,7 @@ pub fn as_mut_slice<'r>(&'r mut self) -> &'r mut [T] {
     /// Fails if the value is a `None` with a custom failure message provided by
     /// `msg`.
     #[inline]
+    #[unstable = "waiting for conventions"]
     pub fn expect(self, msg: &str) -> T {
         match self {
             Some(val) => val,
@@ -262,6 +271,7 @@ pub fn expect(self, msg: &str) -> T {
     /// Instead, prefer to use pattern matching and handle the `None`
     /// case explicitly.
     #[inline]
+    #[unstable = "waiting for conventions"]
     pub fn unwrap(self) -> T {
         match self {
             Some(val) => val,
@@ -271,6 +281,7 @@ pub fn unwrap(self) -> T {
 
     /// Returns the contained value or a default.
     #[inline]
+    #[unstable = "waiting for conventions"]
     pub fn unwrap_or(self, def: T) -> T {
         match self {
             Some(x) => x,
@@ -280,6 +291,7 @@ pub fn unwrap_or(self, def: T) -> T {
 
     /// Returns the contained value or computes it from a closure.
     #[inline]
+    #[unstable = "waiting for conventions"]
     pub fn unwrap_or_else(self, f: || -> T) -> T {
         match self {
             Some(x) => x,
@@ -303,30 +315,45 @@ pub fn unwrap_or_else(self, f: || -> T) -> T {
     /// let num_as_int: Option<uint> = num_as_str.map(|n| n.len());
     /// ```
     #[inline]
+    #[unstable = "waiting for unboxed closures"]
     pub fn map<U>(self, f: |T| -> U) -> Option<U> {
         match self { Some(x) => Some(f(x)), None => None }
     }
 
     /// Applies a function to the contained value or returns a default.
     #[inline]
+    #[unstable = "waiting for unboxed closures"]
     pub fn map_or<U>(self, def: U, f: |T| -> U) -> U {
         match self { None => def, Some(t) => f(t) }
     }
 
+    /// Applies a function to the contained value or computes a default.
+    #[inline]
+    #[unstable = "waiting for unboxed closures"]
+    pub fn map_or_else<U>(self, def: || -> U, f: |T| -> U) -> U {
+        match self { None => def(), Some(t) => f(t) }
+    }
+
+    /// Deprecated.
+    ///
     /// Applies a function to the contained value or does nothing.
     /// Returns true if the contained value was mutated.
+    #[deprecated = "removed due to lack of use"]
     pub fn mutate(&mut self, f: |T| -> T) -> bool {
         if self.is_some() {
-            *self = Some(f(self.take_unwrap()));
+            *self = Some(f(self.take().unwrap()));
             true
         } else { false }
     }
 
+    /// Deprecated.
+    ///
     /// Applies a function to the contained value or sets it to a default.
     /// Returns true if the contained value was mutated, or false if set to the default.
+    #[deprecated = "removed due to lack of use"]
     pub fn mutate_or_set(&mut self, def: T, f: |T| -> T) -> bool {
         if self.is_some() {
-            *self = Some(f(self.take_unwrap()));
+            *self = Some(f(self.take().unwrap()));
             true
         } else {
             *self = Some(def);
@@ -340,18 +367,21 @@ pub fn mutate_or_set(&mut self, def: T, f: |T| -> T) -> bool {
 
     /// Returns an iterator over the possibly contained value.
     #[inline]
+    #[unstable = "waiting for iterator conventions"]
     pub fn iter<'r>(&'r self) -> Item<&'r T> {
         Item{opt: self.as_ref()}
     }
 
     /// Returns a mutable iterator over the possibly contained value.
     #[inline]
+    #[unstable = "waiting for iterator conventions"]
     pub fn mut_iter<'r>(&'r mut self) -> Item<&'r mut T> {
         Item{opt: self.as_mut()}
     }
 
     /// Returns a consuming iterator over the possibly contained value.
     #[inline]
+    #[unstable = "waiting for iterator conventions"]
     pub fn move_iter(self) -> Item<T> {
         Item{opt: self}
     }
@@ -362,6 +392,7 @@ pub fn move_iter(self) -> Item<T> {
 
     /// Returns `None` if the option is `None`, otherwise returns `optb`.
     #[inline]
+    #[stable]
     pub fn and<U>(self, optb: Option<U>) -> Option<U> {
         match self {
             Some(_) => optb,
@@ -372,6 +403,7 @@ pub fn and<U>(self, optb: Option<U>) -> Option<U> {
     /// Returns `None` if the option is `None`, otherwise calls `f` with the
     /// wrapped value and returns the result.
     #[inline]
+    #[unstable = "waiting for unboxed closures"]
     pub fn and_then<U>(self, f: |T| -> Option<U>) -> Option<U> {
         match self {
             Some(x) => f(x),
@@ -381,6 +413,7 @@ pub fn and_then<U>(self, f: |T| -> Option<U>) -> Option<U> {
 
     /// Returns the option if it contains a value, otherwise returns `optb`.
     #[inline]
+    #[stable]
     pub fn or(self, optb: Option<T>) -> Option<T> {
         match self {
             Some(_) => self,
@@ -391,6 +424,7 @@ pub fn or(self, optb: Option<T>) -> Option<T> {
     /// Returns the option if it contains a value, otherwise calls `f` and
     /// returns the result.
     #[inline]
+    #[unstable = "waiting for unboxed closures"]
     pub fn or_else(self, f: || -> Option<T>) -> Option<T> {
         match self {
             Some(_) => self,
@@ -404,12 +438,16 @@ pub fn or_else(self, f: || -> Option<T>) -> Option<T> {
 
     /// Takes the value out of the option, leaving a `None` in its place.
     #[inline]
+    #[stable]
     pub fn take(&mut self) -> Option<T> {
         mem::replace(self, None)
     }
 
+    /// Deprecated.
+    ///
     /// Filters an optional value using a given function.
     #[inline(always)]
+    #[deprecated = "removed due to lack of use"]
     pub fn filtered(self, f: |t: &T| -> bool) -> Option<T> {
         match self {
             Some(x) => if f(&x) { Some(x) } else { None },
@@ -417,8 +455,11 @@ pub fn filtered(self, f: |t: &T| -> bool) -> Option<T> {
         }
     }
 
+    /// Deprecated.
+    ///
     /// Applies a function zero or more times until the result is `None`.
     #[inline]
+    #[deprecated = "removed due to lack of use"]
     pub fn while_some(self, f: |v: T| -> Option<T>) {
         let mut opt = self;
         loop {
@@ -433,6 +474,8 @@ pub fn while_some(self, f: |v: T| -> Option<T>) {
     // Common special cases
     /////////////////////////////////////////////////////////////////////////
 
+    /// Deprecated: use `take().unwrap()` instead.
+    ///
     /// The option dance. Moves a value out of an option type and returns it,
     /// replacing the original with `None`.
     ///
@@ -440,6 +483,7 @@ pub fn while_some(self, f: |v: T| -> Option<T>) {
     ///
     /// Fails if the value equals `None`.
     #[inline]
+    #[deprecated = "use take().unwrap() instead"]
     pub fn take_unwrap(&mut self) -> T {
         match self.take() {
             Some(x) => x,
@@ -447,6 +491,8 @@ pub fn take_unwrap(&mut self) -> T {
         }
     }
 
+    /// Deprecated: use `as_ref().unwrap()` instead.
+    ///
     /// Gets an immutable reference to the value inside an option.
     ///
     /// # Failure
@@ -460,6 +506,7 @@ pub fn take_unwrap(&mut self) -> T {
     /// Instead, prefer to use pattern matching and handle the `None`
     /// case explicitly.
     #[inline]
+    #[deprecated = "use .as_ref().unwrap() instead"]
     pub fn get_ref<'a>(&'a self) -> &'a T {
         match *self {
             Some(ref x) => x,
@@ -467,6 +514,8 @@ pub fn get_ref<'a>(&'a self) -> &'a T {
         }
     }
 
+    /// Deprecated: use `as_mut().unwrap()` instead.
+    ///
     /// Gets a mutable reference to the value inside an option.
     ///
     /// # Failure
@@ -480,6 +529,7 @@ pub fn get_ref<'a>(&'a self) -> &'a T {
     /// Instead, prefer to use pattern matching and handle the `None`
     /// case explicitly.
     #[inline]
+    #[deprecated = "use .as_mut().unwrap() instead"]
     pub fn get_mut_ref<'a>(&'a mut self) -> &'a mut T {
         match *self {
             Some(ref mut x) => x,
@@ -512,6 +562,7 @@ impl<T: Default> Option<T> {
     /// assert_eq!(0i, bad_year);
     /// ```
     #[inline]
+    #[unstable = "waiting for conventions"]
     pub fn unwrap_or_default(self) -> T {
         match self {
             Some(x) => x,
@@ -527,6 +578,7 @@ pub fn unwrap_or_default(self) -> T {
 impl<T> Slice<T> for Option<T> {
     /// Convert from `Option<T>` to `&[T]` (without copying)
     #[inline]
+    #[stable]
     fn as_slice<'a>(&'a self) -> &'a [T] {
         match *self {
             Some(ref x) => slice::ref_slice(x),
@@ -552,6 +604,7 @@ fn default() -> Option<T> { None }
 /// The `Item` iterator is returned by the `iter`, `mut_iter` and `move_iter`
 /// methods on `Option`.
 #[deriving(Clone)]
+#[unstable = "waiting for iterator conventions"]
 pub struct Item<A> {
     opt: Option<A>
 }
@@ -584,54 +637,62 @@ impl<A> ExactSize<A> for Item<A> {}
 // Free functions
 /////////////////////////////////////////////////////////////////////////////
 
-/// Takes each element in the `Iterator`: if it is `None`, no further
-/// elements are taken, and the `None` is returned. Should no `None` occur, a
-/// vector containing the values of each `Option` is returned.
-///
-/// Here is an example which increments every integer in a vector,
-/// checking for overflow:
-///
-/// ```rust
-/// use std::option;
-/// use std::uint;
-///
-/// let v = vec!(1u, 2u);
-/// let res: Option<Vec<uint>> = option::collect(v.iter().map(|x: &uint|
-///     if *x == uint::MAX { None }
-///     else { Some(x + 1) }
-/// ));
-/// assert!(res == Some(vec!(2u, 3u)));
-/// ```
+/// Deprecated: use `Iterator::collect` instead.
 #[inline]
-pub fn collect<T, Iter: Iterator<Option<T>>, V: FromIterator<T>>(iter: Iter) -> Option<V> {
-    // FIXME(#11084): This could be replaced with Iterator::scan when this
-    // performance bug is closed.
-
-    struct Adapter<Iter> {
-        iter: Iter,
-        found_none: bool,
-    }
-
-    impl<T, Iter: Iterator<Option<T>>> Iterator<T> for Adapter<Iter> {
-        #[inline]
-        fn next(&mut self) -> Option<T> {
-            match self.iter.next() {
-                Some(Some(value)) => Some(value),
-                Some(None) => {
-                    self.found_none = true;
-                    None
+#[deprecated = "use Iterator::collect instead"]
+pub fn collect<T, Iter: Iterator<Option<T>>, V: FromIterator<T>>(mut iter: Iter) -> Option<V> {
+    iter.collect()
+}
+
+impl<A, V: FromIterator<A>> FromIterator<Option<A>> for Option<V> {
+    /// Takes each element in the `Iterator`: if it is `None`, no further
+    /// elements are taken, and the `None` is returned. Should no `None` occur, a
+    /// container with the values of each `Option` is returned.
+    ///
+    /// Here is an example which increments every integer in a vector,
+    /// checking for overflow:
+    ///
+    /// ```rust
+    /// use std::uint;
+    ///
+    /// let v = vec!(1u, 2u);
+    /// let res: Option<Vec<uint>> = v.iter().map(|x: &uint|
+    ///     if *x == uint::MAX { None }
+    ///     else { Some(x + 1) }
+    /// ).collect();
+    /// assert!(res == Some(vec!(2u, 3u)));
+    /// ```
+    #[inline]
+    fn from_iter<I: Iterator<Option<A>>>(iter: I) -> Option<V> {
+        // FIXME(#11084): This could be replaced with Iterator::scan when this
+        // performance bug is closed.
+
+        struct Adapter<Iter> {
+            iter: Iter,
+            found_none: bool,
+        }
+
+        impl<T, Iter: Iterator<Option<T>>> Iterator<T> for Adapter<Iter> {
+            #[inline]
+            fn next(&mut self) -> Option<T> {
+                match self.iter.next() {
+                    Some(Some(value)) => Some(value),
+                    Some(None) => {
+                        self.found_none = true;
+                        None
+                    }
+                    None => None,
                 }
-                None => None,
             }
         }
-    }
 
-    let mut adapter = Adapter { iter: iter, found_none: false };
-    let v: V = FromIterator::from_iter(adapter.by_ref());
+        let mut adapter = Adapter { iter: iter, found_none: false };
+        let v: V = FromIterator::from_iter(adapter.by_ref());
 
-    if adapter.found_none {
-        None
-    } else {
-        Some(v)
+        if adapter.found_none {
+            None
+        } else {
+            Some(v)
+        }
     }
 }
index 5daa693c77400267221036f4dbf2faf0a0029b13..188ef2a3b8879cccdba84198e7bde613ce38e9dc 100644 (file)
@@ -51,12 +51,6 @@ pub struct Procedure {
 ///
 /// This struct does not have a `Repr` implementation
 /// because there is no way to refer to all trait objects generically.
-#[cfg(stage0)]
-pub struct TraitObject {
-    pub vtable: *mut (),
-    pub data: *mut (),
-}
-#[cfg(not(stage0))]
 pub struct TraitObject {
     pub data: *mut (),
     pub vtable: *mut (),
index 980a9c7506f362291695eaa20e81a40cc8af74a2..bf351ecc89b1fd44702ef8c049c730fc6c99aaf2 100644 (file)
 //! the context. The caller of `fail!` should assume that execution
 //! will not resume after failure, that failure is catastrophic.
 
+#![stable]
+
 use clone::Clone;
 use cmp::PartialEq;
 use std::fmt::Show;
-use iter::{Iterator, FromIterator};
+use slice;
+use slice::Slice;
+use iter::{Iterator, DoubleEndedIterator, FromIterator, ExactSize};
 use option::{None, Option, Some};
 
 /// `Result` is a type that represents either success (`Ok`) or failure (`Err`).
 /// See the [`std::result`](index.html) module documentation for details.
 #[deriving(Clone, PartialEq, PartialOrd, Eq, Ord, Show)]
 #[must_use]
+#[stable]
 pub enum Result<T, E> {
     /// Contains the success value
     Ok(T),
@@ -315,6 +320,7 @@ impl<T, E> Result<T, E> {
     /// # }
     /// ~~~
     #[inline]
+    #[stable]
     pub fn is_ok(&self) -> bool {
         match *self {
             Ok(_) => true,
@@ -335,6 +341,7 @@ pub fn is_ok(&self) -> bool {
     /// assert!(bogus.is_err());
     /// ~~~
     #[inline]
+    #[stable]
     pub fn is_err(&self) -> bool {
         !self.is_ok()
     }
@@ -362,6 +369,7 @@ pub fn is_err(&self) -> bool {
     /// let bdays: File = bdays.ok().expect("unable to open birthday file");
     /// ~~~
     #[inline]
+    #[stable]
     pub fn ok(self) -> Option<T> {
         match self {
             Ok(x)  => Some(x),
@@ -374,6 +382,7 @@ pub fn ok(self) -> Option<T> {
     /// Converts `self` into an `Option<T>`, consuming `self`,
     /// and discarding the value, if any.
     #[inline]
+    #[stable]
     pub fn err(self) -> Option<E> {
         match self {
             Ok(_)  => None,
@@ -390,6 +399,7 @@ pub fn err(self) -> Option<E> {
     /// Produces a new `Result`, containing a reference
     /// into the original, leaving the original in place.
     #[inline]
+    #[stable]
     pub fn as_ref<'r>(&'r self) -> Result<&'r T, &'r E> {
         match *self {
             Ok(ref x) => Ok(x),
@@ -399,6 +409,7 @@ pub fn as_ref<'r>(&'r self) -> Result<&'r T, &'r E> {
 
     /// Convert from `Result<T, E>` to `Result<&mut T, &mut E>`
     #[inline]
+    #[unstable = "waiting for mut conventions"]
     pub fn as_mut<'r>(&'r mut self) -> Result<&'r mut T, &'r mut E> {
         match *self {
             Ok(ref mut x) => Ok(x),
@@ -406,6 +417,20 @@ pub fn as_mut<'r>(&'r mut self) -> Result<&'r mut T, &'r mut E> {
         }
     }
 
+    /// Convert from `Result<T, E>` to `&mut [T]` (without copying)
+    #[inline]
+    #[unstable = "waiting for mut conventions"]
+    pub fn as_mut_slice<'r>(&'r mut self) -> &'r mut [T] {
+        match *self {
+            Ok(ref mut x) => slice::mut_ref_slice(x),
+            Err(_) => {
+                // work around lack of implicit coercion from fixed-size array to slice
+                let emp: &mut [_] = &mut [];
+                emp
+            }
+        }
+    }
+
     /////////////////////////////////////////////////////////////////////////
     // Transforming contained values
     /////////////////////////////////////////////////////////////////////////
@@ -441,6 +466,7 @@ pub fn as_mut<'r>(&'r mut self) -> Result<&'r mut T, &'r mut E> {
     /// assert!(sum == 10);
     /// ~~~
     #[inline]
+    #[unstable = "waiting for unboxed closures"]
     pub fn map<U>(self, op: |T| -> U) -> Result<U,E> {
         match self {
           Ok(t) => Ok(op(t)),
@@ -454,6 +480,7 @@ pub fn map<U>(self, op: |T| -> U) -> Result<U,E> {
     /// This function can be used to pass through a successful result while handling
     /// an error.
     #[inline]
+    #[unstable = "waiting for unboxed closures"]
     pub fn map_err<F>(self, op: |E| -> F) -> Result<T,F> {
         match self {
           Ok(t) => Ok(t),
@@ -461,12 +488,39 @@ pub fn map_err<F>(self, op: |E| -> F) -> Result<T,F> {
         }
     }
 
+
+    /////////////////////////////////////////////////////////////////////////
+    // Iterator constructors
+    /////////////////////////////////////////////////////////////////////////
+
+    /// Returns an iterator over the possibly contained value.
+    #[inline]
+    #[unstable = "waiting for iterator conventions"]
+    pub fn iter<'r>(&'r self) -> Item<&'r T> {
+        Item{opt: self.as_ref().ok()}
+    }
+
+    /// Returns a mutable iterator over the possibly contained value.
+    #[inline]
+    #[unstable = "waiting for iterator conventions"]
+    pub fn mut_iter<'r>(&'r mut self) -> Item<&'r mut T> {
+        Item{opt: self.as_mut().ok()}
+    }
+
+    /// Returns a consuming iterator over the possibly contained value.
+    #[inline]
+    #[unstable = "waiting for iterator conventions"]
+    pub fn move_iter(self) -> Item<T> {
+        Item{opt: self.ok()}
+    }
+
     ////////////////////////////////////////////////////////////////////////
     // Boolean operations on the values, eager and lazy
     /////////////////////////////////////////////////////////////////////////
 
     /// Returns `res` if the result is `Ok`, otherwise returns the `Err` value of `self`.
     #[inline]
+    #[stable]
     pub fn and<U>(self, res: Result<U, E>) -> Result<U, E> {
         match self {
             Ok(_) => res,
@@ -478,6 +532,7 @@ pub fn and<U>(self, res: Result<U, E>) -> Result<U, E> {
     ///
     /// This function can be used for control flow based on result values
     #[inline]
+    #[unstable = "waiting for unboxed closures"]
     pub fn and_then<U>(self, op: |T| -> Result<U, E>) -> Result<U, E> {
         match self {
             Ok(t) => op(t),
@@ -487,6 +542,7 @@ pub fn and_then<U>(self, op: |T| -> Result<U, E>) -> Result<U, E> {
 
     /// Returns `res` if the result is `Err`, otherwise returns the `Ok` value of `self`.
     #[inline]
+    #[stable]
     pub fn or(self, res: Result<T, E>) -> Result<T, E> {
         match self {
             Ok(_) => self,
@@ -498,6 +554,7 @@ pub fn or(self, res: Result<T, E>) -> Result<T, E> {
     ///
     /// This function can be used for control flow based on result values
     #[inline]
+    #[unstable = "waiting for unboxed closures"]
     pub fn or_else<F>(self, op: |E| -> Result<T, F>) -> Result<T, F> {
         match self {
             Ok(t) => Ok(t),
@@ -508,6 +565,7 @@ pub fn or_else<F>(self, op: |E| -> Result<T, F>) -> Result<T, F> {
     /// Unwraps a result, yielding the content of an `Ok`.
     /// Else it returns `optb`.
     #[inline]
+    #[unstable = "waiting for conventions"]
     pub fn unwrap_or(self, optb: T) -> T {
         match self {
             Ok(t) => t,
@@ -518,6 +576,7 @@ pub fn unwrap_or(self, optb: T) -> T {
     /// Unwraps a result, yielding the content of an `Ok`.
     /// If the value is an `Err` then it calls `op` with its value.
     #[inline]
+    #[unstable = "waiting for conventions"]
     pub fn unwrap_or_else(self, op: |E| -> T) -> T {
         match self {
             Ok(t) => t,
@@ -541,6 +600,7 @@ impl<T, E: Show> Result<T, E> {
     /// Fails if the value is an `Err`, with a custom failure message provided
     /// by the `Err`'s value.
     #[inline]
+    #[unstable = "waiting for conventions"]
     pub fn unwrap(self) -> T {
         match self {
             Ok(t) => t,
@@ -558,6 +618,7 @@ impl<T: Show, E> Result<T, E> {
     /// Fails if the value is an `Ok`, with a custom failure message provided
     /// by the `Ok`'s value.
     #[inline]
+    #[unstable = "waiting for conventions"]
     pub fn unwrap_err(self) -> E {
         match self {
             Ok(t) =>
@@ -568,57 +629,124 @@ pub fn unwrap_err(self) -> E {
 }
 
 /////////////////////////////////////////////////////////////////////////////
-// Free functions
+// Trait implementations
 /////////////////////////////////////////////////////////////////////////////
 
-/// Takes each element in the `Iterator`: if it is an `Err`, no further
-/// elements are taken, and the `Err` is returned. Should no `Err` occur, a
-/// vector containing the values of each `Result` is returned.
-///
-/// Here is an example which increments every integer in a vector,
-/// checking for overflow:
-///
-/// ```rust
-/// use std::result;
-/// use std::uint;
+impl<T, E> Slice<T> for Result<T, E> {
+    /// Convert from `Result<T, E>` to `&[T]` (without copying)
+    #[inline]
+    #[stable]
+    fn as_slice<'a>(&'a self) -> &'a [T] {
+        match *self {
+            Ok(ref x) => slice::ref_slice(x),
+            Err(_) => {
+                // work around lack of implicit coercion from fixed-size array to slice
+                let emp: &[_] = &[];
+                emp
+            }
+        }
+    }
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// The Result Iterator
+/////////////////////////////////////////////////////////////////////////////
+
+/// A `Result` iterator that yields either one or zero elements
 ///
-/// let v = vec!(1u, 2u);
-/// let res: Result<Vec<uint>, &'static str> = result::collect(v.iter().map(|x: &uint|
-///     if *x == uint::MAX { Err("Overflow!") }
-///     else { Ok(x + 1) }
-/// ));
-/// assert!(res == Ok(vec!(2u, 3u)));
-/// ```
-#[inline]
-pub fn collect<T, E, Iter: Iterator<Result<T, E>>, V: FromIterator<T>>(iter: Iter) -> Result<V, E> {
-    // FIXME(#11084): This could be replaced with Iterator::scan when this
-    // performance bug is closed.
+/// The `Item` iterator is returned by the `iter`, `mut_iter` and `move_iter`
+/// methods on `Result`.
+#[deriving(Clone)]
+#[unstable = "waiting for iterator conventions"]
+pub struct Item<T> {
+    opt: Option<T>
+}
+
+impl<T> Iterator<T> for Item<T> {
+    #[inline]
+    fn next(&mut self) -> Option<T> {
+        self.opt.take()
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (uint, Option<uint>) {
+        match self.opt {
+            Some(_) => (1, Some(1)),
+            None => (0, Some(0)),
+        }
+    }
+}
 
-    struct Adapter<Iter, E> {
-        iter: Iter,
-        err: Option<E>,
+impl<A> DoubleEndedIterator<A> for Item<A> {
+    #[inline]
+    fn next_back(&mut self) -> Option<A> {
+        self.opt.take()
     }
+}
+
+impl<A> ExactSize<A> for Item<A> {}
 
-    impl<T, E, Iter: Iterator<Result<T, E>>> Iterator<T> for Adapter<Iter, E> {
-        #[inline]
-        fn next(&mut self) -> Option<T> {
-            match self.iter.next() {
-                Some(Ok(value)) => Some(value),
-                Some(Err(err)) => {
-                    self.err = Some(err);
-                    None
+/////////////////////////////////////////////////////////////////////////////
+// Free functions
+/////////////////////////////////////////////////////////////////////////////
+
+/// Deprecated: use `Iterator::collect`.
+#[inline]
+#[deprecated = "use Iterator::collect instead"]
+pub fn collect<T, E, Iter: Iterator<Result<T, E>>, V: FromIterator<T>>(mut iter: Iter)
+                                                                       -> Result<V, E> {
+    iter.collect()
+}
+
+impl<A, E, V: FromIterator<A>> FromIterator<Result<A, E>> for Result<V, E> {
+    /// Takes each element in the `Iterator`: if it is an `Err`, no further
+    /// elements are taken, and the `Err` is returned. Should no `Err` occur, a
+    /// container with the values of each `Result` is returned.
+    ///
+    /// Here is an example which increments every integer in a vector,
+    /// checking for overflow:
+    ///
+    /// ```rust
+    /// use std::uint;
+    ///
+    /// let v = vec!(1u, 2u);
+    /// let res: Result<Vec<uint>, &'static str> = v.iter().map(|x: &uint|
+    ///     if *x == uint::MAX { Err("Overflow!") }
+    ///     else { Ok(x + 1) }
+    /// ).collect();
+    /// assert!(res == Ok(vec!(2u, 3u)));
+    /// ```
+    #[inline]
+    fn from_iter<I: Iterator<Result<A, E>>>(iter: I) -> Result<V, E> {
+        // FIXME(#11084): This could be replaced with Iterator::scan when this
+        // performance bug is closed.
+
+        struct Adapter<Iter, E> {
+            iter: Iter,
+            err: Option<E>,
+        }
+
+        impl<T, E, Iter: Iterator<Result<T, E>>> Iterator<T> for Adapter<Iter, E> {
+            #[inline]
+            fn next(&mut self) -> Option<T> {
+                match self.iter.next() {
+                    Some(Ok(value)) => Some(value),
+                    Some(Err(err)) => {
+                        self.err = Some(err);
+                        None
+                    }
+                    None => None,
                 }
-                None => None,
             }
         }
-    }
 
-    let mut adapter = Adapter { iter: iter, err: None };
-    let v: V = FromIterator::from_iter(adapter.by_ref());
+        let mut adapter = Adapter { iter: iter, err: None };
+        let v: V = FromIterator::from_iter(adapter.by_ref());
 
-    match adapter.err {
-        Some(err) => Err(err),
-        None => Ok(v),
+        match adapter.err {
+            Some(err) => Err(err),
+            None => Ok(v),
+        }
     }
 }
 
@@ -627,6 +755,7 @@ fn next(&mut self) -> Option<T> {
 /// If an `Err` is encountered, it is immediately returned.
 /// Otherwise, the folded value is returned.
 #[inline]
+#[experimental]
 pub fn fold<T,
             V,
             E,
@@ -644,12 +773,15 @@ pub fn fold<T,
     Ok(init)
 }
 
+/// Deprecated.
+///
 /// Perform a trivial fold operation over the result values
 /// from an iterator.
 ///
 /// If an `Err` is encountered, it is immediately returned.
 /// Otherwise, a simple `Ok(())` is returned.
 #[inline]
+#[deprecated = "use fold instead"]
 pub fn fold_<T,E,Iter:Iterator<Result<T,E>>>(iterator: Iter) -> Result<(),E> {
     fold(iterator, (), |_, _| ())
 }
index 5a70cd8c847dacab567827e60873fd9b23d9943a..5070a3973d140b977611d723160ddb0101bbe768 100644 (file)
@@ -1125,7 +1125,6 @@ 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.
-#[cfg(not(stage0))]
 #[experimental = "needs review"]
 pub struct Splits<'a, T:'a> {
     v: &'a [T],
@@ -1133,14 +1132,6 @@ pub struct Splits<'a, T:'a> {
     finished: bool
 }
 
-/// Dox.
-#[cfg(stage0)]
-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]
@@ -1192,7 +1183,6 @@ fn next_back(&mut self) -> Option<&'a [T]> {
 
 /// An iterator over the subslices of the vector which are separated
 /// by elements that match `pred`.
-#[cfg(not(stage0))]
 #[experimental = "needs review"]
 pub struct MutSplits<'a, T:'a> {
     v: &'a mut [T],
@@ -1200,14 +1190,6 @@ pub struct MutSplits<'a, T:'a> {
     finished: bool
 }
 
-/// Dox
-#[cfg(stage0)]
-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]
@@ -1270,7 +1252,6 @@ 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.
-#[cfg(not(stage0))]
 #[experimental = "needs review"]
 pub struct SplitsN<'a, T:'a> {
     iter: Splits<'a, T>,
@@ -1278,14 +1259,6 @@ pub struct SplitsN<'a, T:'a> {
     invert: bool
 }
 
-/// Dox.
-#[cfg(stage0)]
-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]
@@ -1315,17 +1288,6 @@ fn size_hint(&self) -> (uint, Option<uint>) {
 
 /// An iterator over the (overlapping) slices of length `size` within
 /// a vector.
-#[cfg(stage0)]
-#[deriving(Clone)]
-#[experimental = "needs review"]
-pub struct Windows<'a, T> {
-    v: &'a [T],
-    size: uint
-}
-
-/// An iterator over the (overlapping) slices of length `size` within
-/// a vector.
-#[cfg(not(stage0))]
 #[deriving(Clone)]
 #[experimental = "needs review"]
 pub struct Windows<'a, T:'a> {
@@ -1361,21 +1323,8 @@ 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.
-#[cfg(stage0)]
 #[deriving(Clone)]
 #[experimental = "needs review"]
-pub struct Chunks<'a, T> {
-    v: &'a [T],
-    size: uint
-}
-
-/// An iterator over a vector in (non-overlapping) 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.
-#[cfg(not(stage0))]
-#[deriving(Clone)]
 pub struct Chunks<'a, T:'a> {
     v: &'a [T],
     size: uint
@@ -1447,20 +1396,12 @@ 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.
-#[cfg(not(stage0))]
 #[experimental = "needs review"]
 pub struct MutChunks<'a, T:'a> {
     v: &'a mut [T],
     chunk_size: uint
 }
 
-/// Dox.
-#[cfg(stage0)]
-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]
index 5cbeda94d0f8607d95c8c48300c0636ebb99d2d7..b067e6299ee2e0a6c29fd2c803ea9cdb60d55004 100644 (file)
@@ -394,9 +394,9 @@ fn new() -> NaiveSearcher {
     fn next(&mut self, haystack: &[u8], needle: &[u8]) -> Option<(uint, uint)> {
         while self.position + needle.len() <= haystack.len() {
             if haystack.slice(self.position, self.position + needle.len()) == needle {
-                let matchPos = self.position;
+                let match_pos = self.position;
                 self.position += needle.len(); // add 1 for all matches
-                return Some((matchPos, matchPos + needle.len()));
+                return Some((match_pos, match_pos + needle.len()));
             } else {
                 self.position += 1;
             }
@@ -410,7 +410,7 @@ fn next(&mut self, haystack: &[u8], needle: &[u8]) -> Option<(uint, uint)> {
 #[deriving(Clone)]
 struct TwoWaySearcher {
     // constants
-    critPos: uint,
+    crit_pos: uint,
     period: uint,
     byteset: u64,
 
@@ -423,32 +423,31 @@ struct TwoWaySearcher {
 // Crochemore, M., Perrin, D., 1991, Two-way string-matching, Journal of the ACM 38(3):651-675.
 impl TwoWaySearcher {
     fn new(needle: &[u8]) -> TwoWaySearcher {
-        let (critPos1, period1) = TwoWaySearcher::maximal_suffix(needle, false);
-        let (critPos2, period2) = TwoWaySearcher::maximal_suffix(needle, true);
+        let (crit_pos1, period1) = TwoWaySearcher::maximal_suffix(needle, false);
+        let (crit_pos2, period2) = TwoWaySearcher::maximal_suffix(needle, true);
 
-        let critPos;
+        let crit_pos;
         let period;
-        if critPos1 > critPos2 {
-            critPos = critPos1;
+        if crit_pos1 > crit_pos2 {
+            crit_pos = crit_pos1;
             period = period1;
         } else {
-            critPos = critPos2;
+            crit_pos = crit_pos2;
             period = period2;
         }
 
         let byteset = needle.iter()
                             .fold(0, |a, &b| (1 << ((b & 0x3f) as uint)) | a);
 
-
-        // The logic here (calculating critPos and period, the final if statement to see which
+        // The logic here (calculating crit_pos and period, the final if statement to see which
         // period to use for the TwoWaySearcher) is essentially an implementation of the
         // "small-period" function from the paper (p. 670)
         //
-        // In the paper they check whether `needle.slice_to(critPos)` is a suffix of
-        // `needle.slice(critPos, critPos + period)`, which is precisely what this does
-        if needle.slice_to(critPos) == needle.slice(period, period + critPos) {
+        // In the paper they check whether `needle.slice_to(crit_pos)` is a suffix of
+        // `needle.slice(crit_pos, crit_pos + period)`, which is precisely what this does
+        if needle.slice_to(crit_pos) == needle.slice(period, period + crit_pos) {
             TwoWaySearcher {
-                critPos: critPos,
+                crit_pos: crit_pos,
                 period: period,
                 byteset: byteset,
 
@@ -457,8 +456,8 @@ fn new(needle: &[u8]) -> TwoWaySearcher {
             }
         } else {
             TwoWaySearcher {
-                critPos: critPos,
-                period: cmp::max(critPos, needle.len() - critPos) + 1,
+                crit_pos: crit_pos,
+                period: cmp::max(crit_pos, needle.len() - crit_pos) + 1,
                 byteset: byteset,
 
                 position: 0,
@@ -468,7 +467,7 @@ fn new(needle: &[u8]) -> TwoWaySearcher {
     }
 
     #[inline]
-    fn next(&mut self, haystack: &[u8], needle: &[u8], longPeriod: bool) -> Option<(uint, uint)> {
+    fn next(&mut self, haystack: &[u8], needle: &[u8], long_period: bool) -> Option<(uint, uint)> {
         'search: loop {
             // Check that we have room to search in
             if self.position + needle.len() > haystack.len() {
@@ -484,11 +483,12 @@ fn next(&mut self, haystack: &[u8], needle: &[u8], longPeriod: bool) -> Option<(
             }
 
             // See if the right part of the needle matches
-            let start = if longPeriod { self.critPos } else { cmp::max(self.critPos, self.memory) };
+            let start = if long_period { self.crit_pos }
+                        else { cmp::max(self.crit_pos, self.memory) };
             for i in range(start, needle.len()) {
                 if needle[i] != haystack[self.position + i] {
-                    self.position += i - self.critPos + 1;
-                    if !longPeriod {
+                    self.position += i - self.crit_pos + 1;
+                    if !long_period {
                         self.memory = 0;
                     }
                     continue 'search;
@@ -496,11 +496,11 @@ fn next(&mut self, haystack: &[u8], needle: &[u8], longPeriod: bool) -> Option<(
             }
 
             // See if the left part of the needle matches
-            let start = if longPeriod { 0 } else { self.memory };
-            for i in range(start, self.critPos).rev() {
+            let start = if long_period { 0 } else { self.memory };
+            for i in range(start, self.crit_pos).rev() {
                 if needle[i] != haystack[self.position + i] {
                     self.position += self.period;
-                    if !longPeriod {
+                    if !long_period {
                         self.memory = needle.len() - self.period;
                     }
                     continue 'search;
@@ -508,12 +508,12 @@ fn next(&mut self, haystack: &[u8], needle: &[u8], longPeriod: bool) -> Option<(
             }
 
             // We have found a match!
-            let matchPos = self.position;
+            let match_pos = self.position;
             self.position += needle.len(); // add self.period for all matches
-            if !longPeriod {
+            if !long_period {
                 self.memory = 0; // set to needle.len() - self.period for all matches
             }
-            return Some((matchPos, matchPos + needle.len()));
+            return Some((match_pos, match_pos + needle.len()));
         }
     }
 
index 776637f3be97d5c59c49d85f87ea594bdfc046ba..2dad9fc3a22c42def94cc7973600ae2fcfecb0d2 100644 (file)
@@ -73,7 +73,7 @@ fn test_option_dance() {
     let mut y = Some(5i);
     let mut y2 = 0;
     for _x in x.iter() {
-        y2 = y.take_unwrap();
+        y2 = y.take().unwrap();
     }
     assert_eq!(y2, 5);
     assert!(y.is_none());
@@ -82,8 +82,8 @@ fn test_option_dance() {
 #[test] #[should_fail]
 fn test_option_too_much_dance() {
     let mut y = Some(marker::NoCopy);
-    let _y2 = y.take_unwrap();
-    let _y3 = y.take_unwrap();
+    let _y2 = y.take().unwrap();
+    let _y3 = y.take().unwrap();
 }
 
 #[test]
index cc97eeffe7ae9d11f9b7378dbd9db989f53256f3..6341a38056359bf495d21bd1798c3f241643d23e 100644 (file)
@@ -25,7 +25,7 @@
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
        html_root_url = "http://doc.rust-lang.org/master/")]
 #![experimental]
-#![feature(managed_boxes, macro_rules, issue_5723_bootstrap)]
+#![feature(managed_boxes, macro_rules)]
 #![allow(experimental)]
 
 pub mod fmt;
index b89ea4d373ddc9b1bea52cb56373fb2a4ccc62ff..80d0f8a879412630446f26b10d98598323010c43 100644 (file)
@@ -193,17 +193,6 @@ fn visit_estr_slice(&mut self) -> bool {
         true
     }
 
-    // NOTE: remove after snapshot
-    #[cfg(stage0)]
-    fn visit_estr_fixed(&mut self, n: uint,
-                        sz: uint,
-                        align: uint) -> bool {
-        self.align(align);
-        if ! self.inner.visit_estr_fixed(n, sz, align) { return false; }
-        self.bump(sz);
-        true
-    }
-
     fn visit_box(&mut self, mtbl: uint, inner: *const TyDesc) -> bool {
         self.align_to::<Gc<u8>>();
         if ! self.inner.visit_box(mtbl, inner) { return false; }
@@ -239,17 +228,6 @@ fn visit_evec_slice(&mut self, mtbl: uint, inner: *const TyDesc) -> bool {
         true
     }
 
-    #[cfg(stage0)]
-    fn visit_evec_fixed(&mut self, n: uint, sz: uint, align: uint,
-                        mtbl: uint, inner: *const TyDesc) -> bool {
-        self.align(align);
-        if ! self.inner.visit_evec_fixed(n, sz, align, mtbl, inner) {
-            return false;
-        }
-        self.bump(sz);
-        true
-    }
-    #[cfg(not(stage0))]
     fn visit_evec_fixed(&mut self, n: uint, sz: uint, align: uint,
                         inner: *const TyDesc) -> bool {
         self.align(align);
index dbd2c09497be8bc71a3b30e4a4f4977dd654531a..1f66d0352da59d8c639287c1072baff0431fb95b 100644 (file)
@@ -274,12 +274,6 @@ fn visit_estr_slice(&mut self) -> bool {
         self.get::<&str>(|this, s| this.write_escaped_slice(*s))
     }
 
-    // Type no longer exists, vestigial function.
-    // NOTE: remove after snapshot
-    #[cfg(stage0)]
-    fn visit_estr_fixed(&mut self, _n: uint, _sz: uint,
-                        _align: uint) -> bool { fail!(); }
-
     fn visit_box(&mut self, mtbl: uint, inner: *const TyDesc) -> bool {
         try!(self, self.writer.write("box(GC) ".as_bytes()));
         self.write_mut_qualifier(mtbl);
@@ -330,17 +324,6 @@ fn visit_evec_slice(&mut self, mtbl: uint, inner: *const TyDesc) -> bool {
         })
     }
 
-    // NOTE: remove after snapshot
-    #[cfg(stage0)]
-    fn visit_evec_fixed(&mut self, n: uint, sz: uint, _align: uint,
-                        _: uint, inner: *const TyDesc) -> bool {
-        let assumed_size = if sz == 0 { n } else { sz };
-        self.get::<()>(|this, b| {
-            this.write_vec_range(b, assumed_size, inner)
-        })
-    }
-
-    #[cfg(not(stage0))]
     fn visit_evec_fixed(&mut self, n: uint, sz: uint, _align: uint,
                         inner: *const TyDesc) -> bool {
         let assumed_size = if sz == 0 { n } else { sz };
index cef258fac20f0d98ffbcf3117c096dc3d56cb16c..560681765cd460838ecf104b4c7837927f72038a 100644 (file)
@@ -21,9 +21,6 @@
 #![crate_type = "dylib"]
 #![feature(macro_rules, globs, import_shadowing)]
 
-// NOTE(stage0, pcwalton): Remove after snapshot.
-#![allow(unknown_features)]
-
 use std::char;
 use std::str;
 
index 475dd2c6743450c3488d1dede07845a72b2ac03a..3ffd39a0065e4b8ef2cfac015d8576142a0b285d 100644 (file)
@@ -91,9 +91,6 @@
 #![feature(import_shadowing)]
 #![deny(missing_doc)]
 
-// NOTE(stage0, pcwalton): Remove after snapshot.
-#![allow(unknown_features)]
-
 #[cfg(test)] extern crate debug;
 #[cfg(test)] #[phase(plugin, link)] extern crate log;
 
index c9af44c9479252534b9a2a29e3d4d7686ba00a51..90afee652646ce71f02bd163a1b0848da88fe0f5 100644 (file)
@@ -106,7 +106,7 @@ fn check_windows_verbatim(_: &Path) -> bool { false }
     let mut root = os::getcwd();
     let pat_root = Path::new(pattern).root_path();
     if pat_root.is_some() {
-        if check_windows_verbatim(pat_root.get_ref()) {
+        if check_windows_verbatim(pat_root.as_ref().unwrap()) {
             // FIXME: How do we want to handle verbatim paths? I'm inclined to return nothing,
             // since we can't very well find all UNC shares with a 1-letter server name.
             return Paths {
@@ -116,7 +116,7 @@ fn check_windows_verbatim(_: &Path) -> bool { false }
                 todo: Vec::new(),
             };
         }
-        root.push(pat_root.get_ref());
+        root.push(pat_root.as_ref().unwrap());
     }
 
     let root_len = pat_root.map_or(0u, |p| p.as_vec().len());
index 10cc7e8afe92fc95e47bfd6db4e832e199739420..d8325e05cdf4ccc03c6965493446b44d2ffbce2f 100644 (file)
@@ -271,7 +271,6 @@ pub fn main() {
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![license = "MIT/ASL2"]
-#![feature(issue_5723_bootstrap)]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
        html_root_url = "http://doc.rust-lang.org/master/")]
index 17c75b76bc1e1ef7599072129074557ba4959f54..ab06f327592d44fa203e73a69ac8b5ab5f780b1d 100644 (file)
 /// Some clients will have a pre-allocated vector ready to hand off in
 /// a slice; others will want to create the set on the fly and hand
 /// off ownership, via `Growable`.
-#[cfg(not(stage0))]
 pub enum MaybeOwnedVector<'a,T:'a> {
     Growable(Vec<T>),
     Borrowed(&'a [T]),
 }
 
-/// Stage0 only.
-#[cfg(stage0)]
-pub enum MaybeOwnedVector<'a,T> {
-    Growable(Vec<T>),
-    Borrowed(&'a [T]),
-}
-
 /// Trait for moving into a `MaybeOwnedVector`
 pub trait IntoMaybeOwnedVector<'a,T> {
     /// Moves self into a `MaybeOwnedVector`
index 5c280a31db792565d3bc3b4940d9dc73804759a6..cc77d151231e87484d329aa9245f049f7b0bf6c2 100644 (file)
@@ -305,7 +305,7 @@ pub fn start(argc: int, argv: *const *const u8,
     let mut main = Some(main);
     let mut ret = None;
     simple::task().run(|| {
-        ret = Some(run(event_loop_factory, main.take_unwrap()));
+        ret = Some(run(event_loop_factory, main.take().unwrap()));
     }).destroy();
     // unsafe is ok b/c we're sure that the runtime is gone
     unsafe { rt::cleanup() }
index 22001cf1070179189ff1e7a6d5bdebbe4290ae0f..084a66fdddf154c26f2daef852910273fe7fbbb8 100644 (file)
@@ -203,7 +203,7 @@ pub fn bootstrap(mut self: Box<Scheduler>) {
         let mut sched_task = self.run(sched_task);
 
         // Close the idle callback.
-        let mut sched = sched_task.sched.take_unwrap();
+        let mut sched = sched_task.sched.take().unwrap();
         sched.idle_callback.take();
         // Make one go through the loop to run the close callback.
         let mut stask = sched.run(sched_task);
@@ -702,7 +702,7 @@ pub fn resume_task_immediately(self: Box<Scheduler>,
             assert!(sched.sched_task.is_none());
             sched.sched_task = Some(stask);
         });
-        (cur.sched.take_unwrap(), cur)
+        (cur.sched.take().unwrap(), cur)
     }
 
     fn resume_task_immediately_cl(sched: Box<Scheduler>,
@@ -738,7 +738,7 @@ pub fn deschedule_running_task_and_then(mut self: Box<Scheduler>,
                                             f: |&mut Scheduler, BlockedTask|) {
         // Trickier - we need to get the scheduler task out of self
         // and use it as the destination.
-        let stask = self.sched_task.take_unwrap();
+        let stask = self.sched_task.take().unwrap();
         // Otherwise this is the same as below.
         self.switch_running_tasks_and_then(cur, stask, f)
     }
@@ -788,7 +788,7 @@ fn switch_task(sched: Box<Scheduler>,
                 sched.enqueue_task(last_task);
             }
         });
-        (cur.sched.take_unwrap(), cur)
+        (cur.sched.take().unwrap(), cur)
     }
 
     // * Task Context Helpers
@@ -800,9 +800,9 @@ pub fn terminate_current_task(mut self: Box<Scheduler>,
                                   -> ! {
         // Similar to deschedule running task and then, but cannot go through
         // the task-blocking path. The task is already dying.
-        let stask = self.sched_task.take_unwrap();
+        let stask = self.sched_task.take().unwrap();
         let _cur = self.change_task_context(cur, stask, |sched, mut dead_task| {
-            let coroutine = dead_task.coroutine.take_unwrap();
+            let coroutine = dead_task.coroutine.take().unwrap();
             coroutine.recycle(&mut sched.stack_pool);
             sched.task_state.decrement();
         });
@@ -818,7 +818,7 @@ pub fn run_task(self: Box<Scheduler>,
     }
 
     pub fn run_task_later(mut cur: Box<GreenTask>, next: Box<GreenTask>) {
-        let mut sched = cur.sched.take_unwrap();
+        let mut sched = cur.sched.take().unwrap();
         sched.enqueue_task(next);
         cur.put_with_sched(sched);
     }
@@ -838,7 +838,7 @@ pub fn yield_now(mut self: Box<Scheduler>, cur: Box<GreenTask>) {
             self.yield_check_count = reset_yield_check(&mut self.rng);
             // Tell the scheduler to start stealing on the next iteration
             self.steal_for_yield = true;
-            let stask = self.sched_task.take_unwrap();
+            let stask = self.sched_task.take().unwrap();
             let cur = self.change_task_context(cur, stask, |sched, task| {
                 sched.enqueue_task(task);
             });
@@ -878,7 +878,7 @@ pub fn maybe_yield(mut self: Box<Scheduler>, cur: Box<GreenTask>) {
     pub fn sched_id(&self) -> uint { self as *const Scheduler as uint }
 
     pub fn run_cleanup_job(&mut self) {
-        let cleanup_job = self.cleanup_job.take_unwrap();
+        let cleanup_job = self.cleanup_job.take().unwrap();
         cleanup_job.run(self)
     }
 
@@ -1235,7 +1235,7 @@ fn on_appropriate_sched() -> bool {
 
             fn run(next: Box<GreenTask>) {
                 let mut task = GreenTask::convert(Local::take());
-                let sched = task.sched.take_unwrap();
+                let sched = task.sched.take().unwrap();
                 sched.run_task(task, next)
             }
 
index ffd94e0b86f2e992589937465c77fc25115dd3b9..2d67307431b86806b9e27fca75eb8bcb05db13ed 100644 (file)
@@ -110,7 +110,7 @@ pub enum Home {
     // requested. This is the "try/catch" block for this green task and
     // is the wrapper for *all* code run in the task.
     let mut start = Some(start);
-    let task = task.swap().run(|| start.take_unwrap()()).destroy();
+    let task = task.swap().run(|| start.take().unwrap()()).destroy();
 
     // Once the function has exited, it's time to run the termination
     // routine. This means we need to context switch one more time but
@@ -212,7 +212,7 @@ pub fn give_home(&mut self, new_home: Home) {
 
     pub fn take_unwrap_home(&mut self) -> Home {
         match self.task_type {
-            TypeGreen(ref mut home) => home.take_unwrap(),
+            TypeGreen(ref mut home) => home.take().unwrap(),
             TypeSched => rtabort!("type error: used SchedTask as GreenTask"),
         }
     }
@@ -277,7 +277,7 @@ pub fn put_task(&mut self, task: Box<Task>) {
     }
 
     pub fn swap(mut self: Box<GreenTask>) -> Box<Task> {
-        let mut task = self.task.take_unwrap();
+        let mut task = self.task.take().unwrap();
         task.put_runtime(self);
         return task;
     }
@@ -288,7 +288,7 @@ pub fn put(self: Box<GreenTask>) {
     }
 
     fn terminate(mut self: Box<GreenTask>) -> ! {
-        let sched = self.sched.take_unwrap();
+        let sched = self.sched.take().unwrap();
         sched.terminate_current_task(self)
     }
 
@@ -324,13 +324,13 @@ fn reawaken_remotely(mut self: Box<GreenTask>) {
 impl Runtime for GreenTask {
     fn yield_now(mut self: Box<GreenTask>, cur_task: Box<Task>) {
         self.put_task(cur_task);
-        let sched = self.sched.take_unwrap();
+        let sched = self.sched.take().unwrap();
         sched.yield_now(self);
     }
 
     fn maybe_yield(mut self: Box<GreenTask>, cur_task: Box<Task>) {
         self.put_task(cur_task);
-        let sched = self.sched.take_unwrap();
+        let sched = self.sched.take().unwrap();
         sched.maybe_yield(self);
     }
 
@@ -339,7 +339,7 @@ fn deschedule(mut self: Box<GreenTask>,
                   cur_task: Box<Task>,
                   f: |BlockedTask| -> Result<(), BlockedTask>) {
         self.put_task(cur_task);
-        let mut sched = self.sched.take_unwrap();
+        let mut sched = self.sched.take().unwrap();
 
         // In order for this task to be reawoken in all possible contexts, we
         // may need a handle back in to the current scheduler. When we're woken
@@ -418,7 +418,7 @@ fn reawaken(mut self: Box<GreenTask>, to_wake: Box<Task>) {
         match running_task.maybe_take_runtime::<GreenTask>() {
             Some(mut running_green_task) => {
                 running_green_task.put_task(running_task);
-                let sched = running_green_task.sched.take_unwrap();
+                let sched = running_green_task.sched.take().unwrap();
 
                 if sched.pool_id == self.pool_id {
                     sched.run_task(running_green_task, self);
index 949dd08eaa343cc098db121f0f9aae587bea5f56..b8a7ac019c35c4507b812bfedde914ae4e728213 100644 (file)
 */
 
 #![allow(non_camel_case_types)]
-#![allow(non_snake_case_functions)]
+#![allow(non_snake_case)]
 #![allow(non_uppercase_statics)]
 #![allow(missing_doc)]
-#![allow(uppercase_variables)]
+#![allow(non_snake_case)]
 
 #[cfg(test)] extern crate std;
 #[cfg(test)] extern crate test;
index d692c99e8c261cedb8eecdc12689f8f6e4d5b1e9..a93cf4c15682fd83ef0bfc8cb4ace3c0b8bde85a 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use regex::Regex;
 use std::ascii::AsciiExt;
 use std::cmp;
 
@@ -28,14 +29,23 @@ fn parse_log_level(level: &str) -> Option<u32> {
     }).map(|p| cmp::min(p, ::MAX_LOG_LEVEL))
 }
 
-/// Parse a logging specification string (e.g: "crate1,crate2::mod3,crate3::x=1")
+/// Parse a logging specification string (e.g: "crate1,crate2::mod3,crate3::x=1/foo")
 /// and return a vector with log directives.
 ///
 /// Valid log levels are 0-255, with the most likely ones being 1-4 (defined in
 /// std::).  Also supports string log levels of error, warn, info, and debug
-pub fn parse_logging_spec(spec: &str) -> Vec<LogDirective> {
+pub fn parse_logging_spec(spec: &str) -> (Vec<LogDirective>, Option<Regex>) {
     let mut dirs = Vec::new();
-    for s in spec.split(',') {
+
+    let mut parts = spec.split('/');
+    let mods = parts.next();
+    let filter = parts.next();
+    if parts.next().is_some() {
+        println!("warning: invalid logging spec '{}', \
+                 ignoring it (too many '/'s)", spec);
+        return (dirs, None);
+    }
+    mods.map(|m| { for s in m.split(',') {
         if s.len() == 0 { continue }
         let mut parts = s.split('=');
         let (log_level, name) = match (parts.next(), parts.next().map(|s| s.trim()), parts.next()) {
@@ -68,8 +78,19 @@ pub fn parse_logging_spec(spec: &str) -> Vec<LogDirective> {
             name: name.map(|s| s.to_string()),
             level: log_level,
         });
-    }
-    return dirs;
+    }});
+
+    let filter = filter.map_or(None, |filter| {
+        match Regex::new(filter) {
+            Ok(re) => Some(re),
+            Err(e) => {
+                println!("warning: invalid regex filter - {}", e);
+                None
+            }
+        }
+    });
+
+    return (dirs, filter);
 }
 
 #[cfg(test)]
@@ -78,7 +99,7 @@ mod tests {
 
     #[test]
     fn parse_logging_spec_valid() {
-        let dirs = parse_logging_spec("crate1::mod1=1,crate1::mod2,crate2=4");
+        let (dirs, filter) = parse_logging_spec("crate1::mod1=1,crate1::mod2,crate2=4");
         let dirs = dirs.as_slice();
         assert_eq!(dirs.len(), 3);
         assert_eq!(dirs[0].name, Some("crate1::mod1".to_string()));
@@ -89,57 +110,99 @@ fn parse_logging_spec_valid() {
 
         assert_eq!(dirs[2].name, Some("crate2".to_string()));
         assert_eq!(dirs[2].level, 4);
+        assert!(filter.is_none());
     }
 
     #[test]
     fn parse_logging_spec_invalid_crate() {
         // test parse_logging_spec with multiple = in specification
-        let dirs = parse_logging_spec("crate1::mod1=1=2,crate2=4");
+        let (dirs, filter) = parse_logging_spec("crate1::mod1=1=2,crate2=4");
         let dirs = dirs.as_slice();
         assert_eq!(dirs.len(), 1);
         assert_eq!(dirs[0].name, Some("crate2".to_string()));
         assert_eq!(dirs[0].level, 4);
+        assert!(filter.is_none());
     }
 
     #[test]
     fn parse_logging_spec_invalid_log_level() {
         // test parse_logging_spec with 'noNumber' as log level
-        let dirs = parse_logging_spec("crate1::mod1=noNumber,crate2=4");
+        let (dirs, filter) = parse_logging_spec("crate1::mod1=noNumber,crate2=4");
         let dirs = dirs.as_slice();
         assert_eq!(dirs.len(), 1);
         assert_eq!(dirs[0].name, Some("crate2".to_string()));
         assert_eq!(dirs[0].level, 4);
+        assert!(filter.is_none());
     }
 
     #[test]
     fn parse_logging_spec_string_log_level() {
         // test parse_logging_spec with 'warn' as log level
-        let dirs = parse_logging_spec("crate1::mod1=wrong,crate2=warn");
+        let (dirs, filter) = parse_logging_spec("crate1::mod1=wrong,crate2=warn");
         let dirs = dirs.as_slice();
         assert_eq!(dirs.len(), 1);
         assert_eq!(dirs[0].name, Some("crate2".to_string()));
         assert_eq!(dirs[0].level, ::WARN);
+        assert!(filter.is_none());
     }
 
     #[test]
     fn parse_logging_spec_empty_log_level() {
         // test parse_logging_spec with '' as log level
-        let dirs = parse_logging_spec("crate1::mod1=wrong,crate2=");
+        let (dirs, filter) = parse_logging_spec("crate1::mod1=wrong,crate2=");
         let dirs = dirs.as_slice();
         assert_eq!(dirs.len(), 1);
         assert_eq!(dirs[0].name, Some("crate2".to_string()));
         assert_eq!(dirs[0].level, ::MAX_LOG_LEVEL);
+        assert!(filter.is_none());
     }
 
     #[test]
     fn parse_logging_spec_global() {
         // test parse_logging_spec with no crate
-        let dirs = parse_logging_spec("warn,crate2=4");
+        let (dirs, filter) = parse_logging_spec("warn,crate2=4");
         let dirs = dirs.as_slice();
         assert_eq!(dirs.len(), 2);
         assert_eq!(dirs[0].name, None);
         assert_eq!(dirs[0].level, 2);
         assert_eq!(dirs[1].name, Some("crate2".to_string()));
         assert_eq!(dirs[1].level, 4);
+        assert!(filter.is_none());
+    }
+
+    #[test]
+    fn parse_logging_spec_valid_filter() {
+        let (dirs, filter) = parse_logging_spec("crate1::mod1=1,crate1::mod2,crate2=4/abc");
+        let dirs = dirs.as_slice();
+        assert_eq!(dirs.len(), 3);
+        assert_eq!(dirs[0].name, Some("crate1::mod1".to_string()));
+        assert_eq!(dirs[0].level, 1);
+
+        assert_eq!(dirs[1].name, Some("crate1::mod2".to_string()));
+        assert_eq!(dirs[1].level, ::MAX_LOG_LEVEL);
+
+        assert_eq!(dirs[2].name, Some("crate2".to_string()));
+        assert_eq!(dirs[2].level, 4);
+        assert!(filter.is_some() && filter.unwrap().to_string().as_slice() == "abc");
+    }
+
+    #[test]
+    fn parse_logging_spec_invalid_crate_filter() {
+        let (dirs, filter) = parse_logging_spec("crate1::mod1=1=2,crate2=4/a.c");
+        let dirs = dirs.as_slice();
+        assert_eq!(dirs.len(), 1);
+        assert_eq!(dirs[0].name, Some("crate2".to_string()));
+        assert_eq!(dirs[0].level, 4);
+        assert!(filter.is_some() && filter.unwrap().to_string().as_slice() == "a.c");
+    }
+
+    #[test]
+    fn parse_logging_spec_empty_with_filter() {
+        let (dirs, filter) = parse_logging_spec("crate1/a*c");
+        let dirs = dirs.as_slice();
+        assert_eq!(dirs.len(), 1);
+        assert_eq!(dirs[0].name, Some("crate1".to_string()));
+        assert_eq!(dirs[0].level, ::MAX_LOG_LEVEL);
+        assert!(filter.is_some() && filter.unwrap().to_string().as_slice() == "a*c");
     }
 }
index 554f27b881b7269700937bdac03eb50f7fae7b69..0bad742933b1c2739d20fb175011a1f8090d5b85 100644 (file)
@@ -80,14 +80,32 @@ fn main() {
 
 Some examples of valid values of `RUST_LOG` are:
 
-```text
-hello                // turns on all logging for the 'hello' module
-info                 // turns on all info logging
-hello=debug          // turns on debug logging for 'hello'
-hello=3              // turns on info logging for 'hello'
-hello,std::option    // turns on hello, and std's option logging
-error,hello=warn     // turn on global error logging and also warn for hello
-```
+* `hello` turns on all logging for the 'hello' module
+* `info` turns on all info logging
+* `hello=debug` turns on debug logging for 'hello'
+* `hello=3` turns on info logging for 'hello'
+* `hello,std::option` turns on hello, and std's option logging
+* `error,hello=warn` turn on global error logging and also warn for hello
+
+## Filtering results
+
+A RUST_LOG directive may include a regex filter. The syntax is to append `/`
+followed by a regex. Each message is checked against the regex, and is only
+logged if it matches. Note that the matching is done after formatting the log
+string but before adding any logging meta-data. There is a single filter for all
+modules.
+
+Some examples:
+
+* `hello/foo` turns on all logging for the 'hello' module where the log message
+includes 'foo'.
+* `info/f.o` turns on all info logging where the log message includes 'foo',
+'f1o', 'fao', etc.
+* `hello=debug/foo*foo` turns on debug logging for 'hello' where the the log
+message includes 'foofoo' or 'fofoo' or 'fooooooofoo', etc.
+* `error,hello=warn/[0-9] scopes` turn on global error logging and also warn for
+ hello. In both cases the log message must include a single digit number
+ followed by 'scopes'
 
 ## Performance and Side Effects
 
@@ -117,6 +135,9 @@ fn main() {
 #![feature(macro_rules)]
 #![deny(missing_doc)]
 
+extern crate regex;
+
+use regex::Regex;
 use std::fmt;
 use std::io::LineBufferedWriter;
 use std::io;
@@ -146,6 +167,9 @@ fn main() {
 static mut DIRECTIVES: *const Vec<directive::LogDirective> =
     0 as *const Vec<directive::LogDirective>;
 
+/// Optional regex filter.
+static mut FILTER: *const Regex = 0 as *const _;
+
 /// Debug log level
 pub static DEBUG: u32 = 4;
 /// Info log level
@@ -222,6 +246,13 @@ fn drop(&mut self) {
 /// invoked through the logging family of macros.
 #[doc(hidden)]
 pub fn log(level: u32, loc: &'static LogLocation, args: &fmt::Arguments) {
+    // Test the literal string from args against the current filter, if there
+    // is one.
+    match unsafe { FILTER.to_option() } {
+        Some(filter) if filter.is_match(args.to_string().as_slice()) => return,
+        _ => {}
+    }
+
     // Completely remove the local logger from TLS in case anyone attempts to
     // frob the slot while we're doing the logging. This will destroy any logger
     // set during logging.
@@ -321,9 +352,9 @@ fn enabled(level: u32,
 /// This is not threadsafe at all, so initialization os performed through a
 /// `Once` primitive (and this function is called from that primitive).
 fn init() {
-    let mut directives = match os::getenv("RUST_LOG") {
+    let (mut directives, filter) = match os::getenv("RUST_LOG") {
         Some(spec) => directive::parse_logging_spec(spec.as_slice()),
-        None => Vec::new(),
+        None => (Vec::new(), None),
     };
 
     // Sort the provided directives by length of their name, this allows a
@@ -342,15 +373,26 @@ fn init() {
     unsafe {
         LOG_LEVEL = max_level;
 
+        assert!(FILTER.is_null());
+        match filter {
+            Some(f) => FILTER = mem::transmute(box f),
+            None => {}
+        }
+
         assert!(DIRECTIVES.is_null());
         DIRECTIVES = mem::transmute(box directives);
 
-        // Schedule the cleanup for this global for when the runtime exits.
+        // Schedule the cleanup for the globals for when the runtime exits.
         rt::at_exit(proc() {
             assert!(!DIRECTIVES.is_null());
             let _directives: Box<Vec<directive::LogDirective>> =
                 mem::transmute(DIRECTIVES);
             DIRECTIVES = 0 as *const Vec<directive::LogDirective>;
+
+            if !FILTER.is_null() {
+                let _filter: Box<Regex> = mem::transmute(FILTER);
+                FILTER = 0 as *const _;
+            }
         });
     }
 }
index 2dc6539b1780620b904ea408c3a6194a4268bd73..276194feaf0e39ce0a2de99a610ed7828ec50f77 100644 (file)
@@ -21,7 +21,7 @@
 //! play. The only dependencies of these modules are the normal system libraries
 //! that you would find on the respective platform.
 
-#![allow(non_snake_case_functions)]
+#![allow(non_snake_case)]
 
 use libc::c_int;
 use libc;
index b8ec0cd549611dd59758d7e7b8d8de012ad4aee5..0cc7158bb5d32c9d28ecdeeb0570f6ead1cbf30a 100644 (file)
@@ -838,7 +838,7 @@ fn free_handle(_handle: *mut ()) {
 
 #[cfg(unix)]
 fn translate_status(status: c_int) -> rtio::ProcessExit {
-    #![allow(non_snake_case_functions)]
+    #![allow(non_snake_case)]
     #[cfg(target_os = "linux")]
     #[cfg(target_os = "android")]
     mod imp {
index 06d48f2f886b8ea7796b6440b85f28e2127f66d6..06b78a54e53ee8906110ae29d8a41f3dde70831d 100644 (file)
@@ -119,7 +119,7 @@ fn signal(active: &mut Vec<Box<Inner>>,
         let mut timer = match active.shift() {
             Some(timer) => timer, None => return
         };
-        let mut cb = timer.cb.take_unwrap();
+        let mut cb = timer.cb.take().unwrap();
         cb.call();
         if timer.repeat {
             timer.cb = Some(cb);
index c7b89b6cb915375d9825842560e773e7e7c2bd59..06f89d38ca0a183da8e7b9a8795a53ade841ec39 100644 (file)
@@ -139,7 +139,7 @@ pub fn start(argc: int, argv: *const *const u8, main: proc()) -> int {
         unsafe {
             rt::stack::record_os_managed_stack_bounds(my_stack_bottom, my_stack_top);
         }
-        exit_code = Some(run(main.take_unwrap()));
+        exit_code = Some(run(main.take().unwrap()));
     }).destroy());
     unsafe { rt::cleanup(); }
     // If the exit code wasn't set, then the task block must have failed.
index 5c3beeec8abd70ac4997eb16371fbae7bc4eeb1d..ba3f101720fa858a7f66af12b3adf1aafd224bf3 100644 (file)
@@ -92,7 +92,7 @@ pub fn spawn_opts(opts: TaskOpts, f: proc():Send) {
         let mut f = Some(f);
         let mut task = task;
         task.put_runtime(ops);
-        drop(task.run(|| { f.take_unwrap()() }).destroy());
+        drop(task.run(|| { f.take().unwrap()() }).destroy());
         drop(token);
     })
 }
index ba45d2b2e73ff2c569dc240c3b97a96ad41b1907..68cfe061121eab064daec80244deae6ae448f1c8 100644 (file)
@@ -78,6 +78,7 @@
 pub static ZERO_BIG_DIGIT: BigDigit = 0;
 static ZERO_VEC: [BigDigit, ..1] = [ZERO_BIG_DIGIT];
 
+#[allow(non_snake_case)]
 pub mod BigDigit {
     use super::BigDigit;
     use super::DoubleBigDigit;
index f3e4b0b21adf85ba94b9f918bd48fdacd5d3406c..6f85460ab956e4ad5956dd3dde7edc1b551a2334 100644 (file)
@@ -137,15 +137,14 @@ pub fn ceil(&self) -> Ratio<T> {
     }
 
     /// Rounds to the nearest integer. Rounds half-way cases away from zero.
-    ///
-    /// Note: This function is currently broken and always rounds away from zero.
     #[inline]
     pub fn round(&self) -> Ratio<T> {
-        // FIXME(#15826)
         if *self < Zero::zero() {
-            Ratio::from_integer((self.numer - self.denom + One::one()) / self.denom)
+            // a/b - 1/2 = (2*a - b)/(2*b)
+            Ratio::from_integer((self.numer + self.numer - self.denom) / (self.denom + self.denom))
         } else {
-            Ratio::from_integer((self.numer + self.denom - One::one()) / self.denom)
+            // a/b + 1/2 = (2*a + b)/(2*b)
+            Ratio::from_integer((self.numer + self.numer + self.denom) / (self.denom + self.denom))
         }
     }
 
@@ -388,7 +387,11 @@ mod test {
     pub static _2: Rational = Ratio { numer: 2, denom: 1};
     pub static _1_2: Rational = Ratio { numer: 1, denom: 2};
     pub static _3_2: Rational = Ratio { numer: 3, denom: 2};
-    pub static _neg1_2: Rational =  Ratio { numer: -1, denom: 2};
+    pub static _neg1_2: Rational = Ratio { numer: -1, denom: 2};
+    pub static _1_3: Rational = Ratio { numer: 1, denom: 3};
+    pub static _neg1_3: Rational = Ratio { numer: -1, denom: 3};
+    pub static _2_3: Rational = Ratio { numer: 2, denom: 3};
+    pub static _neg2_3: Rational = Ratio { numer: -2, denom: 3};
 
     pub fn to_big(n: Rational) -> BigRational {
         Ratio::new(
@@ -578,6 +581,26 @@ fn test_div_0() {
 
     #[test]
     fn test_round() {
+        assert_eq!(_1_3.ceil(), _1);
+        assert_eq!(_1_3.floor(), _0);
+        assert_eq!(_1_3.round(), _0);
+        assert_eq!(_1_3.trunc(), _0);
+
+        assert_eq!(_neg1_3.ceil(), _0);
+        assert_eq!(_neg1_3.floor(), -_1);
+        assert_eq!(_neg1_3.round(), _0);
+        assert_eq!(_neg1_3.trunc(), _0);
+
+        assert_eq!(_2_3.ceil(), _1);
+        assert_eq!(_2_3.floor(), _0);
+        assert_eq!(_2_3.round(), _1);
+        assert_eq!(_2_3.trunc(), _0);
+
+        assert_eq!(_neg2_3.ceil(), _0);
+        assert_eq!(_neg2_3.floor(), -_1);
+        assert_eq!(_neg2_3.round(), -_1);
+        assert_eq!(_neg2_3.trunc(), _0);
+
         assert_eq!(_1_2.ceil(), _1);
         assert_eq!(_1_2.floor(), _0);
         assert_eq!(_1_2.round(), _1);
index 447e3eea06147924b527f5440b141825614f841d..d15c65799f42e1b1f40bb7e43bdf6a3866f10e60 100644 (file)
@@ -79,13 +79,6 @@ pub struct Weighted<T> {
     pub item: T,
 }
 
-/// Note: stage0-specific version that lacks bound on A.
-#[cfg(stage0)]
-pub struct WeightedChoice<'a, T> {
-    items: &'a mut [Weighted<T>],
-    weight_range: Range<uint>
-}
-
 /// A distribution that selects from a finite collection of weighted items.
 ///
 /// Each item has an associated weight that influences how likely it
@@ -112,7 +105,6 @@ pub struct WeightedChoice<'a, T> {
 ///      println!("{}", wc.ind_sample(&mut rng));
 /// }
 /// ```
-#[cfg(not(stage0))]
 pub struct WeightedChoice<'a, T:'a> {
     items: &'a mut [Weighted<T>],
     weight_range: Range<uint>
index f1ed9ae899707b625ceb3dd6115007c723fcd553..52112380c600a38f2a618af9c0064aeea3a7a8f6 100644 (file)
@@ -269,16 +269,9 @@ fn shuffle<T>(&mut self, values: &mut [T]) {
     }
 }
 
-/// Note: stage0-specific version that lacks bound on A.
-#[cfg(stage0)]
-pub struct Generator<'a, T, R> {
-    rng: &'a mut R,
-}
-
 /// Iterator which will generate a stream of random items.
 ///
 /// This iterator is created via the `gen_iter` method on `Rng`.
-#[cfg(not(stage0))]
 pub struct Generator<'a, T, R:'a> {
     rng: &'a mut R,
 }
@@ -289,16 +282,9 @@ fn next(&mut self) -> Option<T> {
     }
 }
 
-/// Note: stage0-specific version.
-#[cfg(stage0)]
-pub struct AsciiGenerator<'a, R> {
-    rng: &'a mut R,
-}
-
 /// Iterator which will continuously generate random ascii characters.
 ///
 /// This iterator is created via the `gen_ascii_chars` method on `Rng`.
-#[cfg(not(stage0))]
 pub struct AsciiGenerator<'a, R:'a> {
     rng: &'a mut R,
 }
index a05c877a6a6e10e10df2de96a239dddec6b049c7..933f2b223e9ecb09faae9e9d3a24d38e3693f3e4 100644 (file)
@@ -24,7 +24,7 @@
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
        html_root_url = "http://doc.rust-lang.org/master/",
        html_playground_url = "http://play.rust-lang.org/")]
-#![feature(macro_rules, phase, issue_5723_bootstrap)]
+#![feature(macro_rules, phase)]
 #![allow(missing_doc)]
 
 extern crate serialize;
@@ -662,14 +662,6 @@ pub mod writer {
     pub type EncodeResult = io::IoResult<()>;
 
     // rbml writing
-    #[cfg(stage0)]
-    pub struct Encoder<'a, W> {
-        pub writer: &'a mut W,
-        size_positions: Vec<uint>,
-    }
-
-    // rbml writing
-    #[cfg(not(stage0))]
     pub struct Encoder<'a, W:'a> {
         pub writer: &'a mut W,
         size_positions: Vec<uint>,
@@ -1132,7 +1124,7 @@ fn test_v(v: Option<int>) {
 
 #[cfg(test)]
 mod bench {
-    #![allow(non_snake_case_functions)]
+    #![allow(non_snake_case)]
     use test::Bencher;
     use super::reader;
 
index 4bd9d1a8666c0949f28707294c4b28bf01c8a25e..aa85a68b5b50990d486f8038a2bc6bd448511886 100644 (file)
@@ -7,7 +7,7 @@
 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
-#![allow(non_snake_case_functions)]
+#![allow(non_snake_case)]
 
 use std::rand::{Rng, task_rng};
 use stdtest::Bencher;
index 739ec2cf43ffe9564ecfcdf12d40ef0de2270062..d51d5a0aef2e1694d01d664230ac462c3720d62a 100644 (file)
@@ -35,9 +35,6 @@
 // LLVM to optimize these function calls to themselves!
 #![no_builtins]
 
-// NOTE(stage0, pcwalton): Remove after snapshot.
-#![allow(unknown_features)]
-
 #[cfg(test)] extern crate native;
 #[cfg(test)] extern crate test;
 #[cfg(test)] extern crate debug;
index 77e73c46c402cf2f6ac23962b2dc4d80124759be..0c9260bdc7d99c7d172bfb4a0580d00a4eb68e2a 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_snake_case)]
+
 register_diagnostic!(E0001, r##"
     This error suggests that the expression arm corresponding to the noted pattern
     will never be reached as for all possible values of the expression being matched,
index 14642a3708a93c50cb5f02b70fa5cdcaf0830c46..3d0678aa0e7ac4faa863d506e01fe26441bb2114 100644 (file)
 
 use back::link;
 use driver::session::Session;
-use driver::{config, PpMode, PpSourceMode};
-use driver::{PpmFlowGraph, PpmExpanded, PpmExpandedIdentified, PpmTyped};
-use driver::{PpmIdentified, PpmNormal, PpmSource};
+use driver::config;
 use front;
 use lint;
 use llvm::{ContextRef, ModuleRef};
 use metadata::common::LinkMeta;
 use metadata::creader;
-use middle::borrowck::{FnPartsWithCFG};
-use middle::borrowck;
-use middle::borrowck::graphviz as borrowck_dot;
-use middle::cfg;
-use middle::cfg::graphviz::LabelledCFG;
 use middle::{trans, freevars, stability, kind, ty, typeck, reachable};
 use middle::dependency_format;
 use middle;
 use plugin;
 
 use util::common::time;
-use util::ppaux;
 use util::nodemap::{NodeSet};
 
-use graphviz as dot;
-
 use serialize::{json, Encodable};
 
-use std::from_str::FromStr;
 use std::io;
 use std::io::fs;
-use std::io::MemReader;
-use std::option;
 use syntax::ast;
-use syntax::ast_map;
-use syntax::ast_map::blocks;
-use syntax::ast_map::NodePrinter;
 use syntax::attr;
 use syntax::attr::{AttrMetaMethods};
 use syntax::diagnostics;
 use syntax::parse;
 use syntax::parse::token;
-use syntax::print::{pp, pprust};
 use syntax;
 
 pub fn host_triple() -> &'static str {
@@ -223,7 +206,7 @@ pub fn phase_2_configure_and_expand(sess: &Session,
     let mut addl_plugins = Some(addl_plugins);
     let Plugins { macros, registrars }
         = time(time_passes, "plugin loading", (), |_|
-               plugin::load::load_plugins(sess, &krate, addl_plugins.take_unwrap()));
+               plugin::load::load_plugins(sess, &krate, addl_plugins.take().unwrap()));
 
     let mut registry = Registry::new(&krate);
 
@@ -242,13 +225,17 @@ pub fn phase_2_configure_and_expand(sess: &Session,
         }
     });
 
-    let Registry { syntax_exts, lint_passes, .. } = registry;
+    let Registry { syntax_exts, lint_passes, lint_groups, .. } = registry;
 
     {
         let mut ls = sess.lint_store.borrow_mut();
         for pass in lint_passes.move_iter() {
             ls.register_pass(Some(sess), true, pass);
         }
+
+        for (name, to) in lint_groups.move_iter() {
+            ls.register_group(Some(sess), true, name, to);
+        }
     }
 
     // Lint plugins are registered; now we can process command line flags.
@@ -614,504 +601,6 @@ fn write_out_deps(sess: &Session,
     }
 }
 
-// This slightly awkward construction is to allow for each PpMode to
-// choose whether it needs to do analyses (which can consume the
-// Session) and then pass through the session (now attached to the
-// analysis results) on to the chosen pretty-printer, along with the
-// `&PpAnn` object.
-//
-// Note that since the `&PrinterSupport` is freshly constructed on each
-// call, it would not make sense to try to attach the lifetime of `self`
-// to the lifetime of the `&PrinterObject`.
-//
-// (The `use_once_payload` is working around the current lack of once
-// functions in the compiler.)
-trait CratePrinter {
-    /// Constructs a `PrinterSupport` object and passes it to `f`.
-    fn call_with_pp_support<A,B>(&self,
-                                 sess: Session,
-                                 krate: &ast::Crate,
-                                 ast_map: Option<syntax::ast_map::Map>,
-                                 id: String,
-                                 use_once_payload: B,
-                                 f: |&PrinterSupport, B| -> A) -> A;
-}
-
-trait SessionCarrier {
-    /// Provides a uniform interface for re-extracting a reference to a
-    /// `Session` from a value that now owns it.
-    fn sess<'a>(&'a self) -> &'a Session;
-}
-
-trait AstMapCarrier {
-    /// Provides a uniform interface for re-extracting a reference to an
-    /// `ast_map::Map` from a value that now owns it.
-    fn ast_map<'a>(&'a self) -> Option<&'a ast_map::Map>;
-}
-
-trait PrinterSupport : SessionCarrier + AstMapCarrier {
-    /// Produces the pretty-print annotation object.
-    ///
-    /// Usually implemented via `self as &pprust::PpAnn`.
-    ///
-    /// (Rust does not yet support upcasting from a trait object to
-    /// an object for one of its super-traits.)
-    fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn;
-}
-
-struct NoAnn {
-    sess: Session,
-    ast_map: Option<ast_map::Map>,
-}
-
-impl PrinterSupport for NoAnn {
-    fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn { self as &pprust::PpAnn }
-}
-
-impl SessionCarrier for NoAnn {
-    fn sess<'a>(&'a self) -> &'a Session { &self.sess }
-}
-
-impl AstMapCarrier for NoAnn {
-    fn ast_map<'a>(&'a self) -> Option<&'a ast_map::Map> {
-        self.ast_map.as_ref()
-    }
-}
-
-impl pprust::PpAnn for NoAnn {}
-
-struct IdentifiedAnnotation {
-    sess: Session,
-    ast_map: Option<ast_map::Map>,
-}
-
-impl PrinterSupport for IdentifiedAnnotation {
-    fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn { self as &pprust::PpAnn }
-}
-
-impl SessionCarrier for IdentifiedAnnotation {
-    fn sess<'a>(&'a self) -> &'a Session { &self.sess }
-}
-
-impl AstMapCarrier for IdentifiedAnnotation {
-    fn ast_map<'a>(&'a self) -> Option<&'a ast_map::Map> {
-        self.ast_map.as_ref()
-    }
-}
-
-impl pprust::PpAnn for IdentifiedAnnotation {
-    fn pre(&self,
-           s: &mut pprust::State,
-           node: pprust::AnnNode) -> io::IoResult<()> {
-        match node {
-            pprust::NodeExpr(_) => s.popen(),
-            _ => Ok(())
-        }
-    }
-    fn post(&self,
-            s: &mut pprust::State,
-            node: pprust::AnnNode) -> io::IoResult<()> {
-        match node {
-            pprust::NodeItem(item) => {
-                try!(pp::space(&mut s.s));
-                s.synth_comment(item.id.to_string())
-            }
-            pprust::NodeBlock(blk) => {
-                try!(pp::space(&mut s.s));
-                s.synth_comment(format!("block {}", blk.id))
-            }
-            pprust::NodeExpr(expr) => {
-                try!(pp::space(&mut s.s));
-                try!(s.synth_comment(expr.id.to_string()));
-                s.pclose()
-            }
-            pprust::NodePat(pat) => {
-                try!(pp::space(&mut s.s));
-                s.synth_comment(format!("pat {}", pat.id))
-            }
-        }
-    }
-}
-
-struct TypedAnnotation {
-    analysis: CrateAnalysis,
-}
-
-impl PrinterSupport for TypedAnnotation {
-    fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn { self as &pprust::PpAnn }
-}
-
-impl SessionCarrier for TypedAnnotation {
-    fn sess<'a>(&'a self) -> &'a Session { &self.analysis.ty_cx.sess }
-}
-
-impl AstMapCarrier for TypedAnnotation {
-    fn ast_map<'a>(&'a self) -> Option<&'a ast_map::Map> {
-        Some(&self.analysis.ty_cx.map)
-    }
-}
-
-impl pprust::PpAnn for TypedAnnotation {
-    fn pre(&self,
-           s: &mut pprust::State,
-           node: pprust::AnnNode) -> io::IoResult<()> {
-        match node {
-            pprust::NodeExpr(_) => s.popen(),
-            _ => Ok(())
-        }
-    }
-    fn post(&self,
-            s: &mut pprust::State,
-            node: pprust::AnnNode) -> io::IoResult<()> {
-        let tcx = &self.analysis.ty_cx;
-        match node {
-            pprust::NodeExpr(expr) => {
-                try!(pp::space(&mut s.s));
-                try!(pp::word(&mut s.s, "as"));
-                try!(pp::space(&mut s.s));
-                try!(pp::word(&mut s.s,
-                              ppaux::ty_to_string(
-                                  tcx,
-                                  ty::expr_ty(tcx, expr)).as_slice()));
-                s.pclose()
-            }
-            _ => Ok(())
-        }
-    }
-}
-
-fn gather_flowgraph_variants(sess: &Session) -> Vec<borrowck_dot::Variant> {
-    let print_loans   = config::FLOWGRAPH_PRINT_LOANS;
-    let print_moves   = config::FLOWGRAPH_PRINT_MOVES;
-    let print_assigns = config::FLOWGRAPH_PRINT_ASSIGNS;
-    let print_all     = config::FLOWGRAPH_PRINT_ALL;
-    let opt = |print_which| sess.debugging_opt(print_which);
-    let mut variants = Vec::new();
-    if opt(print_all) || opt(print_loans) {
-        variants.push(borrowck_dot::Loans);
-    }
-    if opt(print_all) || opt(print_moves) {
-        variants.push(borrowck_dot::Moves);
-    }
-    if opt(print_all) || opt(print_assigns) {
-        variants.push(borrowck_dot::Assigns);
-    }
-    variants
-}
-
-#[deriving(Clone, Show)]
-pub enum UserIdentifiedItem {
-    ItemViaNode(ast::NodeId),
-    ItemViaPath(Vec<String>),
-}
-
-impl FromStr for UserIdentifiedItem {
-    fn from_str(s: &str) -> Option<UserIdentifiedItem> {
-        let extract_path_parts = || {
-            let v : Vec<_> = s.split_str("::")
-                .map(|x|x.to_string())
-                .collect();
-            Some(ItemViaPath(v))
-        };
-
-        from_str(s).map(ItemViaNode).or_else(extract_path_parts)
-    }
-}
-
-enum NodesMatchingUII<'a> {
-    NodesMatchingDirect(option::Item<ast::NodeId>),
-    NodesMatchingSuffix(ast_map::NodesMatchingSuffix<'a, String>),
-}
-
-impl<'a> Iterator<ast::NodeId> for NodesMatchingUII<'a> {
-    fn next(&mut self) -> Option<ast::NodeId> {
-        match self {
-            &NodesMatchingDirect(ref mut iter) => iter.next(),
-            &NodesMatchingSuffix(ref mut iter) => iter.next(),
-        }
-    }
-}
-
-impl UserIdentifiedItem {
-    fn reconstructed_input(&self) -> String {
-        match *self {
-            ItemViaNode(node_id) => node_id.to_string(),
-            ItemViaPath(ref parts) => parts.connect("::"),
-        }
-    }
-
-    fn all_matching_node_ids<'a>(&'a self, map: &'a ast_map::Map) -> NodesMatchingUII<'a> {
-        match *self {
-            ItemViaNode(node_id) =>
-                NodesMatchingDirect(Some(node_id).move_iter()),
-            ItemViaPath(ref parts) =>
-                NodesMatchingSuffix(map.nodes_matching_suffix(parts.as_slice())),
-        }
-    }
-
-    fn to_one_node_id(self, user_option: &str, sess: &Session, map: &ast_map::Map) -> ast::NodeId {
-        let fail_because = |is_wrong_because| -> ast::NodeId {
-            let message =
-                format!("{:s} needs NodeId (int) or unique \
-                         path suffix (b::c::d); got {:s}, which {:s}",
-                        user_option,
-                        self.reconstructed_input(),
-                        is_wrong_because);
-            sess.fatal(message.as_slice())
-        };
-
-        let mut saw_node = ast::DUMMY_NODE_ID;
-        let mut seen = 0u;
-        for node in self.all_matching_node_ids(map) {
-            saw_node = node;
-            seen += 1;
-            if seen > 1 {
-                fail_because("does not resolve uniquely");
-            }
-        }
-        if seen == 0 {
-            fail_because("does not resolve to any item");
-        }
-
-        assert!(seen == 1);
-        return saw_node;
-    }
-}
-
-impl CratePrinter for PpSourceMode {
-    fn call_with_pp_support<A,B>(&self,
-                                 sess: Session,
-                                 krate: &ast::Crate,
-                                 ast_map: Option<syntax::ast_map::Map>,
-                                 id: String,
-                                 payload: B,
-                                 f: |&PrinterSupport, B| -> A) -> A {
-        match *self {
-            PpmNormal | PpmExpanded => {
-                let annotation = NoAnn { sess: sess, ast_map: ast_map };
-                f(&annotation, payload)
-            }
-
-            PpmIdentified | PpmExpandedIdentified => {
-                let annotation = IdentifiedAnnotation { sess: sess, ast_map: ast_map };
-                f(&annotation, payload)
-            }
-            PpmTyped => {
-                let ast_map = ast_map.expect("--pretty=typed missing ast_map");
-                let analysis = phase_3_run_analysis_passes(sess, krate, ast_map, id);
-                let annotation = TypedAnnotation { analysis: analysis };
-                f(&annotation, payload)
-            }
-        }
-    }
-}
-
-fn needs_ast_map(ppm: &PpMode, opt_uii: &Option<UserIdentifiedItem>) -> bool {
-    match *ppm {
-        PpmSource(PpmNormal) |
-        PpmSource(PpmIdentified) => opt_uii.is_some(),
-
-        PpmSource(PpmExpanded) |
-        PpmSource(PpmExpandedIdentified) |
-        PpmSource(PpmTyped) |
-        PpmFlowGraph => true
-    }
-}
-
-fn needs_expansion(ppm: &PpMode) -> bool {
-    match *ppm {
-        PpmSource(PpmNormal) |
-        PpmSource(PpmIdentified) => false,
-
-        PpmSource(PpmExpanded) |
-        PpmSource(PpmExpandedIdentified) |
-        PpmSource(PpmTyped) |
-        PpmFlowGraph => true
-    }
-}
-pub fn pretty_print_input(sess: Session,
-                          cfg: ast::CrateConfig,
-                          input: &Input,
-                          ppm: PpMode,
-                          opt_uii: Option<UserIdentifiedItem>,
-                          ofile: Option<Path>) {
-    let krate = phase_1_parse_input(&sess, cfg, input);
-    let id = link::find_crate_name(Some(&sess), krate.attrs.as_slice(), input);
-
-    let is_expanded = needs_expansion(&ppm);
-    let (krate, ast_map) = if needs_ast_map(&ppm, &opt_uii) {
-        let k = phase_2_configure_and_expand(&sess, krate, id.as_slice(), None);
-        let (krate, ast_map) = match k {
-            None => return,
-            Some(p) => p,
-        };
-        (krate, Some(ast_map))
-    } else {
-        (krate, None)
-    };
-
-    let src_name = source_name(input);
-    let src = Vec::from_slice(sess.codemap()
-                                  .get_filemap(src_name.as_slice())
-                                  .src
-                                  .as_bytes());
-    let mut rdr = MemReader::new(src);
-
-    let out = match ofile {
-        None => box io::stdout() as Box<Writer+'static>,
-        Some(p) => {
-            let r = io::File::create(&p);
-            match r {
-                Ok(w) => box w as Box<Writer+'static>,
-                Err(e) => fail!("print-print failed to open {} due to {}",
-                                p.display(), e),
-            }
-        }
-    };
-
-    match (ppm, opt_uii) {
-        (PpmSource(s), None) =>
-            s.call_with_pp_support(
-                sess, &krate, ast_map, id, out, |annotation, out| {
-                    debug!("pretty printing source code {}", s);
-                    let sess = annotation.sess();
-                    pprust::print_crate(sess.codemap(),
-                                        sess.diagnostic(),
-                                        &krate,
-                                        src_name.to_string(),
-                                        &mut rdr,
-                                        out,
-                                        annotation.pp_ann(),
-                                        is_expanded)
-                }),
-
-        (PpmSource(s), Some(uii)) =>
-            s.call_with_pp_support(
-                sess, &krate, ast_map, id, (out,uii), |annotation, (out,uii)| {
-                    debug!("pretty printing source code {}", s);
-                    let sess = annotation.sess();
-                    let ast_map = annotation.ast_map()
-                        .expect("--pretty missing ast_map");
-                    let mut pp_state =
-                        pprust::State::new_from_input(sess.codemap(),
-                                                      sess.diagnostic(),
-                                                      src_name.to_string(),
-                                                      &mut rdr,
-                                                      out,
-                                                      annotation.pp_ann(),
-                                                      is_expanded);
-                    for node_id in uii.all_matching_node_ids(ast_map) {
-                        let node = ast_map.get(node_id);
-                        try!(pp_state.print_node(&node));
-                        try!(pp::space(&mut pp_state.s));
-                        try!(pp_state.synth_comment(ast_map.path_to_string(node_id)));
-                        try!(pp::hardbreak(&mut pp_state.s));
-                    }
-                    pp::eof(&mut pp_state.s)
-                }),
-
-        (PpmFlowGraph, opt_uii) => {
-            debug!("pretty printing flow graph for {}", opt_uii);
-            let uii = opt_uii.unwrap_or_else(|| {
-                sess.fatal(format!("`pretty flowgraph=..` needs NodeId (int) or
-                                     unique path suffix (b::c::d)").as_slice())
-
-            });
-            let ast_map = ast_map.expect("--pretty flowgraph missing ast_map");
-            let nodeid = uii.to_one_node_id("--pretty", &sess, &ast_map);
-
-            let node = ast_map.find(nodeid).unwrap_or_else(|| {
-                sess.fatal(format!("--pretty flowgraph couldn't find id: {}",
-                                   nodeid).as_slice())
-            });
-
-            let code = blocks::Code::from_node(node);
-            match code {
-                Some(code) => {
-                    let variants = gather_flowgraph_variants(&sess);
-                    let analysis = phase_3_run_analysis_passes(sess, &krate,
-                                                               ast_map, id);
-                    print_flowgraph(variants, analysis, code, out)
-                }
-                None => {
-                    let message = format!("--pretty=flowgraph needs \
-                                           block, fn, or method; got {:?}",
-                                          node);
-
-                    // point to what was found, if there's an
-                    // accessible span.
-                    match ast_map.opt_span(nodeid) {
-                        Some(sp) => sess.span_fatal(sp, message.as_slice()),
-                        None => sess.fatal(message.as_slice())
-                    }
-                }
-            }
-        }
-    }.unwrap()
-}
-
-fn print_flowgraph<W:io::Writer>(variants: Vec<borrowck_dot::Variant>,
-                                 analysis: CrateAnalysis,
-                                 code: blocks::Code,
-                                 mut out: W) -> io::IoResult<()> {
-    let ty_cx = &analysis.ty_cx;
-    let cfg = match code {
-        blocks::BlockCode(block) => cfg::CFG::new(ty_cx, &*block),
-        blocks::FnLikeCode(fn_like) => cfg::CFG::new(ty_cx, &*fn_like.body()),
-    };
-    debug!("cfg: {:?}", cfg);
-
-    match code {
-        _ if variants.len() == 0 => {
-            let lcfg = LabelledCFG {
-                ast_map: &ty_cx.map,
-                cfg: &cfg,
-                name: format!("node_{}", code.id()),
-            };
-            let r = dot::render(&lcfg, &mut out);
-            return expand_err_details(r);
-        }
-        blocks::BlockCode(_) => {
-            ty_cx.sess.err("--pretty flowgraph with -Z flowgraph-print \
-                            annotations requires fn-like node id.");
-            return Ok(())
-        }
-        blocks::FnLikeCode(fn_like) => {
-            let fn_parts = FnPartsWithCFG::from_fn_like(&fn_like, &cfg);
-            let (bccx, analysis_data) =
-                borrowck::build_borrowck_dataflow_data_for_fn(ty_cx, fn_parts);
-
-            let lcfg = LabelledCFG {
-                ast_map: &ty_cx.map,
-                cfg: &cfg,
-                name: format!("node_{}", code.id()),
-            };
-            let lcfg = borrowck_dot::DataflowLabeller {
-                inner: lcfg,
-                variants: variants,
-                borrowck_ctxt: &bccx,
-                analysis_data: &analysis_data,
-            };
-            let r = dot::render(&lcfg, &mut out);
-            return expand_err_details(r);
-        }
-    }
-
-    fn expand_err_details(r: io::IoResult<()>) -> io::IoResult<()> {
-        r.map_err(|ioerr| {
-            let orig_detail = ioerr.detail.clone();
-            let m = "graphviz::render failed";
-            io::IoError {
-                detail: Some(match orig_detail {
-                    None => m.into_string(),
-                    Some(d) => format!("{}: {}", m, d)
-                }),
-                ..ioerr
-            }
-        })
-    }
-}
-
 pub fn collect_crate_types(session: &Session,
                            attrs: &[ast::Attribute]) -> Vec<config::CrateType> {
     // Unconditionally collect crate types from attributes to make them used
index dc600e0da3ec06ae26253c8ada1eee7ff7f2b918..5e00b9e9e0e05ddebf7fbdb8f1d862d5d9b564f0 100644 (file)
@@ -33,6 +33,7 @@
 pub mod driver;
 pub mod session;
 pub mod config;
+pub mod pretty;
 
 
 pub fn main_args(args: &[String]) -> int {
@@ -96,11 +97,11 @@ fn run_compiler(args: &[String]) {
     let ofile = matches.opt_str("o").map(|o| Path::new(o));
 
     let pretty = matches.opt_default("pretty", "normal").map(|a| {
-        parse_pretty(&sess, a.as_slice())
+        pretty::parse_pretty(&sess, a.as_slice())
     });
     match pretty {
         Some((ppm, opt_uii)) => {
-            driver::pretty_print_input(sess, cfg, &input, ppm, opt_uii, ofile);
+            pretty::pretty_print_input(sess, cfg, &input, ppm, opt_uii, ofile);
             return;
         }
         None => {/* continue */ }
@@ -180,14 +181,26 @@ fn sort_lints(lints: Vec<(&'static Lint, bool)>) -> Vec<&'static Lint> {
         lints
     }
 
+    fn sort_lint_groups(lints: Vec<(&'static str, Vec<lint::LintId>, bool)>)
+                     -> Vec<(&'static str, Vec<lint::LintId>)> {
+        let mut lints: Vec<_> = lints.move_iter().map(|(x, y, _)| (x, y)).collect();
+        lints.sort_by(|&(x, _): &(&'static str, Vec<lint::LintId>),
+                       &(y, _): &(&'static str, Vec<lint::LintId>)| {
+            x.cmp(&y)
+        });
+        lints
+    }
+
     let (plugin, builtin) = lint_store.get_lints().partitioned(|&(_, p)| p);
     let plugin = sort_lints(plugin);
     let builtin = sort_lints(builtin);
 
-    // FIXME (#7043): We should use the width in character cells rather than
-    // the number of codepoints.
+    let (plugin_groups, builtin_groups) = lint_store.get_lint_groups().partitioned(|&(_, _, p)| p);
+    let plugin_groups = sort_lint_groups(plugin_groups);
+    let builtin_groups = sort_lint_groups(builtin_groups);
+
     let max_name_len = plugin.iter().chain(builtin.iter())
-        .map(|&s| s.name.char_len())
+        .map(|&s| s.name.width(true))
         .max().unwrap_or(0);
     let padded = |x: &str| {
         " ".repeat(max_name_len - x.char_len()).append(x)
@@ -208,16 +221,48 @@ fn sort_lints(lints: Vec<(&'static Lint, bool)>) -> Vec<&'static Lint> {
 
     print_lints(builtin);
 
-    match (loaded_plugins, plugin.len()) {
-        (false, 0) => {
-            println!("Compiler plugins can provide additional lints. To see a listing of these, \
-                      re-run `rustc -W help` with a crate filename.");
+
+
+    let max_name_len = plugin_groups.iter().chain(builtin_groups.iter())
+        .map(|&(s, _)| s.width(true))
+        .max().unwrap_or(0);
+    let padded = |x: &str| {
+        " ".repeat(max_name_len - x.char_len()).append(x)
+    };
+
+    println!("Lint groups provided by rustc:\n");
+    println!("    {}  {}", padded("name"), "sub-lints");
+    println!("    {}  {}", padded("----"), "---------");
+
+    let print_lint_groups = |lints: Vec<(&'static str, Vec<lint::LintId>)>| {
+        for (name, to) in lints.move_iter() {
+            let name = name.chars().map(|x| x.to_lowercase())
+                           .collect::<String>().replace("_", "-");
+            let desc = to.move_iter().map(|x| x.as_str()).collect::<Vec<String>>().connect(", ");
+            println!("    {}  {}",
+                     padded(name.as_slice()), desc);
         }
-        (false, _) => fail!("didn't load lint plugins but got them anyway!"),
-        (true, 0) => println!("This crate does not load any lint plugins."),
-        (true, _) => {
-            println!("Lint checks provided by plugins loaded by this crate:\n");
-            print_lints(plugin);
+        println!("\n");
+    };
+
+    print_lint_groups(builtin_groups);
+
+    match (loaded_plugins, plugin.len(), plugin_groups.len()) {
+        (false, 0, _) | (false, _, 0) => {
+            println!("Compiler plugins can provide additional lints and lint groups. To see a \
+                      listing of these, re-run `rustc -W help` with a crate filename.");
+        }
+        (false, _, _) => fail!("didn't load lint plugins but got them anyway!"),
+        (true, 0, 0) => println!("This crate does not load any lint plugins or lint groups."),
+        (true, l, g) => {
+            if l > 0 {
+                println!("Lint checks provided by plugins loaded by this crate:\n");
+                print_lints(plugin);
+            }
+            if g > 0 {
+                println!("Lint groups provided by plugins loaded by this crate:\n");
+                print_lint_groups(plugin_groups);
+            }
         }
     }
 }
@@ -340,43 +385,6 @@ fn print_crate_info(sess: &Session,
     }
 }
 
-#[deriving(PartialEq, Show)]
-pub enum PpSourceMode {
-    PpmNormal,
-    PpmExpanded,
-    PpmTyped,
-    PpmIdentified,
-    PpmExpandedIdentified,
-}
-
-#[deriving(PartialEq, Show)]
-pub enum PpMode {
-    PpmSource(PpSourceMode),
-    PpmFlowGraph,
-}
-
-fn parse_pretty(sess: &Session, name: &str) -> (PpMode, Option<driver::UserIdentifiedItem>) {
-    let mut split = name.splitn(1, '=');
-    let first = split.next().unwrap();
-    let opt_second = split.next();
-    let first = match first {
-        "normal"       => PpmSource(PpmNormal),
-        "expanded"     => PpmSource(PpmExpanded),
-        "typed"        => PpmSource(PpmTyped),
-        "expanded,identified" => PpmSource(PpmExpandedIdentified),
-        "identified"   => PpmSource(PpmIdentified),
-        "flowgraph"    => PpmFlowGraph,
-        _ => {
-            sess.fatal(format!(
-                "argument to `pretty` must be one of `normal`, \
-                 `expanded`, `flowgraph=<nodeid>`, `typed`, `identified`, \
-                 or `expanded,identified`; got {}", name).as_slice());
-        }
-    };
-    let opt_second = opt_second.and_then::<driver::UserIdentifiedItem>(from_str);
-    (first, opt_second)
-}
-
 fn parse_crate_attrs(sess: &Session, input: &Input) ->
                      Vec<ast::Attribute> {
     let result = match *input {
diff --git a/src/librustc/driver/pretty.rs b/src/librustc/driver/pretty.rs
new file mode 100644 (file)
index 0000000..67dbc6f
--- /dev/null
@@ -0,0 +1,615 @@
+// 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.
+
+//! The various pretty print routines.
+
+use back::link;
+
+use driver::config;
+use driver::driver::{mod, CrateAnalysis};
+use driver::session::Session;
+
+use middle::ty;
+use middle::borrowck::{mod, FnPartsWithCFG};
+use middle::borrowck::graphviz as borrowck_dot;
+use middle::cfg;
+use middle::cfg::graphviz::LabelledCFG;
+
+use util::ppaux;
+
+use syntax::ast;
+use syntax::ast_map::{mod, blocks, NodePrinter};
+use syntax::print::{pp, pprust};
+
+use graphviz as dot;
+
+use std::io::{mod, MemReader};
+use std::from_str::FromStr;
+use std::option;
+
+
+#[deriving(PartialEq, Show)]
+pub enum PpSourceMode {
+    PpmNormal,
+    PpmExpanded,
+    PpmTyped,
+    PpmIdentified,
+    PpmExpandedIdentified,
+    PpmExpandedHygiene,
+}
+
+#[deriving(PartialEq, Show)]
+pub enum PpMode {
+    PpmSource(PpSourceMode),
+    PpmFlowGraph,
+}
+
+pub fn parse_pretty(sess: &Session, name: &str) -> (PpMode, Option<UserIdentifiedItem>) {
+    let mut split = name.splitn(1, '=');
+    let first = split.next().unwrap();
+    let opt_second = split.next();
+    let first = match first {
+        "normal"       => PpmSource(PpmNormal),
+        "expanded"     => PpmSource(PpmExpanded),
+        "typed"        => PpmSource(PpmTyped),
+        "expanded,identified" => PpmSource(PpmExpandedIdentified),
+        "expanded,hygiene" => PpmSource(PpmExpandedHygiene),
+        "identified"   => PpmSource(PpmIdentified),
+        "flowgraph"    => PpmFlowGraph,
+        _ => {
+            sess.fatal(format!(
+                "argument to `pretty` must be one of `normal`, \
+                 `expanded`, `flowgraph=<nodeid>`, `typed`, `identified`, \
+                 or `expanded,identified`; got {}", name).as_slice());
+        }
+    };
+    let opt_second = opt_second.and_then::<UserIdentifiedItem>(from_str);
+    (first, opt_second)
+}
+
+
+
+// This slightly awkward construction is to allow for each PpMode to
+// choose whether it needs to do analyses (which can consume the
+// Session) and then pass through the session (now attached to the
+// analysis results) on to the chosen pretty-printer, along with the
+// `&PpAnn` object.
+//
+// Note that since the `&PrinterSupport` is freshly constructed on each
+// call, it would not make sense to try to attach the lifetime of `self`
+// to the lifetime of the `&PrinterObject`.
+//
+// (The `use_once_payload` is working around the current lack of once
+// functions in the compiler.)
+
+impl PpSourceMode {
+    /// Constructs a `PrinterSupport` object and passes it to `f`.
+    fn call_with_pp_support<A,B>(&self,
+                                 sess: Session,
+                                 krate: &ast::Crate,
+                                 ast_map: Option<ast_map::Map>,
+                                 id: String,
+                                 payload: B,
+                                 f: |&PrinterSupport, B| -> A) -> A {
+        match *self {
+            PpmNormal | PpmExpanded => {
+                let annotation = NoAnn { sess: sess, ast_map: ast_map };
+                f(&annotation, payload)
+            }
+
+            PpmIdentified | PpmExpandedIdentified => {
+                let annotation = IdentifiedAnnotation { sess: sess, ast_map: ast_map };
+                f(&annotation, payload)
+            }
+            PpmExpandedHygiene => {
+                let annotation = HygieneAnnotation { sess: sess, ast_map: ast_map };
+                f(&annotation, payload)
+            }
+            PpmTyped => {
+                let ast_map = ast_map.expect("--pretty=typed missing ast_map");
+                let analysis = driver::phase_3_run_analysis_passes(sess, krate, ast_map, id);
+                let annotation = TypedAnnotation { analysis: analysis };
+                f(&annotation, payload)
+            }
+        }
+    }
+}
+
+trait SessionCarrier {
+    /// Provides a uniform interface for re-extracting a reference to a
+    /// `Session` from a value that now owns it.
+    fn sess<'a>(&'a self) -> &'a Session;
+}
+
+trait AstMapCarrier {
+    /// Provides a uniform interface for re-extracting a reference to an
+    /// `ast_map::Map` from a value that now owns it.
+    fn ast_map<'a>(&'a self) -> Option<&'a ast_map::Map>;
+}
+
+trait PrinterSupport : SessionCarrier + AstMapCarrier {
+    /// Produces the pretty-print annotation object.
+    ///
+    /// Usually implemented via `self as &pprust::PpAnn`.
+    ///
+    /// (Rust does not yet support upcasting from a trait object to
+    /// an object for one of its super-traits.)
+    fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn;
+}
+
+struct NoAnn {
+    sess: Session,
+    ast_map: Option<ast_map::Map>,
+}
+
+impl PrinterSupport for NoAnn {
+    fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn { self as &pprust::PpAnn }
+}
+
+impl SessionCarrier for NoAnn {
+    fn sess<'a>(&'a self) -> &'a Session { &self.sess }
+}
+
+impl AstMapCarrier for NoAnn {
+    fn ast_map<'a>(&'a self) -> Option<&'a ast_map::Map> {
+        self.ast_map.as_ref()
+    }
+}
+
+impl pprust::PpAnn for NoAnn {}
+
+struct IdentifiedAnnotation {
+    sess: Session,
+    ast_map: Option<ast_map::Map>,
+}
+
+impl PrinterSupport for IdentifiedAnnotation {
+    fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn { self as &pprust::PpAnn }
+}
+
+impl SessionCarrier for IdentifiedAnnotation {
+    fn sess<'a>(&'a self) -> &'a Session { &self.sess }
+}
+
+impl AstMapCarrier for IdentifiedAnnotation {
+    fn ast_map<'a>(&'a self) -> Option<&'a ast_map::Map> {
+        self.ast_map.as_ref()
+    }
+}
+
+impl pprust::PpAnn for IdentifiedAnnotation {
+    fn pre(&self,
+           s: &mut pprust::State,
+           node: pprust::AnnNode) -> io::IoResult<()> {
+        match node {
+            pprust::NodeExpr(_) => s.popen(),
+            _ => Ok(())
+        }
+    }
+    fn post(&self,
+            s: &mut pprust::State,
+            node: pprust::AnnNode) -> io::IoResult<()> {
+        match node {
+            pprust::NodeIdent(_) | pprust::NodeName(_) => Ok(()),
+
+            pprust::NodeItem(item) => {
+                try!(pp::space(&mut s.s));
+                s.synth_comment(item.id.to_string())
+            }
+            pprust::NodeBlock(blk) => {
+                try!(pp::space(&mut s.s));
+                s.synth_comment(format!("block {}", blk.id))
+            }
+            pprust::NodeExpr(expr) => {
+                try!(pp::space(&mut s.s));
+                try!(s.synth_comment(expr.id.to_string()));
+                s.pclose()
+            }
+            pprust::NodePat(pat) => {
+                try!(pp::space(&mut s.s));
+                s.synth_comment(format!("pat {}", pat.id))
+            }
+        }
+    }
+}
+
+struct HygieneAnnotation {
+    sess: Session,
+    ast_map: Option<ast_map::Map>,
+}
+
+impl PrinterSupport for HygieneAnnotation {
+    fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn { self as &pprust::PpAnn }
+}
+
+impl SessionCarrier for HygieneAnnotation {
+    fn sess<'a>(&'a self) -> &'a Session { &self.sess }
+}
+
+impl AstMapCarrier for HygieneAnnotation {
+    fn ast_map<'a>(&'a self) -> Option<&'a ast_map::Map> {
+        self.ast_map.as_ref()
+    }
+}
+
+impl pprust::PpAnn for HygieneAnnotation {
+    fn post(&self,
+            s: &mut pprust::State,
+            node: pprust::AnnNode) -> io::IoResult<()> {
+        match node {
+            pprust::NodeIdent(&ast::Ident { name: ast::Name(nm), ctxt }) => {
+                try!(pp::space(&mut s.s));
+                // FIXME #16420: this doesn't display the connections
+                // between syntax contexts
+                s.synth_comment(format!("{}#{}", nm, ctxt))
+            }
+            pprust::NodeName(&ast::Name(nm)) => {
+                try!(pp::space(&mut s.s));
+                s.synth_comment(nm.to_string())
+            }
+            _ => Ok(())
+        }
+    }
+}
+
+
+struct TypedAnnotation {
+    analysis: CrateAnalysis,
+}
+
+impl PrinterSupport for TypedAnnotation {
+    fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn { self as &pprust::PpAnn }
+}
+
+impl SessionCarrier for TypedAnnotation {
+    fn sess<'a>(&'a self) -> &'a Session { &self.analysis.ty_cx.sess }
+}
+
+impl AstMapCarrier for TypedAnnotation {
+    fn ast_map<'a>(&'a self) -> Option<&'a ast_map::Map> {
+        Some(&self.analysis.ty_cx.map)
+    }
+}
+
+impl pprust::PpAnn for TypedAnnotation {
+    fn pre(&self,
+           s: &mut pprust::State,
+           node: pprust::AnnNode) -> io::IoResult<()> {
+        match node {
+            pprust::NodeExpr(_) => s.popen(),
+            _ => Ok(())
+        }
+    }
+    fn post(&self,
+            s: &mut pprust::State,
+            node: pprust::AnnNode) -> io::IoResult<()> {
+        let tcx = &self.analysis.ty_cx;
+        match node {
+            pprust::NodeExpr(expr) => {
+                try!(pp::space(&mut s.s));
+                try!(pp::word(&mut s.s, "as"));
+                try!(pp::space(&mut s.s));
+                try!(pp::word(&mut s.s,
+                              ppaux::ty_to_string(
+                                  tcx,
+                                  ty::expr_ty(tcx, expr)).as_slice()));
+                s.pclose()
+            }
+            _ => Ok(())
+        }
+    }
+}
+
+fn gather_flowgraph_variants(sess: &Session) -> Vec<borrowck_dot::Variant> {
+    let print_loans   = config::FLOWGRAPH_PRINT_LOANS;
+    let print_moves   = config::FLOWGRAPH_PRINT_MOVES;
+    let print_assigns = config::FLOWGRAPH_PRINT_ASSIGNS;
+    let print_all     = config::FLOWGRAPH_PRINT_ALL;
+    let opt = |print_which| sess.debugging_opt(print_which);
+    let mut variants = Vec::new();
+    if opt(print_all) || opt(print_loans) {
+        variants.push(borrowck_dot::Loans);
+    }
+    if opt(print_all) || opt(print_moves) {
+        variants.push(borrowck_dot::Moves);
+    }
+    if opt(print_all) || opt(print_assigns) {
+        variants.push(borrowck_dot::Assigns);
+    }
+    variants
+}
+
+#[deriving(Clone, Show)]
+pub enum UserIdentifiedItem {
+    ItemViaNode(ast::NodeId),
+    ItemViaPath(Vec<String>),
+}
+
+impl FromStr for UserIdentifiedItem {
+    fn from_str(s: &str) -> Option<UserIdentifiedItem> {
+        let extract_path_parts = || {
+            let v : Vec<_> = s.split_str("::")
+                .map(|x|x.to_string())
+                .collect();
+            Some(ItemViaPath(v))
+        };
+
+        from_str(s).map(ItemViaNode).or_else(extract_path_parts)
+    }
+}
+
+enum NodesMatchingUII<'a> {
+    NodesMatchingDirect(option::Item<ast::NodeId>),
+    NodesMatchingSuffix(ast_map::NodesMatchingSuffix<'a, String>),
+}
+
+impl<'a> Iterator<ast::NodeId> for NodesMatchingUII<'a> {
+    fn next(&mut self) -> Option<ast::NodeId> {
+        match self {
+            &NodesMatchingDirect(ref mut iter) => iter.next(),
+            &NodesMatchingSuffix(ref mut iter) => iter.next(),
+        }
+    }
+}
+
+impl UserIdentifiedItem {
+    fn reconstructed_input(&self) -> String {
+        match *self {
+            ItemViaNode(node_id) => node_id.to_string(),
+            ItemViaPath(ref parts) => parts.connect("::"),
+        }
+    }
+
+    fn all_matching_node_ids<'a>(&'a self, map: &'a ast_map::Map) -> NodesMatchingUII<'a> {
+        match *self {
+            ItemViaNode(node_id) =>
+                NodesMatchingDirect(Some(node_id).move_iter()),
+            ItemViaPath(ref parts) =>
+                NodesMatchingSuffix(map.nodes_matching_suffix(parts.as_slice())),
+        }
+    }
+
+    fn to_one_node_id(self, user_option: &str, sess: &Session, map: &ast_map::Map) -> ast::NodeId {
+        let fail_because = |is_wrong_because| -> ast::NodeId {
+            let message =
+                format!("{:s} needs NodeId (int) or unique \
+                         path suffix (b::c::d); got {:s}, which {:s}",
+                        user_option,
+                        self.reconstructed_input(),
+                        is_wrong_because);
+            sess.fatal(message.as_slice())
+        };
+
+        let mut saw_node = ast::DUMMY_NODE_ID;
+        let mut seen = 0u;
+        for node in self.all_matching_node_ids(map) {
+            saw_node = node;
+            seen += 1;
+            if seen > 1 {
+                fail_because("does not resolve uniquely");
+            }
+        }
+        if seen == 0 {
+            fail_because("does not resolve to any item");
+        }
+
+        assert!(seen == 1);
+        return saw_node;
+    }
+}
+
+fn needs_ast_map(ppm: &PpMode, opt_uii: &Option<UserIdentifiedItem>) -> bool {
+    match *ppm {
+        PpmSource(PpmNormal) |
+        PpmSource(PpmIdentified) => opt_uii.is_some(),
+
+        PpmSource(PpmExpanded) |
+        PpmSource(PpmExpandedIdentified) |
+        PpmSource(PpmExpandedHygiene) |
+        PpmSource(PpmTyped) |
+        PpmFlowGraph => true
+    }
+}
+
+fn needs_expansion(ppm: &PpMode) -> bool {
+    match *ppm {
+        PpmSource(PpmNormal) |
+        PpmSource(PpmIdentified) => false,
+
+        PpmSource(PpmExpanded) |
+        PpmSource(PpmExpandedIdentified) |
+        PpmSource(PpmExpandedHygiene) |
+        PpmSource(PpmTyped) |
+        PpmFlowGraph => true
+    }
+}
+
+pub fn pretty_print_input(sess: Session,
+                          cfg: ast::CrateConfig,
+                          input: &driver::Input,
+                          ppm: PpMode,
+                          opt_uii: Option<UserIdentifiedItem>,
+                          ofile: Option<Path>) {
+    let krate = driver::phase_1_parse_input(&sess, cfg, input);
+    let id = link::find_crate_name(Some(&sess), krate.attrs.as_slice(), input);
+
+    let is_expanded = needs_expansion(&ppm);
+    let (krate, ast_map) = if needs_ast_map(&ppm, &opt_uii) {
+        let k = driver::phase_2_configure_and_expand(&sess, krate, id.as_slice(), None);
+        let (krate, ast_map) = match k {
+            None => return,
+            Some(p) => p,
+        };
+        (krate, Some(ast_map))
+    } else {
+        (krate, None)
+    };
+
+    let src_name = driver::source_name(input);
+    let src = Vec::from_slice(sess.codemap()
+                                  .get_filemap(src_name.as_slice())
+                                  .src
+                                  .as_bytes());
+    let mut rdr = MemReader::new(src);
+
+    let out = match ofile {
+        None => box io::stdout() as Box<Writer+'static>,
+        Some(p) => {
+            let r = io::File::create(&p);
+            match r {
+                Ok(w) => box w as Box<Writer+'static>,
+                Err(e) => fail!("print-print failed to open {} due to {}",
+                                p.display(), e),
+            }
+        }
+    };
+
+    match (ppm, opt_uii) {
+        (PpmSource(s), None) =>
+            s.call_with_pp_support(
+                sess, &krate, ast_map, id, out, |annotation, out| {
+                    debug!("pretty printing source code {}", s);
+                    let sess = annotation.sess();
+                    pprust::print_crate(sess.codemap(),
+                                        sess.diagnostic(),
+                                        &krate,
+                                        src_name.to_string(),
+                                        &mut rdr,
+                                        out,
+                                        annotation.pp_ann(),
+                                        is_expanded)
+                }),
+
+        (PpmSource(s), Some(uii)) =>
+            s.call_with_pp_support(
+                sess, &krate, ast_map, id, (out,uii), |annotation, (out,uii)| {
+                    debug!("pretty printing source code {}", s);
+                    let sess = annotation.sess();
+                    let ast_map = annotation.ast_map()
+                        .expect("--pretty missing ast_map");
+                    let mut pp_state =
+                        pprust::State::new_from_input(sess.codemap(),
+                                                      sess.diagnostic(),
+                                                      src_name.to_string(),
+                                                      &mut rdr,
+                                                      out,
+                                                      annotation.pp_ann(),
+                                                      is_expanded);
+                    for node_id in uii.all_matching_node_ids(ast_map) {
+                        let node = ast_map.get(node_id);
+                        try!(pp_state.print_node(&node));
+                        try!(pp::space(&mut pp_state.s));
+                        try!(pp_state.synth_comment(ast_map.path_to_string(node_id)));
+                        try!(pp::hardbreak(&mut pp_state.s));
+                    }
+                    pp::eof(&mut pp_state.s)
+                }),
+
+        (PpmFlowGraph, opt_uii) => {
+            debug!("pretty printing flow graph for {}", opt_uii);
+            let uii = opt_uii.unwrap_or_else(|| {
+                sess.fatal(format!("`pretty flowgraph=..` needs NodeId (int) or
+                                     unique path suffix (b::c::d)").as_slice())
+
+            });
+            let ast_map = ast_map.expect("--pretty flowgraph missing ast_map");
+            let nodeid = uii.to_one_node_id("--pretty", &sess, &ast_map);
+
+            let node = ast_map.find(nodeid).unwrap_or_else(|| {
+                sess.fatal(format!("--pretty flowgraph couldn't find id: {}",
+                                   nodeid).as_slice())
+            });
+
+            let code = blocks::Code::from_node(node);
+            match code {
+                Some(code) => {
+                    let variants = gather_flowgraph_variants(&sess);
+                    let analysis = driver::phase_3_run_analysis_passes(sess, &krate,
+                                                                       ast_map, id);
+                    print_flowgraph(variants, analysis, code, out)
+                }
+                None => {
+                    let message = format!("--pretty=flowgraph needs \
+                                           block, fn, or method; got {:?}",
+                                          node);
+
+                    // point to what was found, if there's an
+                    // accessible span.
+                    match ast_map.opt_span(nodeid) {
+                        Some(sp) => sess.span_fatal(sp, message.as_slice()),
+                        None => sess.fatal(message.as_slice())
+                    }
+                }
+            }
+        }
+    }.unwrap()
+}
+
+fn print_flowgraph<W:io::Writer>(variants: Vec<borrowck_dot::Variant>,
+                                 analysis: CrateAnalysis,
+                                 code: blocks::Code,
+                                 mut out: W) -> io::IoResult<()> {
+    let ty_cx = &analysis.ty_cx;
+    let cfg = match code {
+        blocks::BlockCode(block) => cfg::CFG::new(ty_cx, &*block),
+        blocks::FnLikeCode(fn_like) => cfg::CFG::new(ty_cx, &*fn_like.body()),
+    };
+    debug!("cfg: {:?}", cfg);
+
+    match code {
+        _ if variants.len() == 0 => {
+            let lcfg = LabelledCFG {
+                ast_map: &ty_cx.map,
+                cfg: &cfg,
+                name: format!("node_{}", code.id()),
+            };
+            let r = dot::render(&lcfg, &mut out);
+            return expand_err_details(r);
+        }
+        blocks::BlockCode(_) => {
+            ty_cx.sess.err("--pretty flowgraph with -Z flowgraph-print \
+                            annotations requires fn-like node id.");
+            return Ok(())
+        }
+        blocks::FnLikeCode(fn_like) => {
+            let fn_parts = FnPartsWithCFG::from_fn_like(&fn_like, &cfg);
+            let (bccx, analysis_data) =
+                borrowck::build_borrowck_dataflow_data_for_fn(ty_cx, fn_parts);
+
+            let lcfg = LabelledCFG {
+                ast_map: &ty_cx.map,
+                cfg: &cfg,
+                name: format!("node_{}", code.id()),
+            };
+            let lcfg = borrowck_dot::DataflowLabeller {
+                inner: lcfg,
+                variants: variants,
+                borrowck_ctxt: &bccx,
+                analysis_data: &analysis_data,
+            };
+            let r = dot::render(&lcfg, &mut out);
+            return expand_err_details(r);
+        }
+    }
+
+    fn expand_err_details(r: io::IoResult<()>) -> io::IoResult<()> {
+        r.map_err(|ioerr| {
+            let orig_detail = ioerr.detail.clone();
+            let m = "graphviz::render failed";
+            io::IoError {
+                detail: Some(match orig_detail {
+                    None => m.into_string(),
+                    Some(d) => format!("{}: {}", m, d)
+                }),
+                ..ioerr
+            }
+        })
+    }
+}
index 9b3cc2b6a0a0002ed2ed0646d7f1cb5005076f65..0d4f4f556e16c6ef172847791164ff104a82dfa8 100644 (file)
@@ -31,7 +31,6 @@
 #![allow(deprecated)]
 #![feature(macro_rules, globs, struct_variant, managed_boxes, quote)]
 #![feature(default_type_params, phase, unsafe_destructor)]
-#![feature(issue_5723_bootstrap)]
 
 #![allow(unknown_features)] // NOTE: Remove after next snapshot
 #![feature(rustc_diagnostic_macros)]
@@ -136,6 +135,7 @@ pub mod util {
     pub mod common;
     pub mod ppaux;
     pub mod nodemap;
+    pub mod snapshot_vec;
 }
 
 pub mod lib {
index 01fea98dfa0768546cc5a74f07000da3508bb394..4b43c685fa97bd4ca432d07f002d9b877b317224 100644 (file)
@@ -58,7 +58,7 @@ fn get_lints(&self) -> LintArray {
 
     fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
         match e.node {
-            ast::ExprWhile(cond, _) => {
+            ast::ExprWhile(cond, _, _) => {
                 match cond.node {
                     ast::ExprLit(lit) => {
                         match lit.node {
@@ -736,20 +736,16 @@ fn check_must_use(cx: &Context, attrs: &[ast::Attribute], sp: Span) -> bool {
     }
 }
 
-declare_lint!(NON_CAMEL_CASE_TYPES, Warn,
-              "types, variants and traits should have camel case names")
+declare_lint!(pub NON_CAMEL_CASE_TYPES, Warn,
+              "types, variants, traits and type parameters should have camel case names")
 
 pub struct NonCamelCaseTypes;
 
-impl LintPass for NonCamelCaseTypes {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(NON_CAMEL_CASE_TYPES)
-    }
-
-    fn check_item(&mut self, cx: &Context, it: &ast::Item) {
+impl NonCamelCaseTypes {
+    fn check_case(&self, cx: &Context, sort: &str, ident: ast::Ident, span: Span) {
         fn is_camel_case(ident: ast::Ident) -> bool {
             let ident = token::get_ident(ident);
-            assert!(!ident.get().is_empty());
+            if ident.get().is_empty() { return true; }
             let ident = ident.get().trim_chars('_');
 
             // start with a non-lowercase letter rather than non-uppercase
@@ -764,20 +760,26 @@ fn to_camel_case(s: &str) -> String {
             )).collect()
         }
 
-        fn check_case(cx: &Context, sort: &str, ident: ast::Ident, span: Span) {
-            let s = token::get_ident(ident);
+        let s = token::get_ident(ident);
 
-            if !is_camel_case(ident) {
-                let c = to_camel_case(s.get());
-                let m = if c.is_empty() {
-                    format!("{} `{}` should have a camel case name such as `CamelCase`", sort, s)
-                } else {
-                    format!("{} `{}` should have a camel case name such as `{}`", sort, s, c)
-                };
-                cx.span_lint(NON_CAMEL_CASE_TYPES, span, m.as_slice());
-            }
+        if !is_camel_case(ident) {
+            let c = to_camel_case(s.get());
+            let m = if c.is_empty() {
+                format!("{} `{}` should have a camel case name such as `CamelCase`", sort, s)
+            } else {
+                format!("{} `{}` should have a camel case name such as `{}`", sort, s, c)
+            };
+            cx.span_lint(NON_CAMEL_CASE_TYPES, span, m.as_slice());
         }
+    }
+}
+
+impl LintPass for NonCamelCaseTypes {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(NON_CAMEL_CASE_TYPES)
+    }
 
+    fn check_item(&mut self, cx: &Context, it: &ast::Item) {
         let has_extern_repr = it.attrs.iter().map(|attr| {
             attr::find_repr_attrs(cx.tcx.sess.diagnostic(), attr).iter()
                 .any(|r| r == &attr::ReprExtern)
@@ -786,21 +788,27 @@ fn check_case(cx: &Context, sort: &str, ident: ast::Ident, span: Span) {
 
         match it.node {
             ast::ItemTy(..) | ast::ItemStruct(..) => {
-                check_case(cx, "type", it.ident, it.span)
+                self.check_case(cx, "type", it.ident, it.span)
             }
             ast::ItemTrait(..) => {
-                check_case(cx, "trait", it.ident, it.span)
+                self.check_case(cx, "trait", it.ident, it.span)
             }
             ast::ItemEnum(ref enum_definition, _) => {
                 if has_extern_repr { return }
-                check_case(cx, "type", it.ident, it.span);
+                self.check_case(cx, "type", it.ident, it.span);
                 for variant in enum_definition.variants.iter() {
-                    check_case(cx, "variant", variant.node.name, variant.span);
+                    self.check_case(cx, "variant", variant.node.name, variant.span);
                 }
             }
             _ => ()
         }
     }
+
+    fn check_generics(&mut self, cx: &Context, it: &ast::Generics) {
+        for gen in it.ty_params.iter() {
+            self.check_case(cx, "type parameter", gen.ident, gen.span);
+        }
+    }
 }
 
 #[deriving(PartialEq)]
@@ -836,17 +844,18 @@ fn method_context(cx: &Context, m: &ast::Method) -> MethodContext {
     }
 }
 
-declare_lint!(NON_SNAKE_CASE_FUNCTIONS, Warn,
-              "methods and functions should have snake case names")
+declare_lint!(pub NON_SNAKE_CASE, Warn,
+              "methods, functions, lifetime parameters and modules should have snake case names")
 
-pub struct NonSnakeCaseFunctions;
+pub struct NonSnakeCase;
 
-impl NonSnakeCaseFunctions {
+impl NonSnakeCase {
     fn check_snake_case(&self, cx: &Context, sort: &str, ident: ast::Ident, span: Span) {
         fn is_snake_case(ident: ast::Ident) -> bool {
             let ident = token::get_ident(ident);
-            assert!(!ident.get().is_empty());
-            let ident = ident.get().trim_chars('_');
+            if ident.get().is_empty() { return true; }
+            let ident = ident.get().trim_left_chars('\'');
+            let ident = ident.trim_chars('_');
 
             let mut allow_underscore = true;
             ident.chars().all(|c| {
@@ -865,7 +874,7 @@ fn to_snake_case(str: &str) -> String {
                 let mut buf = String::new();
                 if s.is_empty() { continue; }
                 for ch in s.chars() {
-                    if !buf.is_empty() && ch.is_uppercase() {
+                    if !buf.is_empty() && buf.as_slice() != "'" && ch.is_uppercase() {
                         words.push(buf);
                         buf = String::new();
                     }
@@ -879,16 +888,16 @@ fn to_snake_case(str: &str) -> String {
         let s = token::get_ident(ident);
 
         if !is_snake_case(ident) {
-            cx.span_lint(NON_SNAKE_CASE_FUNCTIONS, span,
+            cx.span_lint(NON_SNAKE_CASE, span,
                 format!("{} `{}` should have a snake case name such as `{}`",
                         sort, s, to_snake_case(s.get())).as_slice());
         }
     }
 }
 
-impl LintPass for NonSnakeCaseFunctions {
+impl LintPass for NonSnakeCase {
     fn get_lints(&self) -> LintArray {
-        lint_array!(NON_SNAKE_CASE_FUNCTIONS)
+        lint_array!(NON_SNAKE_CASE)
     }
 
     fn check_fn(&mut self, cx: &Context,
@@ -908,12 +917,52 @@ fn check_fn(&mut self, cx: &Context,
         }
     }
 
+    fn check_item(&mut self, cx: &Context, it: &ast::Item) {
+        match it.node {
+            ast::ItemMod(_) => {
+                self.check_snake_case(cx, "module", it.ident, it.span);
+            }
+            _ => {}
+        }
+    }
+
     fn check_ty_method(&mut self, cx: &Context, t: &ast::TypeMethod) {
         self.check_snake_case(cx, "trait method", t.ident, t.span);
     }
+
+    fn check_lifetime_decl(&mut self, cx: &Context, t: &ast::LifetimeDef) {
+        self.check_snake_case(cx, "lifetime", t.lifetime.name.ident(), t.lifetime.span);
+    }
+
+    fn check_pat(&mut self, cx: &Context, p: &ast::Pat) {
+        match &p.node {
+            &ast::PatIdent(_, ref path1, _) => {
+                match cx.tcx.def_map.borrow().find(&p.id) {
+                    Some(&def::DefLocal(_, _)) | Some(&def::DefBinding(_, _)) |
+                            Some(&def::DefArg(_, _)) => {
+                        self.check_snake_case(cx, "variable", path1.node, p.span);
+                    }
+                    _ => {}
+                }
+            }
+            _ => {}
+        }
+    }
+
+    fn check_struct_def(&mut self, cx: &Context, s: &ast::StructDef,
+            _: ast::Ident, _: &ast::Generics, _: ast::NodeId) {
+        for sf in s.fields.iter() {
+            match sf.node {
+                ast::StructField_ { kind: ast::NamedField(ident, _), .. } => {
+                    self.check_snake_case(cx, "structure field", ident, sf.span);
+                }
+                _ => {}
+            }
+        }
+    }
 }
 
-declare_lint!(NON_UPPERCASE_STATICS, Allow,
+declare_lint!(pub NON_UPPERCASE_STATICS, Allow,
               "static constants should have uppercase identifiers")
 
 pub struct NonUppercaseStatics;
@@ -942,17 +991,6 @@ fn check_item(&mut self, cx: &Context, it: &ast::Item) {
             _ => {}
         }
     }
-}
-
-declare_lint!(NON_UPPERCASE_PATTERN_STATICS, Warn,
-              "static constants in match patterns should be all caps")
-
-pub struct NonUppercasePatternStatics;
-
-impl LintPass for NonUppercasePatternStatics {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(NON_UPPERCASE_PATTERN_STATICS)
-    }
 
     fn check_pat(&mut self, cx: &Context, p: &ast::Pat) {
         // Lint for constants that look like binding identifiers (#7526)
@@ -960,7 +998,7 @@ fn check_pat(&mut self, cx: &Context, p: &ast::Pat) {
             (&ast::PatIdent(_, ref path1, _), Some(&def::DefStatic(_, false))) => {
                 let s = token::get_ident(path1.node);
                 if s.get().chars().any(|c| c.is_lowercase()) {
-                    cx.span_lint(NON_UPPERCASE_PATTERN_STATICS, path1.span,
+                    cx.span_lint(NON_UPPERCASE_STATICS, path1.span,
                         format!("static constant in pattern `{}` should have an uppercase \
                                  name such as `{}`",
                                 s.get(), s.get().chars().map(|c| c.to_uppercase())
@@ -972,54 +1010,6 @@ fn check_pat(&mut self, cx: &Context, p: &ast::Pat) {
     }
 }
 
-declare_lint!(UPPERCASE_VARIABLES, Warn,
-              "variable and structure field names should start with a lowercase character")
-
-pub struct UppercaseVariables;
-
-impl LintPass for UppercaseVariables {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UPPERCASE_VARIABLES)
-    }
-
-    fn check_pat(&mut self, cx: &Context, p: &ast::Pat) {
-        match &p.node {
-            &ast::PatIdent(_, ref path1, _) => {
-                match cx.tcx.def_map.borrow().find(&p.id) {
-                    Some(&def::DefLocal(_, _)) | Some(&def::DefBinding(_, _)) |
-                            Some(&def::DefArg(_, _)) => {
-                        let s = token::get_ident(path1.node);
-                        if s.get().len() > 0 && s.get().char_at(0).is_uppercase() {
-                            cx.span_lint(UPPERCASE_VARIABLES, path1.span,
-                                         "variable names should start with \
-                                          a lowercase character");
-                        }
-                    }
-                    _ => {}
-                }
-            }
-            _ => {}
-        }
-    }
-
-    fn check_struct_def(&mut self, cx: &Context, s: &ast::StructDef,
-            _: ast::Ident, _: &ast::Generics, _: ast::NodeId) {
-        for sf in s.fields.iter() {
-            match sf.node {
-                ast::StructField_ { kind: ast::NamedField(ident, _), .. } => {
-                    let s = token::get_ident(ident);
-                    if s.get().char_at(0).is_uppercase() {
-                        cx.span_lint(UPPERCASE_VARIABLES, sf.span,
-                                     "structure field names should start with \
-                                      a lowercase character");
-                    }
-                }
-                _ => {}
-            }
-        }
-    }
-}
-
 declare_lint!(UNNECESSARY_PARENS, Warn,
               "`if`, `match`, `while` and `return` do not need parentheses")
 
@@ -1083,7 +1073,7 @@ fn get_lints(&self) -> LintArray {
     fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
         let (value, msg, struct_lit_needs_parens) = match e.node {
             ast::ExprIf(cond, _, _) => (cond, "`if` condition", true),
-            ast::ExprWhile(cond, _) => (cond, "`while` condition", true),
+            ast::ExprWhile(cond, _, _) => (cond, "`while` condition", true),
             ast::ExprMatch(head, _) => (head, "`match` head expression", true),
             ast::ExprRet(Some(value)) => (value, "`return` value", false),
             ast::ExprAssign(_, value) => (value, "assigned value", false),
@@ -1153,7 +1143,7 @@ fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
     }
 }
 
-declare_lint!(UNUSED_MUT, Warn,
+declare_lint!(pub UNUSED_MUT, Warn,
               "detect mut variables which don't need to be mutable")
 
 pub struct UnusedMut;
index cf018927f70b460aae25795e75bf91e22387d1a9..b40916dcc30aaefe3c14dba1d593d15983daebe4 100644 (file)
@@ -66,6 +66,10 @@ pub struct LintStore {
 
     /// Current levels of each lint, and where they were set.
     levels: HashMap<LintId, LevelSource>,
+
+    /// Map of registered lint groups to what lints they expand to. The bool
+    /// is true if the lint group was added by a plugin.
+    lint_groups: HashMap<&'static str, (Vec<LintId>, bool)>,
 }
 
 impl LintStore {
@@ -90,6 +94,7 @@ pub fn new() -> LintStore {
             passes: Some(vec!()),
             by_name: HashMap::new(),
             levels: HashMap::new(),
+            lint_groups: HashMap::new(),
         }
     }
 
@@ -97,6 +102,10 @@ pub fn get_lints<'t>(&'t self) -> &'t [(&'static Lint, bool)] {
         self.lints.as_slice()
     }
 
+    pub fn get_lint_groups<'t>(&'t self) -> Vec<(&'static str, Vec<LintId>, bool)> {
+        self.lint_groups.iter().map(|(k, &(ref v, b))| (*k, v.clone(), b)).collect()
+    }
+
     pub fn register_pass(&mut self, sess: Option<&Session>,
                          from_plugin: bool, pass: LintPassObject) {
         for &lint in pass.get_lints().iter() {
@@ -123,6 +132,25 @@ pub fn register_pass(&mut self, sess: Option<&Session>,
         self.passes.get_mut_ref().push(pass);
     }
 
+    pub fn register_group(&mut self, sess: Option<&Session>,
+                          from_plugin: bool, name: &'static str,
+                          to: Vec<LintId>) {
+        let new = self.lint_groups.insert(name, (to, from_plugin));
+
+        if !new {
+            let msg = format!("duplicate specification of lint group {}", name);
+            match (sess, from_plugin) {
+                // We load builtin lints first, so a duplicate is a compiler bug.
+                // Use early_error when handling -W help with no crate.
+                (None, _) => early_error(msg.as_slice()),
+                (Some(sess), false) => sess.bug(msg.as_slice()),
+
+                // A duplicate name from a plugin is a user error.
+                (Some(sess), true)  => sess.err(msg.as_slice()),
+            }
+        }
+    }
+
     pub fn register_builtin(&mut self, sess: Option<&Session>) {
         macro_rules! add_builtin ( ( $sess:ident, $($name:ident),*, ) => (
             {$(
@@ -136,6 +164,10 @@ macro_rules! add_builtin_with_new ( ( $sess:ident, $($name:ident),*, ) => (
             )*}
         ))
 
+        macro_rules! add_lint_group ( ( $sess:ident, $name:expr, $($lint:ident),* ) => (
+            self.register_group($sess, false, $name, vec![$(LintId::of(builtin::$lint)),*]);
+        ))
+
         add_builtin!(sess,
                      HardwiredLints,
                      WhileTrue,
@@ -146,10 +178,8 @@ macro_rules! add_builtin_with_new ( ( $sess:ident, $($name:ident),*, ) => (
                      PathStatement,
                      UnusedResult,
                      NonCamelCaseTypes,
-                     NonSnakeCaseFunctions,
+                     NonSnakeCase,
                      NonUppercaseStatics,
-                     NonUppercasePatternStatics,
-                     UppercaseVariables,
                      UnnecessaryParens,
                      UnusedUnsafe,
                      UnsafeBlock,
@@ -164,6 +194,13 @@ macro_rules! add_builtin_with_new ( ( $sess:ident, $($name:ident),*, ) => (
                               MissingDoc,
         )
 
+        add_lint_group!(sess, "bad_style",
+                        NON_CAMEL_CASE_TYPES, NON_SNAKE_CASE, NON_UPPERCASE_STATICS)
+
+        add_lint_group!(sess, "unused",
+                        UNUSED_IMPORTS, UNUSED_VARIABLE, DEAD_ASSIGNMENT, DEAD_CODE,
+                        UNUSED_MUT, UNREACHABLE_CODE)
+
         // We have one lint pass defined in this module.
         self.register_pass(sess, false, box GatherNodeLevels as LintPassObject);
     }
@@ -172,8 +209,20 @@ pub fn process_command_line(&mut self, sess: &Session) {
         for &(ref lint_name, level) in sess.opts.lint_opts.iter() {
             match self.by_name.find_equiv(&lint_name.as_slice()) {
                 Some(&lint_id) => self.set_level(lint_id, (level, CommandLine)),
-                None => sess.err(format!("unknown {} flag: {}",
-                                         level.as_str(), lint_name).as_slice()),
+                None => {
+                    match self.lint_groups.iter().map(|(&x, &(ref y, _))| (x, y.clone()))
+                                                 .collect::<HashMap<&'static str, Vec<LintId>>>()
+                                                 .find_equiv(&lint_name.as_slice()) {
+                        Some(v) => {
+                            v.iter()
+                             .map(|lint_id: &LintId|
+                                     self.set_level(*lint_id, (level, CommandLine)))
+                             .collect::<Vec<()>>();
+                        }
+                        None => sess.err(format!("unknown {} flag: {}",
+                                                 level.as_str(), lint_name).as_slice()),
+                    }
+                }
             }
         }
     }
@@ -207,7 +256,7 @@ pub struct Context<'a> {
 macro_rules! run_lints ( ($cx:expr, $f:ident, $($args:expr),*) => ({
     // Move the vector of passes out of `$cx` so that we can
     // iterate over it mutably while passing `$cx` to the methods.
-    let mut passes = $cx.lints.passes.take_unwrap();
+    let mut passes = $cx.lints.passes.take().unwrap();
     for obj in passes.mut_iter() {
         obj.$f($cx, $($args),*);
     }
@@ -307,7 +356,7 @@ fn new(tcx: &'a ty::ctxt,
             krate: krate,
             exported_items: exported_items,
             lints: lint_store,
-            level_stack: vec!(),
+            level_stack: vec![],
             node_levels: RefCell::new(HashMap::new()),
         }
     }
@@ -361,35 +410,46 @@ fn with_lint_attrs(&mut self,
         let mut pushed = 0u;
 
         for result in gather_attrs(attrs).move_iter() {
-            let (lint_id, level, span) = match result {
+            let v = match result {
                 Err(span) => {
                     self.tcx.sess.span_err(span, "malformed lint attribute");
                     continue;
                 }
                 Ok((lint_name, level, span)) => {
                     match self.lints.by_name.find_equiv(&lint_name.get()) {
-                        Some(&lint_id) => (lint_id, level, span),
+                        Some(&lint_id) => vec![(lint_id, level, span)],
                         None => {
-                            self.span_lint(builtin::UNRECOGNIZED_LINT, span,
-                                           format!("unknown `{}` attribute: `{}`",
-                                                   level.as_str(), lint_name).as_slice());
-                            continue;
+                            match self.lints.lint_groups.find_equiv(&lint_name.get()) {
+                                Some(&(ref v, _)) => v.iter()
+                                                      .map(|lint_id: &LintId|
+                                                           (*lint_id, level, span))
+                                                      .collect(),
+                                None => {
+                                    self.span_lint(builtin::UNRECOGNIZED_LINT, span,
+                                               format!("unknown `{}` attribute: `{}`",
+                                                       level.as_str(), lint_name).as_slice());
+                                    continue;
+                                }
+                            }
                         }
                     }
                 }
             };
 
-            let now = self.lints.get_level_source(lint_id).val0();
-            if now == Forbid && level != Forbid {
-                let lint_name = lint_id.as_str();
-                self.tcx.sess.span_err(span,
-                                       format!("{}({}) overruled by outer forbid({})",
-                                               level.as_str(), lint_name, lint_name).as_slice());
-            } else if now != level {
-                let src = self.lints.get_level_source(lint_id).val1();
-                self.level_stack.push((lint_id, (now, src)));
-                pushed += 1;
-                self.lints.set_level(lint_id, (level, Node(span)));
+            for (lint_id, level, span) in v.move_iter() {
+                let now = self.lints.get_level_source(lint_id).val0();
+                if now == Forbid && level != Forbid {
+                    let lint_name = lint_id.as_str();
+                    self.tcx.sess.span_err(span,
+                                           format!("{}({}) overruled by outer forbid({})",
+                                                   level.as_str(), lint_name,
+                                                   lint_name).as_slice());
+                } else if now != level {
+                    let src = self.lints.get_level_source(lint_id).val1();
+                    self.level_stack.push((lint_id, (now, src)));
+                    pushed += 1;
+                    self.lints.set_level(lint_id, (level, Node(span)));
+                }
             }
         }
 
index 2acc92cd2275def6762c6521bc5ac53a5d7c9b1c..776067d49a218a1f01c21a9027f3c41c2af1da6c 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -227,7 +227,7 @@ fn expr(&mut self, expr: Gc<ast::Expr>, pred: CFGIndex) -> CFGIndex {
                 self.add_node(expr.id, [then_exit, else_exit])           // 4, 5
             }
 
-            ast::ExprWhile(ref cond, ref body) => {
+            ast::ExprWhile(ref cond, ref body, _) => {
                 //
                 //         [pred]
                 //           |
index 12841fb20d26fdcf4161644f6bb63a538e6a68bf..a40294328c71be484b64d33dcff380736a789cac 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -35,7 +35,7 @@ fn visit_item(&mut self, i: &ast::Item, _cx: Context) {
 
     fn visit_expr(&mut self, e: &ast::Expr, cx:Context) {
         match e.node {
-            ast::ExprWhile(ref e, ref b) => {
+            ast::ExprWhile(ref e, ref b, _) => {
                 self.visit_expr(&**e, cx);
                 self.visit_block(&**b, Loop);
             }
index 91c227cd5bca9ed3092a6c950319599405a39410..097f49a1e6e55173dffc27103386a73d8e0c1a85 100644 (file)
@@ -80,13 +80,6 @@ pub trait DataFlowOperator : BitwiseOperator {
     fn initial_value(&self) -> bool;
 }
 
-#[cfg(stage0)]
-struct PropagationContext<'a, 'b, O> {
-    dfcx: &'a mut DataFlowContext<'b, O>,
-    changed: bool
-}
-
-#[cfg(not(stage0))]
 struct PropagationContext<'a, 'b:'a, O:'a> {
     dfcx: &'a mut DataFlowContext<'b, O>,
     changed: bool
@@ -111,6 +104,7 @@ fn pre(&self,
            ps: &mut pprust::State,
            node: pprust::AnnNode) -> io::IoResult<()> {
         let id = match node {
+            pprust::NodeIdent(_) | pprust::NodeName(_) => 0,
             pprust::NodeExpr(expr) => expr.id,
             pprust::NodeBlock(blk) => blk.id,
             pprust::NodeItem(_) => 0,
index ae9a3fa6a67a5a0cc9b39ec4ad8f8c6cad9906fd..7177516e539298dd03466d5827ab07d0db1c4d85 100644 (file)
@@ -192,14 +192,6 @@ fn from_method_origin(tcx: &ty::ctxt, origin: &MethodOrigin)
 // supplies types from the tree. After type checking is complete, you
 // can just use the tcx as the typer.
 
-#[cfg(stage0)]
-pub struct ExprUseVisitor<'d,'t,TYPER> {
-    typer: &'t TYPER,
-    mc: mc::MemCategorizationContext<'t,TYPER>,
-    delegate: &'d mut Delegate+'d,
-}
-
-#[cfg(not(stage0))]
 pub struct ExprUseVisitor<'d,'t,TYPER:'t> {
     typer: &'t TYPER,
     mc: mc::MemCategorizationContext<'t,TYPER>,
@@ -410,7 +402,7 @@ pub fn walk_expr(&mut self, expr: &ast::Expr) {
                 self.walk_block(&**blk);
             }
 
-            ast::ExprWhile(ref cond_expr, ref blk) => {
+            ast::ExprWhile(ref cond_expr, ref blk, _) => {
                 self.consume_expr(&**cond_expr);
                 self.walk_block(&**blk);
             }
index 38288bf301161b735c4be0c7c05d0e82af12cd0e..6ff09916b35ae585f3c08428ba70abc4dfbcc031 100644 (file)
@@ -1017,7 +1017,7 @@ fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode)
             self.propagate_through_expr(&**cond, ln)
           }
 
-          ExprWhile(ref cond, ref blk) => {
+          ExprWhile(ref cond, ref blk, _) => {
             self.propagate_through_loop(expr,
                                         WhileLoop(cond.clone()),
                                         &**blk,
index 662b55ba3610982fd52f6c7c347a2a24bbacbd13..23cab419aa2c78597b4c4d49d2f3dbc412ba8964 100644 (file)
@@ -240,12 +240,6 @@ fn id(&self) -> ast::NodeId { self.id }
     fn span(&self) -> Span { self.span }
 }
 
-#[cfg(stage0)]
-pub struct MemCategorizationContext<'t,TYPER> {
-    typer: &'t TYPER
-}
-
-#[cfg(not(stage0))]
 pub struct MemCategorizationContext<'t,TYPER:'t> {
     typer: &'t TYPER
 }
index 11dd3eee88e888f42d93dbd1810e5e13bd255d4c..21bfcfeec70b51603e6f32ab31fb03a7051dfaf0 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -496,7 +496,7 @@ fn resolve_expr(visitor: &mut RegionResolutionVisitor,
             visitor.region_maps.mark_as_terminating_scope(body.id);
         }
 
-        ast::ExprWhile(expr, body) => {
+        ast::ExprWhile(expr, body, _) => {
             visitor.region_maps.mark_as_terminating_scope(expr.id);
             visitor.region_maps.mark_as_terminating_scope(body.id);
         }
index 58be2c73bd9b0ceb0dfcb1ab7d6beec7e14cb449..0c8697d31f3c98dd2023d1013d9578b96344b004 100644 (file)
@@ -23,7 +23,7 @@
 
 use syntax::ast::{Arm, BindByRef, BindByValue, BindingMode, Block, Crate};
 use syntax::ast::{DeclItem, DefId, Expr, ExprAgain, ExprBreak, ExprField};
-use syntax::ast::{ExprFnBlock, ExprForLoop, ExprLoop, ExprMethodCall};
+use syntax::ast::{ExprFnBlock, ExprForLoop, ExprLoop, ExprWhile, ExprMethodCall};
 use syntax::ast::{ExprPath, ExprProc, ExprStruct, ExprUnboxedFn, FnDecl};
 use syntax::ast::{ForeignItem, ForeignItemFn, ForeignItemStatic, Generics};
 use syntax::ast::{Ident, ImplItem, Item, ItemEnum, ItemFn, ItemForeignMod};
@@ -2822,9 +2822,10 @@ fn check_for_conflicts_between_imports_and_items(&mut self,
                  .contains_key(&name) {
             match import_resolution.type_target {
                 Some(ref target) if !target.shadowable => {
-                    self.session.span_err(import_span,
-                                          "import conflicts with imported \
-                                           crate in this module");
+                    let msg = format!("import `{}` conflicts with imported \
+                                       crate in this module",
+                                      token::get_name(name).get());
+                    self.session.span_err(import_span, msg.as_slice());
                 }
                 Some(_) | None => {}
             }
@@ -2845,9 +2846,10 @@ fn check_for_conflicts_between_imports_and_items(&mut self,
                 match *name_bindings.value_def.borrow() {
                     None => {}
                     Some(ref value) => {
-                        self.session.span_err(import_span,
-                                              "import conflicts with value \
-                                               in this module");
+                        let msg = format!("import `{}` conflicts with value \
+                                           in this module",
+                                          token::get_name(name).get());
+                        self.session.span_err(import_span, msg.as_slice());
                         match value.value_span {
                             None => {}
                             Some(span) => {
@@ -2867,9 +2869,10 @@ fn check_for_conflicts_between_imports_and_items(&mut self,
                 match *name_bindings.type_def.borrow() {
                     None => {}
                     Some(ref ty) => {
-                        self.session.span_err(import_span,
-                                              "import conflicts with type in \
-                                               this module");
+                        let msg = format!("import `{}` conflicts with type in \
+                                           this module",
+                                          token::get_name(name).get());
+                        self.session.span_err(import_span, msg.as_slice());
                         match ty.type_span {
                             None => {}
                             Some(span) => {
@@ -5622,7 +5625,7 @@ fn resolve_expr(&mut self, expr: &Expr) {
                 visit::walk_expr(self, expr, ());
             }
 
-            ExprLoop(_, Some(label)) => {
+            ExprLoop(_, Some(label)) | ExprWhile(_, _, Some(label)) => {
                 self.with_label_rib(|this| {
                     let def_like = DlDef(DefLabel(expr.id));
 
index bbd6c252849b3db483c0b616e24f487969ec9556..9531e824298dbd5c33396a644d95797ea3f2b939 100644 (file)
@@ -340,21 +340,12 @@ struct ArmData<'a, 'b> {
  * As we proceed `bound_ptrs` are filled with pointers to values to be bound,
  * these pointers are stored in llmatch variables just before executing `data` arm.
  */
-#[cfg(not(stage0))]
 struct Match<'a, 'b:'a> {
     pats: Vec<Gc<ast::Pat>>,
     data: &'a ArmData<'a, 'b>,
     bound_ptrs: Vec<(Ident, ValueRef)>
 }
 
-///Dox
-#[cfg(stage0)]
-struct Match<'a, 'b> {
-    pats: Vec<Gc<ast::Pat>>,
-    data: &'a ArmData<'a, 'b>,
-    bound_ptrs: Vec<(Ident, ValueRef)>
-}
-
 impl<'a, 'b> Repr for Match<'a, 'b> {
     fn repr(&self, tcx: &ty::ctxt) -> String {
         if tcx.sess.verbose() {
index 8968c8cc2599f5d443b7af554c50bc964d693b4a..f05602bbb58c830fabc42bc4cf9b418a06781887 100644 (file)
@@ -166,7 +166,7 @@ fn drop(&mut self) {
             let end = time::precise_time_ns();
             let elapsed = ((end - self.start) / 1_000_000) as uint;
             let iend = self.ccx.stats.n_llvm_insns.get();
-            self.ccx.stats.fn_stats.borrow_mut().push((self.name.take_unwrap(),
+            self.ccx.stats.fn_stats.borrow_mut().push((self.name.take().unwrap(),
                                                        elapsed,
                                                        iend - self.istart));
             self.ccx.stats.n_fns.set(self.ccx.stats.n_fns.get() + 1);
index d2ddf3ff696627c76e1ded2d0da9d31b8b55b6e0..76059e8df4f8cd046fdf81faa566608ef6b9e9e3 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 #![allow(dead_code)] // FFI wrappers
-#![allow(non_snake_case_functions)]
+#![allow(non_snake_case)]
 
 use llvm;
 use llvm::{CallConv, AtomicBinOp, AtomicOrdering, AsmDialect, AttrBuilder};
index 0e2bf2104fd55923bb61f002e59b03e855261489..ccfc79ac0c5002bec9ce1074297c366250d6df6f 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![allow(non_uppercase_pattern_statics)]
+#![allow(non_uppercase_statics)]
 
 use llvm;
 use llvm::{Integer, Pointer, Float, Double, Struct, Array};
index ac4c56a1d1f11669a2df8dca07b664f2d42c72c5..77815285428fdb3a5cd3954be758b2a3a7c1f22f 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![allow(non_uppercase_pattern_statics)]
+#![allow(non_uppercase_statics)]
 
 use libc::c_uint;
 use std::cmp;
index 2ab4814fa0cc3c633e3a2a579d6efc37ca9c0bc6..0d4cb637ae0cd7b95bb4f55e8476752405ca16dc 100644 (file)
@@ -11,7 +11,7 @@
 // The classification code for the x86_64 ABI is taken from the clay language
 // https://github.com/jckarter/clay/blob/master/compiler/src/externals.cpp
 
-#![allow(non_uppercase_pattern_statics)]
+#![allow(non_uppercase_statics)]
 
 use llvm;
 use llvm::{Integer, Pointer, Float, Double};
index 05528d2b3d88e60876ff07de8f1d48cbe06e05bc..d92364b2570108ab9e2cccfc373c9ee59c6c8c53 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![allow(non_camel_case_types, non_snake_case_functions)]
+#![allow(non_camel_case_types, non_snake_case)]
 
 //! Code that is useful in various trans modules.
 
index 26973910400ee1f0a60ccaebc75413d56a0580fe..62cd38c1e909ab38d60d3039b8eddc7609facb19 100644 (file)
@@ -235,6 +235,9 @@ struct List {
 static UNKNOWN_FILE_METADATA: DIFile = (0 as DIFile);
 static UNKNOWN_SCOPE_METADATA: DIScope = (0 as DIScope);
 
+static FLAGS_NONE: c_uint = 0;
+static FLAGS_ARTIFICAL: c_uint = llvm::debuginfo::FlagArtificial as c_uint;
+
 //=-----------------------------------------------------------------------------
 //  Public Interface of debuginfo module
 //=-----------------------------------------------------------------------------
@@ -1447,7 +1450,7 @@ fn is_node_local_to_unit(cx: &CrateContext, node_id: ast::NodeId) -> bool
     !cx.reachable.contains(&node_id)
 }
 
-#[allow(non_snake_case_functions)]
+#[allow(non_snake_case)]
 fn create_DIArray(builder: DIBuilderRef, arr: &[DIDescriptor]) -> DIArray {
     return unsafe {
         llvm::LLVMDIBuilderGetOrCreateArray(builder, arr.as_ptr(), arr.len() as u32)
@@ -1732,6 +1735,7 @@ struct MemberDescription {
     llvm_type: Type,
     type_metadata: DIType,
     offset: MemberOffset,
+    flags: c_uint
 }
 
 // A factory for MemberDescriptions. It produces a list of member descriptions
@@ -1890,6 +1894,7 @@ fn create_member_descriptions(&self, cx: &CrateContext) -> Vec<MemberDescription
                 llvm_type: type_of::type_of(cx, field.mt.ty),
                 type_metadata: type_metadata(cx, field.mt.ty, self.span),
                 offset: offset,
+                flags: FLAGS_NONE,
             }
         }).collect()
     }
@@ -1950,6 +1955,7 @@ fn create_member_descriptions(&self, cx: &CrateContext)
                 llvm_type: type_of::type_of(cx, component_type),
                 type_metadata: type_metadata(cx, component_type, self.span),
                 offset: ComputedMemberOffset,
+                flags: FLAGS_NONE,
             }
         }).collect()
     }
@@ -2035,6 +2041,7 @@ fn create_member_descriptions(&self, cx: &CrateContext) -> Vec<MemberDescription
                             llvm_type: variant_llvm_type,
                             type_metadata: variant_type_metadata,
                             offset: FixedMemberOffset { bytes: 0 },
+                            flags: FLAGS_NONE
                         }
                     }).collect()
             },
@@ -2068,6 +2075,7 @@ fn create_member_descriptions(&self, cx: &CrateContext) -> Vec<MemberDescription
                             llvm_type: variant_llvm_type,
                             type_metadata: variant_type_metadata,
                             offset: FixedMemberOffset { bytes: 0 },
+                            flags: FLAGS_NONE
                         }
                     ]
                 }
@@ -2101,6 +2109,7 @@ fn create_member_descriptions(&self, cx: &CrateContext) -> Vec<MemberDescription
                     llvm_type: non_null_llvm_type,
                     type_metadata: non_null_type_metadata,
                     offset: FixedMemberOffset { bytes: 0 },
+                    flags: FLAGS_NONE
                 };
 
                 let unique_type_id = debug_context(cx).type_map
@@ -2138,6 +2147,7 @@ fn create_member_descriptions(&self, cx: &CrateContext) -> Vec<MemberDescription
                         llvm_type: artificial_struct_llvm_type,
                         type_metadata: artificial_struct_metadata,
                         offset: FixedMemberOffset { bytes: 0 },
+                        flags: FLAGS_NONE
                     }
                 ]
             },
@@ -2182,6 +2192,7 @@ fn create_member_descriptions(&self, cx: &CrateContext) -> Vec<MemberDescription
                         llvm_type: variant_llvm_type,
                         type_metadata: variant_type_metadata,
                         offset: FixedMemberOffset { bytes: 0 },
+                        flags: FLAGS_NONE
                     }
                 ]
             },
@@ -2208,6 +2219,11 @@ fn create_member_descriptions(&self, cx: &CrateContext) -> Vec<MemberDescription
                     _ => type_metadata(cx, ty, self.span)
                 },
                 offset: ComputedMemberOffset,
+                flags: if self.discriminant_type_metadata.is_some() &&  i == 0 {
+                    FLAGS_ARTIFICAL
+                } else {
+                    FLAGS_NONE
+                }
             }
         }).collect()
     }
@@ -2523,7 +2539,7 @@ fn set_members_of_composite_type(cx: &CrateContext,
                         bytes_to_bits(member_size),
                         bytes_to_bits(member_align),
                         bytes_to_bits(member_offset),
-                        0,
+                        member_description.flags,
                         member_description.type_metadata)
                 }
             })
@@ -2610,30 +2626,35 @@ fn at_box_metadata(cx: &CrateContext,
             llvm_type: *member_llvm_types.get(0),
             type_metadata: type_metadata(cx, int_type, codemap::DUMMY_SP),
             offset: ComputedMemberOffset,
+            flags: FLAGS_ARTIFICAL,
         },
         MemberDescription {
             name: "drop_glue".to_string(),
             llvm_type: *member_llvm_types.get(1),
             type_metadata: nil_pointer_type_metadata,
             offset: ComputedMemberOffset,
+            flags: FLAGS_ARTIFICAL,
         },
         MemberDescription {
             name: "prev".to_string(),
             llvm_type: *member_llvm_types.get(2),
             type_metadata: nil_pointer_type_metadata,
             offset: ComputedMemberOffset,
+            flags: FLAGS_ARTIFICAL,
         },
         MemberDescription {
             name: "next".to_string(),
             llvm_type: *member_llvm_types.get(3),
             type_metadata: nil_pointer_type_metadata,
             offset: ComputedMemberOffset,
+            flags: FLAGS_ARTIFICAL,
         },
         MemberDescription {
             name: "val".to_string(),
             llvm_type: *member_llvm_types.get(4),
             type_metadata: content_type_metadata,
             offset: ComputedMemberOffset,
+            flags: FLAGS_ARTIFICAL,
         }
     ];
 
@@ -2734,12 +2755,14 @@ fn vec_slice_metadata(cx: &CrateContext,
             llvm_type: *member_llvm_types.get(0),
             type_metadata: element_type_metadata,
             offset: ComputedMemberOffset,
+            flags: FLAGS_ARTIFICAL
         },
         MemberDescription {
             name: "length".to_string(),
             llvm_type: *member_llvm_types.get(1),
             type_metadata: type_metadata(cx, ty::mk_uint(), span),
             offset: ComputedMemberOffset,
+            flags: FLAGS_ARTIFICAL
         },
     ];
 
@@ -3107,7 +3130,7 @@ fn debug_context<'a>(cx: &'a CrateContext) -> &'a CrateDebugContext {
 }
 
 #[inline]
-#[allow(non_snake_case_functions)]
+#[allow(non_snake_case)]
 fn DIB(cx: &CrateContext) -> DIBuilderRef {
     cx.dbg_cx.get_ref().builder
 }
@@ -3489,7 +3512,7 @@ fn walk_expr(cx: &CrateContext,
                 }
             }
 
-            ast::ExprWhile(ref cond_exp, ref loop_body) => {
+            ast::ExprWhile(ref cond_exp, ref loop_body, _) => {
                 walk_expr(cx, &**cond_exp, scope_stack, scope_map);
 
                 with_new_scope(cx,
index c49bb7f4e6b9d0197f9a9a3fcd7b9f7c5be07c9a..72f99a3802dcbc2ff62015e24ac3ff0732dc411f 100644 (file)
@@ -900,7 +900,7 @@ fn trans_rvalue_stmt_unadjusted<'a>(bcx: &'a Block<'a>,
         ast::ExprRet(ex) => {
             controlflow::trans_ret(bcx, ex)
         }
-        ast::ExprWhile(ref cond, ref body) => {
+        ast::ExprWhile(ref cond, ref body, _) => {
             controlflow::trans_while(bcx, expr.id, &**cond, &**body)
         }
         ast::ExprForLoop(ref pat, ref head, ref body, _) => {
index 24c939dc3be8b1318ff6a46c2dddf4d43d6a07de..51cd9a115cd7c4d8d5f1ea8b52b43212c7b1a6f7 100644 (file)
@@ -403,11 +403,11 @@ fn make_drop_glue<'a>(bcx: &'a Block<'a>, v0: ValueRef, t: ty::t) -> &'a Block<'
         ty::ty_uniq(content_ty) => {
             match ty::get(content_ty).sty {
                 ty::ty_vec(ty, None) => {
-                    tvec::make_drop_glue_unboxed(bcx, v0, ty)
+                    tvec::make_drop_glue_unboxed(bcx, v0, ty, true)
                 }
                 ty::ty_str => {
                     let unit_ty = ty::sequence_element_type(bcx.tcx(), t);
-                    tvec::make_drop_glue_unboxed(bcx, v0, unit_ty)
+                    tvec::make_drop_glue_unboxed(bcx, v0, unit_ty, true)
                 }
                 ty::ty_trait(..) => {
                     let lluniquevalue = GEPi(bcx, v0, [0, abi::trt_field_box]);
@@ -507,7 +507,7 @@ fn make_drop_glue<'a>(bcx: &'a Block<'a>, v0: ValueRef, t: ty::t) -> &'a Block<'
                  None);
             bcx
         }
-        ty::ty_vec(ty, None) => tvec::make_drop_glue_unboxed(bcx, v0, ty),
+        ty::ty_vec(ty, None) => tvec::make_drop_glue_unboxed(bcx, v0, ty, false),
         _ => {
             assert!(ty::type_is_sized(bcx.tcx(), t));
             if ty::type_needs_drop(bcx.tcx(), t) &&
index 7d8e4679ae302d2ff4f3e412c93d92a89dfc9c82..3c61708fb7b83ac89368c918d01af2018cf4941c 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![allow(non_uppercase_pattern_statics)]
+#![allow(non_uppercase_statics)]
 
 use llvm;
 use llvm::{SequentiallyConsistent, Acquire, Release, Xchg, ValueRef};
index e19ee035a781e3a02169232b68c70b17caaa5783..f2a7f1dc4f8ee287d9814bb153384857b05ca6c6 100644 (file)
@@ -147,7 +147,7 @@ pub fn monomorphic_fn(ccx: &CrateContext,
             decl_internal_rust_fn(ccx, mono_ty, s.as_slice())
         };
 
-        ccx.monomorphized.borrow_mut().insert(hash_id.take_unwrap(), lldecl);
+        ccx.monomorphized.borrow_mut().insert(hash_id.take().unwrap(), lldecl);
         lldecl
     };
 
index 94ca520c533f9348e8c05e6944a3dea95bccf83e..a6ba758d5f810cf5b0a3e86a29f596541baa879d 100644 (file)
@@ -54,25 +54,31 @@ pub fn pointer_add_byte(bcx: &Block, ptr: ValueRef, bytes: ValueRef) -> ValueRef
 pub fn make_drop_glue_unboxed<'a>(
                               bcx: &'a Block<'a>,
                               vptr: ValueRef,
-                              unit_ty: ty::t)
+                              unit_ty: ty::t,
+                              should_deallocate: bool)
                               -> &'a Block<'a> {
     let not_null = IsNotNull(bcx, vptr);
     with_cond(bcx, not_null, |bcx| {
         let tcx = bcx.tcx();
         let _icx = push_ctxt("tvec::make_drop_glue_unboxed");
 
-        let len = get_len(bcx, vptr);
         let dataptr = get_dataptr(bcx, vptr);
         let bcx = if ty::type_needs_drop(tcx, unit_ty) {
+            let len = get_len(bcx, vptr);
             iter_vec_raw(bcx, dataptr, unit_ty, len, glue::drop_ty)
         } else {
             bcx
         };
 
-        let not_null = IsNotNull(bcx, dataptr);
-        with_cond(bcx, not_null, |bcx| {
-            glue::trans_exchange_free(bcx, dataptr, 0, 8)
-        })
+        if should_deallocate {
+            let not_null = IsNotNull(bcx, dataptr);
+            with_cond(bcx, not_null, |bcx| {
+                // FIXME: #13994: the old `Box<[T]>` will not support sized deallocation
+                glue::trans_exchange_free(bcx, dataptr, 0, 8)
+            })
+        } else {
+            bcx
+        }
     })
 }
 
index 017d61137e4b0d0bcbcb59e79facd5071301613e..7b98d65a3105b88a5b1f06e3c0bcb0f2492b90ce 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![allow(non_uppercase_pattern_statics)]
+#![allow(non_uppercase_statics)]
 
 use llvm;
 use llvm::{TypeRef, Bool, False, True, TypeKind, ValueRef};
index c2d0d27be6df773f9f8ca679cb0478e4c48f7586..051ddd572416ea0687ce12c3f1431b9cf5909d49 100644 (file)
@@ -30,7 +30,6 @@
 use middle::subst;
 use middle::ty;
 use middle::typeck;
-use middle::typeck::MethodCall;
 use middle::ty_fold;
 use middle::ty_fold::{TypeFoldable,TypeFolder};
 use middle;
@@ -2119,6 +2118,7 @@ pub struct TypeContents {
 
 macro_rules! def_type_content_sets(
     (mod $mname:ident { $($name:ident = $bits:expr),+ }) => {
+        #[allow(non_snake_case)]
         mod $mname {
             use middle::ty::TypeContents;
             $(pub static $name: TypeContents = TypeContents { bits: $bits };)+
index b9e96c785337a34e2c3fd4b3197e24ed76923edf..71075297b07ad30debe2b859954fe770db509cdb 100644 (file)
@@ -2028,7 +2028,7 @@ fn try_overloaded_call(fcx: &FnCtxt,
             span_err!(fcx.tcx().sess, call_expression.span, E0056,
                 "overloaded calls are experimental");
             span_note!(fcx.tcx().sess, call_expression.span,
-                "add `#[feature(overloaded_calls)]` to \
+                "add `#![feature(overloaded_calls)]` to \
                 the crate attributes to enable");
         }
 
@@ -2168,12 +2168,13 @@ fn lookup_method_for_for_loop(fcx: &FnCtxt,
         }
     };
 
+    let expr_type = fcx.expr_ty(&*iterator_expr);
     let method = method::lookup_in_trait(fcx,
                                          iterator_expr.span,
                                          Some(&*iterator_expr),
                                          token::intern("next"),
                                          trait_did,
-                                         fcx.expr_ty(&*iterator_expr),
+                                         expr_type,
                                          [],
                                          DontAutoderefReceiver,
                                          IgnoreStaticMethods);
@@ -2183,9 +2184,15 @@ fn lookup_method_for_for_loop(fcx: &FnCtxt,
     let method_type = match method {
         Some(ref method) => method.ty,
         None => {
-            fcx.tcx().sess.span_err(iterator_expr.span,
-                                    "`for` loop expression does not \
-                                     implement the `Iterator` trait");
+            let true_expr_type = fcx.infcx().resolve_type_vars_if_possible(expr_type);
+
+            if !ty::type_is_error(true_expr_type) {
+                let ty_string = fcx.infcx().ty_to_string(true_expr_type);
+                fcx.tcx().sess.span_err(iterator_expr.span,
+                                        format!("`for` loop expression has type `{}` which does \
+                                                 not implement the `Iterator` trait",
+                                                ty_string).as_slice());
+            }
             ty::mk_err()
         }
     };
@@ -3750,7 +3757,7 @@ fn check_struct_enum_variant(fcx: &FnCtxt,
         check_then_else(fcx, &**cond, &**then_blk, opt_else_expr.clone(),
                         id, expr.span, expected);
       }
-      ast::ExprWhile(ref cond, ref body) => {
+      ast::ExprWhile(ref cond, ref body, _) => {
         check_expr_has_type(fcx, &**cond, ty::mk_bool());
         check_block_no_value(fcx, &**body);
         let cond_ty = fcx.expr_ty(&**cond);
index 72f33a2f9848c707ac52207795e9569d41b1f4fb..db9d52814b6e169462c32363af321eed1aefaac3 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -749,7 +749,7 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
             rcx.set_repeating_scope(repeating_scope);
         }
 
-        ast::ExprWhile(ref cond, ref body) => {
+        ast::ExprWhile(ref cond, ref body, _) => {
             let repeating_scope = rcx.set_repeating_scope(cond.id);
             rcx.visit_expr(&**cond, ());
 
@@ -1381,8 +1381,8 @@ fn link_by_ref(rcx: &Rcx,
            expr.repr(tcx), callee_scope);
     let mc = mc::MemCategorizationContext::new(rcx);
     let expr_cmt = ignore_err!(mc.cat_expr(expr));
-    let region_min = ty::ReScope(callee_scope);
-    link_region(rcx, expr.span, region_min, ty::ImmBorrow, expr_cmt);
+    let borrow_region = ty::ReScope(callee_scope);
+    link_region(rcx, expr.span, borrow_region, ty::ImmBorrow, expr_cmt);
 }
 
 fn link_region_from_node_type(rcx: &Rcx,
@@ -1408,102 +1408,54 @@ fn link_region_from_node_type(rcx: &Rcx,
 
 fn link_region(rcx: &Rcx,
                span: Span,
-               region_min: ty::Region,
-               kind: ty::BorrowKind,
-               cmt_borrowed: mc::cmt) {
+               borrow_region: ty::Region,
+               borrow_kind: ty::BorrowKind,
+               borrow_cmt: mc::cmt) {
     /*!
-     * Informs the inference engine that a borrow of `cmt`
-     * must have the borrow kind `kind` and lifetime `region_min`.
-     * If `cmt` is a deref of a region pointer with
-     * lifetime `r_borrowed`, this will add the constraint that
-     * `region_min <= r_borrowed`.
+     * Informs the inference engine that `borrow_cmt` is being
+     * borrowed with kind `borrow_kind` and lifetime `borrow_region`.
+     * In order to ensure borrowck is satisfied, this may create
+     * constraints between regions, as explained in
+     * `link_reborrowed_region()`.
      */
 
-    // Iterate through all the things that must be live at least
-    // for the lifetime `region_min` for the borrow to be valid:
-    let mut cmt_borrowed = cmt_borrowed;
+    let mut borrow_cmt = borrow_cmt;
+    let mut borrow_kind = borrow_kind;
+
     loop {
-        debug!("link_region(region_min={}, kind={}, cmt_borrowed={})",
-               region_min.repr(rcx.tcx()),
-               kind.repr(rcx.tcx()),
-               cmt_borrowed.repr(rcx.tcx()));
-        match cmt_borrowed.cat.clone() {
-            mc::cat_deref(base, _, mc::BorrowedPtr(_, r_borrowed)) |
-            mc::cat_deref(base, _, mc::Implicit(_, r_borrowed)) => {
-                // References to an upvar `x` are translated to
-                // `*x`, since that is what happens in the
-                // underlying machine.  We detect such references
-                // and treat them slightly differently, both to
-                // offer better error messages and because we need
-                // to infer the kind of borrow (mut, const, etc)
-                // to use for each upvar.
-                let cause = match base.cat {
-                    mc::cat_upvar(ref upvar_id, _) => {
-                        match rcx.fcx.inh.upvar_borrow_map.borrow_mut()
-                                 .find_mut(upvar_id) {
-                            Some(upvar_borrow) => {
-                                debug!("link_region: {} <= {}",
-                                       region_min.repr(rcx.tcx()),
-                                       upvar_borrow.region.repr(rcx.tcx()));
-                                adjust_upvar_borrow_kind_for_loan(
-                                    *upvar_id,
-                                    upvar_borrow,
-                                    kind);
-                                infer::ReborrowUpvar(span, *upvar_id)
-                            }
-                            None => {
-                                rcx.tcx().sess.span_bug(
-                                    span,
-                                    format!("Illegal upvar id: {}",
-                                            upvar_id.repr(
-                                                rcx.tcx())).as_slice());
-                            }
-                        }
+        debug!("link_region(borrow_region={}, borrow_kind={}, borrow_cmt={})",
+               borrow_region.repr(rcx.tcx()),
+               borrow_kind.repr(rcx.tcx()),
+               borrow_cmt.repr(rcx.tcx()));
+        match borrow_cmt.cat.clone() {
+            mc::cat_deref(ref_cmt, _,
+                          mc::Implicit(ref_kind, ref_region)) |
+            mc::cat_deref(ref_cmt, _,
+                          mc::BorrowedPtr(ref_kind, ref_region)) => {
+                match link_reborrowed_region(rcx, span,
+                                             borrow_region, borrow_kind,
+                                             ref_cmt, ref_region, ref_kind) {
+                    Some((c, k)) => {
+                        borrow_cmt = c;
+                        borrow_kind = k;
                     }
-
-                    _ => {
-                        infer::Reborrow(span)
+                    None => {
+                        return;
                     }
-                };
-
-                debug!("link_region: {} <= {}",
-                       region_min.repr(rcx.tcx()),
-                       r_borrowed.repr(rcx.tcx()));
-                rcx.fcx.mk_subr(cause, region_min, r_borrowed);
-
-                if kind != ty::ImmBorrow {
-                    // If this is a mutable borrow, then the thing
-                    // being borrowed will have to be unique.
-                    // In user code, this means it must be an `&mut`
-                    // borrow, but for an upvar, we might opt
-                    // for an immutable-unique borrow.
-                    adjust_upvar_borrow_kind_for_unique(rcx, base);
                 }
-
-                // Borrowing an `&mut` pointee for `region_min` is
-                // only valid if the pointer resides in a unique
-                // location which is itself valid for
-                // `region_min`.  We don't care about the unique
-                // part, but we may need to influence the
-                // inference to ensure that the location remains
-                // valid.
-                //
-                // FIXME(#8624) fixing borrowck will require this
-                // if m == ast::m_mutbl {
-                //    cmt_borrowed = cmt_base;
-                // } else {
-                //    return;
-                // }
-                return;
             }
+
             mc::cat_discr(cmt_base, _) |
             mc::cat_downcast(cmt_base) |
             mc::cat_deref(cmt_base, _, mc::GcPtr(..)) |
             mc::cat_deref(cmt_base, _, mc::OwnedPtr) |
             mc::cat_interior(cmt_base, _) => {
-                // Interior or owned data requires its base to be valid
-                cmt_borrowed = cmt_base;
+                // Borrowing interior or owned data requires the base
+                // to be valid and borrowable in the same fashion.
+                borrow_cmt = cmt_base;
+                borrow_kind = borrow_kind;
             }
+
             mc::cat_deref(_, _, mc::UnsafePtr(..)) |
             mc::cat_static_item |
             mc::cat_copied_upvar(..) |
@@ -1519,6 +1471,154 @@ fn link_region(rcx: &Rcx,
     }
 }
 
+fn link_reborrowed_region(rcx: &Rcx,
+                          span: Span,
+                          borrow_region: ty::Region,
+                          borrow_kind: ty::BorrowKind,
+                          ref_cmt: mc::cmt,
+                          ref_region: ty::Region,
+                          ref_kind: ty::BorrowKind)
+                          -> Option<(mc::cmt, ty::BorrowKind)>
+{
+    /*!
+     * This is the most complicated case: the path being borrowed is
+     * itself the referent of a borrowed pointer. Let me give an
+     * example fragment of code to make clear(er) the situation:
+     *
+     *    let r: &'a mut T = ...;  // the original reference "r" has lifetime 'a
+     *    ...
+     *    &'z *r                   // the reborrow has lifetime 'z
+     *
+     * Now, in this case, our primary job is to add the inference
+     * constraint that `'z <= 'a`. Given this setup, let's clarify the
+     * parameters in (roughly) terms of the example:
+     *
+     *     A borrow of: `& 'z bk * r` where `r` has type `& 'a bk T`
+     *     borrow_region   ^~                 ref_region    ^~
+     *     borrow_kind        ^~               ref_kind        ^~
+     *     ref_cmt                 ^
+     *
+     * Here `bk` stands for some borrow-kind (e.g., `mut`, `uniq`, etc).
+     *
+     * Unfortunately, there are some complications beyond the simple
+     * scenario I just painted:
+     *
+     * 1. The reference `r` might in fact be a "by-ref" upvar. In that
+     *    case, we have two jobs. First, we are inferring whether this reference
+     *    should be an `&T`, `&mut T`, or `&uniq T` reference, and we must
+     *    adjust that based on this borrow (e.g., if this is an `&mut` borrow,
+     *    then `r` must be an `&mut` reference). Second, whenever we link
+     *    two regions (here, `'z <= 'a`), we supply a *cause*, and in this
+     *    case we adjust the cause to indicate that the reference being
+     *    "reborrowed" is itself an upvar. This provides a nicer error message
+     *    should something go wrong.
+     *
+     * 2. There may in fact be more levels of reborrowing. In the
+     *    example, I said the borrow was like `&'z *r`, but it might
+     *    in fact be a borrow like `&'z **q` where `q` has type `&'a
+     *    &'b mut T`. In that case, we want to ensure that `'z <= 'a`
+     *    and `'z <= 'b`. This is explained more below.
+     *
+     * The return value of this function indicates whether we need to
+     * recurse and process `ref_cmt` (see case 2 above).
+     */
+
+    // Detect references to an upvar `x`:
+    let cause = match ref_cmt.cat {
+        mc::cat_upvar(ref upvar_id, _) => {
+            let mut upvar_borrow_map =
+                rcx.fcx.inh.upvar_borrow_map.borrow_mut();
+            match upvar_borrow_map.find_mut(upvar_id) {
+                Some(upvar_borrow) => {
+                    // Adjust mutability that we infer for the upvar
+                    // so it can accommodate being borrowed with
+                    // mutability `kind`:
+                    adjust_upvar_borrow_kind_for_loan(*upvar_id,
+                                                      upvar_borrow,
+                                                      borrow_kind);
+
+                    infer::ReborrowUpvar(span, *upvar_id)
+                }
+                None => {
+                    rcx.tcx().sess.span_bug(
+                        span,
+                        format!("Illegal upvar id: {}",
+                                upvar_id.repr(
+                                    rcx.tcx())).as_slice());
+                }
+            }
+        }
+
+        _ => {
+            infer::Reborrow(span)
+        }
+    };
+
+    debug!("link_reborrowed_region: {} <= {}",
+           borrow_region.repr(rcx.tcx()),
+           ref_region.repr(rcx.tcx()));
+    rcx.fcx.mk_subr(cause, borrow_region, ref_region);
+
+    // Decide whether we need to recurse and link any regions within
+    // the `ref_cmt`. This is concerned for the case where the value
+    // being reborrowed is in fact a borrowed pointer found within
+    // another borrowed pointer. For example:
+    //
+    //    let p: &'b &'a mut T = ...;
+    //    ...
+    //    &'z **p
+    //
+    // What makes this case particularly tricky is that, if the data
+    // being borrowed is a `&mut` or `&uniq` borrow, borrowck requires
+    // not only that `'z <= 'a`, (as before) but also `'z <= 'b`
+    // (otherwise the user might mutate through the `&mut T` reference
+    // after `'b` expires and invalidate the borrow we are looking at
+    // now).
+    //
+    // So let's re-examine our parameters in light of this more
+    // complicated (possible) scenario:
+    //
+    //     A borrow of: `& 'z bk * * p` where `p` has type `&'b bk & 'a bk T`
+    //     borrow_region   ^~                 ref_region             ^~
+    //     borrow_kind        ^~               ref_kind                 ^~
+    //     ref_cmt                 ^~~
+    //
+    // (Note that since we have not examined `ref_cmt.cat`, we don't
+    // know whether this scenario has occurred; but I wanted to show
+    // how all the types get adjusted.)
+    match ref_kind {
+        ty::ImmBorrow => {
+            // The reference being reborrowed is a sharable ref of
+            // type `&'a T`. In this case, it doesn't matter where we
+            // *found* the `&T` pointer, the memory it references will
+            // be valid and immutable for `'a`. So we can stop here.
+            //
+            // (Note that the `borrow_kind` must also be ImmBorrow or
+            // else the user is borrowed imm memory as mut memory,
+            // which means they'll get an error downstream in borrowck
+            // anyhow.)
+            return None;
+        }
+
+        ty::MutBorrow | ty::UniqueImmBorrow => {
+            // The reference being reborrowed is either an `&mut T` or
+            // `&uniq T`. This is the case where recursion is needed.
+            //
+            // One interesting twist is that we can weaken the borrow
+            // kind when we recurse: to reborrow an `&mut` referent as
+            // mutable, borrowck requires a unique path to the `&mut`
+            // reference but not necessarily a *mutable* path.
+            let new_borrow_kind = match borrow_kind {
+                ty::ImmBorrow =>
+                    ty::ImmBorrow,
+                ty::MutBorrow | ty::UniqueImmBorrow =>
+                    ty::UniqueImmBorrow
+            };
+            return Some((ref_cmt, new_borrow_kind));
+        }
+    }
+}
+
 fn adjust_borrow_kind_for_assignment_lhs(rcx: &Rcx,
                                          lhs: &ast::Expr) {
     /*!
@@ -1534,6 +1634,12 @@ fn adjust_borrow_kind_for_assignment_lhs(rcx: &Rcx,
 
 fn adjust_upvar_borrow_kind_for_mut(rcx: &Rcx,
                                     cmt: mc::cmt) {
+    /*!
+     * Indicates that `cmt` is being directly mutated (e.g., assigned
+     * to).  If cmt contains any by-ref upvars, this implies that
+     * those upvars must be borrowed using an `&mut` borow.
+     */
+
     let mut cmt = cmt;
     loop {
         debug!("adjust_upvar_borrow_kind_for_mut(cmt={})",
index abf366381139cdead006d0d081137a2c9e6bcd10..9013b468d3f89742e8bc0485b151aad91ab0af01 100644 (file)
@@ -247,7 +247,7 @@ pub fn coerce_borrowed_pointer(&self,
         let a_borrowed = ty::mk_rptr(self.get_ref().infcx.tcx,
                                      r_borrow,
                                      mt {ty: inner_ty, mutbl: mutbl_b});
-        if_ok!(sub.tys(a_borrowed, b));
+        try!(sub.tys(a_borrowed, b));
 
         Ok(Some(AutoDerefRef(AutoDerefRef {
             autoderefs: 1,
@@ -273,7 +273,7 @@ fn coerce_unsized_with_borrow(&self,
                 let r_borrow = self.get_ref().infcx.next_region_var(coercion);
                 let unsized_ty = ty::mk_slice(self.get_ref().infcx.tcx, r_borrow,
                                               mt {ty: t_a, mutbl: mutbl_b});
-                if_ok!(self.get_ref().infcx.try(|| sub.tys(unsized_ty, b)));
+                try!(self.get_ref().infcx.try(|| sub.tys(unsized_ty, b)));
                 Ok(Some(AutoDerefRef(AutoDerefRef {
                     autoderefs: 0,
                     autoref: Some(ty::AutoPtr(r_borrow,
@@ -316,7 +316,7 @@ fn coerce_unsized(&self,
                             let ty = ty::mk_rptr(self.get_ref().infcx.tcx,
                                                  r_borrow,
                                                  ty::mt{ty: ty, mutbl: mt_b.mutbl});
-                            if_ok!(self.get_ref().infcx.try(|| sub.tys(ty, b)));
+                            try!(self.get_ref().infcx.try(|| sub.tys(ty, b)));
                             debug!("Success, coerced with AutoDerefRef(1, \
                                     AutoPtr(AutoUnsize({:?})))", kind);
                             Ok(Some(AutoDerefRef(AutoDerefRef {
@@ -334,7 +334,7 @@ fn coerce_unsized(&self,
                     match self.unsize_ty(sty_a, t_b) {
                         Some((ty, kind)) => {
                             let ty = ty::mk_uniq(self.get_ref().infcx.tcx, ty);
-                            if_ok!(self.get_ref().infcx.try(|| sub.tys(ty, b)));
+                            try!(self.get_ref().infcx.try(|| sub.tys(ty, b)));
                             debug!("Success, coerced with AutoDerefRef(1, \
                                     AutoUnsizeUniq({:?}))", kind);
                             Ok(Some(AutoDerefRef(AutoDerefRef {
@@ -458,7 +458,7 @@ fn coerce_borrowed_object(&self,
             }
         };
 
-        if_ok!(self.subtype(a_borrowed, b));
+        try!(self.subtype(a_borrowed, b));
         Ok(Some(AutoDerefRef(AutoDerefRef {
             autoderefs: 1,
             autoref: Some(AutoPtr(r_a, b_mutbl, None))
@@ -512,7 +512,7 @@ fn coerce_from_bare_fn(&self, a: ty::t, fn_ty_a: &ty::BareFnTy, b: ty::t)
                                                 sig: fn_ty_a.sig.clone(),
                                                 .. *fn_ty_b
                                            });
-            if_ok!(self.subtype(a_closure, b));
+            try!(self.subtype(a_closure, b));
             Ok(Some(adj))
         })
     }
@@ -536,7 +536,7 @@ pub fn coerce_unsafe_ptr(&self,
 
         // check that the types which they point at are compatible
         let a_unsafe = ty::mk_ptr(self.get_ref().infcx.tcx, mt_a);
-        if_ok!(self.subtype(a_unsafe, b));
+        try!(self.subtype(a_unsafe, b));
 
         // although references and unsafe ptrs have the same
         // representation, we still register an AutoDerefRef so that
index 47085877ad7763832813c814a2a8477db73f6367..2a44ef9de2b1b6cf98a6b66f467366349650f1b2 100644 (file)
@@ -8,43 +8,29 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ______________________________________________________________________
-// Type combining
+///////////////////////////////////////////////////////////////////////////
+// Type combining
 //
-// There are three type combiners: sub, lub, and glb.  Each implements
-// the trait `Combine` and contains methods for combining two
-// instances of various things and yielding a new instance.  These
-// combiner methods always yield a `result<T>`---failure is propagated
-// upward using `and_then()` methods.  There is a lot of common code for
-// these operations, implemented as default methods on the `Combine`
-// trait.
+// There are four type combiners: equate, sub, lub, and glb.  Each
+// implements the trait `Combine` and contains methods for combining
+// two instances of various things and yielding a new instance.  These
+// combiner methods always yield a `Result<T>`.  There is a lot of
+// common code for these operations, implemented as default methods on
+// the `Combine` trait.
 //
-// In reality, the sub operation is rather different from lub/glb, but
-// they are combined into one trait to avoid duplication (they used to
-// be separate but there were many bugs because there were two copies
-// of most routines).
+// Each operation may have side-effects on the inference context,
+// though these can be unrolled using snapshots. On success, the
+// LUB/GLB operations return the appropriate bound. The Eq and Sub
+// operations generally return the first operand.
 //
-// The differences are:
-//
-// - when making two things have a sub relationship, the order of the
-//   arguments is significant (a <: b) and the return value of the
-//   combine functions is largely irrelevant.  The important thing is
-//   whether the action succeeds or fails.  If it succeeds, then side
-//   effects have been committed into the type variables.
-//
-// - for GLB/LUB, the order of arguments is not significant (GLB(a,b) ==
-//   GLB(b,a)) and the return value is important (it is the GLB).  Of
-//   course GLB/LUB may also have side effects.
-//
-// Contravariance
+// ## Contravariance
 //
 // When you are relating two things which have a contravariant
 // relationship, you should use `contratys()` or `contraregions()`,
 // rather than inversing the order of arguments!  This is necessary
 // because the order of arguments is not relevant for LUB and GLB.  It
 // is also useful to track which value is the "expected" value in
-// terms of error reporting, although we do not do that properly right
-// now.
+// terms of error reporting.
 
 
 use middle::subst;
 use middle::ty::{IntType, UintType};
 use middle::ty::{BuiltinBounds};
 use middle::ty;
-use middle::typeck::infer::{ToUres};
+use middle::typeck::infer::equate::Equate;
 use middle::typeck::infer::glb::Glb;
 use middle::typeck::infer::lub::Lub;
 use middle::typeck::infer::sub::Sub;
 use middle::typeck::infer::unify::InferCtxtMethodsForSimplyUnifiableTypes;
-use middle::typeck::infer::{InferCtxt, cres, ures};
-use middle::typeck::infer::{TypeTrace};
-use util::common::indent;
+use middle::typeck::infer::{InferCtxt, cres};
+use middle::typeck::infer::{MiscVariable, TypeTrace};
+use middle::typeck::infer::type_variable::{RelationDir, EqTo,
+                                           SubtypeOf, SupertypeOf};
+use middle::ty_fold::{RegionFolder, TypeFoldable};
 use util::ppaux::Repr;
 
 use std::result;
@@ -75,6 +63,7 @@ pub trait Combine {
     fn a_is_expected(&self) -> bool;
     fn trace(&self) -> TypeTrace;
 
+    fn equate<'a>(&'a self) -> Equate<'a>;
     fn sub<'a>(&'a self) -> Sub<'a>;
     fn lub<'a>(&'a self) -> Lub<'a>;
     fn glb<'a>(&'a self) -> Glb<'a>;
@@ -101,7 +90,7 @@ fn tps(&self,
         try!(result::fold_(as_
                           .iter()
                           .zip(bs.iter())
-                          .map(|(a, b)| eq_tys(self, *a, *b))));
+                          .map(|(a, b)| self.equate().tys(*a, *b))));
         Ok(Vec::from_slice(as_))
     }
 
@@ -121,7 +110,7 @@ fn substs(&self,
         for &space in subst::ParamSpace::all().iter() {
             let a_tps = a_subst.types.get_slice(space);
             let b_tps = b_subst.types.get_slice(space);
-            let tps = if_ok!(self.tps(space, a_tps, b_tps));
+            let tps = try!(self.tps(space, a_tps, b_tps));
 
             let a_regions = a_subst.regions().get_slice(space);
             let b_regions = b_subst.regions().get_slice(space);
@@ -137,11 +126,11 @@ fn substs(&self,
                 }
             };
 
-            let regions = if_ok!(relate_region_params(self,
-                                                      item_def_id,
-                                                      r_variances,
-                                                      a_regions,
-                                                      b_regions));
+            let regions = try!(relate_region_params(self,
+                                                    item_def_id,
+                                                    r_variances,
+                                                    a_regions,
+                                                    b_regions));
 
             substs.types.replace(space, tps);
             substs.mut_regions().replace(space, regions);
@@ -177,15 +166,12 @@ fn relate_region_params<C:Combine>(this: &C,
                 let b_r = b_rs[i];
                 let variance = variances[i];
                 let r = match variance {
-                    ty::Invariant => {
-                        eq_regions(this, a_r, b_r)
-                            .and_then(|()| Ok(a_r))
-                    }
+                    ty::Invariant => this.equate().regions(a_r, b_r),
                     ty::Covariant => this.regions(a_r, b_r),
                     ty::Contravariant => this.contraregions(a_r, b_r),
                     ty::Bivariant => Ok(a_r),
                 };
-                rs.push(if_ok!(r));
+                rs.push(try!(r));
             }
             Ok(rs)
         }
@@ -193,9 +179,9 @@ fn relate_region_params<C:Combine>(this: &C,
 
     fn bare_fn_tys(&self, a: &ty::BareFnTy,
                    b: &ty::BareFnTy) -> cres<ty::BareFnTy> {
-        let fn_style = if_ok!(self.fn_styles(a.fn_style, b.fn_style));
-        let abi = if_ok!(self.abi(a.abi, b.abi));
-        let sig = if_ok!(self.fn_sigs(&a.sig, &b.sig));
+        let fn_style = try!(self.fn_styles(a.fn_style, b.fn_style));
+        let abi = try!(self.abi(a.abi, b.abi));
+        let sig = try!(self.fn_sigs(&a.sig, &b.sig));
         Ok(ty::BareFnTy {fn_style: fn_style,
                 abi: abi,
                 sig: sig})
@@ -207,7 +193,7 @@ fn closure_tys(&self, a: &ty::ClosureTy,
         let store = match (a.store, b.store) {
             (ty::RegionTraitStore(a_r, a_m),
              ty::RegionTraitStore(b_r, b_m)) if a_m == b_m => {
-                let r = if_ok!(self.contraregions(a_r, b_r));
+                let r = try!(self.contraregions(a_r, b_r));
                 ty::RegionTraitStore(r, a_m)
             }
 
@@ -219,11 +205,11 @@ fn closure_tys(&self, a: &ty::ClosureTy,
                 return Err(ty::terr_sigil_mismatch(expected_found(self, a.store, b.store)))
             }
         };
-        let fn_style = if_ok!(self.fn_styles(a.fn_style, b.fn_style));
-        let onceness = if_ok!(self.oncenesses(a.onceness, b.onceness));
-        let bounds = if_ok!(self.existential_bounds(a.bounds, b.bounds));
-        let sig = if_ok!(self.fn_sigs(&a.sig, &b.sig));
-        let abi = if_ok!(self.abi(a.abi, b.abi));
+        let fn_style = try!(self.fn_styles(a.fn_style, b.fn_style));
+        let onceness = try!(self.oncenesses(a.onceness, b.onceness));
+        let bounds = try!(self.existential_bounds(a.bounds, b.bounds));
+        let sig = try!(self.fn_sigs(&a.sig, &b.sig));
+        let abi = try!(self.abi(a.abi, b.abi));
         Ok(ty::ClosureTy {
             fn_style: fn_style,
             onceness: onceness,
@@ -311,7 +297,7 @@ fn trait_refs(&self,
             Err(ty::terr_traits(
                                 expected_found(self, a.def_id, b.def_id)))
         } else {
-            let substs = if_ok!(self.substs(a.def_id, &a.substs, &b.substs));
+            let substs = try!(self.substs(a.def_id, &a.substs, &b.substs));
             Ok(ty::TraitRef { def_id: a.def_id,
                               substs: substs })
         }
@@ -334,34 +320,6 @@ pub fn expected_found<C:Combine,T>(
     }
 }
 
-pub fn eq_tys<C:Combine>(this: &C, a: ty::t, b: ty::t) -> ures {
-    let suber = this.sub();
-    this.infcx().try(|| {
-        suber.tys(a, b).and_then(|_ok| suber.contratys(a, b)).to_ures()
-    })
-}
-
-pub fn eq_regions<C:Combine>(this: &C, a: ty::Region, b: ty::Region)
-                          -> ures {
-    debug!("eq_regions({}, {})",
-            a.repr(this.infcx().tcx),
-            b.repr(this.infcx().tcx));
-    let sub = this.sub();
-    indent(|| {
-        this.infcx().try(|| {
-            sub.regions(a, b).and_then(|_r| sub.contraregions(a, b))
-        }).or_else(|e| {
-            // substitute a better error, but use the regions
-            // found in the original error
-            match e {
-              ty::terr_regions_does_not_outlive(a1, b1) =>
-                Err(ty::terr_regions_not_same(a1, b1)),
-              _ => Err(e)
-            }
-        }).to_ures()
-    })
-}
-
 pub fn super_fn_sigs<C:Combine>(this: &C, a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig> {
 
     fn argvecs<C:Combine>(this: &C, a_args: &[ty::t], b_args: &[ty::t]) -> cres<Vec<ty::t> > {
@@ -377,10 +335,10 @@ fn argvecs<C:Combine>(this: &C, a_args: &[ty::t], b_args: &[ty::t]) -> cres<Vec<
         return Err(ty::terr_variadic_mismatch(expected_found(this, a.variadic, b.variadic)));
     }
 
-    let inputs = if_ok!(argvecs(this,
+    let inputs = try!(argvecs(this,
                                 a.inputs.as_slice(),
                                 b.inputs.as_slice()));
-    let output = if_ok!(this.tys(a.output, b.output));
+    let output = try!(this.tys(a.output, b.output));
     Ok(FnSig {binder_id: a.binder_id,
               inputs: inputs,
               output: output,
@@ -430,7 +388,7 @@ fn check_ptr_to_unsized<C:Combine>(this: &C,
 
         // Relate integral variables to other types
         (&ty::ty_infer(IntVar(a_id)), &ty::ty_infer(IntVar(b_id))) => {
-            if_ok!(this.infcx().simple_vars(this.a_is_expected(),
+            try!(this.infcx().simple_vars(this.a_is_expected(),
                                             a_id, b_id));
             Ok(a)
         }
@@ -453,8 +411,7 @@ fn check_ptr_to_unsized<C:Combine>(this: &C,
 
         // Relate floating-point variables to other types
         (&ty::ty_infer(FloatVar(a_id)), &ty::ty_infer(FloatVar(b_id))) => {
-            if_ok!(this.infcx().simple_vars(this.a_is_expected(),
-                                            a_id, b_id));
+            try!(this.infcx().simple_vars(this.a_is_expected(), a_id, b_id));
             Ok(a)
         }
         (&ty::ty_infer(FloatVar(v_id)), &ty::ty_float(v)) => {
@@ -469,7 +426,8 @@ fn check_ptr_to_unsized<C:Combine>(this: &C,
       (&ty::ty_bool, _) |
       (&ty::ty_int(_), _) |
       (&ty::ty_uint(_), _) |
-      (&ty::ty_float(_), _) => {
+      (&ty::ty_float(_), _) |
+      (&ty::ty_err, _) => {
         if ty::get(a).sty == ty::get(b).sty {
             Ok(a)
         } else {
@@ -485,7 +443,7 @@ fn check_ptr_to_unsized<C:Combine>(this: &C,
       (&ty::ty_enum(a_id, ref a_substs),
        &ty::ty_enum(b_id, ref b_substs))
       if a_id == b_id => {
-          let substs = if_ok!(this.substs(a_id,
+          let substs = try!(this.substs(a_id,
                                           a_substs,
                                           b_substs));
           Ok(ty::mk_enum(tcx, a_id, substs))
@@ -495,8 +453,8 @@ fn check_ptr_to_unsized<C:Combine>(this: &C,
        &ty::ty_trait(ref b_))
       if a_.def_id == b_.def_id => {
           debug!("Trying to match traits {:?} and {:?}", a, b);
-          let substs = if_ok!(this.substs(a_.def_id, &a_.substs, &b_.substs));
-          let bounds = if_ok!(this.existential_bounds(a_.bounds, b_.bounds));
+          let substs = try!(this.substs(a_.def_id, &a_.substs, &b_.substs));
+          let bounds = try!(this.existential_bounds(a_.bounds, b_.bounds));
           Ok(ty::mk_trait(tcx,
                           a_.def_id,
                           substs.clone(),
@@ -505,14 +463,17 @@ fn check_ptr_to_unsized<C:Combine>(this: &C,
 
       (&ty::ty_struct(a_id, ref a_substs), &ty::ty_struct(b_id, ref b_substs))
       if a_id == b_id => {
-            let substs = if_ok!(this.substs(a_id, a_substs, b_substs));
+            let substs = try!(this.substs(a_id, a_substs, b_substs));
             Ok(ty::mk_struct(tcx, a_id, substs))
       }
 
       (&ty::ty_unboxed_closure(a_id, a_region),
        &ty::ty_unboxed_closure(b_id, b_region))
       if a_id == b_id => {
-          let region = if_ok!(this.regions(a_region, b_region));
+          // All ty_unboxed_closure types with the same id represent
+          // the (anonymous) type of the same closure expression. So
+          // all of their regions should be equated.
+          let region = try!(this.equate().regions(a_region, b_region));
           Ok(ty::mk_unboxed_closure(tcx, a_id, region))
       }
 
@@ -521,27 +482,27 @@ fn check_ptr_to_unsized<C:Combine>(this: &C,
       }
 
       (&ty::ty_uniq(a_inner), &ty::ty_uniq(b_inner)) => {
-            let typ = if_ok!(this.tys(a_inner, b_inner));
+            let typ = try!(this.tys(a_inner, b_inner));
             check_ptr_to_unsized(this, a, b, a_inner, b_inner, ty::mk_uniq(tcx, typ))
       }
 
       (&ty::ty_ptr(ref a_mt), &ty::ty_ptr(ref b_mt)) => {
-            let mt = if_ok!(this.mts(a_mt, b_mt));
+            let mt = try!(this.mts(a_mt, b_mt));
             check_ptr_to_unsized(this, a, b, a_mt.ty, b_mt.ty, ty::mk_ptr(tcx, mt))
       }
 
       (&ty::ty_rptr(a_r, ref a_mt), &ty::ty_rptr(b_r, ref b_mt)) => {
-            let r = if_ok!(this.contraregions(a_r, b_r));
+            let r = try!(this.contraregions(a_r, b_r));
             // FIXME(14985)  If we have mutable references to trait objects, we
             // used to use covariant subtyping. I have preserved this behaviour,
             // even though it is probably incorrect. So don't go down the usual
             // path which would require invariance.
             let mt = match (&ty::get(a_mt.ty).sty, &ty::get(b_mt.ty).sty) {
                 (&ty::ty_trait(..), &ty::ty_trait(..)) if a_mt.mutbl == b_mt.mutbl => {
-                    let ty = if_ok!(this.tys(a_mt.ty, b_mt.ty));
+                    let ty = try!(this.tys(a_mt.ty, b_mt.ty));
                     ty::mt { ty: ty, mutbl: a_mt.mutbl }
                 }
-                _ => if_ok!(this.mts(a_mt, b_mt))
+                _ => try!(this.mts(a_mt, b_mt))
             };
             check_ptr_to_unsized(this, a, b, a_mt.ty, b_mt.ty, ty::mk_rptr(tcx, r, mt))
       }
@@ -592,7 +553,7 @@ fn unify_integral_variable<C:Combine>(
         vid: ty::IntVid,
         val: ty::IntVarValue) -> cres<ty::t>
     {
-        if_ok!(this.infcx().simple_var_t(vid_is_expected, vid, val));
+        try!(this.infcx().simple_var_t(vid_is_expected, vid, val));
         match val {
             IntType(v) => Ok(ty::mk_mach_int(v)),
             UintType(v) => Ok(ty::mk_mach_uint(v))
@@ -605,7 +566,122 @@ fn unify_float_variable<C:Combine>(
         vid: ty::FloatVid,
         val: ast::FloatTy) -> cres<ty::t>
     {
-        if_ok!(this.infcx().simple_var_t(vid_is_expected, vid, val));
+        try!(this.infcx().simple_var_t(vid_is_expected, vid, val));
         Ok(ty::mk_mach_float(val))
     }
 }
+
+impl<'f> CombineFields<'f> {
+    pub fn switch_expected(&self) -> CombineFields<'f> {
+        CombineFields {
+            a_is_expected: !self.a_is_expected,
+            ..(*self).clone()
+        }
+    }
+
+    fn equate(&self) -> Equate<'f> {
+        Equate((*self).clone())
+    }
+
+    fn sub(&self) -> Sub<'f> {
+        Sub((*self).clone())
+    }
+
+    pub fn instantiate(&self,
+                       a_ty: ty::t,
+                       dir: RelationDir,
+                       b_vid: ty::TyVid)
+                       -> cres<()>
+    {
+        let tcx = self.infcx.tcx;
+        let mut stack = Vec::new();
+        stack.push((a_ty, dir, b_vid));
+        loop {
+            // For each turn of the loop, we extract a tuple
+            //
+            //     (a_ty, dir, b_vid)
+            //
+            // to relate. Here dir is either SubtypeOf or
+            // SupertypeOf. The idea is that we should ensure that
+            // the type `a_ty` is a subtype or supertype (respectively) of the
+            // type to which `b_vid` is bound.
+            //
+            // If `b_vid` has not yet been instantiated with a type
+            // (which is always true on the first iteration, but not
+            // necessarily true on later iterations), we will first
+            // instantiate `b_vid` with a *generalized* version of
+            // `a_ty`. Generalization introduces other inference
+            // variables wherever subtyping could occur (at time of
+            // this writing, this means replacing free regions with
+            // region variables).
+            let (a_ty, dir, b_vid) = match stack.pop() {
+                None => break,
+                Some(e) => e,
+            };
+
+            debug!("instantiate(a_ty={} dir={} b_vid={})",
+                   a_ty.repr(tcx),
+                   dir,
+                   b_vid.repr(tcx));
+
+            // Check whether `vid` has been instantiated yet.  If not,
+            // make a generalized form of `ty` and instantiate with
+            // that.
+            let b_ty = self.infcx.type_variables.borrow().probe(b_vid);
+            let b_ty = match b_ty {
+                Some(t) => t, // ...already instantiated.
+                None => {     // ...not yet instantiated:
+                    // Generalize type if necessary.
+                    let generalized_ty = match dir {
+                        EqTo => a_ty,
+                        SupertypeOf | SubtypeOf => self.generalize(a_ty)
+                    };
+                    debug!("instantiate(a_ty={}, dir={}, \
+                                        b_vid={}, generalized_ty={})",
+                           a_ty.repr(tcx), dir, b_vid.repr(tcx),
+                           generalized_ty.repr(tcx));
+                    self.infcx.type_variables
+                        .borrow_mut()
+                        .instantiate_and_push(
+                            b_vid, generalized_ty, &mut stack);
+                    generalized_ty
+                }
+            };
+
+            // The original triple was `(a_ty, dir, b_vid)` -- now we have
+            // resolved `b_vid` to `b_ty`, so apply `(a_ty, dir, b_ty)`:
+            //
+            // FIXME(#16847): This code is non-ideal because all these subtype
+            // relations wind up attributed to the same spans. We need
+            // to associate causes/spans with each of the relations in
+            // the stack to get this right.
+            match dir {
+                EqTo => {
+                    try!(self.equate().tys(a_ty, b_ty));
+                }
+
+                SubtypeOf => {
+                    try!(self.sub().tys(a_ty, b_ty));
+                }
+
+                SupertypeOf => {
+                    try!(self.sub().contratys(a_ty, b_ty));
+                }
+            }
+        }
+
+        Ok(())
+    }
+
+    fn generalize(&self, t: ty::t) -> ty::t {
+        // FIXME(#16847): This is non-ideal because we don't give a
+        // very descriptive origin for this region variable.
+
+        let infcx = self.infcx;
+        let span = self.trace.origin.span();
+        t.fold_with(
+            &mut RegionFolder::regions(
+                self.infcx.tcx,
+                |_| infcx.next_region_var(MiscVariable(span))))
+    }
+}
diff --git a/src/librustc/middle/typeck/infer/equate.rs b/src/librustc/middle/typeck/infer/equate.rs
new file mode 100644 (file)
index 0000000..223d37e
--- /dev/null
@@ -0,0 +1,149 @@
+// 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 middle::ty::{BuiltinBounds};
+use middle::ty;
+use middle::ty::TyVar;
+use middle::typeck::infer::combine::*;
+use middle::typeck::infer::{cres};
+use middle::typeck::infer::glb::Glb;
+use middle::typeck::infer::InferCtxt;
+use middle::typeck::infer::lub::Lub;
+use middle::typeck::infer::sub::Sub;
+use middle::typeck::infer::{TypeTrace, Subtype};
+use middle::typeck::infer::type_variable::{EqTo};
+use util::ppaux::{Repr};
+
+use syntax::ast::{Onceness, FnStyle};
+
+pub struct Equate<'f> {
+    fields: CombineFields<'f>
+}
+
+#[allow(non_snake_case)]
+pub fn Equate<'f>(cf: CombineFields<'f>) -> Equate<'f> {
+    Equate { fields: cf }
+}
+
+impl<'f> Combine for Equate<'f> {
+    fn infcx<'a>(&'a self) -> &'a InferCtxt<'a> { self.fields.infcx }
+    fn tag(&self) -> String { "eq".to_string() }
+    fn a_is_expected(&self) -> bool { self.fields.a_is_expected }
+    fn trace(&self) -> TypeTrace { self.fields.trace.clone() }
+
+    fn equate<'a>(&'a self) -> Equate<'a> { Equate(self.fields.clone()) }
+    fn sub<'a>(&'a self) -> Sub<'a> { Sub(self.fields.clone()) }
+    fn lub<'a>(&'a self) -> Lub<'a> { Lub(self.fields.clone()) }
+    fn glb<'a>(&'a self) -> Glb<'a> { Glb(self.fields.clone()) }
+
+    fn contratys(&self, a: ty::t, b: ty::t) -> cres<ty::t> {
+        self.tys(a, b)
+    }
+
+    fn contraregions(&self, a: ty::Region, b: ty::Region) -> cres<ty::Region> {
+        self.regions(a, b)
+    }
+
+    fn regions(&self, a: ty::Region, b: ty::Region) -> cres<ty::Region> {
+        debug!("{}.regions({}, {})",
+               self.tag(),
+               a.repr(self.fields.infcx.tcx),
+               b.repr(self.fields.infcx.tcx));
+        self.infcx().region_vars.make_eqregion(Subtype(self.trace()), a, b);
+        Ok(a)
+    }
+
+    fn mts(&self, a: &ty::mt, b: &ty::mt) -> cres<ty::mt> {
+        debug!("mts({} <: {})",
+               a.repr(self.fields.infcx.tcx),
+               b.repr(self.fields.infcx.tcx));
+
+        if a.mutbl != b.mutbl { return Err(ty::terr_mutability); }
+        let t = try!(self.tys(a.ty, b.ty));
+        Ok(ty::mt { mutbl: a.mutbl, ty: t })
+    }
+
+    fn fn_styles(&self, a: FnStyle, b: FnStyle) -> cres<FnStyle> {
+        if a != b {
+            Err(ty::terr_fn_style_mismatch(expected_found(self, a, b)))
+        } else {
+            Ok(a)
+        }
+    }
+
+    fn oncenesses(&self, a: Onceness, b: Onceness) -> cres<Onceness> {
+        if a != b {
+            Err(ty::terr_onceness_mismatch(expected_found(self, a, b)))
+        } else {
+            Ok(a)
+        }
+    }
+
+    fn builtin_bounds(&self,
+                      a: BuiltinBounds,
+                      b: BuiltinBounds)
+                      -> cres<BuiltinBounds>
+    {
+        // More bounds is a subtype of fewer bounds.
+        //
+        // e.g., fn:Copy() <: fn(), because the former is a function
+        // that only closes over copyable things, but the latter is
+        // any function at all.
+        if a != b {
+            Err(ty::terr_builtin_bounds(expected_found(self, a, b)))
+        } else {
+            Ok(a)
+        }
+    }
+
+    fn tys(&self, a: ty::t, b: ty::t) -> cres<ty::t> {
+        debug!("{}.tys({}, {})", self.tag(),
+               a.repr(self.fields.infcx.tcx), b.repr(self.fields.infcx.tcx));
+        if a == b { return Ok(a); }
+
+        let infcx = self.fields.infcx;
+        let a = infcx.type_variables.borrow().replace_if_possible(a);
+        let b = infcx.type_variables.borrow().replace_if_possible(b);
+        match (&ty::get(a).sty, &ty::get(b).sty) {
+            (&ty::ty_bot, &ty::ty_bot) => {
+                Ok(a)
+            }
+
+            (&ty::ty_bot, _) |
+            (_, &ty::ty_bot) => {
+                Err(ty::terr_sorts(expected_found(self, a, b)))
+            }
+
+            (&ty::ty_infer(TyVar(a_id)), &ty::ty_infer(TyVar(b_id))) => {
+                infcx.type_variables.borrow_mut().relate_vars(a_id, EqTo, b_id);
+                Ok(a)
+            }
+
+            (&ty::ty_infer(TyVar(a_id)), _) => {
+                try!(self.fields.instantiate(b, EqTo, a_id));
+                Ok(a)
+            }
+
+            (_, &ty::ty_infer(TyVar(b_id))) => {
+                try!(self.fields.instantiate(a, EqTo, b_id));
+                Ok(a)
+            }
+
+            _ => {
+                super_tys(self, a, b)
+            }
+        }
+    }
+
+    fn fn_sigs(&self, a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig> {
+        try!(self.sub().fn_sigs(a, b));
+        self.sub().fn_sigs(b, a)
+    }
+}
index 2883a960df9d70a6b1fac916db7bf80a9b803d38..bd355d2f580b9dbc79087742d2d764b9a299d52f 100644 (file)
@@ -583,6 +583,19 @@ fn report_concrete_failure(&self,
                     sub,
                     "");
             }
+            infer::ProcCapture(span, id) => {
+                self.tcx.sess.span_err(
+                    span,
+                    format!("captured variable `{}` must be 'static \
+                             to be captured in a proc",
+                            ty::local_var_name_str(self.tcx, id).get())
+                        .as_slice());
+                note_and_explain_region(
+                    self.tcx,
+                    "captured variable is only valid for ",
+                    sup,
+                    "");
+            }
             infer::IndexSlice(span) => {
                 self.tcx.sess.span_err(span,
                                        "index of slice outside its lifetime");
@@ -1423,11 +1436,11 @@ fn report_inference_failure(&self,
                         bound_region_to_string(self.tcx, "lifetime parameter ", true, br))
             }
             infer::EarlyBoundRegion(_, name) => {
-                format!(" for lifetime parameter `{}",
+                format!(" for lifetime parameter `{}`",
                         token::get_name(name).get())
             }
             infer::BoundRegionInCoherence(name) => {
-                format!(" for lifetime parameter `{} in coherence check",
+                format!(" for lifetime parameter `{}` in coherence check",
                         token::get_name(name).get())
             }
             infer::UpvarRegion(ref upvar_id, _) => {
@@ -1528,6 +1541,15 @@ fn note_region_origin(&self, origin: &SubregionOrigin) {
                                 self.tcx,
                                 id).get().to_string()).as_slice());
             }
+            infer::ProcCapture(span, id) => {
+                self.tcx.sess.span_note(
+                    span,
+                    format!("...so that captured variable `{}` \
+                            is 'static",
+                            ty::local_var_name_str(
+                                self.tcx,
+                                id).get()).as_slice());
+            }
             infer::IndexSlice(span) => {
                 self.tcx.sess.span_note(
                     span,
@@ -1571,8 +1593,8 @@ fn note_region_origin(&self, origin: &SubregionOrigin) {
             infer::AutoBorrow(span) => {
                 self.tcx.sess.span_note(
                     span,
-                    "...so that reference is valid \
-                     at the time of implicit borrow");
+                    "...so that auto-reference is valid \
+                     at the time of borrow");
             }
             infer::ExprTypeIsNotInScope(t, span) => {
                 self.tcx.sess.span_note(
index 00eaa4d235b2e1ddf8e2d5cd0c2913648b7fa4be..8ae141ea19cc20d99b2d45ee7fe699962c1c43ed 100644 (file)
@@ -12,9 +12,9 @@
 use middle::ty::{BuiltinBounds};
 use middle::ty::RegionVid;
 use middle::ty;
-use middle::typeck::infer::then;
 use middle::typeck::infer::combine::*;
 use middle::typeck::infer::lattice::*;
+use middle::typeck::infer::equate::Equate;
 use middle::typeck::infer::lub::Lub;
 use middle::typeck::infer::sub::Sub;
 use middle::typeck::infer::{cres, InferCtxt};
 use util::ppaux::mt_to_string;
 use util::ppaux::Repr;
 
-pub struct Glb<'f>(pub CombineFields<'f>);  // "greatest lower bound" (common subtype)
+/// "Greatest lower bound" (common subtype)
+pub struct Glb<'f> {
+    fields: CombineFields<'f>
+}
 
-impl<'f> Glb<'f> {
-    pub fn get_ref<'a>(&'a self) -> &'a CombineFields<'f> { let Glb(ref v) = *self; v }
+#[allow(non_snake_case)]
+pub fn Glb<'f>(cf: CombineFields<'f>) -> Glb<'f> {
+    Glb { fields: cf }
 }
 
 impl<'f> Combine for Glb<'f> {
-    fn infcx<'a>(&'a self) -> &'a InferCtxt<'a> { self.get_ref().infcx }
+    fn infcx<'a>(&'a self) -> &'a InferCtxt<'a> { self.fields.infcx }
     fn tag(&self) -> String { "glb".to_string() }
-    fn a_is_expected(&self) -> bool { self.get_ref().a_is_expected }
-    fn trace(&self) -> TypeTrace { self.get_ref().trace.clone() }
+    fn a_is_expected(&self) -> bool { self.fields.a_is_expected }
+    fn trace(&self) -> TypeTrace { self.fields.trace.clone() }
 
-    fn sub<'a>(&'a self) -> Sub<'a> { Sub(self.get_ref().clone()) }
-    fn lub<'a>(&'a self) -> Lub<'a> { Lub(self.get_ref().clone()) }
-    fn glb<'a>(&'a self) -> Glb<'a> { Glb(self.get_ref().clone()) }
+    fn equate<'a>(&'a self) -> Equate<'a> { Equate(self.fields.clone()) }
+    fn sub<'a>(&'a self) -> Sub<'a> { Sub(self.fields.clone()) }
+    fn lub<'a>(&'a self) -> Lub<'a> { Lub(self.fields.clone()) }
+    fn glb<'a>(&'a self) -> Glb<'a> { Glb(self.fields.clone()) }
 
     fn mts(&self, a: &ty::mt, b: &ty::mt) -> cres<ty::mt> {
-        let tcx = self.get_ref().infcx.tcx;
+        let tcx = self.fields.infcx.tcx;
 
         debug!("{}.mts({}, {})",
                self.tag(),
@@ -54,27 +59,25 @@ fn mts(&self, a: &ty::mt, b: &ty::mt) -> cres<ty::mt> {
                mt_to_string(tcx, b));
 
         match (a.mutbl, b.mutbl) {
-          // If one side or both is mut, then the GLB must use
-          // the precise type from the mut side.
-          (MutMutable, MutMutable) => {
-            eq_tys(self, a.ty, b.ty).then(|| {
-                Ok(ty::mt {ty: a.ty, mutbl: MutMutable})
-            })
-          }
-
-          // If one side or both is immutable, we can use the GLB of
-          // both sides but mutbl must be `MutImmutable`.
-          (MutImmutable, MutImmutable) => {
-            self.tys(a.ty, b.ty).and_then(|t| {
+            // If one side or both is mut, then the GLB must use
+            // the precise type from the mut side.
+            (MutMutable, MutMutable) => {
+                let t = try!(self.equate().tys(a.ty, b.ty));
+                Ok(ty::mt {ty: t, mutbl: MutMutable})
+            }
+
+            // If one side or both is immutable, we can use the GLB of
+            // both sides but mutbl must be `MutImmutable`.
+            (MutImmutable, MutImmutable) => {
+                let t = try!(self.tys(a.ty, b.ty));
                 Ok(ty::mt {ty: t, mutbl: MutImmutable})
-            })
-          }
-
-          // There is no mutual subtype of these combinations.
-          (MutMutable, MutImmutable) |
-          (MutImmutable, MutMutable) => {
-              Err(ty::terr_mutability)
-          }
+            }
+
+            // There is no mutual subtype of these combinations.
+            (MutMutable, MutImmutable) |
+            (MutImmutable, MutMutable) => {
+                Err(ty::terr_mutability)
+            }
         }
     }
 
@@ -108,10 +111,10 @@ fn builtin_bounds(&self,
     fn regions(&self, a: ty::Region, b: ty::Region) -> cres<ty::Region> {
         debug!("{}.regions({:?}, {:?})",
                self.tag(),
-               a.repr(self.get_ref().infcx.tcx),
-               b.repr(self.get_ref().infcx.tcx));
+               a.repr(self.fields.infcx.tcx),
+               b.repr(self.fields.infcx.tcx));
 
-        Ok(self.get_ref().infcx.region_vars.glb_regions(Subtype(self.trace()), a, b))
+        Ok(self.fields.infcx.region_vars.glb_regions(Subtype(self.trace()), a, b))
     }
 
     fn contraregions(&self, a: ty::Region, b: ty::Region)
@@ -128,33 +131,33 @@ fn fn_sigs(&self, a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig> {
         // please see the large comment in `region_inference.rs`.
 
         debug!("{}.fn_sigs({:?}, {:?})",
-               self.tag(), a.repr(self.get_ref().infcx.tcx), b.repr(self.get_ref().infcx.tcx));
+               self.tag(), a.repr(self.fields.infcx.tcx), b.repr(self.fields.infcx.tcx));
         let _indenter = indenter();
 
         // Make a mark so we can examine "all bindings that were
         // created as part of this type comparison".
-        let mark = self.get_ref().infcx.region_vars.mark();
+        let mark = self.fields.infcx.region_vars.mark();
 
         // Instantiate each bound region with a fresh region variable.
         let (a_with_fresh, a_map) =
-            self.get_ref().infcx.replace_late_bound_regions_with_fresh_regions(
+            self.fields.infcx.replace_late_bound_regions_with_fresh_regions(
                 self.trace(), a);
         let a_vars = var_ids(self, &a_map);
         let (b_with_fresh, b_map) =
-            self.get_ref().infcx.replace_late_bound_regions_with_fresh_regions(
+            self.fields.infcx.replace_late_bound_regions_with_fresh_regions(
                 self.trace(), b);
         let b_vars = var_ids(self, &b_map);
 
         // Collect constraints.
-        let sig0 = if_ok!(super_fn_sigs(self, &a_with_fresh, &b_with_fresh));
-        debug!("sig0 = {}", sig0.repr(self.get_ref().infcx.tcx));
+        let sig0 = try!(super_fn_sigs(self, &a_with_fresh, &b_with_fresh));
+        debug!("sig0 = {}", sig0.repr(self.fields.infcx.tcx));
 
         // Generalize the regions appearing in fn_ty0 if possible
         let new_vars =
-            self.get_ref().infcx.region_vars.vars_created_since_mark(mark);
+            self.fields.infcx.region_vars.vars_created_since_mark(mark);
         let sig1 =
             fold_regions_in_sig(
-                self.get_ref().infcx.tcx,
+                self.fields.infcx.tcx,
                 &sig0,
                 |r| {
                 generalize_region(self,
@@ -166,7 +169,7 @@ fn fn_sigs(&self, a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig> {
                                   b_vars.as_slice(),
                                   r)
             });
-        debug!("sig1 = {}", sig1.repr(self.get_ref().infcx.tcx));
+        debug!("sig1 = {}", sig1.repr(self.fields.infcx.tcx));
         return Ok(sig1);
 
         fn generalize_region(this: &Glb,
@@ -182,7 +185,7 @@ fn generalize_region(this: &Glb,
                 return r0;
             }
 
-            let tainted = this.get_ref().infcx.region_vars.tainted(mark, r0);
+            let tainted = this.fields.infcx.region_vars.tainted(mark, r0);
 
             let mut a_r = None;
             let mut b_r = None;
@@ -249,14 +252,14 @@ fn rev_lookup(this: &Glb,
                     return ty::ReLateBound(new_binder_id, *a_br);
                 }
             }
-            this.get_ref().infcx.tcx.sess.span_bug(
-                this.get_ref().trace.origin.span(),
+            this.fields.infcx.tcx.sess.span_bug(
+                this.fields.trace.origin.span(),
                 format!("could not find original bound region for {:?}",
                         r).as_slice())
         }
 
         fn fresh_bound_variable(this: &Glb, binder_id: NodeId) -> ty::Region {
-            this.get_ref().infcx.region_vars.new_bound(binder_id)
+            this.fields.infcx.region_vars.new_bound(binder_id)
         }
     }
 }
index 708eb498f8421ea5fb059a08ccf5b109b9a2459d..f09773d30b5149feb7b91046f6ae46d0c4d0cd52 100644 (file)
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 /*!
- *
  * # Lattice Variables
  *
  * This file contains generic code for operating on inference variables
 
 use middle::ty::{RegionVid, TyVar};
 use middle::ty;
-use middle::typeck::infer::{ToUres};
 use middle::typeck::infer::*;
 use middle::typeck::infer::combine::*;
 use middle::typeck::infer::glb::Glb;
 use middle::typeck::infer::lub::Lub;
-use middle::typeck::infer::unify::*;
-use middle::typeck::infer::sub::Sub;
 use util::ppaux::Repr;
 
 use std::collections::HashMap;
 
-trait LatticeValue : Clone + Repr + PartialEq {
-    fn sub(cf: CombineFields, a: &Self, b: &Self) -> ures;
-    fn lub(cf: CombineFields, a: &Self, b: &Self) -> cres<Self>;
-    fn glb(cf: CombineFields, a: &Self, b: &Self) -> cres<Self>;
-}
-
-pub type LatticeOp<'a, T> =
-    |cf: CombineFields, a: &T, b: &T|: 'a -> cres<T>;
-
-impl LatticeValue for ty::t {
-    fn sub(cf: CombineFields, a: &ty::t, b: &ty::t) -> ures {
-        Sub(cf).tys(*a, *b).to_ures()
-    }
-
-    fn lub(cf: CombineFields, a: &ty::t, b: &ty::t) -> cres<ty::t> {
-        Lub(cf).tys(*a, *b)
-    }
-
-    fn glb(cf: CombineFields, a: &ty::t, b: &ty::t) -> cres<ty::t> {
-        Glb(cf).tys(*a, *b)
-    }
-}
-
-pub trait CombineFieldsLatticeMethods<T:LatticeValue, K:UnifyKey<Bounds<T>>> {
-    /// make variable a subtype of variable
-    fn var_sub_var(&self,
-                   a_id: K,
-                   b_id: K)
-                   -> ures;
-
-    /// make variable a subtype of T
-    fn var_sub_t(&self,
-                 a_id: K,
-                 b: T)
-                 -> ures;
-
-    /// make T a subtype of variable
-    fn t_sub_var(&self,
-                 a: T,
-                 b_id: K)
-                 -> ures;
-
-    fn set_var_to_merged_bounds(&self,
-                                v_id: K,
-                                a: &Bounds<T>,
-                                b: &Bounds<T>,
-                                rank: uint)
-                                -> ures;
-}
-
-pub trait CombineFieldsLatticeMethods2<T:LatticeValue> {
-    fn merge_bnd(&self,
-                 a: &Bound<T>,
-                 b: &Bound<T>,
-                 lattice_op: LatticeOp<T>)
-                 -> cres<Bound<T>>;
-
-    fn bnds(&self, a: &Bound<T>, b: &Bound<T>) -> ures;
-}
-
-impl<'f,T:LatticeValue, K:UnifyKey<Bounds<T>>>
-    CombineFieldsLatticeMethods<T,K> for CombineFields<'f>
-{
-    fn var_sub_var(&self,
-                   a_id: K,
-                   b_id: K)
-                   -> ures
-    {
-        /*!
-         * Make one variable a subtype of another variable.  This is a
-         * subtle and tricky process, as described in detail at the
-         * top of infer.rs.
-         */
-
-        let tcx = self.infcx.tcx;
-        let table = UnifyKey::unification_table(self.infcx);
-
-        // Need to make sub_id a subtype of sup_id.
-        let node_a = table.borrow_mut().get(tcx, a_id);
-        let node_b = table.borrow_mut().get(tcx, b_id);
-        let a_id = node_a.key.clone();
-        let b_id = node_b.key.clone();
-        let a_bounds = node_a.value.clone();
-        let b_bounds = node_b.value.clone();
-
-        debug!("vars({}={} <: {}={})",
-               a_id, a_bounds.repr(tcx),
-               b_id, b_bounds.repr(tcx));
-
-        if a_id == b_id { return Ok(()); }
-
-        // If both A's UB and B's LB have already been bound to types,
-        // see if we can make those types subtypes.
-        match (&a_bounds.ub, &b_bounds.lb) {
-            (&Some(ref a_ub), &Some(ref b_lb)) => {
-                let r = self.infcx.try(
-                    || LatticeValue::sub(self.clone(), a_ub, b_lb));
-                match r {
-                    Ok(()) => {
-                        return Ok(());
-                    }
-                    Err(_) => { /*fallthrough */ }
-                }
-            }
-            _ => { /*fallthrough*/ }
-        }
-
-        // Otherwise, we need to merge A and B so as to guarantee that
-        // A remains a subtype of B.  Actually, there are other options,
-        // but that's the route we choose to take.
-
-        let (new_root, new_rank) =
-            table.borrow_mut().unify(tcx, &node_a, &node_b);
-        self.set_var_to_merged_bounds(new_root,
-                                      &a_bounds, &b_bounds,
-                                      new_rank)
-    }
-
-    /// make variable a subtype of T
-    fn var_sub_t(&self,
-                 a_id: K,
-                 b: T)
-                 -> ures
-    {
-        /*!
-         * Make a variable (`a_id`) a subtype of the concrete type `b`.
-         */
-
-        let tcx = self.infcx.tcx;
-        let table = UnifyKey::unification_table(self.infcx);
-        let node_a = table.borrow_mut().get(tcx, a_id);
-        let a_id = node_a.key.clone();
-        let a_bounds = &node_a.value;
-        let b_bounds = &Bounds { lb: None, ub: Some(b.clone()) };
-
-        debug!("var_sub_t({}={} <: {})",
-               a_id,
-               a_bounds.repr(self.infcx.tcx),
-               b.repr(self.infcx.tcx));
-
-        self.set_var_to_merged_bounds(
-            a_id, a_bounds, b_bounds, node_a.rank)
-    }
-
-    fn t_sub_var(&self,
-                 a: T,
-                 b_id: K)
-                 -> ures
-    {
-        /*!
-         * Make a concrete type (`a`) a subtype of the variable `b_id`
-         */
-
-        let tcx = self.infcx.tcx;
-        let table = UnifyKey::unification_table(self.infcx);
-        let a_bounds = &Bounds { lb: Some(a.clone()), ub: None };
-        let node_b = table.borrow_mut().get(tcx, b_id);
-        let b_id = node_b.key.clone();
-        let b_bounds = &node_b.value;
-
-        debug!("t_sub_var({} <: {}={})",
-               a.repr(self.infcx.tcx),
-               b_id,
-               b_bounds.repr(self.infcx.tcx));
-
-        self.set_var_to_merged_bounds(
-            b_id, a_bounds, b_bounds, node_b.rank)
-    }
-
-    fn set_var_to_merged_bounds(&self,
-                                v_id: K,
-                                a: &Bounds<T>,
-                                b: &Bounds<T>,
-                                rank: uint)
-                                -> ures
-    {
-        /*!
-         * Updates the bounds for the variable `v_id` to be the intersection
-         * of `a` and `b`.  That is, the new bounds for `v_id` will be
-         * a bounds c such that:
-         *    c.ub <: a.ub
-         *    c.ub <: b.ub
-         *    a.lb <: c.lb
-         *    b.lb <: c.lb
-         * If this cannot be achieved, the result is failure.
-         */
-
-        // Think of the two diamonds, we want to find the
-        // intersection.  There are basically four possibilities (you
-        // can swap A/B in these pictures):
-        //
-        //       A         A
-        //      / \       / \
-        //     / B \     / B \
-        //    / / \ \   / / \ \
-        //   * *   * * * /   * *
-        //    \ \ / /   \   / /
-        //     \ B /   / \ / /
-        //      \ /   *   \ /
-        //       A     \ / A
-        //              B
-
-        let tcx = self.infcx.tcx;
-        let table = UnifyKey::unification_table(self.infcx);
-
-        debug!("merge({},{},{})",
-               v_id,
-               a.repr(self.infcx.tcx),
-               b.repr(self.infcx.tcx));
-
-        // First, relate the lower/upper bounds of A and B.
-        // Note that these relations *must* hold for us
-        // to be able to merge A and B at all, and relating
-        // them explicitly gives the type inferencer more
-        // information and helps to produce tighter bounds
-        // when necessary.
-        let () = if_ok!(self.bnds(&a.lb, &b.ub));
-        let () = if_ok!(self.bnds(&b.lb, &a.ub));
-        let ub = if_ok!(self.merge_bnd(&a.ub, &b.ub, LatticeValue::glb));
-        let lb = if_ok!(self.merge_bnd(&a.lb, &b.lb, LatticeValue::lub));
-        let bounds = Bounds { lb: lb, ub: ub };
-        debug!("merge({}): bounds={}",
-               v_id,
-               bounds.repr(self.infcx.tcx));
-
-        // the new bounds must themselves
-        // be relatable:
-        let () = if_ok!(self.bnds(&bounds.lb, &bounds.ub));
-        table.borrow_mut().set(tcx, v_id, Root(bounds, rank));
-        Ok(())
-    }
-}
-
-impl<'f,T:LatticeValue>
-    CombineFieldsLatticeMethods2<T> for CombineFields<'f>
-{
-    fn merge_bnd(&self,
-                 a: &Bound<T>,
-                 b: &Bound<T>,
-                 lattice_op: LatticeOp<T>)
-                 -> cres<Bound<T>>
-    {
-        /*!
-         * Combines two bounds into a more general bound.
-         */
-
-        debug!("merge_bnd({},{})",
-               a.repr(self.infcx.tcx),
-               b.repr(self.infcx.tcx));
-        match (a, b) {
-            (&None,          &None) => Ok(None),
-            (&Some(_),       &None) => Ok((*a).clone()),
-            (&None,          &Some(_)) => Ok((*b).clone()),
-            (&Some(ref v_a), &Some(ref v_b)) => {
-                lattice_op(self.clone(), v_a, v_b).and_then(|v| Ok(Some(v)))
-            }
-        }
-    }
-
-    fn bnds(&self,
-            a: &Bound<T>,
-            b: &Bound<T>)
-            -> ures
-    {
-        debug!("bnds({} <: {})",
-               a.repr(self.infcx.tcx),
-               b.repr(self.infcx.tcx));
-
-        match (a, b) {
-            (&None, &None) |
-            (&Some(_), &None) |
-            (&None, &Some(_)) => {
-                Ok(())
-            }
-            (&Some(ref t_a), &Some(ref t_b)) => {
-                LatticeValue::sub(self.clone(), t_a, t_b)
-            }
-        }
-    }
-}
-
-// ______________________________________________________________________
-// Lattice operations on variables
-//
-// This is common code used by both LUB and GLB to compute the LUB/GLB
-// for pairs of variables or for variables and values.
-
 pub trait LatticeDir {
-    fn combine_fields<'a>(&'a self) -> CombineFields<'a>;
-    fn bnd<T:Clone>(&self, b: &Bounds<T>) -> Option<T>;
-    fn with_bnd<T:Clone>(&self, b: &Bounds<T>, t: T) -> Bounds<T>;
-}
-
-pub trait TyLatticeDir {
+    // Relates the bottom type to `t` and returns LUB(t, _|_) or
+    // GLB(t, _|_) as appropriate.
     fn ty_bot(&self, t: ty::t) -> cres<ty::t>;
-}
 
-impl<'f> LatticeDir for Lub<'f> {
-    fn combine_fields<'a>(&'a self) -> CombineFields<'a> { self.get_ref().clone() }
-    fn bnd<T:Clone>(&self, b: &Bounds<T>) -> Option<T> { b.ub.clone() }
-    fn with_bnd<T:Clone>(&self, b: &Bounds<T>, t: T) -> Bounds<T> {
-        Bounds { ub: Some(t), ..(*b).clone() }
-    }
+    // Relates the type `v` to `a` and `b` such that `v` represents
+    // the LUB/GLB of `a` and `b` as appropriate.
+    fn relate_bound<'a>(&'a self, v: ty::t, a: ty::t, b: ty::t) -> cres<()>;
 }
 
-impl<'f> TyLatticeDir for Lub<'f> {
+impl<'a> LatticeDir for Lub<'a> {
     fn ty_bot(&self, t: ty::t) -> cres<ty::t> {
         Ok(t)
     }
-}
 
-impl<'f> LatticeDir for Glb<'f> {
-    fn combine_fields<'a>(&'a self) -> CombineFields<'a> { self.get_ref().clone() }
-    fn bnd<T:Clone>(&self, b: &Bounds<T>) -> Option<T> { b.lb.clone() }
-    fn with_bnd<T:Clone>(&self, b: &Bounds<T>, t: T) -> Bounds<T> {
-        Bounds { lb: Some(t), ..(*b).clone() }
+    fn relate_bound<'a>(&'a self, v: ty::t, a: ty::t, b: ty::t) -> cres<()> {
+        let sub = self.sub();
+        try!(sub.tys(a, v));
+        try!(sub.tys(b, v));
+        Ok(())
     }
 }
 
-impl<'f> TyLatticeDir for Glb<'f> {
-    fn ty_bot(&self, _t: ty::t) -> cres<ty::t> {
+impl<'a> LatticeDir for Glb<'a> {
+    fn ty_bot(&self, _: ty::t) -> cres<ty::t> {
         Ok(ty::mk_bot())
     }
+
+    fn relate_bound<'a>(&'a self, v: ty::t, a: ty::t, b: ty::t) -> cres<()> {
+        let sub = self.sub();
+        try!(sub.tys(v, a));
+        try!(sub.tys(v, b));
+        Ok(())
+    }
 }
 
-pub fn super_lattice_tys<L:LatticeDir+TyLatticeDir+Combine>(this: &L,
-                                                            a: ty::t,
-                                                            b: ty::t)
-                                                            -> cres<ty::t> {
+pub fn super_lattice_tys<L:LatticeDir+Combine>(this: &L,
+                                               a: ty::t,
+                                               b: ty::t)
+                                               -> cres<ty::t>
+{
     debug!("{}.lattice_tys({}, {})",
            this.tag(),
            a.repr(this.infcx().tcx),
@@ -383,156 +91,27 @@ pub fn super_lattice_tys<L:LatticeDir+TyLatticeDir+Combine>(this: &L,
         return Ok(a);
     }
 
-    let tcx = this.infcx().tcx;
-
+    let infcx = this.infcx();
+    let a = infcx.type_variables.borrow().replace_if_possible(a);
+    let b = infcx.type_variables.borrow().replace_if_possible(b);
     match (&ty::get(a).sty, &ty::get(b).sty) {
-        (&ty::ty_bot, _) => { return this.ty_bot(b); }
-        (_, &ty::ty_bot) => { return this.ty_bot(a); }
-
-        (&ty::ty_infer(TyVar(a_id)), &ty::ty_infer(TyVar(b_id))) => {
-            let r = if_ok!(lattice_vars(this, a_id, b_id,
-                                        |x, y| this.tys(*x, *y)));
-            return match r {
-                VarResult(v) => Ok(ty::mk_var(tcx, v)),
-                ValueResult(t) => Ok(t)
-            };
-        }
-
-        (&ty::ty_infer(TyVar(a_id)), _) => {
-            return lattice_var_and_t(this, a_id, &b,
-                                     |x, y| this.tys(*x, *y));
-        }
-
-        (_, &ty::ty_infer(TyVar(b_id))) => {
-            return lattice_var_and_t(this, b_id, &a,
-                                     |x, y| this.tys(*x, *y));
+        (&ty::ty_bot, _) => { this.ty_bot(b) }
+        (_, &ty::ty_bot) => { this.ty_bot(a) }
+
+        (&ty::ty_infer(TyVar(..)), _) |
+        (_, &ty::ty_infer(TyVar(..))) => {
+            let v = infcx.next_ty_var();
+            try!(this.relate_bound(v, a, b));
+            Ok(v)
         }
 
         _ => {
-            return super_tys(this, a, b);
-        }
-    }
-}
-
-pub type LatticeDirOp<'a, T> = |a: &T, b: &T|: 'a -> cres<T>;
-
-#[deriving(Clone)]
-pub enum LatticeVarResult<K,T> {
-    VarResult(K),
-    ValueResult(T)
-}
-
-/**
- * Computes the LUB or GLB of two bounded variables.  These could be any
- * sort of variables, but in the comments on this function I'll assume
- * we are doing an LUB on two type variables.
- *
- * This computation can be done in one of two ways:
- *
- * - If both variables have an upper bound, we may just compute the
- *   LUB of those bounds and return that, in which case we are
- *   returning a type.  This is indicated with a `ValueResult` return.
- *
- * - If the variables do not both have an upper bound, we will unify
- *   the variables and return the unified variable, in which case the
- *   result is a variable.  This is indicated with a `VarResult`
- *   return. */
-pub fn lattice_vars<L:LatticeDir+Combine,
-                    T:LatticeValue,
-                    K:UnifyKey<Bounds<T>>>(
-    this: &L,                           // defines whether we want LUB or GLB
-    a_vid: K,                           // first variable
-    b_vid: K,                           // second variable
-    lattice_dir_op: LatticeDirOp<T>)    // LUB or GLB operation on types
-    -> cres<LatticeVarResult<K,T>>
-{
-    let tcx = this.infcx().tcx;
-    let table = UnifyKey::unification_table(this.infcx());
-
-    let node_a = table.borrow_mut().get(tcx, a_vid);
-    let node_b = table.borrow_mut().get(tcx, b_vid);
-    let a_vid = node_a.key.clone();
-    let b_vid = node_b.key.clone();
-    let a_bounds = &node_a.value;
-    let b_bounds = &node_b.value;
-
-    debug!("{}.lattice_vars({}={} <: {}={})",
-           this.tag(),
-           a_vid, a_bounds.repr(tcx),
-           b_vid, b_bounds.repr(tcx));
-
-    // Same variable: the easy case.
-    if a_vid == b_vid {
-        return Ok(VarResult(a_vid));
-    }
-
-    // If both A and B have an UB type, then we can just compute the
-    // LUB of those types:
-    let (a_bnd, b_bnd) = (this.bnd(a_bounds), this.bnd(b_bounds));
-    match (a_bnd, b_bnd) {
-        (Some(ref a_ty), Some(ref b_ty)) => {
-            match this.infcx().try(|| lattice_dir_op(a_ty, b_ty) ) {
-                Ok(t) => return Ok(ValueResult(t)),
-                Err(_) => { /*fallthrough */ }
-            }
-        }
-        _ => {/*fallthrough*/}
-    }
-
-    // Otherwise, we need to merge A and B into one variable.  We can
-    // then use either variable as an upper bound:
-    let cf = this.combine_fields();
-    let () = try!(cf.var_sub_var(a_vid.clone(), b_vid.clone()));
-    Ok(VarResult(a_vid.clone()))
-}
-
-pub fn lattice_var_and_t<L:LatticeDir+Combine,
-                         T:LatticeValue,
-                         K:UnifyKey<Bounds<T>>>(
-    this: &L,
-    a_id: K,
-    b: &T,
-    lattice_dir_op: LatticeDirOp<T>)
-    -> cres<T>
-{
-    let tcx = this.infcx().tcx;
-    let table = UnifyKey::unification_table(this.infcx());
-
-    let node_a = table.borrow_mut().get(tcx, a_id);
-    let a_id = node_a.key.clone();
-    let a_bounds = &node_a.value;
-
-    // The comments in this function are written for LUB, but they
-    // apply equally well to GLB if you inverse upper/lower/sub/super/etc.
-
-    debug!("{}.lattice_var_and_t({}={} <: {})",
-           this.tag(),
-           a_id,
-           a_bounds.repr(this.infcx().tcx),
-           b.repr(this.infcx().tcx));
-
-    match this.bnd(a_bounds) {
-        Some(ref a_bnd) => {
-            // If a has an upper bound, return the LUB(a.ub, b)
-            debug!("bnd=Some({})", a_bnd.repr(this.infcx().tcx));
-            lattice_dir_op(a_bnd, b)
-        }
-        None => {
-            // If a does not have an upper bound, make b the upper bound of a
-            // and then return b.
-            debug!("bnd=None");
-            let a_bounds = this.with_bnd(a_bounds, (*b).clone());
-            let () = try!(this.combine_fields().bnds(&a_bounds.lb,
-                                                     &a_bounds.ub));
-            table.borrow_mut().set(tcx,
-                                   a_id.clone(),
-                                   Root(a_bounds.clone(), node_a.rank));
-            Ok((*b).clone())
+            super_tys(this, a, b)
         }
     }
 }
 
-// ___________________________________________________________________________
+///////////////////////////////////////////////////////////////////////////
 // Random utility functions used by LUB/GLB when computing LUB/GLB of
 // fn types
 
index 8707efc622b6cfe625a7ac0dd515fe7ea040a14e..49760ac92bf7df29002ca67fd696130a9dcc18b9 100644 (file)
@@ -11,8 +11,8 @@
 use middle::ty::{BuiltinBounds};
 use middle::ty::RegionVid;
 use middle::ty;
-use middle::typeck::infer::then;
 use middle::typeck::infer::combine::*;
+use middle::typeck::infer::equate::Equate;
 use middle::typeck::infer::glb::Glb;
 use middle::typeck::infer::lattice::*;
 use middle::typeck::infer::sub::Sub;
 use util::ppaux::mt_to_string;
 use util::ppaux::Repr;
 
-pub struct Lub<'f>(pub CombineFields<'f>);  // least-upper-bound: common supertype
+/// "Least upper bound" (common supertype)
+pub struct Lub<'f> {
+    fields: CombineFields<'f>
+}
 
-impl<'f> Lub<'f> {
-    pub fn get_ref<'a>(&'a self) -> &'a CombineFields<'f> { let Lub(ref v) = *self; v }
+#[allow(non_snake_case)]
+pub fn Lub<'f>(cf: CombineFields<'f>) -> Lub<'f> {
+    Lub { fields: cf }
 }
 
 impl<'f> Combine for Lub<'f> {
-    fn infcx<'a>(&'a self) -> &'a InferCtxt<'a> { self.get_ref().infcx }
+    fn infcx<'a>(&'a self) -> &'a InferCtxt<'a> { self.fields.infcx }
     fn tag(&self) -> String { "lub".to_string() }
-    fn a_is_expected(&self) -> bool { self.get_ref().a_is_expected }
-    fn trace(&self) -> TypeTrace { self.get_ref().trace.clone() }
+    fn a_is_expected(&self) -> bool { self.fields.a_is_expected }
+    fn trace(&self) -> TypeTrace { self.fields.trace.clone() }
 
-    fn sub<'a>(&'a self) -> Sub<'a> { Sub(self.get_ref().clone()) }
-    fn lub<'a>(&'a self) -> Lub<'a> { Lub(self.get_ref().clone()) }
-    fn glb<'a>(&'a self) -> Glb<'a> { Glb(self.get_ref().clone()) }
+    fn equate<'a>(&'a self) -> Equate<'a> { Equate(self.fields.clone()) }
+    fn sub<'a>(&'a self) -> Sub<'a> { Sub(self.fields.clone()) }
+    fn lub<'a>(&'a self) -> Lub<'a> { Lub(self.fields.clone()) }
+    fn glb<'a>(&'a self) -> Glb<'a> { Glb(self.fields.clone()) }
 
     fn mts(&self, a: &ty::mt, b: &ty::mt) -> cres<ty::mt> {
-        let tcx = self.get_ref().infcx.tcx;
+        let tcx = self.fields.infcx.tcx;
 
         debug!("{}.mts({}, {})",
                self.tag(),
@@ -58,17 +63,15 @@ fn mts(&self, a: &ty::mt, b: &ty::mt) -> cres<ty::mt> {
 
         let m = a.mutbl;
         match m {
-          MutImmutable => {
-            self.tys(a.ty, b.ty).and_then(|t| Ok(ty::mt {ty: t, mutbl: m}) )
-          }
-
-          MutMutable => {
-            self.get_ref().infcx.try(|| {
-                eq_tys(self, a.ty, b.ty).then(|| {
-                    Ok(ty::mt {ty: a.ty, mutbl: m})
-                })
-            }).or_else(|e| Err(e))
-          }
+            MutImmutable => {
+                let t = try!(self.tys(a.ty, b.ty));
+                Ok(ty::mt {ty: t, mutbl: m})
+            }
+
+            MutMutable => {
+                let t = try!(self.equate().tys(a.ty, b.ty));
+                Ok(ty::mt {ty: t, mutbl: m})
+            }
         }
     }
 
@@ -107,10 +110,10 @@ fn contraregions(&self, a: ty::Region, b: ty::Region)
     fn regions(&self, a: ty::Region, b: ty::Region) -> cres<ty::Region> {
         debug!("{}.regions({}, {})",
                self.tag(),
-               a.repr(self.get_ref().infcx.tcx),
-               b.repr(self.get_ref().infcx.tcx));
+               a.repr(self.fields.infcx.tcx),
+               b.repr(self.fields.infcx.tcx));
 
-        Ok(self.get_ref().infcx.region_vars.lub_regions(Subtype(self.trace()), a, b))
+        Ok(self.fields.infcx.region_vars.lub_regions(Subtype(self.trace()), a, b))
     }
 
     fn fn_sigs(&self, a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig> {
@@ -119,26 +122,26 @@ fn fn_sigs(&self, a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig> {
 
         // Make a mark so we can examine "all bindings that were
         // created as part of this type comparison".
-        let mark = self.get_ref().infcx.region_vars.mark();
+        let mark = self.fields.infcx.region_vars.mark();
 
         // Instantiate each bound region with a fresh region variable.
         let (a_with_fresh, a_map) =
-            self.get_ref().infcx.replace_late_bound_regions_with_fresh_regions(
+            self.fields.infcx.replace_late_bound_regions_with_fresh_regions(
                 self.trace(), a);
         let (b_with_fresh, _) =
-            self.get_ref().infcx.replace_late_bound_regions_with_fresh_regions(
+            self.fields.infcx.replace_late_bound_regions_with_fresh_regions(
                 self.trace(), b);
 
         // Collect constraints.
-        let sig0 = if_ok!(super_fn_sigs(self, &a_with_fresh, &b_with_fresh));
-        debug!("sig0 = {}", sig0.repr(self.get_ref().infcx.tcx));
+        let sig0 = try!(super_fn_sigs(self, &a_with_fresh, &b_with_fresh));
+        debug!("sig0 = {}", sig0.repr(self.fields.infcx.tcx));
 
         // Generalize the regions appearing in sig0 if possible
         let new_vars =
-            self.get_ref().infcx.region_vars.vars_created_since_mark(mark);
+            self.fields.infcx.region_vars.vars_created_since_mark(mark);
         let sig1 =
             fold_regions_in_sig(
-                self.get_ref().infcx.tcx,
+                self.fields.infcx.tcx,
                 &sig0,
                 |r| generalize_region(self, mark, new_vars.as_slice(),
                                       sig0.binder_id, &a_map, r));
@@ -158,7 +161,7 @@ fn generalize_region(this: &Lub,
                 return r0;
             }
 
-            let tainted = this.get_ref().infcx.region_vars.tainted(mark, r0);
+            let tainted = this.fields.infcx.region_vars.tainted(mark, r0);
 
             // Variables created during LUB computation which are
             // *related* to regions that pre-date the LUB computation
@@ -185,8 +188,8 @@ fn generalize_region(this: &Lub,
                 }
             }
 
-            this.get_ref().infcx.tcx.sess.span_bug(
-                this.get_ref().trace.origin.span(),
+            this.fields.infcx.tcx.sess.span_bug(
+                this.fields.trace.origin.span(),
                 format!("region {:?} is not associated with \
                          any bound region from A!",
                         r0).as_slice())
diff --git a/src/librustc/middle/typeck/infer/macros.rs b/src/librustc/middle/typeck/infer/macros.rs
deleted file mode 100644 (file)
index d3e81f0..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <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.
-
-#![macro_escape]
-
-macro_rules! if_ok(
-    ($inp: expr) => (
-        match $inp {
-            Ok(v) => { v }
-            Err(e) => { return Err(e); }
-        }
-    )
-)
index ed96effdd83dfecebcf9294c84e52577680fccdf..f86857f97f6546db85cadd6156d8e9d3e930638a 100644 (file)
 use middle::ty_fold::TypeFolder;
 use middle::typeck::check::regionmanip::replace_late_bound_regions_in_fn_sig;
 use middle::typeck::infer::coercion::Coerce;
-use middle::typeck::infer::combine::{Combine, CombineFields, eq_tys};
-use middle::typeck::infer::region_inference::{RegionSnapshot};
-use middle::typeck::infer::region_inference::{RegionVarBindings};
+use middle::typeck::infer::combine::{Combine, CombineFields};
+use middle::typeck::infer::region_inference::{RegionVarBindings,
+                                              RegionSnapshot};
 use middle::typeck::infer::resolve::{resolver};
+use middle::typeck::infer::equate::Equate;
 use middle::typeck::infer::sub::Sub;
 use middle::typeck::infer::lub::Lub;
-use middle::typeck::infer::unify::{UnificationTable, Snapshot};
+use middle::typeck::infer::unify::{UnificationTable};
 use middle::typeck::infer::error_reporting::ErrorReporting;
 use std::cell::{RefCell};
 use std::collections::HashMap;
 use util::common::indent;
 use util::ppaux::{bound_region_to_string, ty_to_string, trait_ref_to_string, Repr};
 
-pub mod doc;
-pub mod macros;
+pub mod coercion;
 pub mod combine;
+pub mod doc;
+pub mod equate;
+pub mod error_reporting;
 pub mod glb;
 pub mod lattice;
 pub mod lub;
 pub mod region_inference;
 pub mod resolve;
 pub mod sub;
-pub mod unify;
-pub mod coercion;
-pub mod error_reporting;
 pub mod test;
+pub mod type_variable;
+pub mod unify;
 
 pub type Bound<T> = Option<T>;
 
@@ -79,8 +81,7 @@ pub struct InferCtxt<'a> {
     // We instantiate UnificationTable with bounds<ty::t> because the
     // types that might instantiate a general type variable have an
     // order, represented by its upper and lower bounds.
-    type_unification_table:
-        RefCell<UnificationTable<ty::TyVid, Bounds<ty::t>>>,
+    type_variables: RefCell<type_variable::TypeVariableTable>,
 
     // Map from integral variable to the kind of integer it represents
     int_unification_table:
@@ -161,6 +162,9 @@ pub enum SubregionOrigin {
     // Closure bound must not outlive captured free variables
     FreeVariable(Span, ast::NodeId),
 
+    // Proc upvars must be 'static
+    ProcCapture(Span, ast::NodeId),
+
     // Index into slice must be within its lifetime
     IndexSlice(Span),
 
@@ -290,7 +294,7 @@ pub fn fixup_err_to_string(f: fixup_err) -> String {
 pub fn new_infer_ctxt<'a>(tcx: &'a ty::ctxt) -> InferCtxt<'a> {
     InferCtxt {
         tcx: tcx,
-        type_unification_table: RefCell::new(UnificationTable::new()),
+        type_variables: RefCell::new(type_variable::TypeVariableTable::new()),
         int_unification_table: RefCell::new(UnificationTable::new()),
         float_unification_table: RefCell::new(UnificationTable::new()),
         region_vars: RegionVarBindings::new(tcx),
@@ -392,8 +396,8 @@ pub fn mk_eqty(cx: &InferCtxt,
             origin: origin,
             values: Types(expected_found(a_is_expected, a, b))
         };
-        let suber = cx.sub(a_is_expected, trace);
-        eq_tys(&suber, a, b)
+        try!(cx.equate(a_is_expected, trace).tys(a, b));
+        Ok(())
     })
 }
 
@@ -508,9 +512,9 @@ pub fn uok() -> ures {
 }
 
 pub struct CombinedSnapshot {
-    type_snapshot: Snapshot<ty::TyVid>,
-    int_snapshot: Snapshot<ty::IntVid>,
-    float_snapshot: Snapshot<ty::FloatVid>,
+    type_snapshot: type_variable::Snapshot,
+    int_snapshot: unify::Snapshot<ty::IntVid>,
+    float_snapshot: unify::Snapshot<ty::FloatVid>,
     region_vars_snapshot: RegionSnapshot,
 }
 
@@ -522,6 +526,10 @@ pub fn combine_fields<'a>(&'a self, a_is_expected: bool, trace: TypeTrace)
                        trace: trace}
     }
 
+    pub fn equate<'a>(&'a self, a_is_expected: bool, trace: TypeTrace) -> Equate<'a> {
+        Equate(self.combine_fields(a_is_expected, trace))
+    }
+
     pub fn sub<'a>(&'a self, a_is_expected: bool, trace: TypeTrace) -> Sub<'a> {
         Sub(self.combine_fields(a_is_expected, trace))
     }
@@ -530,13 +538,9 @@ pub fn lub<'a>(&'a self, a_is_expected: bool, trace: TypeTrace) -> Lub<'a> {
         Lub(self.combine_fields(a_is_expected, trace))
     }
 
-    pub fn in_snapshot(&self) -> bool {
-        self.region_vars.in_snapshot()
-    }
-
     fn start_snapshot(&self) -> CombinedSnapshot {
         CombinedSnapshot {
-            type_snapshot: self.type_unification_table.borrow_mut().snapshot(),
+            type_snapshot: self.type_variables.borrow_mut().snapshot(),
             int_snapshot: self.int_unification_table.borrow_mut().snapshot(),
             float_snapshot: self.float_unification_table.borrow_mut().snapshot(),
             region_vars_snapshot: self.region_vars.start_snapshot(),
@@ -550,15 +554,15 @@ fn rollback_to(&self, snapshot: CombinedSnapshot) {
                                float_snapshot,
                                region_vars_snapshot } = snapshot;
 
-        self.type_unification_table
+        self.type_variables
             .borrow_mut()
-            .rollback_to(self.tcx, type_snapshot);
+            .rollback_to(type_snapshot);
         self.int_unification_table
             .borrow_mut()
-            .rollback_to(self.tcx, int_snapshot);
+            .rollback_to(int_snapshot);
         self.float_unification_table
             .borrow_mut()
-            .rollback_to(self.tcx, float_snapshot);
+            .rollback_to(float_snapshot);
         self.region_vars
             .rollback_to(region_vars_snapshot);
     }
@@ -570,7 +574,7 @@ fn commit_from(&self, snapshot: CombinedSnapshot) {
                                float_snapshot,
                                region_vars_snapshot } = snapshot;
 
-        self.type_unification_table
+        self.type_variables
             .borrow_mut()
             .commit(type_snapshot);
         self.int_unification_table
@@ -633,9 +637,9 @@ pub fn add_given(&self,
 
 impl<'a> InferCtxt<'a> {
     pub fn next_ty_var_id(&self) -> TyVid {
-        self.type_unification_table
+        self.type_variables
             .borrow_mut()
-            .new_key(Bounds { lb: None, ub: None })
+            .new_var()
     }
 
     pub fn next_ty_var(&self) -> ty::t {
@@ -933,6 +937,7 @@ pub fn span(&self) -> Span {
             InvokeClosure(a) => a,
             DerefPointer(a) => a,
             FreeVariable(a, _) => a,
+            ProcCapture(a, _) => a,
             IndexSlice(a) => a,
             RelateObjectBound(a) => a,
             RelateProcBound(a, _, _) => a,
@@ -972,6 +977,9 @@ fn repr(&self, tcx: &ty::ctxt) -> String {
             FreeVariable(a, b) => {
                 format!("FreeVariable({}, {})", a.repr(tcx), b)
             }
+            ProcCapture(a, b) => {
+                format!("ProcCapture({}, {})", a.repr(tcx), b)
+            }
             IndexSlice(a) => {
                 format!("IndexSlice({})", a.repr(tcx))
             }
index 7c8d10dd9941644c8d7c485f72e5f044a17ae868..f34894346f64afbc42e5d7a485267f2d5d65c902 100644 (file)
@@ -234,7 +234,7 @@ pub fn new(tcx: &'a ty::ctxt) -> RegionVarBindings<'a> {
         }
     }
 
-    pub fn in_snapshot(&self) -> bool {
+    fn in_snapshot(&self) -> bool {
         self.undo_log.borrow().len() > 0
     }
 
@@ -253,7 +253,7 @@ pub fn mark(&self) -> RegionMark {
     }
 
     pub fn commit(&self, snapshot: RegionSnapshot) {
-        debug!("RegionVarBindings: commit()");
+        debug!("RegionVarBindings: commit({})", snapshot.length);
         assert!(self.undo_log.borrow().len() > snapshot.length);
         assert!(*self.undo_log.borrow().get(snapshot.length) == OpenSnapshot);
 
@@ -406,6 +406,18 @@ pub fn add_given(&self,
         }
     }
 
+    pub fn make_eqregion(&self,
+                         origin: SubregionOrigin,
+                         sub: Region,
+                         sup: Region) {
+        if sub != sup {
+            // Eventually, it would be nice to add direct support for
+            // equating regions.
+            self.make_subregion(origin.clone(), sub, sup);
+            self.make_subregion(origin, sup, sub);
+        }
+    }
+
     pub fn make_subregion(&self,
                           origin: SubregionOrigin,
                           sub: Region,
index 2ae95309d41d98a76e6c00b8f254ddffd415a08c..f9742c522dac4a6d0d5ff753467e27f546a01b11 100644 (file)
 
 
 use middle::ty::{FloatVar, FloatVid, IntVar, IntVid, RegionVid, TyVar, TyVid};
-use middle::ty::{type_is_bot, IntType, UintType};
+use middle::ty::{IntType, UintType};
 use middle::ty;
 use middle::ty_fold;
-use middle::typeck::infer::{Bounds, cyclic_ty, fixup_err, fres, InferCtxt};
-use middle::typeck::infer::{unresolved_float_ty, unresolved_int_ty};
-use middle::typeck::infer::{unresolved_ty};
+use middle::typeck::infer::{cyclic_ty, fixup_err, fres, InferCtxt};
+use middle::typeck::infer::{unresolved_int_ty,unresolved_float_ty,unresolved_ty};
 use syntax::codemap::Span;
 use util::common::indent;
 use util::ppaux::{Repr, ty_to_string};
@@ -132,8 +131,8 @@ pub fn resolve_type_chk(&mut self,
         assert!(self.v_seen.is_empty());
         match self.err {
           None => {
-            debug!("Resolved to {} + {} (modes={:x})",
-                   ty_to_string(self.infcx.tcx, rty),
+            debug!("Resolved {} to {} (modes={:x})",
+                   ty_to_string(self.infcx.tcx, typ),
                    ty_to_string(self.infcx.tcx, rty),
                    self.modes);
             return Ok(rty);
@@ -219,21 +218,16 @@ pub fn resolve_ty_var(&mut self, vid: TyVid) -> ty::t {
             // tend to carry more restrictions or higher
             // perf. penalties, so it pays to know more.
 
-            let node =
-                self.infcx.type_unification_table.borrow_mut().get(tcx, vid);
-            let t1 = match node.value {
-              Bounds { ub:_, lb:Some(t) } if !type_is_bot(t) => {
-                  self.resolve_type(t)
-              }
-              Bounds { ub:Some(t), lb:_ } | Bounds { ub:_, lb:Some(t) } => {
-                  self.resolve_type(t)
-              }
-              Bounds { ub:None, lb:None } => {
-                if self.should(force_tvar) {
-                    self.err = Some(unresolved_ty(vid));
+            let t1 = match self.infcx.type_variables.borrow().probe(vid) {
+                Some(t) => {
+                    self.resolve_type(t)
+                }
+                None => {
+                    if self.should(force_tvar) {
+                        self.err = Some(unresolved_ty(vid));
+                    }
+                    ty::mk_var(tcx, vid)
                 }
-                ty::mk_var(tcx, vid)
-              }
             };
             self.v_seen.pop().unwrap();
             return t1;
index a9e8d1e860333cc9253247451f4f6add05dac5d2..be4abb1ad82612157cfdf2b4165579b48311d4d8 100644 (file)
 use middle::typeck::check::regionmanip::replace_late_bound_regions_in_fn_sig;
 use middle::typeck::infer::combine::*;
 use middle::typeck::infer::{cres, CresCompare};
+use middle::typeck::infer::equate::Equate;
 use middle::typeck::infer::glb::Glb;
 use middle::typeck::infer::InferCtxt;
-use middle::typeck::infer::lattice::CombineFieldsLatticeMethods;
 use middle::typeck::infer::lub::Lub;
-use middle::typeck::infer::then;
 use middle::typeck::infer::{TypeTrace, Subtype};
+use middle::typeck::infer::type_variable::{SubtypeOf, SupertypeOf};
 use util::common::{indenter};
 use util::ppaux::{bound_region_to_string, Repr};
 
 use syntax::ast::{Onceness, FnStyle, MutImmutable, MutMutable};
 
-pub struct Sub<'f>(pub CombineFields<'f>);  // "subtype", "subregion" etc
 
-impl<'f> Sub<'f> {
-    pub fn get_ref<'a>(&'a self) -> &'a CombineFields<'f> { let Sub(ref v) = *self; v }
+/// "Greatest lower bound" (common subtype)
+pub struct Sub<'f> {
+    fields: CombineFields<'f>
+}
+
+#[allow(non_snake_case)]
+pub fn Sub<'f>(cf: CombineFields<'f>) -> Sub<'f> {
+    Sub { fields: cf }
 }
 
 impl<'f> Combine for Sub<'f> {
-    fn infcx<'a>(&'a self) -> &'a InferCtxt<'a> { self.get_ref().infcx }
+    fn infcx<'a>(&'a self) -> &'a InferCtxt<'a> { self.fields.infcx }
     fn tag(&self) -> String { "sub".to_string() }
-    fn a_is_expected(&self) -> bool { self.get_ref().a_is_expected }
-    fn trace(&self) -> TypeTrace { self.get_ref().trace.clone() }
+    fn a_is_expected(&self) -> bool { self.fields.a_is_expected }
+    fn trace(&self) -> TypeTrace { self.fields.trace.clone() }
 
-    fn sub<'a>(&'a self) -> Sub<'a> { Sub(self.get_ref().clone()) }
-    fn lub<'a>(&'a self) -> Lub<'a> { Lub(self.get_ref().clone()) }
-    fn glb<'a>(&'a self) -> Glb<'a> { Glb(self.get_ref().clone()) }
+    fn equate<'a>(&'a self) -> Equate<'a> { Equate(self.fields.clone()) }
+    fn sub<'a>(&'a self) -> Sub<'a> { Sub(self.fields.clone()) }
+    fn lub<'a>(&'a self) -> Lub<'a> { Lub(self.fields.clone()) }
+    fn glb<'a>(&'a self) -> Glb<'a> { Glb(self.fields.clone()) }
 
     fn contratys(&self, a: ty::t, b: ty::t) -> cres<ty::t> {
-        let opp = CombineFields {
-            a_is_expected: !self.get_ref().a_is_expected,
-            ..self.get_ref().clone()
-        };
-        Sub(opp).tys(b, a)
+        Sub(self.fields.switch_expected()).tys(b, a)
     }
 
     fn contraregions(&self, a: ty::Region, b: ty::Region)
-                    -> cres<ty::Region> {
-        let opp = CombineFields {
-            a_is_expected: !self.get_ref().a_is_expected,
-            ..self.get_ref().clone()
-        };
-        Sub(opp).regions(b, a)
-    }
+                     -> cres<ty::Region> {
+                         let opp = CombineFields {
+                             a_is_expected: !self.fields.a_is_expected,
+                             ..self.fields.clone()
+                         };
+                         Sub(opp).regions(b, a)
+                     }
 
     fn regions(&self, a: ty::Region, b: ty::Region) -> cres<ty::Region> {
         debug!("{}.regions({}, {})",
                self.tag(),
-               a.repr(self.get_ref().infcx.tcx),
-               b.repr(self.get_ref().infcx.tcx));
-        self.get_ref().infcx.region_vars.make_subregion(Subtype(self.trace()), a, b);
+               a.repr(self.fields.infcx.tcx),
+               b.repr(self.fields.infcx.tcx));
+        self.fields.infcx.region_vars.make_subregion(Subtype(self.trace()), a, b);
         Ok(a)
     }
 
     fn mts(&self, a: &ty::mt, b: &ty::mt) -> cres<ty::mt> {
         debug!("mts({} <: {})",
-               a.repr(self.get_ref().infcx.tcx),
-               b.repr(self.get_ref().infcx.tcx));
+               a.repr(self.fields.infcx.tcx),
+               b.repr(self.fields.infcx.tcx));
 
         if a.mutbl != b.mutbl {
             return Err(ty::terr_mutability);
         }
 
         match b.mutbl {
-          MutMutable => {
-            // If supertype is mut, subtype must match exactly
-            // (i.e., invariant if mut):
-            eq_tys(self, a.ty, b.ty).then(|| Ok(*a))
-          }
-          MutImmutable => {
-            // Otherwise we can be covariant:
-            self.tys(a.ty, b.ty).and_then(|_t| Ok(*a) )
-          }
+            MutMutable => {
+                // If supertype is mut, subtype must match exactly
+                // (i.e., invariant if mut):
+                try!(self.equate().tys(a.ty, b.ty));
+            }
+            MutImmutable => {
+                // Otherwise we can be covariant:
+                try!(self.tys(a.ty, b.ty));
+            }
         }
+
+        Ok(*a) // return is meaningless in sub, just return *a
     }
 
     fn fn_styles(&self, a: FnStyle, b: FnStyle) -> cres<FnStyle> {
@@ -118,16 +122,21 @@ fn builtin_bounds(&self, a: BuiltinBounds, b: BuiltinBounds)
 
     fn tys(&self, a: ty::t, b: ty::t) -> cres<ty::t> {
         debug!("{}.tys({}, {})", self.tag(),
-               a.repr(self.get_ref().infcx.tcx), b.repr(self.get_ref().infcx.tcx));
+               a.repr(self.fields.infcx.tcx), b.repr(self.fields.infcx.tcx));
         if a == b { return Ok(a); }
-        let _indenter = indenter();
+
+        let infcx = self.fields.infcx;
+        let a = infcx.type_variables.borrow().replace_if_possible(a);
+        let b = infcx.type_variables.borrow().replace_if_possible(b);
         match (&ty::get(a).sty, &ty::get(b).sty) {
             (&ty::ty_bot, _) => {
                 Ok(a)
             }
 
             (&ty::ty_infer(TyVar(a_id)), &ty::ty_infer(TyVar(b_id))) => {
-                if_ok!(self.get_ref().var_sub_var(a_id, b_id));
+                infcx.type_variables
+                    .borrow_mut()
+                    .relate_vars(a_id, SubtypeOf, b_id);
                 Ok(a)
             }
             // The vec/str check here and below is so that we don't unify
@@ -139,7 +148,9 @@ fn tys(&self, a: ty::t, b: ty::t) -> cres<ty::t> {
                 Err(ty::terr_sorts(expected_found(self, a, b)))
             }
             (&ty::ty_infer(TyVar(a_id)), _) => {
-                if_ok!(self.get_ref().var_sub_t(a_id, b));
+                try!(self.fields
+                       .switch_expected()
+                       .instantiate(b, SupertypeOf, a_id));
                 Ok(a)
             }
 
@@ -148,7 +159,7 @@ fn tys(&self, a: ty::t, b: ty::t) -> cres<ty::t> {
                 Err(ty::terr_sorts(expected_found(self, a, b)))
             }
             (_, &ty::ty_infer(TyVar(b_id))) => {
-                if_ok!(self.get_ref().t_sub_var(a, b_id));
+                try!(self.fields.instantiate(a, SubtypeOf, b_id));
                 Ok(a)
             }
 
@@ -164,7 +175,7 @@ fn tys(&self, a: ty::t, b: ty::t) -> cres<ty::t> {
 
     fn fn_sigs(&self, a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig> {
         debug!("fn_sigs(a={}, b={})",
-               a.repr(self.get_ref().infcx.tcx), b.repr(self.get_ref().infcx.tcx));
+               a.repr(self.fields.infcx.tcx), b.repr(self.fields.infcx.tcx));
         let _indenter = indenter();
 
         // Rather than checking the subtype relationship between `a` and `b`
@@ -176,38 +187,38 @@ fn fn_sigs(&self, a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig> {
 
         // Make a mark so we can examine "all bindings that were
         // created as part of this type comparison".
-        let mark = self.get_ref().infcx.region_vars.mark();
+        let mark = self.fields.infcx.region_vars.mark();
 
         // First, we instantiate each bound region in the subtype with a fresh
         // region variable.
         let (a_sig, _) =
-            self.get_ref().infcx.replace_late_bound_regions_with_fresh_regions(
+            self.fields.infcx.replace_late_bound_regions_with_fresh_regions(
                 self.trace(), a);
 
         // Second, we instantiate each bound region in the supertype with a
         // fresh concrete region.
         let (skol_map, b_sig) = {
-            replace_late_bound_regions_in_fn_sig(self.get_ref().infcx.tcx, b, |br| {
-                let skol = self.get_ref().infcx.region_vars.new_skolemized(br);
+            replace_late_bound_regions_in_fn_sig(self.fields.infcx.tcx, b, |br| {
+                let skol = self.fields.infcx.region_vars.new_skolemized(br);
                 debug!("Bound region {} skolemized to {:?}",
-                       bound_region_to_string(self.get_ref().infcx.tcx, "", false, br),
+                       bound_region_to_string(self.fields.infcx.tcx, "", false, br),
                        skol);
                 skol
             })
         };
 
-        debug!("a_sig={}", a_sig.repr(self.get_ref().infcx.tcx));
-        debug!("b_sig={}", b_sig.repr(self.get_ref().infcx.tcx));
+        debug!("a_sig={}", a_sig.repr(self.fields.infcx.tcx));
+        debug!("b_sig={}", b_sig.repr(self.fields.infcx.tcx));
 
         // Compare types now that bound regions have been replaced.
-        let sig = if_ok!(super_fn_sigs(self, &a_sig, &b_sig));
+        let sig = try!(super_fn_sigs(self, &a_sig, &b_sig));
 
         // Presuming type comparison succeeds, we need to check
         // that the skolemized regions do not "leak".
         let new_vars =
-            self.get_ref().infcx.region_vars.vars_created_since_mark(mark);
+            self.fields.infcx.region_vars.vars_created_since_mark(mark);
         for (&skol_br, &skol) in skol_map.iter() {
-            let tainted = self.get_ref().infcx.region_vars.tainted(mark, skol);
+            let tainted = self.fields.infcx.region_vars.tainted(mark, skol);
             for tainted_region in tainted.iter() {
                 // Each skolemized should only be relatable to itself
                 // or new variables:
@@ -224,16 +235,16 @@ fn fn_sigs(&self, a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig> {
                 if self.a_is_expected() {
                     debug!("Not as polymorphic!");
                     return Err(ty::terr_regions_insufficiently_polymorphic(
-                            skol_br, *tainted_region));
+                        skol_br, *tainted_region));
                 } else {
                     debug!("Overly polymorphic!");
                     return Err(ty::terr_regions_overly_polymorphic(
-                            skol_br, *tainted_region));
+                        skol_br, *tainted_region));
                 }
             }
         }
 
         return Ok(sig);
     }
-
 }
+
diff --git a/src/librustc/middle/typeck/infer/type_variable.rs b/src/librustc/middle/typeck/infer/type_variable.rs
new file mode 100644 (file)
index 0000000..5f67f8a
--- /dev/null
@@ -0,0 +1,173 @@
+// 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 middle::ty;
+use std::mem;
+use util::snapshot_vec as sv;
+
+pub struct TypeVariableTable {
+    values: sv::SnapshotVec<TypeVariableData,UndoEntry,Delegate>,
+}
+
+struct TypeVariableData {
+    value: TypeVariableValue
+}
+
+enum TypeVariableValue {
+    Known(ty::t),
+    Bounded(Vec<Relation>),
+}
+
+pub struct Snapshot {
+    snapshot: sv::Snapshot
+}
+
+enum UndoEntry {
+    // The type of the var was specified.
+    SpecifyVar(ty::TyVid, Vec<Relation>),
+    Relate(ty::TyVid, ty::TyVid),
+}
+
+struct Delegate;
+
+type Relation = (RelationDir, ty::TyVid);
+
+#[deriving(PartialEq,Show)]
+pub enum RelationDir {
+    SubtypeOf, SupertypeOf, EqTo
+}
+
+impl RelationDir {
+    fn opposite(self) -> RelationDir {
+        match self {
+            SubtypeOf => SupertypeOf,
+            SupertypeOf => SubtypeOf,
+            EqTo => EqTo
+        }
+    }
+}
+
+impl TypeVariableTable {
+    pub fn new() -> TypeVariableTable {
+        TypeVariableTable { values: sv::SnapshotVec::new(Delegate) }
+    }
+
+    fn relations<'a>(&'a mut self, a: ty::TyVid) -> &'a mut Vec<Relation> {
+        relations(self.values.get_mut(a.index))
+    }
+
+    pub fn relate_vars(&mut self, a: ty::TyVid, dir: RelationDir, b: ty::TyVid) {
+        /*!
+         * Records that `a <: b`, `a :> b`, or `a == b`, depending on `dir`.
+         *
+         * Precondition: neither `a` nor `b` are known.
+         */
+
+        if a != b {
+            self.relations(a).push((dir, b));
+            self.relations(b).push((dir.opposite(), a));
+            self.values.record(Relate(a, b));
+        }
+    }
+
+    pub fn instantiate_and_push(
+        &mut self,
+        vid: ty::TyVid,
+        ty: ty::t,
+        stack: &mut Vec<(ty::t, RelationDir, ty::TyVid)>)
+    {
+        /*!
+         * Instantiates `vid` with the type `ty` and then pushes an
+         * entry onto `stack` for each of the relations of `vid` to
+         * other variables. The relations will have the form `(ty,
+         * dir, vid1)` where `vid1` is some other variable id.
+         */
+
+        let old_value = {
+            let value_ptr = &mut self.values.get_mut(vid.index).value;
+            mem::replace(value_ptr, Known(ty))
+        };
+
+        let relations = match old_value {
+            Bounded(b) => b,
+            Known(_) => fail!("Asked to instantiate variable that is \
+                               already instantiated")
+        };
+
+        for &(dir, vid) in relations.iter() {
+            stack.push((ty, dir, vid));
+        }
+
+        self.values.record(SpecifyVar(vid, relations));
+    }
+
+    pub fn new_var(&mut self) -> ty::TyVid {
+        let index =
+            self.values.push(
+                TypeVariableData { value: Bounded(Vec::new()) });
+        ty::TyVid { index: index }
+    }
+
+    pub fn probe(&self, vid: ty::TyVid) -> Option<ty::t> {
+        match self.values.get(vid.index).value {
+            Bounded(..) => None,
+            Known(t) => Some(t)
+        }
+    }
+
+    pub fn replace_if_possible(&self, t: ty::t) -> ty::t {
+        match ty::get(t).sty {
+            ty::ty_infer(ty::TyVar(v)) => {
+                match self.probe(v) {
+                    None => t,
+                    Some(u) => u
+                }
+            }
+            _ => t,
+        }
+    }
+
+    pub fn snapshot(&mut self) -> Snapshot {
+        Snapshot { snapshot: self.values.start_snapshot() }
+    }
+
+    pub fn rollback_to(&mut self, s: Snapshot) {
+        self.values.rollback_to(s.snapshot);
+    }
+
+    pub fn commit(&mut self, s: Snapshot) {
+        self.values.commit(s.snapshot);
+    }
+}
+
+impl sv::SnapshotVecDelegate<TypeVariableData,UndoEntry> for Delegate {
+    fn reverse(&mut self,
+               values: &mut Vec<TypeVariableData>,
+               action: UndoEntry) {
+        match action {
+            SpecifyVar(vid, relations) => {
+                values.get_mut(vid.index).value = Bounded(relations);
+            }
+
+            Relate(a, b) => {
+                relations(values.get_mut(a.index)).pop();
+                relations(values.get_mut(b.index)).pop();
+            }
+        }
+    }
+}
+
+fn relations<'a>(v: &'a mut TypeVariableData) -> &'a mut Vec<Relation> {
+    match v.value {
+        Known(_) => fail!("var_sub_var: variable is known"),
+        Bounded(ref mut relations) => relations
+    }
+}
+
index 33bdded52341f304b7f8a3716f57de9388edf9d8..adf0a25ce4002e5f8069c59e27afe1a4b679abaa 100644 (file)
 
 use middle::ty::{expected_found, IntVarValue};
 use middle::ty;
-use middle::typeck::infer::{Bounds, uok, ures};
+use middle::typeck::infer::{uok, ures};
 use middle::typeck::infer::InferCtxt;
 use std::cell::RefCell;
 use std::fmt::Show;
-use std::mem;
 use syntax::ast;
 use util::ppaux::Repr;
+use util::snapshot_vec as sv;
 
 /**
  * This trait is implemented by any type that can serve as a type
  * variable. We call such variables *unification keys*. For example,
- * this trait is implemented by `TyVid`, which represents normal
- * type variables, and `IntVid`, which represents integral variables.
+ * this trait is implemented by `IntVid`, which represents integral
+ * variables.
  *
- * Each key type has an associated value type `V`. For example,
- * for `TyVid`, this is `Bounds<ty::t>`, representing a pair of
- * upper- and lower-bound types.
+ * Each key type has an associated value type `V`. For example, for
+ * `IntVid`, this is `Option<IntVarValue>`, representing some
+ * (possibly not yet known) sort of integer.
  *
  * Implementations of this trait are at the end of this file.
  */
@@ -48,11 +48,10 @@ fn unification_table<'v>(infcx: &'v InferCtxt)
 }
 
 /**
- * Trait for valid types that a type variable can be set to.  Note
- * that this is typically not the end type that the value will
- * take on, but rather some wrapper: for example, for normal type
- * variables, the associated type is not `ty::t` but rather
- * `Bounds<ty::t>`.
+ * Trait for valid types that a type variable can be set to. Note that
+ * this is typically not the end type that the value will take on, but
+ * rather an `Option` wrapper (where `None` represents a variable
+ * whose value is not yet set).
  *
  * Implementations of this trait are at the end of this file.
  */
@@ -82,13 +81,8 @@ pub struct UnificationTable<K,V> {
     /**
      * Indicates the current value of each key.
      */
-    values: Vec<VarValue<K,V>>,
 
-    /**
-     * When a snapshot is active, logs each change made to the table
-     * so that they can be unrolled.
-     */
-    undo_log: Vec<UndoLog<K,V>>,
+    values: sv::SnapshotVec<VarValue<K,V>,(),Delegate>,
 }
 
 /**
@@ -96,29 +90,9 @@ pub struct UnificationTable<K,V> {
  * made during the snapshot may either be *committed* or *rolled back*.
  */
 pub struct Snapshot<K> {
-    // Ensure that this snapshot is keyed to the table type.
-    marker1: marker::CovariantType<K>,
-
-    // Snapshots are tokens that should be created/consumed linearly.
-    marker2: marker::NoCopy,
-
-    // Length of the undo log at the time the snapshot was taken.
-    length: uint,
-}
-
-#[deriving(PartialEq)]
-enum UndoLog<K,V> {
-    /// Indicates where a snapshot started.
-    OpenSnapshot,
-
-    /// Indicates a snapshot that has been committed.
-    CommittedSnapshot,
-
-    /// New variable with given index was created.
-    NewVar(uint),
-
-    /// Variable with given index was changed *from* the given value.
-    SetVar(uint, VarValue<K,V>),
+    // Link snapshot to the key type `K` of the table.
+    marker: marker::CovariantType<K>,
+    snapshot: sv::Snapshot,
 }
 
 /**
@@ -131,85 +105,36 @@ pub struct Node<K,V> {
     pub rank: uint,
 }
 
+pub struct Delegate;
+
 // We can't use V:LatticeValue, much as I would like to,
-// because frequently the pattern is that V=Bounds<U> for some
+// because frequently the pattern is that V=Option<U> for some
 // other type parameter U, and we have no way to say
-// Bounds<U>:
+// Option<U>:LatticeValue.
 
 impl<V:PartialEq+Clone+Repr,K:UnifyKey<V>> UnificationTable<K,V> {
     pub fn new() -> UnificationTable<K,V> {
         UnificationTable {
-            values: Vec::new(),
-            undo_log: Vec::new()
+            values: sv::SnapshotVec::new(Delegate),
         }
     }
 
-    pub fn in_snapshot(&self) -> bool {
-        /*! True if a snapshot has been started. */
-
-        self.undo_log.len() > 0
-    }
-
     /**
      * Starts a new snapshot. Each snapshot must be either
      * rolled back or committed in a "LIFO" (stack) order.
      */
     pub fn snapshot(&mut self) -> Snapshot<K> {
-        let length = self.undo_log.len();
-        debug!("{}: snapshot at length {}",
-               UnifyKey::tag(None::<K>),
-               length);
-        self.undo_log.push(OpenSnapshot);
-        Snapshot { length: length,
-                   marker1: marker::CovariantType,
-                   marker2: marker::NoCopy }
-    }
-
-    fn assert_open_snapshot(&self, snapshot: &Snapshot<K>) {
-        // Or else there was a failure to follow a stack discipline:
-        assert!(self.undo_log.len() > snapshot.length);
-
-        // Invariant established by start_snapshot():
-        assert!(*self.undo_log.get(snapshot.length) == OpenSnapshot);
+        Snapshot { marker: marker::CovariantType::<K>,
+                   snapshot: self.values.start_snapshot() }
     }
 
     /**
      * Reverses all changes since the last snapshot. Also
      * removes any keys that have been created since then.
      */
-    pub fn rollback_to(&mut self, tcx: &ty::ctxt, snapshot: Snapshot<K>) {
-        debug!("{}: rollback_to({})",
-               UnifyKey::tag(None::<K>),
-               snapshot.length);
-
-        self.assert_open_snapshot(&snapshot);
-
-        while self.undo_log.len() > snapshot.length + 1 {
-            match self.undo_log.pop().unwrap() {
-                OpenSnapshot => {
-                    // This indicates a failure to obey the stack discipline.
-                    tcx.sess.bug("Cannot rollback an uncommitted snapshot");
-                }
-
-                CommittedSnapshot => {
-                    // This occurs when there are nested snapshots and
-                    // the inner is committed but outer is rolled back.
-                }
-
-                NewVar(i) => {
-                    assert!(self.values.len() == i);
-                    self.values.pop();
-                }
-
-                SetVar(i, v) => {
-                    *self.values.get_mut(i) = v;
-                }
-            }
-        }
-
-        let v = self.undo_log.pop().unwrap();
-        assert!(v == OpenSnapshot);
-        assert!(self.undo_log.len() == snapshot.length);
+    pub fn rollback_to(&mut self, snapshot: Snapshot<K>) {
+        debug!("{}: rollback_to()", UnifyKey::tag(None::<K>));
+        self.values.rollback_to(snapshot.snapshot);
     }
 
     /**
@@ -217,28 +142,12 @@ pub fn rollback_to(&mut self, tcx: &ty::ctxt, snapshot: Snapshot<K>) {
      * can still be undone if there is a snapshot further out.
      */
     pub fn commit(&mut self, snapshot: Snapshot<K>) {
-        debug!("{}: commit({})",
-               UnifyKey::tag(None::<K>),
-               snapshot.length);
-
-        self.assert_open_snapshot(&snapshot);
-
-        if snapshot.length == 0 {
-            // The root snapshot.
-            self.undo_log.truncate(0);
-        } else {
-            *self.undo_log.get_mut(snapshot.length) = CommittedSnapshot;
-        }
+        debug!("{}: commit()", UnifyKey::tag(None::<K>));
+        self.values.commit(snapshot.snapshot);
     }
 
     pub fn new_key(&mut self, value: V) -> K {
-        let index = self.values.len();
-
-        if self.in_snapshot() {
-            self.undo_log.push(NewVar(index));
-        }
-
-        self.values.push(Root(value, 0));
+        let index = self.values.push(Root(value, 0));
         let k = UnifyKey::from_index(index);
         debug!("{}: created new key: {}",
                UnifyKey::tag(None::<K>),
@@ -246,20 +155,6 @@ pub fn new_key(&mut self, value: V) -> K {
         k
     }
 
-    fn swap_value(&mut self,
-                  index: uint,
-                  new_value: VarValue<K,V>)
-                  -> VarValue<K,V>
-    {
-        /*!
-         * Primitive operation to swap a value in the var array.
-         * Caller should update the undo log if we are in a snapshot.
-         */
-
-        let loc = self.values.get_mut(index);
-        mem::replace(loc, new_value)
-    }
-
     pub fn get(&mut self, tcx: &ty::ctxt, vid: K) -> Node<K,V> {
         /*!
          * Find the root node for `vid`. This uses the standard
@@ -274,15 +169,7 @@ pub fn get(&mut self, tcx: &ty::ctxt, vid: K) -> Node<K,V> {
                 let node: Node<K,V> = self.get(tcx, redirect.clone());
                 if node.key != redirect {
                     // Path compression
-                    let old_value =
-                        self.swap_value(index, Redirect(node.key.clone()));
-
-                    // If we are in a snapshot, record this compression,
-                    // because it's possible that the unification which
-                    // caused it will be rolled back later.
-                    if self.in_snapshot() {
-                        self.undo_log.push(SetVar(index, old_value));
-                    }
+                    self.values.set(index, Redirect(node.key.clone()));
                 }
                 node
             }
@@ -310,15 +197,12 @@ pub fn set(&mut self,
          */
 
         assert!(self.is_root(&key));
-        assert!(self.in_snapshot());
 
         debug!("Updating variable {} to {}",
                key.repr(tcx),
                new_value.repr(tcx));
 
-        let index = key.index();
-        let old_value = self.swap_value(index, new_value);
-        self.undo_log.push(SetVar(index, old_value));
+        self.values.set(key.index(), new_value);
     }
 
     pub fn unify(&mut self,
@@ -359,6 +243,12 @@ pub fn unify(&mut self,
     }
 }
 
+impl<K,V> sv::SnapshotVecDelegate<VarValue<K,V>,()> for Delegate {
+    fn reverse(&mut self, _: &mut Vec<VarValue<K,V>>, _: ()) {
+        fail!("Nothing to reverse");
+    }
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // Code to handle simple keys like ints, floats---anything that
 // doesn't have a subtyping relationship we need to worry about.
@@ -373,7 +263,8 @@ pub trait SimplyUnifiable : Clone + PartialEq + Repr {
 
 pub fn err<V:SimplyUnifiable>(a_is_expected: bool,
                               a_t: V,
-                              b_t: V) -> ures {
+                              b_t: V)
+                              -> ures {
     if a_is_expected {
         Err(SimplyUnifiable::to_type_err(
             ty::expected_found {expected: a_t, found: b_t}))
@@ -483,26 +374,6 @@ fn simple_var_t(&self,
 
 ///////////////////////////////////////////////////////////////////////////
 
-// General type keys
-
-impl UnifyKey<Bounds<ty::t>> for ty::TyVid {
-    fn index(&self) -> uint { self.index }
-
-    fn from_index(i: uint) -> ty::TyVid { ty::TyVid { index: i } }
-
-    fn unification_table<'v>(infcx: &'v InferCtxt)
-        -> &'v RefCell<UnificationTable<ty::TyVid, Bounds<ty::t>>>
-    {
-        return &infcx.type_unification_table;
-    }
-
-    fn tag(_: Option<ty::TyVid>) -> &'static str {
-        "TyVid"
-    }
-}
-
-impl UnifyValue for Bounds<ty::t> { }
-
 // Integral type keys
 
 impl UnifyKey<Option<IntVarValue>> for ty::IntVid {
index 2581ba51c2e107b1830a6a5fda3b82b971eda11c..7fa3ee0ac63ed1cb5e82331dc36d2a463bba3030 100644 (file)
@@ -10,7 +10,7 @@
 
 //! Used by plugin crates to tell `rustc` about the plugins they provide.
 
-use lint::LintPassObject;
+use lint::{LintPassObject, LintId, Lint};
 
 use syntax::ext::base::{SyntaxExtension, NamedSyntaxExtension, NormalTT};
 use syntax::ext::base::{IdentTT, LetSyntaxTT, ItemDecorator, ItemModifier, BasicMacroExpander};
@@ -19,6 +19,8 @@
 use syntax::parse::token;
 use syntax::ast;
 
+use std::collections::HashMap;
+
 /// Structure used to register plugins.
 ///
 /// A plugin registrar function takes an `&mut Registry` and should call
@@ -36,6 +38,9 @@ pub struct Registry {
 
     #[doc(hidden)]
     pub lint_passes: Vec<LintPassObject>,
+
+    #[doc(hidden)]
+    pub lint_groups: HashMap<&'static str, Vec<LintId>>,
 }
 
 impl Registry {
@@ -45,6 +50,7 @@ pub fn new(krate: &ast::Crate) -> Registry {
             krate_span: krate.span,
             syntax_exts: vec!(),
             lint_passes: vec!(),
+            lint_groups: HashMap::new(),
         }
     }
 
@@ -80,4 +86,9 @@ pub fn register_macro(&mut self, name: &str, expander: MacroExpanderFn) {
     pub fn register_lint_pass(&mut self, lint_pass: LintPassObject) {
         self.lint_passes.push(lint_pass);
     }
+
+    /// Register a lint group.
+    pub fn register_lint_group(&mut self, name: &'static str, to: Vec<&'static Lint>) {
+        self.lint_groups.insert(name, to.move_iter().map(|x| LintId::of(x)).collect());
+    }
 }
index 34a2faa581c5ec28400f814d5987712fd680109c..a38ee84e95dfb9cf7418d0a9fefd1f89919dc1d5 100644 (file)
@@ -10,6 +10,8 @@
 
 //! An efficient hash map for node IDs
 
+#![allow(non_snake_case)]
+
 use std::collections::{HashMap, HashSet};
 use std::hash::{Hasher, Hash, Writer};
 use syntax::ast;
diff --git a/src/librustc/util/snapshot_vec.rs b/src/librustc/util/snapshot_vec.rs
new file mode 100644 (file)
index 0000000..60e50c8
--- /dev/null
@@ -0,0 +1,195 @@
+// 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 utility class for implementing "snapshottable" things; a
+ * snapshottable data structure permits you to take a snapshot (via
+ * `start_snapshot`) and then, after making some changes, elect either
+ * to rollback to the start of the snapshot or commit those changes.
+ *
+ * This vector is intended to be used as part of an abstraction, not
+ * serve as a complete abstraction on its own. As such, while it will
+ * roll back most changes on its own, it also supports a `get_mut`
+ * operation that gives you an abitrary mutable pointer into the
+ * vector. To ensure that any changes you make this with this pointer
+ * are rolled back, you must invoke `record` to record any changes you
+ * make and also supplying a delegate capable of reversing those
+ * changes.
+ */
+
+use std::kinds::marker;
+use std::mem;
+
+#[deriving(PartialEq)]
+enum UndoLog<T,U> {
+    /// Indicates where a snapshot started.
+    OpenSnapshot,
+
+    /// Indicates a snapshot that has been committed.
+    CommittedSnapshot,
+
+    /// New variable with given index was created.
+    NewElem(uint),
+
+    /// Variable with given index was changed *from* the given value.
+    SetElem(uint, T),
+
+    /// Extensible set of actions
+    Other(U)
+}
+
+pub struct SnapshotVec<T,U,D> {
+    values: Vec<T>,
+    undo_log: Vec<UndoLog<T,U>>,
+    delegate: D
+}
+
+pub struct Snapshot {
+    // Snapshots are tokens that should be created/consumed linearly.
+    marker: marker::NoCopy,
+
+    // Length of the undo log at the time the snapshot was taken.
+    length: uint,
+}
+
+pub trait SnapshotVecDelegate<T,U> {
+    fn reverse(&mut self, values: &mut Vec<T>, action: U);
+}
+
+impl<T,U,D:SnapshotVecDelegate<T,U>> SnapshotVec<T,U,D> {
+    pub fn new(delegate: D) -> SnapshotVec<T,U,D> {
+        SnapshotVec {
+            values: Vec::new(),
+            undo_log: Vec::new(),
+            delegate: delegate
+        }
+    }
+
+    fn in_snapshot(&self) -> bool {
+        !self.undo_log.is_empty()
+    }
+
+    pub fn record(&mut self, action: U) {
+        if self.in_snapshot() {
+            self.undo_log.push(Other(action));
+        }
+    }
+
+    pub fn push(&mut self, elem: T) -> uint {
+        let len = self.values.len();
+        self.values.push(elem);
+
+        if self.in_snapshot() {
+            self.undo_log.push(NewElem(len));
+        }
+
+        len
+    }
+
+    pub fn get<'a>(&'a self, index: uint) -> &'a T {
+        self.values.get(index)
+    }
+
+    pub fn get_mut<'a>(&'a mut self, index: uint) -> &'a mut T {
+        /*!
+         * Returns a mutable pointer into the vec; whatever changes
+         * you make here cannot be undone automatically, so you should
+         * be sure call `record()` with some sort of suitable undo
+         * action.
+         */
+
+        self.values.get_mut(index)
+    }
+
+    pub fn set(&mut self, index: uint, new_elem: T) {
+        /*!
+         * Updates the element at the given index. The old value will
+         * saved (and perhaps restored) if a snapshot is active.
+         */
+
+        let old_elem = mem::replace(self.values.get_mut(index), new_elem);
+        if self.in_snapshot() {
+            self.undo_log.push(SetElem(index, old_elem));
+        }
+    }
+
+    pub fn start_snapshot(&mut self) -> Snapshot {
+        let length = self.undo_log.len();
+        self.undo_log.push(OpenSnapshot);
+        Snapshot { length: length,
+                   marker: marker::NoCopy }
+    }
+
+    fn assert_open_snapshot(&self, snapshot: &Snapshot) {
+        // Or else there was a failure to follow a stack discipline:
+        assert!(self.undo_log.len() > snapshot.length);
+
+        // Invariant established by start_snapshot():
+        assert!(
+            match *self.undo_log.get(snapshot.length) {
+                OpenSnapshot => true,
+                _ => false
+            });
+    }
+
+    pub fn rollback_to(&mut self, snapshot: Snapshot) {
+        debug!("rollback_to({})", snapshot.length);
+
+        self.assert_open_snapshot(&snapshot);
+
+        while self.undo_log.len() > snapshot.length + 1 {
+            match self.undo_log.pop().unwrap() {
+                OpenSnapshot => {
+                    // This indicates a failure to obey the stack discipline.
+                    fail!("Cannot rollback an uncommited snapshot");
+                }
+
+                CommittedSnapshot => {
+                    // This occurs when there are nested snapshots and
+                    // the inner is commited but outer is rolled back.
+                }
+
+                NewElem(i) => {
+                    self.values.pop();
+                    assert!(self.values.len() == i);
+                }
+
+                SetElem(i, v) => {
+                    *self.values.get_mut(i) = v;
+                }
+
+                Other(u) => {
+                    self.delegate.reverse(&mut self.values, u);
+                }
+            }
+        }
+
+        let v = self.undo_log.pop().unwrap();
+        assert!(match v { OpenSnapshot => true, _ => false });
+        assert!(self.undo_log.len() == snapshot.length);
+    }
+
+    /**
+     * Commits all changes since the last snapshot. Of course, they
+     * can still be undone if there is a snapshot further out.
+     */
+    pub fn commit(&mut self, snapshot: Snapshot) {
+        debug!("commit({})", snapshot.length);
+
+        self.assert_open_snapshot(&snapshot);
+
+        if snapshot.length == 0 {
+            // The root snapshot.
+            self.undo_log.truncate(0);
+        } else {
+            *self.undo_log.get_mut(snapshot.length) = CommittedSnapshot;
+        }
+    }
+}
index 522941cee8c9d877940527c30491c75cf2a35dd5..12d10ec66302ab9cc706a240dbdce3ffb70c4f51 100644 (file)
@@ -8,9 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![allow(non_uppercase_pattern_statics)]
+#![allow(non_uppercase_statics)]
 #![allow(non_camel_case_types)]
-#![allow(non_snake_case_functions)]
+#![allow(non_snake_case)]
 #![allow(dead_code)]
 
 #![crate_name = "rustc_llvm"]
@@ -428,7 +428,10 @@ pub enum DIDescriptorFlags {
       FlagObjcClassComplete  = 1 << 9,
       FlagObjectPointer      = 1 << 10,
       FlagVector             = 1 << 11,
-      FlagStaticMember       = 1 << 12
+      FlagStaticMember       = 1 << 12,
+      FlagIndirectVariable   = 1 << 13,
+      FlagLValueReference    = 1 << 14,
+      FlagRValueReference    = 1 << 15
     }
 }
 
index ee1b51683c2d0c297cb76f5fd895c54fec93235a..f7962455c03e332e7f1b4ec4dfa27867f7c19258 100644 (file)
@@ -108,7 +108,7 @@ fn try_inline_def(cx: &core::DocContext,
         _ => return None,
     };
     let fqn = csearch::get_item_path(tcx, did);
-    cx.inlined.borrow_mut().get_mut_ref().insert(did);
+    cx.inlined.borrow_mut().as_mut().unwrap().insert(did);
     ret.push(clean::Item {
         source: clean::Span::empty(),
         name: Some(fqn.last().unwrap().to_string()),
@@ -142,7 +142,7 @@ pub fn record_extern_fqn(cx: &core::DocContext,
         core::Typed(ref tcx) => {
             let fqn = csearch::get_item_path(tcx, did);
             let fqn = fqn.move_iter().map(|i| i.to_string()).collect();
-            cx.external_paths.borrow_mut().get_mut_ref().insert(did, (fqn, kind));
+            cx.external_paths.borrow_mut().as_mut().unwrap().insert(did, (fqn, kind));
         }
         core::NotTyped(..) => {}
     }
@@ -272,7 +272,7 @@ fn populate_impls(cx: &core::DocContext,
 fn build_impl(cx: &core::DocContext,
               tcx: &ty::ctxt,
               did: ast::DefId) -> Option<clean::Item> {
-    if !cx.inlined.borrow_mut().get_mut_ref().insert(did) {
+    if !cx.inlined.borrow_mut().as_mut().unwrap().insert(did) {
         return None
     }
 
index af4df81f99655f76f4c06500727738206733e7bb..a630d6bb5f67a4777a9d3b39d923c874bf9c7f4d 100644 (file)
@@ -468,7 +468,7 @@ fn clean(&self) -> TyParam {
 
 impl Clean<TyParam> for ty::TypeParameterDef {
     fn clean(&self) -> TyParam {
-        get_cx().external_typarams.borrow_mut().get_mut_ref()
+        get_cx().external_typarams.borrow_mut().as_mut().unwrap()
                 .insert(self.def_id, self.ident.clean());
         TyParam {
             name: self.ident.clean(),
@@ -549,8 +549,8 @@ fn clean(&self) -> TyParamBound {
         };
         let fqn = csearch::get_item_path(tcx, did);
         let fqn = fqn.move_iter().map(|i| i.to_string()).collect();
-        cx.external_paths.borrow_mut().get_mut_ref().insert(did,
-                                                            (fqn, TypeTrait));
+        cx.external_paths.borrow_mut().as_mut().unwrap().insert(did,
+                                                                (fqn, TypeTrait));
         TraitBound(ResolvedPath {
             path: path,
             typarams: None,
@@ -571,7 +571,7 @@ fn clean(&self) -> TyParamBound {
                      .collect::<Vec<String>>();
         let path = external_path(fqn.last().unwrap().as_slice(),
                                  &self.substs);
-        cx.external_paths.borrow_mut().get_mut_ref().insert(self.def_id,
+        cx.external_paths.borrow_mut().as_mut().unwrap().insert(self.def_id,
                                                             (fqn, TypeTrait));
         TraitBound(ResolvedPath {
             path: path,
@@ -1299,7 +1299,7 @@ fn clean(&self) -> Type {
                 };
                 let path = external_path(fqn.last().unwrap().to_string().as_slice(),
                                          substs);
-                get_cx().external_paths.borrow_mut().get_mut_ref()
+                get_cx().external_paths.borrow_mut().as_mut().unwrap()
                                        .insert(did, (fqn, kind));
                 ResolvedPath {
                     path: path,
@@ -2091,7 +2091,7 @@ fn register_def(cx: &core::DocContext, def: def::Def) -> ast::DefId {
     match kind {
         TypeTrait => {
             let t = inline::build_external_trait(tcx, did);
-            cx.external_traits.borrow_mut().get_mut_ref().insert(did, t);
+            cx.external_traits.borrow_mut().as_mut().unwrap().insert(did, t);
         }
         _ => {}
     }
@@ -2158,7 +2158,7 @@ fn lang_struct(did: Option<ast::DefId>, t: ty::t, name: &str,
     let fqn: Vec<String> = fqn.move_iter().map(|i| {
         i.to_string()
     }).collect();
-    get_cx().external_paths.borrow_mut().get_mut_ref()
+    get_cx().external_paths.borrow_mut().as_mut().unwrap()
                            .insert(did, (fqn, TypeStruct));
     ResolvedPath {
         typarams: None,
index cb8be9c899757d4c24a97f6cc3393100c34cba5a..101f1c7460571b63ccf4724aa00357afc3c169ca 100644 (file)
@@ -162,7 +162,7 @@ mod imp {
 
     static LOCKFILE_EXCLUSIVE_LOCK: libc::DWORD = 0x00000002;
 
-    #[allow(non_snake_case_functions)]
+    #[allow(non_snake_case)]
     extern "system" {
         fn LockFileEx(hFile: libc::HANDLE,
                       dwFlags: libc::DWORD,
index 8342b6bd6756a3abd9a0b0da92f9501526c22361..fc8fd0d086bc048dce7e09bad398df158f52286a 100644 (file)
@@ -297,7 +297,7 @@ pub fn run(mut krate: clean::Crate, external_html: &ExternalHtml, dst: Path) ->
     let public_items = public_items.unwrap_or(NodeSet::new());
     let paths: HashMap<ast::DefId, (Vec<String>, ItemType)> =
       analysis.as_ref().map(|a| {
-        let paths = a.external_paths.borrow_mut().take_unwrap();
+        let paths = a.external_paths.borrow_mut().take().unwrap();
         paths.move_iter().map(|(k, (v, t))| {
             (k, (v, match t {
                 clean::TypeStruct => item_type::Struct,
@@ -325,13 +325,13 @@ pub fn run(mut krate: clean::Crate, external_html: &ExternalHtml, dst: Path) ->
         public_items: public_items,
         orphan_methods: Vec::new(),
         traits: analysis.as_ref().map(|a| {
-            a.external_traits.borrow_mut().take_unwrap()
+            a.external_traits.borrow_mut().take().unwrap()
         }).unwrap_or(HashMap::new()),
         typarams: analysis.as_ref().map(|a| {
-            a.external_typarams.borrow_mut().take_unwrap()
+            a.external_typarams.borrow_mut().take().unwrap()
         }).unwrap_or(HashMap::new()),
         inlined: analysis.as_ref().map(|a| {
-            a.inlined.borrow_mut().take_unwrap()
+            a.inlined.borrow_mut().take().unwrap()
         }).unwrap_or(HashSet::new()),
     };
     cache.stack.push(krate.name.clone());
@@ -805,7 +805,7 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
                         v.push(Implementor {
                             def_id: item.def_id,
                             generics: i.generics.clone(),
-                            trait_: i.trait_.get_ref().clone(),
+                            trait_: i.trait_.as_ref().unwrap().clone(),
                             for_: i.for_.clone(),
                             stability: item.stability.clone(),
                         });
@@ -819,16 +819,17 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
         // Index this method for searching later on
         match item.name {
             Some(ref s) => {
-                let parent = match item.inner {
+                let (parent, is_method) = match item.inner {
                     clean::TyMethodItem(..) |
                     clean::StructFieldItem(..) |
                     clean::VariantItem(..) => {
-                        (Some(*self.parent_stack.last().unwrap()),
-                         Some(self.stack.slice_to(self.stack.len() - 1)))
+                        ((Some(*self.parent_stack.last().unwrap()),
+                          Some(self.stack.slice_to(self.stack.len() - 1))),
+                          false)
                     }
                     clean::MethodItem(..) => {
                         if self.parent_stack.len() == 0 {
-                            (None, None)
+                            ((None, None), false)
                         } else {
                             let last = self.parent_stack.last().unwrap();
                             let did = *last;
@@ -844,17 +845,18 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
                                 Some(..) => Some(self.stack.as_slice()),
                                 None => None
                             };
-                            (Some(*last), path)
+                            ((Some(*last), path), true)
                         }
                     }
-                    _ => (None, Some(self.stack.as_slice()))
+                    _ => ((None, Some(self.stack.as_slice())), false)
                 };
                 let hidden_field = match item.inner {
                     clean::StructFieldItem(clean::HiddenStructField) => true,
                     _ => false
                 };
+
                 match parent {
-                    (parent, Some(path)) if !self.privmod && !hidden_field => {
+                    (parent, Some(path)) if is_method || (!self.privmod && !hidden_field) => {
                         self.search_index.push(IndexItem {
                             ty: shortty(&item),
                             name: s.to_string(),
@@ -863,7 +865,7 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
                             parent: parent,
                         });
                     }
-                    (Some(parent), None) if !self.privmod => {
+                    (Some(parent), None) if is_method || (!self.privmod && !hidden_field)=> {
                         if ast_util::is_local(parent) {
                             // We have a parent, but we don't know where they're
                             // defined yet. Wait for later to index this item.
@@ -878,7 +880,7 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
 
         // Keep track of the fully qualified path for this item.
         let pushed = if item.name.is_some() {
-            let n = item.name.get_ref();
+            let n = item.name.as_ref().unwrap();
             if n.len() > 0 {
                 self.stack.push(n.to_string());
                 true
@@ -1125,7 +1127,7 @@ fn render(w: io::File, cx: &Context, it: &clean::Item,
                 if title.len() > 0 {
                     title.push_str("::");
                 }
-                title.push_str(it.name.get_ref().as_slice());
+                title.push_str(it.name.as_ref().unwrap().as_slice());
             }
             title.push_str(" - Rust");
             let tyname = shortty(it).to_static_str();
@@ -1191,10 +1193,10 @@ fn render(w: io::File, cx: &Context, it: &clean::Item,
             // modules are special because they add a namespace. We also need to
             // recurse into the items of the module as well.
             clean::ModuleItem(..) => {
-                let name = item.name.get_ref().to_string();
+                let name = item.name.as_ref().unwrap().to_string();
                 let mut item = Some(item);
                 self.recurse(name, |this| {
-                    let item = item.take_unwrap();
+                    let item = item.take().unwrap();
                     let dst = this.dst.join("index.html");
                     let dst = try!(File::create(&dst));
                     try!(render(dst, this, &item, false));
@@ -1398,7 +1400,7 @@ fn item_path(item: &clean::Item) -> String {
 fn full_path(cx: &Context, item: &clean::Item) -> String {
     let mut s = cx.current.connect("::");
     s.push_str("::");
-    s.push_str(item.name.get_ref().as_slice());
+    s.push_str(item.name.as_ref().unwrap().as_slice());
     return s
 }
 
@@ -1809,7 +1811,7 @@ fn item_enum(w: &mut fmt::Formatter, it: &clean::Item,
         try!(write!(w, " {{\n"));
         for v in e.variants.iter() {
             try!(write!(w, "    "));
-            let name = v.name.get_ref().as_slice();
+            let name = v.name.as_ref().unwrap().as_slice();
             match v.inner {
                 clean::VariantItem(ref var) => {
                     match var.kind {
@@ -2098,7 +2100,7 @@ fn block(w: &mut fmt::Formatter, short: &str, longty: &str,
             try!(write!(w, "<div class='block {}'><h2>{}</h2>", short, longty));
             for item in items.iter() {
                 let curty = shortty(cur).to_static_str();
-                let class = if cur.name.get_ref() == item &&
+                let class = if cur.name.as_ref().unwrap() == item &&
                                short == curty { "current" } else { "" };
                 try!(write!(w, "<a class='{ty} {class}' href='{href}{path}'>\
                                 {name}</a>",
index fb1666bef0d2f467d8757c6b8d6bf244a0e7f596..2f140aa8a6802c2841d08419a4b56821f621f48a 100644 (file)
@@ -385,7 +385,7 @@ fn rust_input(cratefile: &str, externs: core::Externs, matches: &getopts::Matche
 
     // Process all of the crate attributes, extracting plugin metadata along
     // with the passes which we are supposed to run.
-    match krate.module.get_ref().doc_list() {
+    match krate.module.as_ref().unwrap().doc_list() {
         Some(nested) => {
             for inner in nested.iter() {
                 match *inner {
index 28514bec5b49130bedbfa143ce16977bab3b8625..e5de2d195ebd67a2c7a2f2a480b9479ae431181a 100644 (file)
@@ -26,17 +26,7 @@ pub struct Exclusive<T> {
     data: UnsafeCell<T>,
 }
 
-/// stage0 only
-#[cfg(stage0)]
-pub struct ExclusiveGuard<'a, T> {
-    // FIXME #12808: strange name to try to avoid interfering with
-    // field accesses of the contained type via Deref
-    _data: &'a mut T,
-    _guard: mutex::LockGuard<'a>,
-}
-
 /// An RAII guard returned via `lock`
-#[cfg(not(stage0))]
 pub struct ExclusiveGuard<'a, T:'a> {
     // FIXME #12808: strange name to try to avoid interfering with
     // field accesses of the contained type via Deref
index 5ca46a728c346b7d4374ab36bab16f844f7e7a0d..594e50d9913cc45da163bfa71b899c9796b7a3b0 100644 (file)
 #![feature(macro_rules, phase, globs, thread_local, managed_boxes, asm)]
 #![feature(linkage, lang_items, unsafe_destructor, default_type_params)]
 #![feature(import_shadowing)]
-#![feature(issue_5723_bootstrap)]
 #![no_std]
 #![experimental]
 
-// NOTE(stage0, pcwalton): Remove after snapshot.
-#![allow(unknown_features)]
-
 #[phase(plugin, link)] extern crate core;
 extern crate alloc;
 extern crate libc;
index a43920d27a763115e0b9203dcb2ae6572945c5d8..69df8a7fd66e316f696068313972d952246c1c5f 100644 (file)
@@ -11,7 +11,7 @@
 //! Unwind library interface
 
 #![allow(non_camel_case_types)]
-#![allow(non_snake_case_functions)]
+#![allow(non_snake_case)]
 #![allow(dead_code)] // these are just bindings
 
 use libc;
index fedea3c31e0b1f249cb9221a8063bcebd736335e..c71f86bb063b6638499ebcce8d004cd260ea777f 100644 (file)
@@ -144,7 +144,6 @@ unsafe fn get_local_map<'a>() -> Option<&'a mut Map> {
 ///
 /// The task-local data can be accessed through this value, and when this
 /// structure is dropped it will return the borrow on the data.
-#[cfg(not(stage0))]
 pub struct Ref<T:'static> {
     // FIXME #12808: strange names to try to avoid interfering with
     // field accesses of the contained type via Deref
@@ -152,15 +151,6 @@ pub struct Ref<T:'static> {
     _marker: marker::NoSend
 }
 
-/// stage0 only
-#[cfg(stage0)]
-pub struct Ref<T> {
-    // FIXME #12808: strange names to try to avoid interfering with
-    // field accesses of the contained type via Deref
-    _inner: &'static TLDValueBox<T>,
-    _marker: marker::NoSend
-}
-
 fn key_to_key_value<T: 'static>(key: Key<T>) -> uint {
     key as *const _ as uint
 }
@@ -218,10 +208,10 @@ pub fn replace(&'static self, data: Option<T>) -> Option<T> {
                         // Do nothing.
                         None
                     }
-                    (0, Some(newValue)) => {
+                    (0, Some(new_value)) => {
                         // The current value is uninitialized and we're storing a new value.
                         unsafe {
-                            ptr::write(&mut (*value_box).value, newValue);
+                            ptr::write(&mut (*value_box).value, new_value);
                             *(*value_box).refcount.get() = 1;
                             None
                         }
@@ -234,10 +224,10 @@ pub fn replace(&'static self, data: Option<T>) -> Option<T> {
                             Some(ret)
                         }
                     }
-                    (1, Some(newValue)) => {
+                    (1, Some(new_value)) => {
                         // We have an initialized value and we're replacing it.
                         let value_ref = unsafe { &mut (*value_box).value };
-                        let ret = mem::replace(value_ref, newValue);
+                        let ret = mem::replace(value_ref, new_value);
                         // Refcount is already 1, leave it as that.
                         Some(ret)
                     }
index 08da9b8aad1b01424236bd4ddbee55c0ec2c2b71..3aa798aa92a2075e81821e0aefa6bb7b1018234b 100644 (file)
@@ -629,7 +629,7 @@ pub unsafe fn free_cond(h: uint) {
         libc::CloseHandle(block);
     }
 
-    #[allow(non_snake_case_functions)]
+    #[allow(non_snake_case)]
     extern "system" {
         fn CreateEventA(lpSecurityAttributes: LPSECURITY_ATTRIBUTES,
                         bManualReset: BOOL,
index e39071864a7ec9ccba73ac05818d2d61ab30dfe7..9d921943313d8e206d125474e97b1afd9263f69a 100644 (file)
@@ -384,7 +384,7 @@ pub fn maybe_take_runtime<T: 'static>(&mut self) -> Option<Box<T>> {
         //      function, and I would be saddened if more usage of the function
         //      crops up.
         unsafe {
-            let imp = self.imp.take_unwrap();
+            let imp = self.imp.take().unwrap();
             let vtable = mem::transmute::<_, &raw::TraitObject>(&imp).vtable;
             match imp.wrap().downcast::<T>() {
                 Ok(t) => Some(t),
@@ -407,7 +407,7 @@ pub fn maybe_take_runtime<T: 'static>(&mut self) -> Option<Box<T>> {
     pub fn spawn_sibling(mut self: Box<Task>,
                          opts: TaskOpts,
                          f: proc(): Send) {
-        let ops = self.imp.take_unwrap();
+        let ops = self.imp.take().unwrap();
         ops.spawn_sibling(self, opts, f)
     }
 
@@ -417,7 +417,7 @@ pub fn spawn_sibling(mut self: Box<Task>,
     pub fn deschedule(mut self: Box<Task>,
                       amt: uint,
                       f: |BlockedTask| -> ::core::result::Result<(), BlockedTask>) {
-        let ops = self.imp.take_unwrap();
+        let ops = self.imp.take().unwrap();
         ops.deschedule(amt, self, f)
     }
 
@@ -425,7 +425,7 @@ pub fn deschedule(mut self: Box<Task>,
     /// current task can accept a change in scheduling. This function can only
     /// be called on tasks that were previously blocked in `deschedule`.
     pub fn reawaken(mut self: Box<Task>) {
-        let ops = self.imp.take_unwrap();
+        let ops = self.imp.take().unwrap();
         ops.reawaken(self);
     }
 
@@ -433,14 +433,14 @@ pub fn reawaken(mut self: Box<Task>) {
     /// eventually return, but possibly not immediately. This is used as an
     /// opportunity to allow other tasks a chance to run.
     pub fn yield_now(mut self: Box<Task>) {
-        let ops = self.imp.take_unwrap();
+        let ops = self.imp.take().unwrap();
         ops.yield_now(self);
     }
 
     /// Similar to `yield_now`, except that this function may immediately return
     /// without yielding (depending on what the runtime decides to do).
     pub fn maybe_yield(mut self: Box<Task>) {
-        let ops = self.imp.take_unwrap();
+        let ops = self.imp.take().unwrap();
         ops.maybe_yield(self);
     }
 
@@ -448,20 +448,20 @@ pub fn maybe_yield(mut self: Box<Task>) {
     /// stored in the task's runtime. This factory may not always be available,
     /// which is why the return type is `Option`
     pub fn local_io<'a>(&'a mut self) -> Option<LocalIo<'a>> {
-        self.imp.get_mut_ref().local_io()
+        self.imp.as_mut().unwrap().local_io()
     }
 
     /// Returns the stack bounds for this task in (lo, hi) format. The stack
     /// bounds may not be known for all tasks, so the return value may be
     /// `None`.
     pub fn stack_bounds(&self) -> (uint, uint) {
-        self.imp.get_ref().stack_bounds()
+        self.imp.as_ref().unwrap().stack_bounds()
     }
 
     /// Returns whether it is legal for this task to block the OS thread that it
     /// is running on.
     pub fn can_block(&self) -> bool {
-        self.imp.get_ref().can_block()
+        self.imp.as_ref().unwrap().can_block()
     }
 
     /// Consume this task, flagging it as a candidate for destruction.
index 43364466dbe3937913a839b6f5c38ee6c5040f97..6d18ec4f9f5ad81035dc8b103f5441e7a5317ccf 100644 (file)
@@ -128,7 +128,7 @@ pub fn join(mut self) -> T {
         unsafe { imp::join(self.native) };
         self.joined = true;
         assert!(self.packet.is_some());
-        self.packet.take_unwrap()
+        self.packet.take().unwrap()
     }
 }
 
@@ -198,7 +198,7 @@ pub unsafe fn yield_now() {
         SwitchToThread();
     }
 
-    #[allow(non_snake_case_functions)]
+    #[allow(non_snake_case)]
     extern "system" {
         fn CreateThread(lpThreadAttributes: LPSECURITY_ATTRIBUTES,
                         dwStackSize: SIZE_T,
index b9b12686170c0eacb01d2672be93bf231079b57b..6078ed990e41d6dd25c5f56dca10199874b1ddc2 100644 (file)
@@ -83,7 +83,7 @@ pub unsafe fn destroy(key: Key) {
 }
 
 #[cfg(windows)]
-#[allow(non_snake_case_functions)]
+#[allow(non_snake_case)]
 extern "system" {
     fn TlsAlloc() -> DWORD;
     fn TlsFree(dwTlsIndex: DWORD) -> BOOL;
index 0fa89ce989a980c4571aa44f2cd5d7ea96d5057a..664c94250073206610792bf489081a97a58adf44 100644 (file)
@@ -26,13 +26,6 @@ pub struct Access<T> {
     inner: Arc<UnsafeCell<Inner<T>>>,
 }
 
-#[cfg(stage0)]
-pub struct Guard<'a, T> {
-    access: &'a mut Access<T>,
-    missile: Option<HomingMissile>,
-}
-
-#[cfg(not(stage0))]
 pub struct Guard<'a, T:'static> {
     access: &'a mut Access<T>,
     missile: Option<HomingMissile>,
index 6eaab1c0961707347b3ab6070affe7105b3b0a82..8b41219db62f154d6b2837b6524aaf9742f1a359 100644 (file)
@@ -86,7 +86,7 @@ pub fn run(loop_: &Loop, node: Option<&str>, service: Option<&str>,
                 });
 
                 match cx.status {
-                    0 => Ok(accum_addrinfo(cx.addrinfo.get_ref())),
+                    0 => Ok(accum_addrinfo(cx.addrinfo.as_ref().unwrap())),
                     n => Err(UvError(n))
                 }
             }
index 97f95145b8992e6be43e19e5f2303c29d92ac577..8bed4cfb8114b590c800b9ba630928ed4f2694d8 100644 (file)
@@ -136,7 +136,7 @@ fn call(&mut self) {
                 // once
                 let MyCallback(ref mut s) = *self;
                 if s.is_some() {
-                    s.take_unwrap().send(1);
+                    s.take().unwrap().send(1);
                 }
             }
         }
index 6e948992979d86e8c4044be8ea5e9f21c32d427b..561a4dffe82f2f6aef886041d404c698fd4ab14f 100644 (file)
@@ -259,7 +259,7 @@ fn wait_until_woken_after(slot: *mut Option<BlockedTask>,
 
 fn wakeup(slot: &mut Option<BlockedTask>) {
     assert!(slot.is_some());
-    let _ = slot.take_unwrap().wake().map(|t| t.reawaken());
+    let _ = slot.take().unwrap().wake().map(|t| t.reawaken());
 }
 
 pub struct Request {
index 84ef9deaf922fd3555dfed54e55a9a76bf049e2d..09d008a9fa9046e666877fd6aa94c8404c93946d 100644 (file)
@@ -596,7 +596,7 @@ fn recv_from(&mut self, buf: &mut [u8])
                 wait_until_woken_after(&mut cx.task, &loop_, || {
                     unsafe { uvll::set_data_for_uv_handle(handle, &mut cx) }
                 });
-                match cx.result.take_unwrap() {
+                match cx.result.take().unwrap() {
                     (n, _) if n < 0 =>
                         Err(uv_error_to_io_error(UvError(n as c_int))),
                     (n, addr) => Ok((n as uint, addr.unwrap()))
@@ -657,7 +657,7 @@ fn send_to(&mut self, buf: &[u8], dst: rtio::SocketAddr) -> Result<(), IoError>
         // here.
         let data = if guard.can_timeout {Some(Vec::from_slice(buf))} else {None};
         let uv_buf = if guard.can_timeout {
-            slice_to_uv_buf(data.get_ref().as_slice())
+            slice_to_uv_buf(data.as_ref().unwrap().as_slice())
         } else {
             slice_to_uv_buf(buf)
         };
index 0486f376bc80658bfb0c7bf39480e1db195e32e1..4a12f959ad9a530c8616f52c3e83636ccfa0f205 100644 (file)
@@ -297,7 +297,7 @@ fn set_timeout(&mut self, timeout: Option<u64>) {
             self.timer = Some(timer);
         }
 
-        let timer = self.timer.get_mut_ref();
+        let timer = self.timer.as_mut().unwrap();
         timer.stop();
         timer.start(timer_cb, ms, 0);
         self.timeout_state = TimeoutPending;
index c49e557a3237dc4d32aa74e80f094ade61362b90..12831002b65ec3c1730334a4d808d1707623531d 100644 (file)
@@ -161,7 +161,7 @@ pub fn write(&mut self, buf: &[u8], may_timeout: bool) -> Result<(), UvError> {
         // bytes.
         let data = if may_timeout {Some(Vec::from_slice(buf))} else {None};
         let uv_buf = if may_timeout {
-            slice_to_uv_buf(data.get_ref().as_slice())
+            slice_to_uv_buf(data.as_ref().unwrap().as_slice())
         } else {
             slice_to_uv_buf(buf)
         };
index d2482ee6b60f533ec218471b5ba7dc8f5ac752f4..88267c0ac45acc614bcb451b6486aa252ec74e62 100644 (file)
@@ -28,14 +28,6 @@ pub struct AccessTimeout<T> {
     pub access: access::Access<T>,
 }
 
-#[cfg(stage0)]
-pub struct Guard<'a, T> {
-    state: &'a mut TimeoutState,
-    pub access: access::Guard<'a, T>,
-    pub can_timeout: bool,
-}
-
-#[cfg(not(stage0))]
 pub struct Guard<'a, T:'static> {
     state: &'a mut TimeoutState,
     pub access: access::Guard<'a, T>,
@@ -148,7 +140,7 @@ pub fn set_timeout(&mut self, ms: Option<u64>,
             self.timer = Some(timer);
         }
 
-        let timer = self.timer.get_mut_ref();
+        let timer = self.timer.as_mut().unwrap();
         unsafe {
             let cx = uvll::get_data_for_uv_handle(timer.handle);
             let cx = cx as *mut TimerContext;
index f6c1cdd2977549f9a5ca7ebd36092fa85872b4cf..412506604c674cc50bf90e8e1c6939ce47b91e87 100644 (file)
@@ -132,9 +132,9 @@ fn period(&mut self, msecs: u64, cb: Box<Callback + Send>) {
     let _f = ForbidSwitch::new("timer callback can't switch");
     let timer: &mut TimerWatcher = unsafe { UvHandle::from_uv_handle(&handle) };
 
-    match timer.action.take_unwrap() {
+    match timer.action.take().unwrap() {
         WakeTask => {
-            let task = timer.blocker.take_unwrap();
+            let task = timer.blocker.take().unwrap();
             let _ = task.wake().map(|t| t.reawaken());
         }
         CallOnce(mut cb) => { cb.call() }
index 61e52a3abd19cc0e11e2ad50d321c1ad5cc63593..30b172c5b6bf010cf229de1b73e463e3b6190eda 100644 (file)
@@ -66,7 +66,7 @@ fn drop(&mut self) {
         // Lastly, after we've closed the pool of handles we pump the event loop
         // one last time to run any closing callbacks to make sure the loop
         // shuts down cleanly.
-        let handle = self.uvio.handle_pool.get_ref().handle();
+        let handle = self.uvio.handle_pool.as_ref().unwrap().handle();
         drop(self.uvio.handle_pool.take());
         self.run();
 
@@ -132,7 +132,7 @@ pub fn make_handle(&mut self) -> HomeHandle {
         // It's understood by the homing code that the "local id" is just the
         // pointer of the local I/O factory cast to a uint.
         let id: uint = unsafe { mem::transmute_copy(&self) };
-        HomeHandle::new(id, &mut **self.handle_pool.get_mut_ref())
+        HomeHandle::new(id, &mut **self.handle_pool.as_mut().unwrap())
     }
 }
 
index d70b6b4d57bb8367eaff7cbec19a08a35edaa7a4..b37b4588af6307c14c510634f06654bb1aad4405 100644 (file)
@@ -2282,7 +2282,7 @@ impl<
             > ToJson for ( $( $tyvar ),* , ) {
 
             #[inline]
-            #[allow(uppercase_variables)]
+            #[allow(non_snake_case)]
             fn to_json(&self) -> Json {
                 match *self {
                     ($(ref $tyvar),*,) => List(vec![$($tyvar.to_json()),*])
index 44ea56f4c73936bb01a8c92cd66d32392b1d6ae0..5c35ad8523382cef363099662becabdac6c3a677 100644 (file)
@@ -24,7 +24,6 @@
        html_root_url = "http://doc.rust-lang.org/master/",
        html_playground_url = "http://play.rust-lang.org/")]
 #![feature(macro_rules, managed_boxes, default_type_params, phase)]
-#![feature(issue_5723_bootstrap)]
 
 // test harness access
 #[cfg(test)]
index bbaac7a96e9ee5df9dd3e33f3594e5aaffd89dd8..2cda00ad6c4af452719d01c423bb0191b4437547 100644 (file)
@@ -481,7 +481,7 @@ macro_rules! tuple (
     () => ();
     ( $($name:ident,)+ ) => (
         impl<E, D:Decoder<E>,$($name:Decodable<D, E>),*> Decodable<D,E> for ($($name,)*) {
-            #[allow(uppercase_variables)]
+            #[allow(non_snake_case)]
             fn decode(d: &mut D) -> Result<($($name,)*), E> {
                 d.read_tuple(|d, amt| {
                     let mut i = 0;
@@ -496,7 +496,7 @@ fn decode(d: &mut D) -> Result<($($name,)*), E> {
             }
         }
         impl<E, S:Encoder<E>,$($name:Encodable<S, E>),*> Encodable<S, E> for ($($name,)*) {
-            #[allow(uppercase_variables)]
+            #[allow(non_snake_case)]
             fn encode(&self, s: &mut S) -> Result<(), E> {
                 let ($(ref $name,)*) = *self;
                 let mut n = 0;
index 714712d9ebaacfa95b8a36b33dbedca5c83fde0b..1985128c4e307c4017962ce06d88f8be29ce91b0 100644 (file)
@@ -409,32 +409,14 @@ fn can_alias_safehash_as_u64() {
         assert_eq!(size_of::<SafeHash>(), size_of::<u64>())
     }
 
-    /// Note: stage0-specific version that lacks bound.
-    #[cfg(stage0)]
-    pub struct Entries<'a, K, V> {
-        table: &'a RawTable<K, V>,
-        idx: uint,
-        elems_seen: uint,
-    }
-
     /// Iterator over shared references to entries in a table.
-    #[cfg(not(stage0))]
     pub struct Entries<'a, K:'a, V:'a> {
         table: &'a RawTable<K, V>,
         idx: uint,
         elems_seen: uint,
     }
 
-    /// Note: stage0-specific version that lacks bound.
-    #[cfg(stage0)]
-    pub struct MutEntries<'a, K, V> {
-        table: &'a mut RawTable<K, V>,
-        idx: uint,
-        elems_seen: uint,
-    }
-
     /// Iterator over mutable references to entries in a table.
-    #[cfg(not(stage0))]
     pub struct MutEntries<'a, K:'a, V:'a> {
         table: &'a mut RawTable<K, V>,
         idx: uint,
index 16c00d76c54655957413db569a200e899d0899d7..eee3e81f5fc062c8c710d61d479ed682c254f1a6 100644 (file)
@@ -328,7 +328,7 @@ pub unsafe fn close(handle: *mut u8) {
         FreeLibrary(handle as *mut libc::c_void); ()
     }
 
-    #[allow(non_snake_case_functions)]
+    #[allow(non_snake_case)]
     extern "system" {
         fn SetLastError(error: libc::size_t);
         fn LoadLibraryW(name: *const libc::c_void) -> *mut libc::c_void;
index 1d638e498d44928b7d2c18059ba9adb590f12db9..0c63f1a901f5a248cfef32e275e908c1b94c24b6 100644 (file)
@@ -182,7 +182,7 @@ pub fn get_ref<'a>(&'a self) -> &'a W { self.inner.get_ref() }
     pub fn unwrap(mut self) -> W {
         // FIXME(#12628): is failing the right thing to do if flushing fails?
         self.flush_buf().unwrap();
-        self.inner.take_unwrap()
+        self.inner.take().unwrap()
     }
 }
 
index ffbcdd87bfe79a677ca63b7edc02d82b4ff21f02..b61e7c6b44191eaccc2ea668635397a9e998afa1 100644 (file)
 ///
 /// Any error other than `EndOfFile` that is produced by the underlying Reader
 /// is returned by the iterator and should be handled by the caller.
-#[cfg(stage0)]
-pub struct Bytes<'r, T> {
-    reader: &'r mut T,
-}
-
-/// An iterator that reads a single byte on each iteration,
-/// until `.read_byte()` returns `EndOfFile`.
-///
-/// # Notes about the Iteration Protocol
-///
-/// The `Bytes` may yield `None` and thus terminate
-/// an iteration, but continue to yield elements if iteration
-/// is attempted again.
-///
-/// # Error
-///
-/// Any error other than `EndOfFile` that is produced by the underlying Reader
-/// is returned by the iterator and should be handled by the caller.
-#[cfg(not(stage0))]
 pub struct Bytes<'r, T:'r> {
     reader: &'r mut T,
 }
index 38aa58f1c6abfefa4e87e980213c187435c3f742..905012b7bf33abf1ec4024bba353d81f0e83888f 100644 (file)
@@ -976,13 +976,6 @@ unsafe fn slice_vec_capacity<'a, T>(v: &'a mut Vec<T>, start: uint, end: uint) -
     })
 }
 
-/// Note: stage0-specific version that lacks bound.
-#[cfg(stage0)]
-pub struct RefReader<'a, R> {
-    /// The underlying reader which this is referencing
-    inner: &'a mut R
-}
-
 /// A `RefReader` is a struct implementing `Reader` which contains a reference
 /// to another reader. This is often useful when composing streams.
 ///
@@ -1007,7 +1000,6 @@ pub struct RefReader<'a, R> {
 ///
 /// # }
 /// ```
-#[cfg(not(stage0))]
 pub struct RefReader<'a, R:'a> {
     /// The underlying reader which this is referencing
     inner: &'a mut R
@@ -1066,16 +1058,8 @@ fn flush(&mut self) -> IoResult<()> { Ok(()) }
     ///
     /// This function will return any I/O error reported while formatting.
     fn write_fmt(&mut self, fmt: &fmt::Arguments) -> IoResult<()> {
-        // Note: stage0-specific version that lacks bound.
-        #[cfg(stage0)]
-        struct Adaptor<'a, T> {
-            inner: &'a mut T,
-            error: IoResult<()>,
-        }
-
         // Create a shim which translates a Writer to a FormatWriter and saves
         // off I/O errors. instead of discarding them
-        #[cfg(not(stage0))]
         struct Adaptor<'a, T:'a> {
             inner: &'a mut T,
             error: IoResult<()>,
@@ -1335,37 +1319,6 @@ fn flush(&mut self) -> IoResult<()> { self.flush() }
 /// println!("input processed: {}", output.unwrap());
 /// # }
 /// ```
-#[cfg(stage0)]
-pub struct RefWriter<'a, W> {
-    /// The underlying writer which this is referencing
-    inner: &'a mut W
-}
-
-/// A `RefWriter` is a struct implementing `Writer` which contains a reference
-/// to another writer. This is often useful when composing streams.
-///
-/// # Example
-///
-/// ```
-/// # fn main() {}
-/// # fn process_input<R: Reader>(r: R) {}
-/// # fn foo () {
-/// use std::io::util::TeeReader;
-/// use std::io::{stdin, MemWriter};
-///
-/// let mut output = MemWriter::new();
-///
-/// {
-///     // Don't give ownership of 'output' to the 'tee'. Instead we keep a
-///     // handle to it in the outer scope
-///     let mut tee = TeeReader::new(stdin(), output.by_ref());
-///     process_input(tee);
-/// }
-///
-/// println!("input processed: {}", output.unwrap());
-/// # }
-/// ```
-#[cfg(not(stage0))]
 pub struct RefWriter<'a, W:'a> {
     /// The underlying writer which this is referencing
     inner: &'a mut W
@@ -1399,25 +1352,6 @@ impl<T: Reader + Writer> Stream for T {}
 ///
 /// Any error other than `EndOfFile` that is produced by the underlying Reader
 /// is returned by the iterator and should be handled by the caller.
-#[cfg(stage0)]
-pub struct Lines<'r, T> {
-    buffer: &'r mut T,
-}
-
-/// An iterator that reads a line on each iteration,
-/// until `.read_line()` encounters `EndOfFile`.
-///
-/// # Notes about the Iteration Protocol
-///
-/// The `Lines` may yield `None` and thus terminate
-/// an iteration, but continue to yield elements if iteration
-/// is attempted again.
-///
-/// # Error
-///
-/// Any error other than `EndOfFile` that is produced by the underlying Reader
-/// is returned by the iterator and should be handled by the caller.
-#[cfg(not(stage0))]
 pub struct Lines<'r, T:'r> {
     buffer: &'r mut T,
 }
@@ -1445,25 +1379,6 @@ fn next(&mut self) -> Option<IoResult<String>> {
 ///
 /// Any error other than `EndOfFile` that is produced by the underlying Reader
 /// is returned by the iterator and should be handled by the caller.
-#[cfg(stage0)]
-pub struct Chars<'r, T> {
-    buffer: &'r mut T
-}
-
-/// An iterator that reads a utf8-encoded character on each iteration,
-/// until `.read_char()` encounters `EndOfFile`.
-///
-/// # Notes about the Iteration Protocol
-///
-/// The `Chars` may yield `None` and thus terminate
-/// an iteration, but continue to yield elements if iteration
-/// is attempted again.
-///
-/// # Error
-///
-/// Any error other than `EndOfFile` that is produced by the underlying Reader
-/// is returned by the iterator and should be handled by the caller.
-#[cfg(not(stage0))]
 pub struct Chars<'r, T:'r> {
     buffer: &'r mut T
 }
@@ -1697,12 +1612,6 @@ fn incoming<'r>(&'r mut self) -> IncomingConnections<'r, Self> {
     }
 }
 
-/// Note: stage0-specific version that lacks bound on A.
-#[cfg(stage0)]
-pub struct IncomingConnections<'a, A> {
-    inc: &'a mut A,
-}
-
 /// An infinite iterator over incoming connection attempts.
 /// Calling `next` will block the task until a connection is attempted.
 ///
@@ -1710,7 +1619,6 @@ pub struct IncomingConnections<'a, A> {
 /// `Some`. The `Some` contains the `IoResult` representing whether the
 /// connection attempt was successful.  A successful connection will be wrapped
 /// in `Ok`. A failed connection is represented as an `Err`.
-#[cfg(not(stage0))]
 pub struct IncomingConnections<'a, A:'a> {
     inc: &'a mut A,
 }
index a6fdceaa3739fc75d23c435bc4ef82e2e185b980..d787f0e98541c703c81bb914a5a17005b72f69b9 100644 (file)
@@ -97,8 +97,8 @@ pub fn connect(host: &str, port: u16) -> IoResult<TcpStream> {
     /// 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
-    /// will be returned. The error's kind will be `TimedOut`.
+    /// specified elapses before a connection is made an error will be
+    /// returned. The error's kind will be `TimedOut`.
     ///
     /// Note that the `addr` argument may one day be split into a separate host
     /// and port, similar to the API seen in `connect`.
index 3bd31c6a839edf2c7e89528b9703ba4885672886..ea851d445316cd6704fec8d8da6315b159e6444f 100644 (file)
@@ -61,7 +61,7 @@ pub fn connect<P: ToCStr>(path: &P) -> IoResult<UnixStream> {
     /// Connect to a pipe named by `path`, timing out if the specified number of
     /// milliseconds.
     ///
-    /// This function is similar to `connect`, except that if `timeout_ms`
+    /// This function is similar to `connect`, except that if `timeout`
     /// elapses the function will return an error of kind `TimedOut`.
     ///
     /// If a `timeout` with zero or negative duration is specified then
index dd6c1f6016c50023a55d1e941d29f37953ddea2f..c1f4161fe181fc7d1386c47068ee019c0257f644 100644 (file)
@@ -54,7 +54,7 @@
 ///     Err(e) => fail!("failed to execute child: {}", e),
 /// };
 ///
-/// let contents = child.stdout.get_mut_ref().read_to_end();
+/// let contents = child.stdout.as_mut().unwrap().read_to_end();
 /// assert!(child.wait().unwrap().success());
 /// ```
 pub struct Process {
@@ -95,7 +95,7 @@ pub struct Process {
 ///   Err(e) => fail!("failed to execute process: {}", e),
 /// };
 ///
-/// let output = process.stdout.get_mut_ref().read_to_end();
+/// let output = process.stdout.as_mut().unwrap().read_to_end();
 /// ```
 #[deriving(Clone)]
 pub struct Command {
index 2faa23a6aa0a5feb008bd9d79a312a0d26d83f98..8def5d5c99752d76728b0a12cf7af7ed106eaf11 100644 (file)
@@ -70,7 +70,7 @@ pub fn new(suffix: &str) -> Option<TempDir> {
     /// temporary directory is prevented.
     pub fn unwrap(self) -> Path {
         let mut tmpdir = self;
-        tmpdir.path.take_unwrap()
+        tmpdir.path.take().unwrap()
     }
 
     /// Access the wrapped `std::path::Path` to the temporary directory.
index 8c1ed7cfa8f928d60cf3d46ac21e94ee5d13f51c..7fed4c94164b6b75c07be6aa3f4c18093061955a 100644 (file)
 #![feature(macro_rules, globs, managed_boxes, linkage)]
 #![feature(default_type_params, phase, lang_items, unsafe_destructor)]
 #![feature(import_shadowing)]
-#![feature(issue_5723_bootstrap)]
 
 // Don't link to std. We are std.
 #![no_std]
 
-// NOTE(stage0, pcwalton): Remove after snapshot.
-#![allow(unknown_features)]
-
 #![allow(deprecated)]
 #![deny(missing_doc)]
 
index f452f8b23e7bac5fa37c4abbb5fd9a08a1a73658..ea278d55db956fcee2e15c49bada2d454aa83ceb 100644 (file)
@@ -29,7 +29,7 @@
 #![experimental]
 
 #![allow(missing_doc)]
-#![allow(non_snake_case_functions)]
+#![allow(non_snake_case)]
 
 use clone::Clone;
 use collections::{Collection, MutableSeq};
index 6a10be84a621be239c95c5a4770fffdcc675b0ff..86036c2a2dcf2d1eb2807b0129532282d1656ebe 100644 (file)
@@ -825,15 +825,7 @@ pub trait GenericPathUnsafe {
     unsafe fn push_unchecked<T: BytesContainer>(&mut self, path: T);
 }
 
-/// Note: stage0-specific version that lacks bound.
-#[cfg(stage0)]
-pub struct Display<'a, P> {
-    path: &'a P,
-    filename: bool
-}
-
 /// Helper struct for printing paths with format!()
-#[cfg(not(stage0))]
 pub struct Display<'a, P:'a> {
     path: &'a P,
     filename: bool
index 07ad08e1b3c03a94d971939f3df2c2e746870088..95be3191bab493eb121b5933bdac6c2e6cda06f0 100644 (file)
@@ -161,7 +161,7 @@ pub struct OsRng {
     static CRYPT_VERIFYCONTEXT: DWORD = 0xF0000000;
     static NTE_BAD_SIGNATURE: DWORD = 0x80090006;
 
-    #[allow(non_snake_case_functions)]
+    #[allow(non_snake_case)]
     extern "system" {
         fn CryptAcquireContextA(phProv: *mut HCRYPTPROV,
                                 pszContainer: LPCSTR,
index 58b3179a297ce747c0eb2cd6ebb6bb94e63599b7..cf99efd24e62ad92a59fad8e87c5b0dc3f4b9a53 100644 (file)
@@ -543,7 +543,7 @@ fn output(w: &mut Writer, idx: int, addr: *mut libc::c_void,
     /// iOS doesn't use all of them it but adding more
     /// platform-specific configs pollutes the code too much
     #[allow(non_camel_case_types)]
-    #[allow(non_snake_case_functions)]
+    #[allow(non_snake_case)]
     #[allow(dead_code)]
     mod uw {
         use libc;
@@ -657,7 +657,7 @@ pub unsafe fn _Unwind_FindEnclosingFunction(pc: *mut libc::c_void)
 /// copy of that function in my mingw install (maybe it was broken?). Instead,
 /// this takes the route of using StackWalk64 in order to walk the stack.
 #[cfg(windows)]
-#[allow(dead_code, uppercase_variables)]
+#[allow(dead_code, non_snake_case)]
 mod imp {
     use c_str::CString;
     use core_collections::Collection;
@@ -674,7 +674,7 @@ mod imp {
     use str::StrSlice;
     use dynamic_lib::DynamicLibrary;
 
-    #[allow(non_snake_case_functions)]
+    #[allow(non_snake_case)]
     extern "system" {
         fn GetCurrentProcess() -> libc::HANDLE;
         fn GetCurrentThread() -> libc::HANDLE;
@@ -701,30 +701,6 @@ mod imp {
     static IMAGE_FILE_MACHINE_IA64: libc::DWORD = 0x0200;
     static IMAGE_FILE_MACHINE_AMD64: libc::DWORD = 0x8664;
 
-    #[cfg(stage0)]
-    #[packed]
-    struct SYMBOL_INFO {
-        SizeOfStruct: libc::c_ulong,
-        TypeIndex: libc::c_ulong,
-        Reserved: [u64, ..2],
-        Index: libc::c_ulong,
-        Size: libc::c_ulong,
-        ModBase: u64,
-        Flags: libc::c_ulong,
-        Value: u64,
-        Address: u64,
-        Register: libc::c_ulong,
-        Scope: libc::c_ulong,
-        Tag: libc::c_ulong,
-        NameLen: libc::c_ulong,
-        MaxNameLen: libc::c_ulong,
-        // note that windows has this as 1, but it basically just means that
-        // the name is inline at the end of the struct. For us, we just bump
-        // the struct size up to MAX_SYM_NAME.
-        Name: [libc::c_char, ..MAX_SYM_NAME],
-    }
-
-    #[cfg(not(stage0))]
     #[repr(C, packed)]
     struct SYMBOL_INFO {
         SizeOfStruct: libc::c_ulong,
index 155dfbc66c00897ccf8c4ee64ec617f6435042c1..17dba9af9e7b39fc4c455a9659712b028bada3a7 100644 (file)
 
 #![experimental]
 
-use {fmt, i32};
+use {fmt, i64};
 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 a microsecond.
+static NANOS_PER_MICRO: i32 = 1000;
+/// The number of nanosecdons in a millisecond.
+static NANOS_PER_MILLI: i32 = 1000_000;
 /// The number of nanoseconds in seconds.
 static NANOS_PER_SEC: i32 = 1_000_000_000;
+/// The number of microseconds per second.
+static MICROS_PER_SEC: i64 = 1000_000;
+/// The number of milliseconds per second.
+static MILLIS_PER_SEC: i64 = 1000;
+/// The number of seconds in a minute.
+static SECS_PER_MINUTE: i64 = 60;
+/// The number of seconds in an hour.
+static SECS_PER_HOUR: i64 = 3600;
 /// The number of (non-leap) seconds in days.
-static SECS_PER_DAY: i32 = 86400;
+static SECS_PER_DAY: i64 = 86400;
+/// The number of (non-leap) seconds in a week.
+static SECS_PER_WEEK: i64 = 604800;
 
 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(Clone, PartialEq, Eq, PartialOrd, Ord)]
 pub struct Duration {
-    days: i32,
-    secs: u32,  // Always < SECS_PER_DAY
-    nanos: u32, // Always < NANOS_PR_SECOND
+    secs: i64,
+    nanos: i32, // Always 0 <= nanos < NANOS_PER_SEC
 }
 
-/// 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 };
+/// The minimum possible `Duration`: `i64::MIN` milliseconds.
+pub static MIN: Duration = Duration {
+    secs: i64::MIN / MILLIS_PER_SEC - 1,
+    nanos: NANOS_PER_SEC + (i64::MIN % MILLIS_PER_SEC) as i32 * NANOS_PER_MILLI
+};
+
+/// The maximum possible `Duration`: `i64::MAX` milliseconds.
+pub static MAX: Duration = Duration {
+    secs: i64::MAX / MILLIS_PER_SEC,
+    nanos: (i64::MAX % MILLIS_PER_SEC) as i32 * NANOS_PER_MILLI
+};
 
 impl Duration {
     /// Makes a new `Duration` with given number of weeks.
-    /// Equivalent to `Duration::new(weeks * 7, 0, 0)` with overflow checks.
-    ///
+    /// Equivalent to `Duration::seconds(weeks * 7 * 24 * 60 * 60), 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)
+    pub fn weeks(weeks: i64) -> Duration {
+        let secs = weeks.checked_mul(&SECS_PER_WEEK).expect("Duration::weeks out of bounds");
+        Duration::seconds(secs)
     }
 
     /// Makes a new `Duration` with given number of days.
-    /// Equivalent to `Duration::new(days, 0, 0)`.
+    /// Equivalent to `Duration::seconds(days * 24 * 60 * 60)` with overflow checks.
+    /// Fails when the duration is out of bounds.
     #[inline]
-    pub fn days(days: i32) -> Duration {
-        Duration { days: days, secs: 0, nanos: 0 }
+    pub fn days(days: i64) -> Duration {
+        let secs = days.checked_mul(&SECS_PER_DAY).expect("Duration::days out of bounds");
+        Duration::seconds(secs)
     }
 
     /// Makes a new `Duration` with given number of hours.
-    /// Equivalent to `Duration::new(0, hours * 3600, 0)` with overflow checks.
+    /// Equivalent to `Duration::seconds(hours * 60 * 60)` with overflow checks.
+    /// Fails when the duration is out of bounds.
     #[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) }
+    pub fn hours(hours: i64) -> Duration {
+        let secs = hours.checked_mul(&SECS_PER_HOUR).expect("Duration::hours ouf of bounds");
+        Duration::seconds(secs)
     }
 
     /// Makes a new `Duration` with given number of minutes.
-    /// Equivalent to `Duration::new(0, mins * 60, 0)` with overflow checks.
+    /// Equivalent to `Duration::seconds(minutes * 60)` with overflow checks.
+    /// Fails when the duration is out of bounds.
     #[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) }
+    pub fn minutes(minutes: i64) -> Duration {
+        let secs = minutes.checked_mul(&SECS_PER_MINUTE).expect("Duration::minutes out of bounds");
+        Duration::seconds(secs)
     }
 
     /// Makes a new `Duration` with given number of seconds.
-    /// Equivalent to `Duration::new(0, secs, 0)`.
+    /// Fails when the duration is more than `i64::MAX` milliseconds
+    /// or less than `i64::MIN` milliseconds.
     #[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) }
+    pub fn seconds(seconds: i64) -> Duration {
+        let d = Duration { secs: seconds, nanos: 0 };
+        if d < MIN || d > MAX {
+            fail!("Duration::seconds out of bounds");
+        }
+        d
     }
 
     /// 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) }
+    pub fn milliseconds(milliseconds: i64) -> Duration {
+        let (secs, millis) = div_mod_floor_64(milliseconds, MILLIS_PER_SEC);
+        let nanos = millis as i32 * NANOS_PER_MILLI;
+        Duration { secs: secs, nanos: nanos }
     }
 
     /// 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) }
+    pub fn microseconds(microseconds: i64) -> Duration {
+        let (secs, micros) = div_mod_floor_64(microseconds, MICROS_PER_SEC);
+        let nanos = micros as i32 * NANOS_PER_MICRO;
+        Duration { secs: secs, nanos: nanos }
     }
 
     /// 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)
+    pub fn nanoseconds(nanos: i64) -> Duration {
+        let (secs, nanos) = div_mod_floor_64(nanos, NANOS_PER_SEC as i64);
+        Duration { secs: secs, nanos: nanos as i32 }
     }
 
     /// Returns the total number of whole weeks in the duration.
     #[inline]
-    pub fn num_weeks(&self) -> i32 {
+    pub fn num_weeks(&self) -> i64 {
         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
-        }
+    pub fn num_days(&self) -> i64 {
+        self.num_seconds() / SECS_PER_DAY
     }
 
     /// Returns the total number of whole hours in the duration.
     #[inline]
     pub fn num_hours(&self) -> i64 {
-        self.num_seconds() / 3600
+        self.num_seconds() / SECS_PER_HOUR
     }
 
     /// Returns the total number of whole minutes in the duration.
     #[inline]
     pub fn num_minutes(&self) -> i64 {
-        self.num_seconds() / 60
+        self.num_seconds() / SECS_PER_MINUTE
     }
 
     /// 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 secs is negative, nanos should be subtracted from the duration.
+        if self.secs < 0 && self.nanos > 0 {
+            self.secs + 1
+        } else {
+            self.secs
         }
-        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)
+    /// Returns the number of nanoseconds such that
+    /// `nanos_mod_sec() + num_seconds() * NANOS_PER_SEC` is the total number of
+    /// nanoseconds in the duration.
+    fn nanos_mod_sec(&self) -> i32 {
+        if self.secs < 0 && self.nanos > 0 {
+            self.nanos - NANOS_PER_SEC
+        } else {
+            self.nanos
         }
-        if self.days < 0 {-millis(self.to_negated_tuple_64())} else {millis(self.to_tuple_64())}
+    }
+
+    /// Returns the total number of whole milliseconds in the duration,
+    pub fn num_milliseconds(&self) -> i64 {
+        // A proper Duration will not overflow, because MIN and MAX are defined
+        // such that the range is exactly i64 milliseconds.
+        let secs_part = self.num_seconds() * MILLIS_PER_SEC;
+        let nanos_part = self.nanos_mod_sec() / NANOS_PER_MILLI;
+        secs_part + nanos_part as i64
     }
 
     /// Returns the total number of whole microseconds in the duration,
-    /// or `None` on the overflow (exceeding 2^63 microseconds in either directions).
+    /// or `None` on overflow (exceeding 2^63 microseconds in either direction).
     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())
-        }
+        let secs_part = try_opt!(self.num_seconds().checked_mul(&MICROS_PER_SEC));
+        let nanos_part = self.nanos_mod_sec() / NANOS_PER_MICRO;
+        secs_part.checked_add(&(nanos_part as i64))
     }
 
     /// Returns the total number of whole nanoseconds in the duration,
-    /// or `None` on the overflow (exceeding 2^63 nanoseconds in either directions).
+    /// or `None` on overflow (exceeding 2^63 nanoseconds in either direction).
     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())
-        }
+        let secs_part = try_opt!(self.num_seconds().checked_mul(&(NANOS_PER_SEC as i64)));
+        let nanos_part = self.nanos_mod_sec();
+        secs_part.checked_add(&(nanos_part as i64))
     }
 }
 
@@ -244,156 +213,130 @@ impl num::Bounded for Duration {
 impl num::Zero for Duration {
     #[inline]
     fn zero() -> Duration {
-        Duration { days: 0, secs: 0, nanos: 0 }
+        Duration { secs: 0, nanos: 0 }
     }
 
     #[inline]
     fn is_zero(&self) -> bool {
-        self.days == 0 && self.secs == 0 && self.nanos == 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
+        if self.nanos == 0 {
+            Duration { secs: -self.secs, nanos: 0 }
+        } else {
+            Duration { secs: -self.secs - 1, nanos: NANOS_PER_SEC - self.nanos }
+        }
     }
 }
 
 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;
+        if nanos >= NANOS_PER_SEC {
+            nanos -= NANOS_PER_SEC;
             secs += 1;
         }
-        if secs >= SECS_PER_DAY as u32 {
-            secs -= SECS_PER_DAY as u32;
-            days += 1;
-        }
-        Duration { days: days, secs: secs, nanos: nanos }
+        Duration { 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 secs = try_opt!(self.secs.checked_add(&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));
+        if nanos >= NANOS_PER_SEC {
+            nanos -= NANOS_PER_SEC;
+            secs = try_opt!(secs.checked_add(&1));
         }
-        Some(Duration { days: days, secs: secs, nanos: nanos })
+        let d = Duration { secs: secs, nanos: nanos };
+        // Even if d is within the bounds of i64 seconds,
+        // it might still overflow i64 milliseconds.
+        if d < MIN || d > MAX { None } else { Some(d) }
     }
 }
 
 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;
+        let mut secs = self.secs - rhs.secs;
+        let mut nanos = self.nanos - rhs.nanos;
         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 }
+        Duration { secs: secs, nanos: nanos }
     }
 }
 
 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;
+        let mut secs = try_opt!(self.secs.checked_sub(&rhs.secs));
+        let mut nanos = self.nanos - rhs.nanos;
         if nanos < 0 {
             nanos += NANOS_PER_SEC;
-            secs -= 1;
-        }
-        if secs < 0 {
-            secs += SECS_PER_DAY;
-            days = try_opt!(days.checked_sub(&1));
+            secs = try_opt!(secs.checked_sub(&1));
         }
-        Some(Duration { days: days, secs: secs as u32, nanos: nanos as u32 })
+        let d = Duration { secs: secs, nanos: nanos };
+        // Even if d is within the bounds of i64 seconds,
+        // it might still overflow i64 milliseconds.
+        if d < MIN || d > MAX { None } else { Some(d) }
     }
 }
 
 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 }
+        // Multiply nanoseconds as i64, because it cannot overflow that way.
+        let total_nanos = self.nanos as i64 * *rhs as i64;
+        let (extra_secs, nanos) = div_mod_floor_64(total_nanos, NANOS_PER_SEC as i64);
+        let secs = self.secs * *rhs as i64 + extra_secs;
+        Duration { secs: secs, nanos: nanos as i32 }
     }
 }
 
 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 }
+        let mut secs = self.secs / *rhs as i64;
+        let carry = self.secs - secs * *rhs as i64;
+        let extra_nanos = carry * NANOS_PER_SEC as i64 / *rhs as i64;
+        let mut nanos = self.nanos / *rhs + extra_nanos as i32;
+        if nanos >= NANOS_PER_SEC {
+            nanos -= NANOS_PER_SEC;
+            secs += 1;
+        }
+        if nanos < 0 {
+            nanos += NANOS_PER_SEC;
+            secs -= 1;
+        }
+        Duration { secs: secs, nanos: nanos }
     }
 }
 
 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;
+        let days = self.num_days();
+        let secs = self.secs - days * SECS_PER_DAY;
+        let hasdate = days != 0;
+        let hastime = (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));
+            try!(write!(f, "{}D", 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));
+                try!(write!(f, "T{}S", secs));
+            } else if self.nanos % NANOS_PER_MILLI == 0 {
+                try!(write!(f, "T{}.{:03}S", secs, self.nanos / NANOS_PER_MILLI));
+            } else if self.nanos % NANOS_PER_MICRO == 0 {
+                try!(write!(f, "T{}.{:06}S", secs, self.nanos / NANOS_PER_MICRO));
             } else {
-                try!(write!(f, "T{}.{:09}S", self.secs, self.nanos));
+                try!(write!(f, "T{}.{:09}S", secs, self.nanos));
             }
         }
         Ok(())
@@ -401,34 +344,6 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 }
 
 // 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))
@@ -459,7 +374,7 @@ fn div_rem_64(this: i64, other: i64) -> (i64, i64) {
 
 #[cfg(test)]
 mod tests {
-    use super::{Duration, MIN_DAYS, MAX_DAYS, MIN, MAX};
+    use super::{Duration, MIN, MAX};
     use {i32, i64};
     use num::{Zero, CheckedAdd, CheckedSub};
     use option::{Some, None};
@@ -475,7 +390,8 @@ fn test_duration() {
                    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),
+        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)),
@@ -492,10 +408,8 @@ fn test_duration_num_days() {
         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);
+        assert_eq!(Duration::days(i32::MAX as i64).num_days(), i32::MAX as i64);
+        assert_eq!(Duration::days(i32::MIN as i64).num_days(), i32::MIN as i64);
     }
 
     #[test]
@@ -508,10 +422,6 @@ fn test_duration_num_seconds() {
         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]
@@ -524,10 +434,10 @@ fn test_duration_num_milliseconds() {
         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);
+        assert_eq!(Duration::milliseconds(i64::MAX).num_milliseconds(), i64::MAX);
+        assert_eq!(Duration::milliseconds(i64::MIN).num_milliseconds(), i64::MIN);
+        assert_eq!(MAX.num_milliseconds(), i64::MAX);
+        assert_eq!(MIN.num_milliseconds(), i64::MIN);
     }
 
     #[test]
@@ -540,19 +450,19 @@ fn test_duration_num_microseconds() {
         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!(Duration::microseconds(i64::MAX).num_microseconds(), Some(i64::MAX));
+        assert_eq!(Duration::microseconds(i64::MIN).num_microseconds(), Some(i64::MIN));
         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(),
+        assert_eq!(Duration::days(i64::MAX / MICROS_PER_DAY).num_microseconds(),
                    Some(i64::MAX / MICROS_PER_DAY * MICROS_PER_DAY));
-        assert_eq!(Duration::days((i64::MIN / MICROS_PER_DAY) as i32).num_microseconds(),
+        assert_eq!(Duration::days(i64::MIN / MICROS_PER_DAY).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);
+        assert_eq!(Duration::days(i64::MAX / MICROS_PER_DAY + 1).num_microseconds(), None);
+        assert_eq!(Duration::days(i64::MIN / MICROS_PER_DAY - 1).num_microseconds(), None);
     }
 
     #[test]
@@ -561,30 +471,32 @@ fn test_duration_num_nanoseconds() {
         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!(Duration::nanoseconds(i64::MAX).num_nanoseconds(), Some(i64::MAX));
+        assert_eq!(Duration::nanoseconds(i64::MIN).num_nanoseconds(), Some(i64::MIN));
         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(),
+        assert_eq!(Duration::days(i64::MAX / NANOS_PER_DAY).num_nanoseconds(),
                    Some(i64::MAX / NANOS_PER_DAY * NANOS_PER_DAY));
-        assert_eq!(Duration::days((i64::MIN / NANOS_PER_DAY) as i32).num_nanoseconds(),
+        assert_eq!(Duration::days(i64::MIN / NANOS_PER_DAY).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);
+        assert_eq!(Duration::days(i64::MAX / NANOS_PER_DAY + 1).num_nanoseconds(), None);
+        assert_eq!(Duration::days(i64::MIN / NANOS_PER_DAY - 1).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::milliseconds(i64::MAX - 1).checked_add(&Duration::microseconds(999)),
+                   Some(Duration::milliseconds(i64::MAX - 2) + Duration::microseconds(1999)));
+        assert!(Duration::milliseconds(i64::MAX).checked_add(&Duration::microseconds(1000))
+                                                .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());
+        assert_eq!(Duration::milliseconds(i64::MIN).checked_sub(&Duration::milliseconds(0)),
+                   Some(Duration::milliseconds(i64::MIN)));
+        assert!(Duration::milliseconds(i64::MIN).checked_sub(&Duration::milliseconds(1))
+                                                .is_none());
     }
 
     #[test]
@@ -601,6 +513,8 @@ fn test_duration_mul() {
                    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));
+        assert_eq!(Duration::milliseconds(1500) * -2, Duration::seconds(-3));
+        assert_eq!(Duration::milliseconds(-1500) * 2, Duration::seconds(-3));
     }
 
     #[test]
@@ -612,6 +526,13 @@ fn test_duration_div() {
         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::seconds(1) / 3, Duration::nanoseconds(333_333_333));
+        assert_eq!(Duration::seconds(4) / 3, Duration::nanoseconds(1_333_333_333));
+        assert_eq!(Duration::seconds(-1) / 2, Duration::milliseconds(-500));
+        assert_eq!(Duration::seconds(1) / -2, Duration::milliseconds(-500));
+        assert_eq!(Duration::seconds(-1) / -2, Duration::milliseconds(500));
+        assert_eq!(Duration::seconds(-4) / 3, Duration::nanoseconds(-1_333_333_333));
+        assert_eq!(Duration::seconds(-4) / -3, Duration::nanoseconds(1_333_333_333));
     }
 
     #[test]
index 16f6eea6144f8afd4f694f7e0e362d188f26645c..c8b86c47c90b5c43f09dd3ad0c86fb9e19aefba5 100644 (file)
@@ -386,18 +386,10 @@ pub struct Receiver<T> {
 /// whenever `next` is called, waiting for a new message, and `None` will be
 /// returned when the corresponding channel has hung up.
 #[unstable]
-#[cfg(not(stage0))]
 pub struct Messages<'a, T:'a> {
     rx: &'a Receiver<T>
 }
 
-/// Stage0 only
-#[cfg(stage0)]
-#[unstable]
-pub struct Messages<'a, T> {
-    rx: &'a Receiver<T>
-}
-
 /// The sending-half of Rust's asynchronous channel type. This half can only be
 /// owned by one task, but it can be cloned to send to other tasks.
 #[unstable]
index 188bea83ac80f9968af8faf30b7cfdd81c44a9ea..5b3cf33ebf0934d9a1128b4599cf4087b110b218 100644 (file)
@@ -107,7 +107,7 @@ pub fn send(&mut self, t: T) -> Result<(), T> {
             // Couldn't send the data, the port hung up first. Return the data
             // back up the stack.
             DISCONNECTED => {
-                Err(self.data.take_unwrap())
+                Err(self.data.take().unwrap())
             }
 
             // Not possible, these are one-use channels
@@ -244,7 +244,7 @@ pub fn drop_port(&mut self) {
             // There's data on the channel, so make sure we destroy it promptly.
             // This is why not using an arc is a little difficult (need the box
             // to stay valid while we take the data).
-            DATA => { self.data.take_unwrap(); }
+            DATA => { self.data.take().unwrap(); }
 
             // We're the only ones that can block on this port
             _ => unreachable!()
index dc9891dd1eedda6af0161dcd9d34d3767e15c263..669c1c958b8842461f410a1337b9e2d13e9c888a 100644 (file)
@@ -76,7 +76,6 @@ pub struct Select {
 /// A handle to a receiver which is currently a member of a `Select` set of
 /// receivers.  This handle is used to keep the receiver in the set as well as
 /// interact with the underlying receiver.
-#[cfg(not(stage0))]
 pub struct Handle<'rx, T:'rx> {
     /// The ID of this handle, used to compare against the return value of
     /// `Select::wait()`
@@ -92,23 +91,6 @@ pub struct Handle<'rx, T:'rx> {
     rx: &'rx Receiver<T>,
 }
 
-/// Stage0 only
-#[cfg(stage0)]
-pub struct Handle<'rx, T> {
-    /// The ID of this handle, used to compare against the return value of
-    /// `Select::wait()`
-    id: uint,
-    selector: &'rx Select,
-    next: *mut Handle<'static, ()>,
-    prev: *mut Handle<'static, ()>,
-    added: bool,
-    packet: &'rx Packet+'rx,
-
-    // due to our fun transmutes, we be sure to place this at the end. (nothing
-    // previous relies on T)
-    rx: &'rx Receiver<T>,
-}
-
 struct Packets { cur: *mut Handle<'static, ()> }
 
 #[doc(hidden)]
index 1ee9fef191866cdeffbbe693edd6cafbdaebd5b3..528a15cf6d7658a10bb26332d814e10794eee340 100644 (file)
@@ -347,7 +347,7 @@ pub fn drop_port(&self) {
         let waiter = match mem::replace(&mut state.blocker, NoneBlocked) {
             NoneBlocked => None,
             BlockedSender(task) => {
-                *state.canceled.take_unwrap() = true;
+                *state.canceled.take().unwrap() = true;
                 Some(task)
             }
             BlockedReceiver(..) => unreachable!(),
@@ -434,7 +434,7 @@ fn dequeue(&mut self) -> T {
         let start = self.start;
         self.size -= 1;
         self.start = (self.start + 1) % self.buf.len();
-        self.buf.get_mut(start).take_unwrap()
+        self.buf.get_mut(start).take().unwrap()
     }
 
     fn size(&self) -> uint { self.size }
@@ -481,7 +481,7 @@ fn dequeue(&mut self) -> Option<BlockedTask> {
         }
         unsafe {
             (*node).next = 0 as *mut Node;
-            Some((*node).task.take_unwrap())
+            Some((*node).task.take().unwrap())
         }
     }
 }
index c2744751ee5c265b6ce79f30583047dba7e3d45c..e0acce1cd945acebe9839cec9b46567cc0103014 100644 (file)
 
 #![feature(phase, globs, macro_rules, unsafe_destructor)]
 #![feature(import_shadowing)]
-#![feature(issue_5723_bootstrap)]
 #![deny(missing_doc)]
 #![no_std]
 
-// NOTE(stage0, pcwalton): Remove after snapshot.
-#![allow(unknown_features)]
-
 #[phase(plugin, link)] extern crate core;
 extern crate alloc;
 extern crate collections;
index e1cae6c62d5287f0254b7b4733e31c7014a234a9..08421d24fbbff7d2dcfd0498f37f9d781f034100 100644 (file)
@@ -180,7 +180,6 @@ pub struct Mutex<T> {
 
 /// An guard which is created by locking a mutex. Through this guard the
 /// underlying data can be accessed.
-#[cfg(not(stage0))]
 pub struct MutexGuard<'a, T:'a> {
     // FIXME #12808: strange name to try to avoid interfering with
     // field accesses of the contained type via Deref
@@ -190,17 +189,6 @@ pub struct MutexGuard<'a, T:'a> {
     pub cond: Condvar<'a>,
 }
 
-/// stage0 only
-#[cfg(stage0)]
-pub struct MutexGuard<'a, T> {
-    // FIXME #12808: strange name to try to avoid interfering with
-    // field accesses of the contained type via Deref
-    _data: &'a mut T,
-    /// Inner condition variable connected to the locked mutex that this guard
-    /// was created from. This can be used for atomic-unlock-and-deschedule.
-    pub cond: Condvar<'a>,
-}
-
 impl<T: Send> Mutex<T> {
     /// Creates a new mutex to protect the user-supplied data.
     pub fn new(user_data: T) -> Mutex<T> {
@@ -292,7 +280,6 @@ pub struct RWLock<T> {
 
 /// A guard which is created by locking an rwlock in write mode. Through this
 /// guard the underlying data can be accessed.
-#[cfg(not(stage0))]
 pub struct RWLockWriteGuard<'a, T:'a> {
     // FIXME #12808: strange name to try to avoid interfering with
     // field accesses of the contained type via Deref
@@ -302,20 +289,8 @@ pub struct RWLockWriteGuard<'a, T:'a> {
     pub cond: Condvar<'a>,
 }
 
-/// stage0 only
-#[cfg(stage0)]
-pub struct RWLockWriteGuard<'a, T> {
-    // FIXME #12808: strange name to try to avoid interfering with
-    // field accesses of the contained type via Deref
-    _data: &'a mut T,
-    /// Inner condition variable that can be used to sleep on the write mode of
-    /// this rwlock.
-    pub cond: Condvar<'a>,
-}
-
 /// A guard which is created by locking an rwlock in read mode. Through this
 /// guard the underlying data can be accessed.
-#[cfg(not(stage0))]
 pub struct RWLockReadGuard<'a, T:'a> {
     // FIXME #12808: strange names to try to avoid interfering with
     // field accesses of the contained type via Deref
@@ -323,15 +298,6 @@ pub struct RWLockReadGuard<'a, T:'a> {
     _guard: raw::RWLockReadGuard<'a>,
 }
 
-/// Stage0 only
-#[cfg(stage0)]
-pub struct RWLockReadGuard<'a, T> {
-    // FIXME #12808: strange names to try to avoid interfering with
-    // field accesses of the contained type via Deref
-    _data: &'a T,
-    _guard: raw::RWLockReadGuard<'a>,
-}
-
 impl<T: Send + Sync> RWLock<T> {
     /// Create a reader/writer lock with the supplied data.
     pub fn new(user_data: T) -> RWLock<T> {
index 012574808f3c673e97531c5e670cf323f49c796f..ad2539fc260082c9028ece661853ad1bf1a8034c 100644 (file)
@@ -122,7 +122,7 @@ pub fn pop(&self) -> PopResult<T> {
                 *self.tail.get() = next;
                 assert!((*tail).value.is_none());
                 assert!((*next).value.is_some());
-                let ret = (*next).value.take_unwrap();
+                let ret = (*next).value.take().unwrap();
                 let _: Box<Node<T>> = mem::transmute(tail);
                 return Data(ret);
             }
index 98934d87474e9b1a579c7ca87ebb43640556155f..b259eb7e579ec0f382e263a25bc1ac1563e53706 100644 (file)
@@ -103,13 +103,6 @@ struct SemInner<Q> {
 }
 
 #[must_use]
-#[cfg(stage0)]
-struct SemGuard<'a, Q> {
-    sem: &'a Sem<Q>,
-}
-
-#[must_use]
-#[cfg(not(stage0))]
 struct SemGuard<'a, Q:'a> {
     sem: &'a Sem<Q>,
 }
@@ -266,7 +259,7 @@ pub fn wait_on(&self, condvar_id: uint) {
             // signaller already sent -- I mean 'unconditionally' in contrast
             // with acquire().)
             (|| {
-                let _ = wait_end.take_unwrap().recv();
+                let _ = wait_end.take().unwrap().recv();
             }).finally(|| {
                 // Reacquire the condvar.
                 match self.order {
@@ -325,7 +318,7 @@ pub fn broadcast_on(&self, condvar_id: uint) -> uint {
                               condvar_id,
                               "cond.signal_on()",
                               || {
-                queue.take_unwrap().broadcast()
+                queue.take().unwrap().broadcast()
             })
         }
     }
index 3280829f958352d781785ea693d72a0d7ee8427f..6d9b8821bd8903cc58767594388f35a725c044ee 100644 (file)
@@ -157,7 +157,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-#[allow(non_snake_case_functions)]
+#[allow(non_snake_case)]
 #[test]
 fn lookup_Rust() {
     let abi = lookup("Rust");
index d574a02fded22088bff65c640359c16d77ac5a65..68a1c521f1942e3be312a816969d38811a35c75b 100644 (file)
@@ -29,7 +29,7 @@
 // FIXME(eddyb) #10676 use Rc<T> in the future.
 pub type P<T> = Gc<T>;
 
-#[allow(non_snake_case_functions)]
+#[allow(non_snake_case)]
 /// Construct a P<T> from a T value.
 pub fn P<T: 'static>(value: T) -> P<T> {
     box(GC) value
@@ -524,7 +524,8 @@ pub enum Expr_ {
     ExprLit(Gc<Lit>),
     ExprCast(Gc<Expr>, P<Ty>),
     ExprIf(Gc<Expr>, P<Block>, Option<Gc<Expr>>),
-    ExprWhile(Gc<Expr>, P<Block>),
+    // FIXME #6993: change to Option<Name> ... or not, if these are hygienic.
+    ExprWhile(Gc<Expr>, P<Block>, Option<Ident>),
     // FIXME #6993: change to Option<Name> ... or not, if these are hygienic.
     ExprForLoop(Gc<Pat>, Gc<Expr>, P<Block>, Option<Ident>),
     // Conditionless loop (can be exited with break, cont, or ret)
index 993c5ce676ae83551ee85a23e2e8fa42b7ae5f9e..d1f78c71e19df97ac9fab9536e3092a4f98ae888 100644 (file)
@@ -68,12 +68,7 @@ fn next(&mut self) -> Option<PathElem> {
     }
 }
 
-#[cfg(stage0)]
-#[deriving(Clone)]
-pub struct Values<'a, T>(pub slice::Items<'a, T>);
-
 // HACK(eddyb) move this into libstd (value wrapper for slice::Items).
-#[cfg(not(stage0))]
 #[deriving(Clone)]
 pub struct Values<'a, T:'a>(pub slice::Items<'a, T>);
 
@@ -483,15 +478,6 @@ pub fn node_to_string(&self, id: NodeId) -> String {
     }
 }
 
-#[cfg(stage0)]
-pub struct NodesMatchingSuffix<'a, S> {
-    map: &'a Map,
-    item_name: &'a S,
-    in_which: &'a [S],
-    idx: NodeId,
-}
-
-#[cfg(not(stage0))]
 pub struct NodesMatchingSuffix<'a, S:'a> {
     map: &'a Map,
     item_name: &'a S,
index cc586a3affac3f0d80d9d68c5ce5a580e7a20371..8ef13ef2604241476872ac3748d668d399d07df7 100644 (file)
@@ -349,14 +349,6 @@ pub trait IdVisitingOperation {
 /// A visitor that applies its operation to all of the node IDs
 /// in a visitable thing.
 
-#[cfg(stage0)]
-pub struct IdVisitor<'a, O> {
-    pub operation: &'a O,
-    pub pass_through_items: bool,
-    pub visited_outermost: bool,
-}
-
-#[cfg(not(stage0))]
 pub struct IdVisitor<'a, O:'a> {
     pub operation: &'a O,
     pub pass_through_items: bool,
index 9dbea1c9ac2c66c8d9b68692834834af10f2a72a..d0f3cf6f9d7ad4a70c71bac1de7d5bdc8084a2d3 100644 (file)
@@ -66,6 +66,12 @@ fn expand_expr(e: Gc<ast::Expr>, fld: &mut MacroExpander) -> Gc<ast::Expr> {
             }
         }
 
+        ast::ExprWhile(cond, body, opt_ident) => {
+            let cond = fld.fold_expr(cond);
+            let (body, opt_ident) = expand_loop_block(body, opt_ident, fld);
+            fld.cx.expr(e.span, ast::ExprWhile(cond, body, opt_ident))
+        }
+
         ast::ExprLoop(loop_block, opt_ident) => {
             let (loop_block, opt_ident) = expand_loop_block(loop_block, opt_ident, fld);
             fld.cx.expr(e.span, ast::ExprLoop(loop_block, opt_ident))
index be1c0d967116ad4fdc43b67c224c6542e5b13f41..7deabed04b824505eb4c754f9ce60f35f2bffa5b 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -1132,18 +1132,20 @@ pub fn noop_fold_expr<T: Folder>(e: Gc<Expr>, folder: &mut T) -> Gc<Expr> {
                    folder.fold_block(tr),
                    fl.map(|x| folder.fold_expr(x)))
         }
-        ExprWhile(cond, body) => {
-            ExprWhile(folder.fold_expr(cond), folder.fold_block(body))
+        ExprWhile(cond, body, opt_ident) => {
+            ExprWhile(folder.fold_expr(cond),
+                      folder.fold_block(body),
+                      opt_ident.map(|i| folder.fold_ident(i)))
         }
-        ExprForLoop(pat, iter, body, ref maybe_ident) => {
+        ExprForLoop(pat, iter, body, ref opt_ident) => {
             ExprForLoop(folder.fold_pat(pat),
                         folder.fold_expr(iter),
                         folder.fold_block(body),
-                        maybe_ident.map(|i| folder.fold_ident(i)))
+                        opt_ident.map(|i| folder.fold_ident(i)))
         }
         ExprLoop(body, opt_ident) => {
             ExprLoop(folder.fold_block(body),
-                     opt_ident.map(|x| folder.fold_ident(x)))
+                     opt_ident.map(|i| folder.fold_ident(i)))
         }
         ExprMatch(expr, ref arms) => {
             ExprMatch(folder.fold_expr(expr),
index 9bbd6b2a36ea3c3db327c4eaa58ca1e92bd41ae6..254428486f8b4f7026a33ebd3280e969d75aa34f 100644 (file)
 
 #![feature(macro_rules, globs, managed_boxes, default_type_params, phase)]
 #![feature(quote, struct_variant, unsafe_destructor, import_shadowing)]
-#![feature(issue_5723_bootstrap)]
 #![allow(deprecated)]
 
-// NOTE(stage0, pcwalton): Remove after snapshot.
-#![allow(unknown_features)]
-
 extern crate fmt_macros;
 extern crate debug;
 #[phase(plugin, link)] extern crate log;
index 37bda15ac2c414301c76b705712dcf5cf17a555a..60f244011529012856cd3653ecdd3a537f22de1c 100644 (file)
@@ -2094,19 +2094,22 @@ pub fn parse_bottom_expr(&mut self) -> Gc<Expr> {
                     return self.parse_for_expr(None);
                 }
                 if self.eat_keyword(keywords::While) {
-                    return self.parse_while_expr();
+                    return self.parse_while_expr(None);
                 }
                 if Parser::token_is_lifetime(&self.token) {
                     let lifetime = self.get_lifetime();
                     self.bump();
                     self.expect(&token::COLON);
+                    if self.eat_keyword(keywords::While) {
+                        return self.parse_while_expr(Some(lifetime))
+                    }
                     if self.eat_keyword(keywords::For) {
                         return self.parse_for_expr(Some(lifetime))
                     }
                     if self.eat_keyword(keywords::Loop) {
                         return self.parse_loop_expr(Some(lifetime))
                     }
-                    self.fatal("expected `for` or `loop` after a label")
+                    self.fatal("expected `while`, `for`, or `loop` after a label")
                 }
                 if self.eat_keyword(keywords::Loop) {
                     return self.parse_loop_expr(None);
@@ -2762,12 +2765,12 @@ pub fn parse_for_expr(&mut self, opt_ident: Option<ast::Ident>) -> Gc<Expr> {
         self.mk_expr(lo, hi, ExprForLoop(pat, expr, loop_block, opt_ident))
     }
 
-    pub fn parse_while_expr(&mut self) -> Gc<Expr> {
+    pub fn parse_while_expr(&mut self, opt_ident: Option<ast::Ident>) -> Gc<Expr> {
         let lo = self.last_span.lo;
         let cond = self.parse_expr_res(RESTRICT_NO_STRUCT_LITERAL);
         let body = self.parse_block();
         let hi = body.span.hi;
-        return self.mk_expr(lo, hi, ExprWhile(cond, body));
+        return self.mk_expr(lo, hi, ExprWhile(cond, body, opt_ident));
     }
 
     pub fn parse_loop_expr(&mut self, opt_ident: Option<ast::Ident>) -> Gc<Expr> {
index da265d8125088242b8bc4f968350efe29b2a642a..afea9e01de986aa10a1716e128f3215a86f54c4b 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -33,6 +33,8 @@
 use std::mem;
 
 pub enum AnnNode<'a> {
+    NodeIdent(&'a ast::Ident),
+    NodeName(&'a ast::Name),
     NodeBlock(&'a ast::Block),
     NodeItem(&'a ast::Item),
     NodeExpr(&'a ast::Expr),
@@ -1438,7 +1440,11 @@ pub fn print_expr(&mut self, expr: &ast::Expr) -> IoResult<()> {
             ast::ExprIf(ref test, ref blk, elseopt) => {
                 try!(self.print_if(&**test, &**blk, elseopt, false));
             }
-            ast::ExprWhile(ref test, ref blk) => {
+            ast::ExprWhile(ref test, ref blk, opt_ident) => {
+                for ident in opt_ident.iter() {
+                    try!(self.print_ident(*ident));
+                    try!(self.word_space(":"));
+                }
                 try!(self.head("while"));
                 try!(self.print_expr(&**test));
                 try!(space(&mut self.s));
@@ -1725,14 +1731,16 @@ pub fn print_decl(&mut self, decl: &ast::Decl) -> IoResult<()> {
     pub fn print_ident(&mut self, ident: ast::Ident) -> IoResult<()> {
         if self.encode_idents_with_hygiene {
             let encoded = ident.encode_with_hygiene();
-            word(&mut self.s, encoded.as_slice())
+            try!(word(&mut self.s, encoded.as_slice()))
         } else {
-            word(&mut self.s, token::get_ident(ident).get())
+            try!(word(&mut self.s, token::get_ident(ident).get()))
         }
+        self.ann.post(self, NodeIdent(&ident))
     }
 
     pub fn print_name(&mut self, name: ast::Name) -> IoResult<()> {
-        word(&mut self.s, token::get_name(name).get())
+        try!(word(&mut self.s, token::get_name(name).get()));
+        self.ann.post(self, NodeName(&name))
     }
 
     pub fn print_for_decl(&mut self, loc: &ast::Local,
index 7a35d82b0e430fc8f56f82612ca77c494afc7dc7..65e192e8437f3a6e9490b73d7f5401ea698097c3 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -775,7 +775,7 @@ pub fn walk_expr<E: Clone, V: Visitor<E>>(visitor: &mut V, expression: &Expr, en
             visitor.visit_block(&**if_block, env.clone());
             walk_expr_opt(visitor, optional_else, env.clone())
         }
-        ExprWhile(ref subexpression, ref block) => {
+        ExprWhile(ref subexpression, ref block, _) => {
             visitor.visit_expr(&**subexpression, env.clone());
             visitor.visit_block(&**block, env.clone())
         }
index 64a61cc6b3bdcd8d53fcf21745aa188d24b67285..cd61f9bb35ed12c2f16c2f22295c629b7206b908 100644 (file)
@@ -27,7 +27,7 @@ pub struct WinConsole<T> {
     background: color::Color,
 }
 
-#[allow(non_snake_case_functions)]
+#[allow(non_snake_case)]
 #[link(name = "kernel32")]
 extern "system" {
     fn SetConsoleTextAttribute(handle: libc::HANDLE, attr: libc::WORD) -> libc::BOOL;
index d6010cd8d7bfbbd467664ccb9b1c237e2d44cf1e..135b267262cc670b9c9c686cec62c649a7f0e7f5 100644 (file)
@@ -10,7 +10,7 @@
 
 // NOTE: The following code was generated by "src/etc/unicode.py", do not edit directly
 
-#![allow(missing_doc, non_uppercase_statics, non_snake_case_functions)]
+#![allow(missing_doc, non_uppercase_statics, non_snake_case)]
 
 fn bsearch_range_table(c: char, r: &'static [(char,char)]) -> bool {
     use core::cmp::{Equal, Less, Greater};
index 0f75cf86c18da443e3917ac909e17b3354f84ec7..91e7589b8caebdb24b7988a1db08272a5b720f51 100644 (file)
@@ -33,7 +33,7 @@ pub fn is_alphabetic(c: char) -> bool {
 /// 'XID_Start' is a Unicode Derived Property specified in
 /// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications),
 /// mostly similar to ID_Start but modified for closure under NFKx.
-#[allow(non_snake_case_functions)]
+#[allow(non_snake_case)]
 pub fn is_XID_start(c: char) -> bool    { derived_property::XID_Start(c) }
 
 /// Returns whether the specified `char` satisfies the 'XID_Continue' Unicode property
@@ -41,7 +41,7 @@ pub fn is_XID_start(c: char) -> bool    { derived_property::XID_Start(c) }
 /// 'XID_Continue' is a Unicode Derived Property specified in
 /// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications),
 /// mostly similar to 'ID_Continue' but modified for closure under NFKx.
-#[allow(non_snake_case_functions)]
+#[allow(non_snake_case)]
 pub fn is_XID_continue(c: char) -> bool { derived_property::XID_Continue(c) }
 
 ///
@@ -174,7 +174,7 @@ pub trait UnicodeChar {
     /// 'XID_Start' is a Unicode Derived Property specified in
     /// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications),
     /// mostly similar to ID_Start but modified for closure under NFKx.
-    #[allow(non_snake_case_functions)]
+    #[allow(non_snake_case)]
     fn is_XID_start(&self) -> bool;
 
     /// Returns whether the specified `char` satisfies the 'XID_Continue'
@@ -183,7 +183,7 @@ pub trait UnicodeChar {
     /// 'XID_Continue' is a Unicode Derived Property specified in
     /// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications),
     /// mostly similar to 'ID_Continue' but modified for closure under NFKx.
-    #[allow(non_snake_case_functions)]
+    #[allow(non_snake_case)]
     fn is_XID_continue(&self) -> bool;
 
 
index c71cf5557e35f89f293056daa90de5762d71af75..88f9c2b4ce39db28e04856b7c65aec1bcf962570 100644 (file)
@@ -245,7 +245,7 @@ fn next(&mut self) -> Option<&'a str> {
             // looking up each character twice.
             cat = match self.cat {
                 None => gr::grapheme_category(ch),
-                _ => self.cat.take_unwrap()
+                _ => self.cat.take().unwrap()
             };
 
             if match cat {
@@ -345,7 +345,7 @@ fn next_back(&mut self) -> Option<&'a str> {
             // cached category, if any
             cat = match self.catb {
                 None => gr::grapheme_category(ch),
-                _ => self.catb.take_unwrap()
+                _ => self.catb.take().unwrap()
             };
 
             // a matching state machine that runs *backwards* across an input string
index f34f1c1371fe7353ec10c3912e5bf6664e6cd148..9fcaa30cf5f762de96d76bb02ab99aa757ccd129 100644 (file)
@@ -1,3 +1,11 @@
+S 2014-08-29 6025926
+  freebsd-x86_64 285330b798eefcc929fc94c9d0604b6172ce3309
+  linux-i386 5b57ab2dc32952dc78551a955f3c1746b2d915a3
+  linux-x86_64 2624aeac3fe1b2359b61c1109e4708680e237ca5
+  macos-i386 deffce32408b023bcda84f6ce338ca3de02f406b
+  macos-x86_64 8ef7351e34fc1583570d752d223ddc6eb68ef27b
+  winnt-i386 c2dfa9a358de8cc554007addbc09e3e43d49aec6
+
 S 2014-08-17 a86d9ad
   freebsd-x86_64 f49e0c8e64c8a60dc47df9965974d2a98ef70b34
   linux-i386 8f2c5f6a1b6504ee63de73c7a53aee1e4b07bca5
diff --git a/src/test/auxiliary/lint_group_plugin_test.rs b/src/test/auxiliary/lint_group_plugin_test.rs
new file mode 100644 (file)
index 0000000..4790ae1
--- /dev/null
@@ -0,0 +1,53 @@
+// 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.
+
+// force-host
+
+#![feature(phase, plugin_registrar)]
+
+extern crate syntax;
+
+// Load rustc as a plugin to get macros
+#[phase(plugin, link)]
+extern crate rustc;
+
+use syntax::ast;
+use syntax::parse::token;
+use rustc::lint::{Context, LintPass, LintPassObject, LintArray};
+use rustc::plugin::Registry;
+
+declare_lint!(TEST_LINT, Warn,
+              "Warn about items named 'lintme'")
+
+declare_lint!(PLEASE_LINT, Warn,
+              "Warn about items named 'pleaselintme'")
+
+struct Pass;
+
+impl LintPass for Pass {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(TEST_LINT, PLEASE_LINT)
+    }
+
+    fn check_item(&mut self, cx: &Context, it: &ast::Item) {
+        let name = token::get_ident(it.ident);
+        if name.get() == "lintme" {
+            cx.span_lint(TEST_LINT, it.span, "item is named 'lintme'");
+        } else if name.get() == "pleaselintme" {
+            cx.span_lint(PLEASE_LINT, it.span, "item is named 'pleaselintme'");
+        }
+    }
+}
+
+#[plugin_registrar]
+pub fn plugin_registrar(reg: &mut Registry) {
+    reg.register_lint_pass(box Pass as LintPassObject);
+    reg.register_lint_group("lint_me", vec![TEST_LINT, PLEASE_LINT]);
+}
index a0ff7736b5c7f8ec8a15b7512b9e094dccd8d8d6..ebd5aa4b37bec1790284b61ba2adee2f6ef42551 100644 (file)
@@ -52,8 +52,8 @@ fn thread_ring(i: uint, count: uint, num_chan: pipe, num_port: pipe) {
     // Send/Receive lots of messages.
     for j in range(0u, count) {
         //println!("task %?, iter %?", i, j);
-        let num_chan2 = num_chan.take_unwrap();
-        let num_port2 = num_port.take_unwrap();
+        let num_chan2 = num_chan.take().unwrap();
+        let num_port2 = num_port.take().unwrap();
         send(&num_chan2, i * j);
         num_chan = Some(num_chan2);
         let _n = recv(&num_port2);
index 6512ecfb3e26063e618a6bbf4b9d2a15e4331c62..764d80984c3040189c86de52ca7a4501c3ebbb1b 100644 (file)
@@ -52,8 +52,8 @@ fn thread_ring(i: uint, count: uint, num_chan: pipe, num_port: pipe) {
     // Send/Receive lots of messages.
     for j in range(0u, count) {
         //println!("task %?, iter %?", i, j);
-        let num_chan2 = num_chan.take_unwrap();
-        let num_port2 = num_port.take_unwrap();
+        let num_chan2 = num_chan.take().unwrap();
+        let num_port2 = num_port.take().unwrap();
         send(&num_chan2, i * j);
         num_chan = Some(num_chan2);
         let _n = recv(&num_port2);
index 2cbbfdb23fe0234df5135867b0a7300cd4766781..49c12334844762b93853ba666c819928ae1aeb73 100644 (file)
@@ -11,7 +11,7 @@
 // no-pretty-expanded FIXME #15189
 
 #![feature(phase)]
-#![allow(non_snake_case_functions)]
+#![allow(non_snake_case)]
 #[phase(plugin)] extern crate green;
 
 use std::from_str::FromStr;
index 7129d4993b74f1cb1116b8f588713aee2b9eafb2..728f6bd043a2680eaaa7fd3c7ba5fa97b4241586 100644 (file)
@@ -10,7 +10,7 @@
 
 // ignore-pretty very bad with line comments
 
-#![allow(non_snake_case_functions)]
+#![allow(non_snake_case)]
 
 use std::io;
 use std::io::stdio::StdReader;
diff --git a/src/test/compile-fail-fulldeps/lint-group-plugin-deny-cmdline.rs b/src/test/compile-fail-fulldeps/lint-group-plugin-deny-cmdline.rs
new file mode 100644 (file)
index 0000000..5edaa78
--- /dev/null
@@ -0,0 +1,27 @@
+// 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:lint_group_plugin_test.rs
+// ignore-stage1
+// compile-flags: -D lint-me
+
+#![feature(phase)]
+
+#[phase(plugin)]
+extern crate lint_group_plugin_test;
+
+fn lintme() { } //~ ERROR item is named 'lintme'
+
+fn pleaselintme() { } //~ ERROR item is named 'pleaselintme'
+
+pub fn main() {
+    lintme();
+    pleaselintme();
+}
index cdfb569762de35a68af839830fb700b0a3e37e23..6360a9135005c3d465703f1045c5cb4c9c42140e 100644 (file)
@@ -23,8 +23,7 @@ fn a(x: &int) {
     let c1 = || set(&mut *x);
     //~^ ERROR cannot borrow
     let c2 = || set(&mut *x);
-    //~^ ERROR closure requires unique access to `x`
-    //~^^ ERROR cannot borrow
+    //~^ ERROR cannot borrow
 }
 
 fn main() {
index 0e1c4758c1be10a23e43e79df363cb01ea6d7ca5..05cadfd536567aeadfd4d7302958c20cb1a05b34 100644 (file)
@@ -17,7 +17,7 @@ struct S<'a> {
 
 fn copy_borrowed_ptr<'a,'b>(p: &'a mut S<'b>) -> S<'b> {
     S { pointer: &mut *p.pointer }
-    //~^ ERROR lifetime of `p` is too short to guarantee its contents can be safely reborrowed
+    //~^ ERROR cannot infer
 }
 
 fn main() {
index ba268cf3d64792920bb790516e41391f6515a5f6..67d07ca4bd1fbc1af752187118f18f9509fa1e95 100644 (file)
@@ -24,8 +24,7 @@ pub fn main() {
         x: 1,
         y: 2,
     };
-    for x in bogus {    //~ ERROR does not implement the `Iterator` trait
+    for x in bogus { //~ ERROR has type `MyStruct` which does not implement the `Iterator` trait
         drop(x);
     }
 }
-
diff --git a/src/test/compile-fail/for-loop-type-error.rs b/src/test/compile-fail/for-loop-type-error.rs
new file mode 100644 (file)
index 0000000..7f0e401
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub fn main() {
+    let x = () + (); //~ ERROR binary operation
+
+    // this shouldn't have a flow-on error:
+    for _ in x {}
+}
index 8ae20dfde9123e68e869ee3a6e53a176de7b5032..995ae7b3d44e70632669f9bc53a91942b38de75b 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 fn test<'x>(x: &'x int) {
-    drop::< <'z>|&'z int| -> &'z int>(|z| {
+    drop::< <'z>|&'z int| -> &'z int >(|z| {
         x
         //~^ ERROR cannot infer an appropriate lifetime
     });
index 7159aa17623c086f862dbeb3c24f91c3b274ec11..2d7458944269cb24efe2ed5796c76b944e59fc0c 100644 (file)
@@ -12,7 +12,7 @@ fn main() {
   let x = [1,2];
   let y = match x {
     [] => None,
-//~^ ERROR expected `[<generic integer #1>, .. 2]`, found a fixed vector pattern of size 0
+//~^ ERROR expected `[<generic integer #0>, .. 2]`, found a fixed vector pattern of size 0
     [a,_] => Some(a)
   };
 }
index d4b31066e5ac216f8e0375481c9f623af2f2fde8..305b1fe2ad7ded015e6c6b79eba5fdf60ded30de 100644 (file)
@@ -12,6 +12,6 @@
 
 fn main() {
     let Slice { data: data, len: len } = "foo";
-    //~^ ERROR mismatched types: expected `&'static str`, found a structure pattern
+    //~^ ERROR mismatched types: expected `&str`, found a structure pattern
 }
 
index afb413584a4814e01bf87a902252393c1375e91d..5d07472afbb2572ea7b1f4b13ed9803304c5a086 100644 (file)
@@ -22,5 +22,5 @@ fn bind<B>(&self, f: |A| -> Vec<B> ) {
 }
 fn main() {
     ["hi"].bind(|x| [x] );
-    //~^ ERROR type `[&'static str, .. 1]` does not implement any method in scope named `bind`
+    //~^ ERROR type `[&str, .. 1]` does not implement any method in scope named `bind`
 }
diff --git a/src/test/compile-fail/kindck-inherited-copy-bound.rs b/src/test/compile-fail/kindck-inherited-copy-bound.rs
new file mode 100644 (file)
index 0000000..2520ed2
--- /dev/null
@@ -0,0 +1,30 @@
+// 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.
+
+// Test that Copy bounds inherited by trait are checked.
+
+use std::any::Any;
+use std::any::AnyRefExt;
+
+trait Foo : Copy {
+}
+
+impl<T:Copy> Foo for T {
+}
+
+fn take_param<T:Foo>(foo: &T) { }
+
+fn main() {
+    let x = box 3i;
+    take_param(&x); //~ ERROR does not fulfill `Copy`
+
+    let y = &x;
+    let z = &x as &Foo; //~ ERROR does not fulfill `Copy`
+}
diff --git a/src/test/compile-fail/kindck-send-object1.rs b/src/test/compile-fail/kindck-send-object1.rs
new file mode 100644 (file)
index 0000000..6a90fd5
--- /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.
+
+// Test which object types are considered sendable. This test
+// is broken into two parts because some errors occur in distinct
+// phases in the compiler. See kindck-send-object2.rs as well!
+
+fn assert_send<T:Send>() { }
+trait Dummy { }
+
+// careful with object types, who knows what they close over...
+fn test51<'a>() {
+    assert_send::<&'a Dummy>(); //~ ERROR does not fulfill the required lifetime
+}
+fn test52<'a>() {
+    assert_send::<&'a Dummy+Send>(); //~ ERROR does not fulfill the required lifetime
+}
+
+// ...unless they are properly bounded
+fn test60() {
+    assert_send::<&'static Dummy+Send>();
+}
+fn test61() {
+    assert_send::<Box<Dummy+Send>>();
+}
+
+// closure and object types can have lifetime bounds which make
+// them not ok
+fn test_70<'a>() {
+    assert_send::<proc():'a>(); //~ ERROR does not fulfill the required lifetime
+}
+
+fn test_71<'a>() {
+    assert_send::<Box<Dummy+'a>>(); //~ ERROR does not fulfill the required lifetime
+}
+
+fn main() { }
diff --git a/src/test/compile-fail/kindck-send-object2.rs b/src/test/compile-fail/kindck-send-object2.rs
new file mode 100644 (file)
index 0000000..7500647
--- /dev/null
@@ -0,0 +1,32 @@
+// 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.
+
+// Continue kindck-send-object1.rs.
+
+fn assert_send<T:Send>() { }
+trait Dummy { }
+
+fn test50() {
+    assert_send::<&'static Dummy>(); //~ ERROR does not fulfill `Send`
+}
+
+fn test53() {
+    assert_send::<Box<Dummy>>(); //~ ERROR does not fulfill `Send`
+}
+
+// ...unless they are properly bounded
+fn test60() {
+    assert_send::<&'static Dummy+Send>();
+}
+fn test61() {
+    assert_send::<Box<Dummy+Send>>();
+}
+
+fn main() { }
diff --git a/src/test/compile-fail/kindck-send-owned.rs b/src/test/compile-fail/kindck-send-owned.rs
new file mode 100644 (file)
index 0000000..0eed056
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test which of the builtin types are considered sendable.
+
+fn assert_send<T:Send>() { }
+
+// owned content are ok
+fn test30() { assert_send::<Box<int>>(); }
+fn test31() { assert_send::<String>(); }
+fn test32() { assert_send::<Vec<int> >(); }
+
+// but not if they own a bad thing
+fn test40<'a>(_: &'a int) {
+    assert_send::<Box<&'a int>>(); //~ ERROR does not fulfill the required lifetime
+}
+
+fn main() { }
diff --git a/src/test/compile-fail/kindck-send-region-pointers.rs b/src/test/compile-fail/kindck-send-region-pointers.rs
new file mode 100644 (file)
index 0000000..cc46d7f
--- /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.
+
+// Test that borrowed pointers are not sendable unless 'static.
+
+fn assert_send<T:Send>() { }
+
+// lifetime pointers with 'static lifetime are ok
+fn test01() { assert_send::<&'static int>(); }
+fn test02() { assert_send::<&'static str>(); }
+fn test03() { assert_send::<&'static [int]>(); }
+
+// whether or not they are mutable
+fn test10() { assert_send::<&'static mut int>(); }
+
+// otherwise lifetime pointers are not ok
+fn test20<'a>(_: &'a int) {
+    assert_send::<&'a int>(); //~ ERROR does not fulfill the required lifetime
+}
+fn test21<'a>(_: &'a int) {
+    assert_send::<&'a str>(); //~ ERROR does not fulfill the required lifetime
+}
+fn test22<'a>(_: &'a int) {
+    assert_send::<&'a [int]>(); //~ ERROR does not fulfill the required lifetime
+}
+
+fn main() { }
diff --git a/src/test/compile-fail/kindck-send-unsafe.rs b/src/test/compile-fail/kindck-send-unsafe.rs
new file mode 100644 (file)
index 0000000..a9bbfcf
--- /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.
+
+fn assert_send<T:Send>() { }
+
+// unsafe ptrs are ok unless they point at unsendable things
+fn test70() {
+    assert_send::<*mut int>();
+}
+fn test71<'a>() {
+    assert_send::<*mut &'a int>(); //~ ERROR does not fulfill the required lifetime
+}
+
+fn main() {
+}
diff --git a/src/test/compile-fail/lint-group-style.rs b/src/test/compile-fail/lint-group-style.rs
new file mode 100644 (file)
index 0000000..63d65fc
--- /dev/null
@@ -0,0 +1,40 @@
+// 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.
+
+#![deny(bad_style)]
+//~^ NOTE lint level defined here
+#![allow(dead_code)]
+
+fn CamelCase() {} //~ ERROR function `CamelCase` should have a snake case name
+
+#[allow(bad_style)]
+mod test {
+    fn CamelCase() {}
+
+    #[forbid(bad_style)]
+    //~^ NOTE lint level defined here
+    //~^^ NOTE lint level defined here
+    mod bad {
+        fn CamelCase() {} //~ ERROR function `CamelCase` should have a snake case name
+
+        static bad: int = 1; //~ ERROR static constant `bad` should have an uppercase name
+    }
+
+    mod warn {
+        #![warn(bad_style)]
+        //~^ NOTE lint level defined here
+
+        fn CamelCase() {} //~ WARN function `CamelCase` should have a snake case name
+
+        struct snake_case; //~ WARN type `snake_case` should have a camel case name
+    }
+}
+
+fn main() {}
index f33c7956a1418f45fab80b5a6ab7cc4d62aa558e..6ce63e2ecdb77dd7db13b861f6163bf4612d3346 100644 (file)
@@ -32,6 +32,8 @@ enum Foo5 {
 trait foo6 { //~ ERROR trait `foo6` should have a camel case name such as `Foo6`
 }
 
+fn f<ty>(_: ty) {} //~ ERROR type parameter `ty` should have a camel case name such as `Ty`
+
 #[repr(C)]
 struct foo7 {
     bar: int,
index 4253286996c5a9efca64688a18992d3e84618b6b..ccbe1f006e308e2514076e8274d0d27c64a4af9f 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![deny(non_snake_case_functions)]
+#![deny(non_snake_case)]
 #![allow(dead_code)]
 
 struct Foo;
diff --git a/src/test/compile-fail/lint-non-snake-case-lifetimes.rs b/src/test/compile-fail/lint-non-snake-case-lifetimes.rs
new file mode 100644 (file)
index 0000000..64669d9
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![deny(non_snake_case)]
+#![allow(dead_code)]
+
+fn f<'FooBar>( //~ ERROR lifetime `'FooBar` should have a snake case name such as `'foo_bar`
+    _: &'FooBar ()
+) {}
+
+fn main() { }
diff --git a/src/test/compile-fail/lint-non-snake-case-modules.rs b/src/test/compile-fail/lint-non-snake-case-modules.rs
new file mode 100644 (file)
index 0000000..5bc8469
--- /dev/null
@@ -0,0 +1,20 @@
+// 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.
+
+#![deny(non_snake_case)]
+#![allow(dead_code)]
+
+mod FooBar { //~ ERROR module `FooBar` should have a snake case name such as `foo_bar`
+    pub struct S;
+}
+
+fn f(_: FooBar::S) { }
+
+fn main() { }
index 279cf6d94cbf13626c615f6e6a5237d33e62bc82..902cd63b1e78cdc2f5e584c09a840d578cc6f3d0 100644 (file)
 // ignore-tidy-linelength
 
 #![allow(dead_code)]
-#![deny(uppercase_variables)]
+#![deny(non_snake_case)]
 
 use std::io::File;
 use std::io::IoError;
 
 struct Something {
-    X: uint //~ ERROR structure field names should start with a lowercase character
+    X: uint //~ ERROR structure field `X` should have a snake case name such as `x`
 }
 
-fn test(Xx: uint) { //~ ERROR variable names should start with a lowercase character
+fn test(Xx: uint) { //~ ERROR variable `Xx` should have a snake case name such as `xx`
     println!("{}", Xx);
 }
 
 fn main() {
-    let Test: uint = 0; //~ ERROR variable names should start with a lowercase character
+    let Test: uint = 0; //~ ERROR variable `Test` should have a snake case name such as `test`
     println!("{}", Test);
 
     let mut f = File::open(&Path::new("something.txt"));
@@ -33,7 +33,7 @@ fn main() {
     match f.read(buff) {
         Ok(cnt) => println!("read this many bytes: {}", cnt),
         Err(IoError{ kind: EndOfFile, .. }) => println!("Got end of file: {}", EndOfFile.to_string()),
-                        //~^ ERROR variable names should start with a lowercase character
+        //~^ ERROR variable `EndOfFile` should have a snake case name such as `end_of_file`
     }
 
     test(1);
index b5ffa3546c19d02cbbaefc8810762a19aa4a94d3..a5dce6ecc6f3e14d0bcdf6f370c741839a256af4 100644 (file)
@@ -11,8 +11,9 @@
 // Issue #7526: lowercase static constants in patterns look like bindings
 
 #![allow(dead_code)]
-#![deny(non_uppercase_pattern_statics)]
+#![deny(non_uppercase_statics)]
 
+#[allow(non_uppercase_statics)]
 pub static a : int = 97;
 
 fn f() {
@@ -25,6 +26,7 @@ fn f() {
 }
 
 mod m {
+    #[allow(non_uppercase_statics)]
     pub static aha : int = 7;
 }
 
index 68e198ea5b7a070f8efca32169eb3bec80b48042..e13a6b211a5038b7526b532bcb9adde394c2c02f 100644 (file)
@@ -17,12 +17,10 @@ struct a_class<'a> { x:&'a int }
 
 fn a_fn1<'a,'b>(e: an_enum<'a>) -> an_enum<'b> {
     return e; //~ ERROR mismatched types: expected `an_enum<'b>`, found `an_enum<'a>`
-    //~^ ERROR cannot infer
 }
 
 fn a_fn3<'a,'b>(e: a_class<'a>) -> a_class<'b> {
     return e; //~ ERROR mismatched types: expected `a_class<'b>`, found `a_class<'a>`
-    //~^ ERROR cannot infer
 }
 
 fn main() { }
index d752bc97cac79b2cf5d814378a0cf966d5efb059..66103eb95888ac941e1cf123c8641d2b0978c584 100644 (file)
@@ -15,7 +15,6 @@ fn with_int(f: |x: &int|) {
 
 fn main() {
     let mut x = None;
-         //~^ ERROR lifetime of variable does not enclose its declaration
-         //~^^ ERROR type of expression contains references that are not valid during the expression
     with_int(|y| x = Some(y));
+         //~^ ERROR cannot infer
 }
index eb72b4b0c53219a532c62ea42451f3302417d09b..fee84cf9656d1ceaae73f4fb5d02a75c55a63579 100644 (file)
@@ -14,6 +14,6 @@ fn with_int(f: |x: &int|) {
 }
 
 fn main() {
-    let mut x: Option<&int> = None;   //~ ERROR cannot infer
-    with_int(|y| x = Some(y));
+    let mut x: Option<&int> = None;
+    with_int(|y| x = Some(y));   //~ ERROR cannot infer
 }
index adef1f901fd0adf4e15f655cd5c57103b5f72de8..b73b5e0649ff5a76a6a7afd612c613183786acbc 100644 (file)
@@ -27,7 +27,7 @@ fn with<R:Deref>(f: |x: &int| -> R) -> int {
 }
 
 fn return_it() -> int {
-    with(|o| o) //~ ERROR cannot infer an appropriate lifetime
+    with(|o| o) //~ ERROR cannot infer
 }
 
 fn main() {
index e5444aadc1ca64d650992cf50ca746a7e337a714..8af341e3ace42b9d949319d92199f98008180d8b 100644 (file)
@@ -22,7 +22,6 @@ struct not_parameterized2 {
 
 fn take1<'a>(p: parameterized1) -> parameterized1<'a> { p }
 //~^ ERROR mismatched types
-//~^^ ERROR cannot infer
 
 fn take3(p: not_parameterized1) -> not_parameterized1 { p }
 fn take4(p: not_parameterized2) -> not_parameterized2 { p }
index d3e9c1f6ea848478afa3bbe7a0ac1f1fc7a75e57..4dd028b78845996e18acfdb6f65d1a0446260bac 100644 (file)
@@ -33,7 +33,6 @@ fn use_<'short,'long>(c: Contravariant<'short>,
     // covariant with respect to its parameter 'a.
 
     let _: Contravariant<'long> = c; //~ ERROR mismatched types
-    //~^ ERROR  cannot infer an appropriate lifetime
 }
 
 fn main() {}
index 2d3ca17301220ed81aa7af9249e3abaeeb536517..93c06aecd30ecffdaf5ad5d732071fa44c06f59b 100644 (file)
@@ -30,7 +30,6 @@ fn use_<'short,'long>(c: Covariant<'long>,
     // contravariant with respect to its parameter 'a.
 
     let _: Covariant<'short> = c; //~ ERROR mismatched types
-    //~^ ERROR  cannot infer an appropriate lifetime
 }
 
 fn main() {}
index cadf66c3286869fdc72776e5f97682a1769323cd..b84f13ec37feb44d16654af4e6bf795c965046f3 100644 (file)
@@ -23,11 +23,9 @@ struct indirect2<'a> {
 }
 
 fn take_direct<'a,'b>(p: direct<'a>) -> direct<'b> { p } //~ ERROR mismatched types
-//~^ ERROR cannot infer
 
 fn take_indirect1(p: indirect1) -> indirect1 { p }
 
 fn take_indirect2<'a,'b>(p: indirect2<'a>) -> indirect2<'b> { p } //~ ERROR mismatched types
-//~^ ERROR cannot infer
 
 fn main() {}
index 519223e97535e58e06bfdbf03de6ea3317c945a5..e862b36dcd1680a2ddd7d8408fd921c13676a125 100644 (file)
@@ -22,18 +22,17 @@ struct c<'a> {
 }
 
 trait set_f<'a> {
-    fn set_f_ok(&self, b: Gc<b<'a>>);
-    fn set_f_bad(&self, b: Gc<b>);
+    fn set_f_ok(&mut self, b: Gc<b<'a>>);
+    fn set_f_bad(&mut self, b: Gc<b>);
 }
 
 impl<'a> set_f<'a> for c<'a> {
-    fn set_f_ok(&self, b: Gc<b<'a>>) {
+    fn set_f_ok(&mut self, b: Gc<b<'a>>) {
         self.f = b;
     }
 
-    fn set_f_bad(&self, b: Gc<b>) {
+    fn set_f_bad(&mut self, b: Gc<b>) {
         self.f = b; //~ ERROR mismatched types: expected `Gc<Gc<&'a int>>`, found `Gc<Gc<&int>>`
-        //~^ ERROR cannot infer
     }
 }
 
diff --git a/src/test/compile-fail/regions-infer-proc-static-upvar.rs b/src/test/compile-fail/regions-infer-proc-static-upvar.rs
new file mode 100644 (file)
index 0000000..7fe8529
--- /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.
+
+// Test that, when a variable of type `&T` is captured inside a proc,
+// we correctly infer/require that its lifetime is 'static.
+
+fn foo(_p: proc():'static) { }
+
+static i: int = 3;
+
+fn capture_local() {
+    let x = 3i;
+    let y = &x; //~ ERROR `x` does not live long enough
+    foo(proc() {
+        let _a = *y;
+    });
+}
+
+fn capture_static() {
+    // Legal because &i can have static lifetime:
+    let y = &i;
+    foo(proc() {
+        let _a = *y;
+    });
+}
+
+fn main() { }
index 50ea8b1f2ed126708fb6085a9b4661beaf8b8f97..783009f6dcbfca4ae240e83f81517911d598d353 100644 (file)
@@ -11,7 +11,7 @@
 // Issue #8624. Test for reborrowing with 3 levels, not just two.
 
 fn copy_borrowed_ptr<'a, 'b, 'c>(p: &'a mut &'b mut &'c mut int) -> &'b mut int {
-    &mut ***p //~ ERROR lifetime of `p` is too short to guarantee its contents
+    &mut ***p //~ ERROR cannot infer
 }
 
 fn main() {
index 385bc11d1a983d233c5303b70d904fe04ce8e6d0..4b1c7a2928b8ef1f67ba268a1b0afb120c3e4393 100644 (file)
@@ -13,7 +13,7 @@
 // for `'a` (which must be a sublifetime of `'b`).
 
 fn copy_borrowed_ptr<'a, 'b>(p: &'a mut &'b mut int) -> &'b mut int {
-    &mut **p //~ ERROR lifetime of `p` is too short
+    &mut **p //~ ERROR cannot infer
 }
 
 fn main() {
index aac81a2af6b1f3ef3448070908512d7525b2ce30..6d9b2619171057fd632f836e258d478965f2c584 100644 (file)
@@ -19,8 +19,6 @@ fn with<R>(f: <'a>|x: &'a int| -> R) -> R {
 fn return_it<'a>() -> &'a int {
     with(|o| o)
         //~^ ERROR cannot infer
-        //~^^ ERROR not valid during the expression
-        //~^^^ ERROR not valid at this point
 }
 
 fn main() {
index dd9421ee2ef2cdf20cf69ae252d07c8f05a19bda..465f4410fbbccb2d05451c0db6240e5433815a9f 100644 (file)
@@ -22,8 +22,6 @@ fn with<R>(f: |x: &int| -> R) -> R {
 fn return_it<'a>() -> &'a int {
     with(|o| o)
         //~^ ERROR cannot infer
-        //~^^ ERROR not valid during the expression
-        //~^^^ ERROR not valid at this point
 }
 
 fn main() {
index 77a54fec7bf7c6204699aefceea5e85a0cb9616a..14ead8da1587b12189c23015e1f09414c5765de3 100644 (file)
@@ -33,7 +33,6 @@ fn use_<'short,'long>(c: S<'long, 'short>,
     // covariant with respect to its parameter 'a.
 
     let _: S<'long, 'long> = c; //~ ERROR mismatched types
-    //~^ ERROR  cannot infer an appropriate lifetime
 }
 
 fn main() {}
index 0fab89264606b3a48e963c123c5b34c92c0b5ded..3fc58071d2ce86c421b8e4cb09774224881ee8f4 100644 (file)
@@ -31,7 +31,6 @@ fn use_<'short,'long>(c: Contravariant<'short>,
     // covariant with respect to its parameter 'a.
 
     let _: Contravariant<'long> = c; //~ ERROR mismatched types
-    //~^ ERROR  cannot infer an appropriate lifetime
 }
 
 fn main() {}
index 7dcdc9875e3954c46086c40192c37e8409bf68cf..844c8151a642ae31f59ba28ef922f524da989894 100644 (file)
@@ -31,7 +31,6 @@ fn use_<'short,'long>(c: Covariant<'long>,
     // contravariant with respect to its parameter 'a.
 
     let _: Covariant<'short> = c; //~ ERROR mismatched types
-    //~^ ERROR cannot infer an appropriate lifetime
 }
 
 fn main() {}
index d13503b23fb16a6c88594cdfb513b4543cc7231d..f27b11d5411c9589b417d9acf0bc93a92b92e812 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::slice as std; //~ ERROR import conflicts with imported crate
+use std::slice as std; //~ ERROR import `std` conflicts with imported crate
 
 fn main() {
 }
index 3834007f5ffe95343c8a178628180094af11bb5b..96800918351c139becbaac93aac5efdb58d746e0 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use std::mem::transmute;
-//~^ ERROR import conflicts with value in this module
+//~^ ERROR import `transmute` conflicts with value in this module
 
 fn transmute() {}
 
diff --git a/src/test/compile-fail/resolve-conflict-type-vs-import.rs b/src/test/compile-fail/resolve-conflict-type-vs-import.rs
new file mode 100644 (file)
index 0000000..fa072fa
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::slice::Items;
+//~^ ERROR import `Items` conflicts with type in this module
+
+struct Items;
+
+fn main() {
+}
+
diff --git a/src/test/debuginfo/gdb-pretty-struct-and-enums-pre-gdb-7-7.rs b/src/test/debuginfo/gdb-pretty-struct-and-enums-pre-gdb-7-7.rs
new file mode 100644 (file)
index 0000000..e9daf31
--- /dev/null
@@ -0,0 +1,75 @@
+// Copyright 2013-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.
+
+// This test uses only GDB Python API features which should be available in
+// older versions of GDB too. A more extensive test can be found in
+// gdb-pretty-struct-and-enums.rs
+
+// ignore-tidy-linelength
+// ignore-lldb
+// ignore-android: FIXME(#10381)
+// compile-flags:-g
+// gdb-use-pretty-printer
+
+// The following line actually doesn't have to do anything with pretty printing,
+// it just tells GDB to print values on one line:
+// gdb-command: set print pretty off
+
+// gdb-command: rbreak zzz
+// gdb-command: run
+// gdb-command: finish
+
+// gdb-command: print regular_struct
+// gdb-check:$1 = RegularStruct = {the_first_field = 101, the_second_field = 102.5, the_third_field = false}
+
+// gdb-command: print empty_struct
+// gdb-check:$2 = EmptyStruct
+
+// gdb-command: print c_style_enum1
+// gdb-check:$3 = CStyleEnumVar1
+
+// gdb-command: print c_style_enum2
+// gdb-check:$4 = CStyleEnumVar2
+
+// gdb-command: print c_style_enum3
+// gdb-check:$5 = CStyleEnumVar3
+
+struct RegularStruct {
+    the_first_field: int,
+    the_second_field: f64,
+    the_third_field: bool,
+}
+
+struct EmptyStruct;
+
+enum CStyleEnum {
+    CStyleEnumVar1,
+    CStyleEnumVar2,
+    CStyleEnumVar3,
+}
+
+fn main() {
+
+    let regular_struct = RegularStruct {
+        the_first_field: 101,
+        the_second_field: 102.5,
+        the_third_field: false
+    };
+
+    let empty_struct = EmptyStruct;
+
+    let c_style_enum1 = CStyleEnumVar1;
+    let c_style_enum2 = CStyleEnumVar2;
+    let c_style_enum3 = CStyleEnumVar3;
+
+    zzz();
+}
+
+fn zzz() { () }
diff --git a/src/test/debuginfo/gdb-pretty-struct-and-enums.rs b/src/test/debuginfo/gdb-pretty-struct-and-enums.rs
new file mode 100644 (file)
index 0000000..5ef63da
--- /dev/null
@@ -0,0 +1,172 @@
+// Copyright 2013-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-tidy-linelength
+// ignore-lldb
+// ignore-android: FIXME(#10381)
+// compile-flags:-g
+// gdb-use-pretty-printer
+
+// This test uses some GDB Python API features (e.g. accessing anonymous fields)
+// which are only available in newer GDB version. The following directive will
+// case the test runner to ignore this test if an older GDB version is used:
+// min-gdb-version 7.7
+
+// The following line actually doesn't have to do anything with pretty printing,
+// it just tells GDB to print values on one line:
+// gdb-command: set print pretty off
+
+// gdb-command: rbreak zzz
+// gdb-command: run
+// gdb-command: finish
+
+// gdb-command: print regular_struct
+// gdb-check:$1 = RegularStruct = {the_first_field = 101, the_second_field = 102.5, the_third_field = false, the_fourth_field = "I'm so pretty, oh so pretty..."}
+
+// gdb-command: print tuple
+// gdb-check:$2 = {true, 103, "blub"}
+
+// gdb-command: print tuple_struct
+// gdb-check:$3 = TupleStruct = {-104.5, 105}
+
+// gdb-command: print empty_struct
+// gdb-check:$4 = EmptyStruct
+
+// gdb-command: print c_style_enum1
+// gdb-check:$5 = CStyleEnumVar1
+
+// gdb-command: print c_style_enum2
+// gdb-check:$6 = CStyleEnumVar2
+
+// gdb-command: print c_style_enum3
+// gdb-check:$7 = CStyleEnumVar3
+
+// gdb-command: print mixed_enum_c_style_var
+// gdb-check:$8 = MixedEnumCStyleVar
+
+// gdb-command: print mixed_enum_tuple_var
+// gdb-check:$9 = MixedEnumTupleVar = {106, 107, false}
+
+// gdb-command: print mixed_enum_struct_var
+// gdb-check:$10 = MixedEnumStructVar = {field1 = 108.5, field2 = 109}
+
+// gdb-command: print some
+// gdb-check:$11 = Some = {110}
+
+// gdb-command: print none
+// gdb-check:$12 = None
+
+// gdb-command: print nested_variant1
+// gdb-check:$13 = NestedVariant1 = {NestedStruct = {regular_struct = RegularStruct = {the_first_field = 111, the_second_field = 112.5, the_third_field = true, the_fourth_field = "NestedStructString1"}, tuple_struct = TupleStruct = {113.5, 114}, empty_struct = EmptyStruct, c_style_enum = CStyleEnumVar2, mixed_enum = MixedEnumTupleVar = {115, 116, false}}}
+
+// gdb-command: print nested_variant2
+// gdb-check:$14 = NestedVariant2 = {abc = NestedStruct = {regular_struct = RegularStruct = {the_first_field = 117, the_second_field = 118.5, the_third_field = false, the_fourth_field = "NestedStructString10"}, tuple_struct = TupleStruct = {119.5, 120}, empty_struct = EmptyStruct, c_style_enum = CStyleEnumVar3, mixed_enum = MixedEnumStructVar = {field1 = 121.5, field2 = -122}}}
+
+#![feature(struct_variant)]
+
+struct RegularStruct {
+    the_first_field: int,
+    the_second_field: f64,
+    the_third_field: bool,
+    the_fourth_field: &'static str,
+}
+
+struct TupleStruct(f64, i16);
+
+struct EmptyStruct;
+
+enum CStyleEnum {
+    CStyleEnumVar1,
+    CStyleEnumVar2,
+    CStyleEnumVar3,
+}
+
+enum MixedEnum {
+    MixedEnumCStyleVar,
+    MixedEnumTupleVar(u32, u16, bool),
+    MixedEnumStructVar { field1: f64, field2: i32 }
+}
+
+struct NestedStruct {
+    regular_struct: RegularStruct,
+    tuple_struct: TupleStruct,
+    empty_struct: EmptyStruct,
+    c_style_enum: CStyleEnum,
+    mixed_enum: MixedEnum,
+}
+
+enum NestedEnum {
+    NestedVariant1(NestedStruct),
+    NestedVariant2 { abc: NestedStruct }
+}
+
+fn main() {
+
+    let regular_struct = RegularStruct {
+        the_first_field: 101,
+        the_second_field: 102.5,
+        the_third_field: false,
+        the_fourth_field: "I'm so pretty, oh so pretty..."
+    };
+
+    let tuple = ( true, 103u32, "blub" );
+
+    let tuple_struct = TupleStruct(-104.5, 105);
+
+    let empty_struct = EmptyStruct;
+
+    let c_style_enum1 = CStyleEnumVar1;
+    let c_style_enum2 = CStyleEnumVar2;
+    let c_style_enum3 = CStyleEnumVar3;
+
+    let mixed_enum_c_style_var = MixedEnumCStyleVar;
+    let mixed_enum_tuple_var = MixedEnumTupleVar(106, 107, false);
+    let mixed_enum_struct_var = MixedEnumStructVar { field1: 108.5, field2: 109 };
+
+    let some = Some(110u);
+    let none: Option<int> = None;
+
+    let nested_variant1 = NestedVariant1(
+        NestedStruct {
+            regular_struct: RegularStruct {
+                the_first_field: 111,
+                the_second_field: 112.5,
+                the_third_field: true,
+                the_fourth_field: "NestedStructString1",
+            },
+            tuple_struct: TupleStruct(113.5, 114),
+            empty_struct: EmptyStruct,
+            c_style_enum: CStyleEnumVar2,
+            mixed_enum: MixedEnumTupleVar(115, 116, false)
+        }
+    );
+
+    let nested_variant2 = NestedVariant2 {
+        abc: NestedStruct {
+            regular_struct: RegularStruct {
+                the_first_field: 117,
+                the_second_field: 118.5,
+                the_third_field: false,
+                the_fourth_field: "NestedStructString10",
+            },
+            tuple_struct: TupleStruct(119.5, 120),
+            empty_struct: EmptyStruct,
+            c_style_enum: CStyleEnumVar3,
+            mixed_enum: MixedEnumStructVar {
+                field1: 121.5,
+                field2: -122
+            }
+        }
+    };
+
+    zzz();
+}
+
+fn zzz() { () }
diff --git a/src/test/run-make/pretty-expanded-hygiene/Makefile b/src/test/run-make/pretty-expanded-hygiene/Makefile
new file mode 100644 (file)
index 0000000..1176344
--- /dev/null
@@ -0,0 +1,20 @@
+-include ../tools.mk
+
+REPLACEMENT := s/[0-9][0-9]*\#[0-9][0-9]*/$(shell date)/g
+
+all:
+       $(RUSTC) -o $(TMPDIR)/input.out --pretty expanded,hygiene input.rs
+
+       # the name/ctxt numbers are very internals-dependent and thus
+       # change relatively frequently, and testing for their exact values
+       # them will fail annoyingly, so we just check their positions
+       # (using a non-constant replacement like this will make it less
+       # likely the compiler matches whatever other dummy value we
+       # choose).
+       #
+       # (These need to be out-of-place because OSX/BSD & GNU sed
+       # differ.)
+       sed "$(REPLACEMENT)" input.pp.rs > $(TMPDIR)/input.pp.rs
+       sed "$(REPLACEMENT)" $(TMPDIR)/input.out > $(TMPDIR)/input.out.replaced
+
+       diff -u $(TMPDIR)/input.out.replaced $(TMPDIR)/input.pp.rs
diff --git a/src/test/run-make/pretty-expanded-hygiene/input.pp.rs b/src/test/run-make/pretty-expanded-hygiene/input.pp.rs
new file mode 100755 (executable)
index 0000000..bf60784
--- /dev/null
@@ -0,0 +1,16 @@
+// 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(macro_rules)]
+// minimal junk
+#![no_std]
+
+
+fn bar /* 62#0 */() { let x /* 59#2 */ = 1; y /* 61#4 */ + x /* 59#5 */ }
diff --git a/src/test/run-make/pretty-expanded-hygiene/input.rs b/src/test/run-make/pretty-expanded-hygiene/input.rs
new file mode 100755 (executable)
index 0000000..c9d603c
--- /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(macro_rules)]
+// minimal junk
+#![no_std]
+
+macro_rules! foo {
+    ($x: ident) => { y + $x }
+}
+
+fn bar() {
+    let x = 1;
+    foo!(x)
+}
diff --git a/src/test/run-make/rustdoc-search-index/Makefile b/src/test/run-make/rustdoc-search-index/Makefile
new file mode 100644 (file)
index 0000000..1248f14
--- /dev/null
@@ -0,0 +1,17 @@
+-include ../tools.mk
+
+# FIXME ignore windows
+ifndef IS_WINDOWS
+
+source=index.rs
+
+all:
+       $(HOST_RPATH_ENV) $(RUSTDOC) -w html -o $(TMPDIR)/doc $(source)
+       cp $(source) $(TMPDIR)
+       cp verify.sh $(TMPDIR)
+       $(call RUN,verify.sh) $(TMPDIR)
+
+else
+all:
+
+endif
diff --git a/src/test/run-make/rustdoc-search-index/index.rs b/src/test/run-make/rustdoc-search-index/index.rs
new file mode 100644 (file)
index 0000000..019d77f
--- /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.
+
+#![crate_name = "rustdoc_test"]
+
+// In: Foo
+pub use private::Foo;
+
+mod private {
+    pub struct Foo;
+    impl Foo {
+        // In: test_method
+        pub fn test_method() {}
+        // Out: priv_method
+        fn priv_method() {}
+    }
+
+    pub trait PrivateTrait {
+        // Out: priv_method
+        fn trait_method() {}
+    }
+}
diff --git a/src/test/run-make/rustdoc-search-index/verify.sh b/src/test/run-make/rustdoc-search-index/verify.sh
new file mode 100755 (executable)
index 0000000..af5033a
--- /dev/null
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+source="$1/index.rs"
+index="$1/doc/search-index.js"
+
+if ! [ -e $index ]
+then
+    echo "Could not find the search index (looked for $index)"
+    exit 1
+fi
+
+ins=$(grep -o 'In: .*' $source | sed 's/In: \(.*\)/\1/g')
+outs=$(grep -o 'Out: .*' $source | sed 's/Out: \(.*\)/\1/g')
+
+for p in $ins
+do
+    if ! grep -q $p $index
+    then
+        echo "'$p' was erroneously excluded from search index."
+        exit 1
+    fi
+done
+
+for p in $outs
+do
+    if grep -q $p $index
+    then
+        echo "'$p' was erroneously included in search index."
+        exit 1
+    fi
+done
+
+exit 0
diff --git a/src/test/run-pass-fulldeps/lint-group-plugin.rs b/src/test/run-pass-fulldeps/lint-group-plugin.rs
new file mode 100644 (file)
index 0000000..726670b
--- /dev/null
@@ -0,0 +1,28 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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:lint_group_plugin_test.rs
+// ignore-stage1
+// ignore-pretty
+
+#![feature(phase)]
+
+#[phase(plugin)]
+extern crate lint_group_plugin_test;
+
+fn lintme() { } //~ WARNING item is named 'lintme'
+fn pleaselintme() { } //~ WARNING item is named 'pleaselintme'
+
+#[allow(lint_me)]
+pub fn main() {
+    fn lintme() { }
+
+    fn pleaselintme() { }
+}
index e6c1046d1fa7c278cebfe27abef42ee5237f1e35..397ce75b6b93e91b53ea5d33246d93928994b1f4 100644 (file)
@@ -19,6 +19,13 @@ macro_rules! loop_x {
     }
 }
 
+macro_rules! while_true {
+    ($e: expr) => {
+        // $e shouldn't be able to interact with this 'x
+        'x: while 1i + 1 == 2 { $e }
+    }
+}
+
 macro_rules! run_once {
     ($e: expr) => {
         // ditto
@@ -49,6 +56,16 @@ pub fn main() {
     };
     assert_eq!(k, 1i);
 
+    let l: int = {
+        'x: for _ in range(0i, 1) {
+            // ditto
+            while_true!(break 'x);
+            i += 1;
+        }
+        i + 1
+    };
+    assert_eq!(l, 1i);
+
     let n: int = {
         'x: for _ in range(0i, 1) {
             // ditto
index 320441204dfe831ad8dcd613f93fe0646cfadd3f..abb0bdab71f8b72498993ebfd528fc940386b216 100644 (file)
@@ -24,6 +24,13 @@ macro_rules! run_once {
     }
 }
 
+macro_rules! while_x {
+    ($e: expr) => {
+        // ditto
+        'x: while 1i + 1 == 2 { $e }
+    }
+}
+
 pub fn main() {
     'x: for _ in range(0i, 1) {
         // this 'x should refer to the outer loop, lexically
@@ -37,6 +44,11 @@ pub fn main() {
         fail!("break doesn't act hygienically inside infinite loop");
     }
 
+    'x: while 1i + 1 == 2 {
+        while_x!(break 'x);
+        fail!("break doesn't act hygienically inside infinite while loop");
+    }
+
     'x: for _ in range(0i, 1) {
         // ditto
         run_once!(continue 'x);
index 091a57620f0566a75ef4edf9d285f2ef61e13c79..9f12cd79876a0f68515112c001da46b023182dee 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -20,4 +20,10 @@ pub fn main() {
             break 'bar;
         }
     }
+
+    'foobar: while 1i + 1 == 2 {
+        loop {
+            break 'foobar;
+        }
+    }
 }
index 92f57f34c947d15b3ec641991ffb45f38515811c..9028e68da1fd9357533b50abea481ee7c0563096 100644 (file)
@@ -16,7 +16,7 @@
 // around this problem locally by renaming the constant in the `use`
 // form to an uppercase identifier that placates the lint.
 
-#![deny(non_uppercase_pattern_statics)]
+#![deny(non_uppercase_statics)]
 
 pub static A : int = 97;
 
@@ -34,6 +34,7 @@ fn f() {
 }
 
 mod m {
+    #[allow(non_uppercase_statics)]
     pub static aha : int = 7;
 }
 
index f599a2b7ad55c9f04923cd15840917c7a7261fd5..e17f140994421a6d7e348d5dfd55f0d65f9d6998 100644 (file)
@@ -61,11 +61,6 @@ fn visit_f64(&mut self) -> bool { true }
     fn visit_char(&mut self) -> bool { true }
 
     fn visit_estr_slice(&mut self) -> bool { true }
-    // NOTE: remove after snapshot
-    #[cfg(stage0)]
-    fn visit_estr_fixed(&mut self,
-                        _sz: uint, _sz2: uint,
-                        _align: uint) -> bool { true }
 
     fn visit_box(&mut self, _mtbl: uint, _inner: *const TyDesc) -> bool { true }
     fn visit_uniq(&mut self, _mtbl: uint, _inner: *const TyDesc) -> bool { true }
diff --git a/src/test/run-pass/regions-infer-reborrow-ref-mut-recurse.rs b/src/test/run-pass/regions-infer-reborrow-ref-mut-recurse.rs
new file mode 100644 (file)
index 0000000..efe3994
--- /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.
+
+// Test an edge case in region inference: the lifetime of the borrow
+// of `*x` must be extended to at least 'a.
+
+fn foo<'a,'b>(x: &'a &'b mut int) -> &'a int {
+    let y = &*x; // should be inferred to have type &'a &'b mut int...
+
+    // ...because if we inferred, say, &'x &'b mut int where 'x <= 'a,
+    // this reborrow would be illegal:
+    &**y
+}
+
+pub fn main() {
+    /* Just want to know that it compiles. */
+}
diff --git a/src/test/run-pass/regions-infer-static-from-proc.rs b/src/test/run-pass/regions-infer-static-from-proc.rs
new file mode 100644 (file)
index 0000000..823644d
--- /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.
+
+// Check that the 'static bound on a proc influences lifetimes of
+// region variables contained within (otherwise, region inference will
+// give `x` a very short lifetime).
+
+static i: uint = 3;
+fn foo(_: proc():'static) {}
+fn read(_: uint) { }
+pub fn main() {
+    let x = &i;
+    foo(proc() {
+        read(*x);
+    });
+}
diff --git a/src/test/run-pass/regions-scope-chain-example.rs b/src/test/run-pass/regions-scope-chain-example.rs
new file mode 100644 (file)
index 0000000..0eacb27
--- /dev/null
@@ -0,0 +1,48 @@
+// 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.
+
+// This is an example where the older inference algorithm failed. The
+// specifics of why it failed are somewhat, but not entirely, tailed
+// to the algorithm. Ultimately the problem is that when computing the
+// mutual supertype of both sides of the `if` it would be faced with a
+// choice of tightening bounds or unifying variables and it took the
+// wrong path. The new algorithm avoids this problem and hence this
+// example typechecks correctly.
+
+enum ScopeChain<'a> {
+    Link(Scope<'a>),
+    End
+}
+
+type Scope<'a> = &'a ScopeChain<'a>;
+
+struct OuterContext;
+
+struct Context<'a> {
+    foo: &'a OuterContext
+}
+
+impl<'a> Context<'a> {
+    fn foo(&mut self, scope: Scope) {
+        let link = if 1i < 2 {
+            let l = Link(scope);
+            self.take_scope(&l);
+            l
+        } else {
+            Link(scope)
+        };
+        self.take_scope(&link);
+    }
+
+    fn take_scope(&mut self, x: Scope) {
+    }
+}
+
+fn main() { }
index b8470ef7b8fac1f5484b011dffa52c11fd049b03..19097c8e26c6a066396e7964592d15eb5e6d5035 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-macos #16872 spurious deadlock
+
 #![feature(phase)]
 
 #[phase(plugin)]
diff --git a/src/test/run-pass/while-label.rs b/src/test/run-pass/while-label.rs
new file mode 100644 (file)
index 0000000..dd53ac8
--- /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.
+
+
+pub fn main() {
+    let mut i = 100i;
+    'w: while 1i + 1 == 2 {
+        i -= 1;
+        if i == 95 {
+            break 'w;
+            fail!("Should have broken out of loop");
+        }
+    }
+    assert_eq!(i, 95);
+}