diff --git a/mk/clean.mk b/mk/clean.mk index aadc55ba6c497..5b90d41ceeceb 100644 --- a/mk/clean.mk +++ b/mk/clean.mk @@ -64,6 +64,7 @@ clean-generic-$(2)-$(1): -name '*.dll' -o \ -name '*.def' -o \ -name '*.py' -o \ + -name '*.pyc' -o \ -name '*.bc' \ \) \ | xargs rm -f @@ -79,7 +80,7 @@ define CLEAN_HOST_STAGE_N clean$(1)_H_$(2): \ $$(foreach crate,$$(CRATES),clean$(1)_H_$(2)-lib-$$(crate)) \ - $$(foreach tool,$$(TOOLS) $$(DEBUGGER_BIN_SCRIPTS),clean$(1)_H_$(2)-tool-$$(tool)) + $$(foreach tool,$$(TOOLS) $$(DEBUGGER_BIN_SCRIPTS_ALL),clean$(1)_H_$(2)-tool-$$(tool)) $$(Q)rm -fr $(2)/rt/libbacktrace clean$(1)_H_$(2)-tool-%: @@ -99,7 +100,7 @@ define CLEAN_TARGET_STAGE_N clean$(1)_T_$(2)_H_$(3): \ $$(foreach crate,$$(CRATES),clean$(1)_T_$(2)_H_$(3)-lib-$$(crate)) \ - $$(foreach tool,$$(TOOLS) $$(DEBUGGER_BIN_SCRIPTS),clean$(1)_T_$(2)_H_$(3)-tool-$$(tool)) + $$(foreach tool,$$(TOOLS) $$(DEBUGGER_BIN_SCRIPTS_ALL),clean$(1)_T_$(2)_H_$(3)-tool-$$(tool)) $$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/libmorestack.a $$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/libcompiler-rt.a $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/librun_pass_stage* # For unix diff --git a/mk/debuggers.mk b/mk/debuggers.mk index 54955f06295fc..899cc42d066e4 100644 --- a/mk/debuggers.mk +++ b/mk/debuggers.mk @@ -12,26 +12,77 @@ # Copy debugger related scripts ###################################################################### -DEBUGGER_RUSTLIB_ETC_SCRIPTS=lldb_rust_formatters.py -DEBUGGER_BIN_SCRIPTS=rust-lldb -DEBUGGER_RUSTLIB_ETC_SCRIPTS_ABS=$(foreach script,$(DEBUGGER_RUSTLIB_ETC_SCRIPTS), \ - $(CFG_SRC_DIR)src/etc/$(script)) -DEBUGGER_BIN_SCRIPTS_ABS=$(foreach script,$(DEBUGGER_BIN_SCRIPTS), \ - $(CFG_SRC_DIR)src/etc/$(script)) +## GDB ## +DEBUGGER_RUSTLIB_ETC_SCRIPTS_GDB=gdb_load_rust_pretty_printers.py \ + gdb_rust_pretty_printing.py +DEBUGGER_RUSTLIB_ETC_SCRIPTS_GDB_ABS=\ + $(foreach script,$(DEBUGGER_RUSTLIB_ETC_SCRIPTS_GDB), \ + $(CFG_SRC_DIR)src/etc/$(script)) + +DEBUGGER_BIN_SCRIPTS_GDB=rust-gdb +DEBUGGER_BIN_SCRIPTS_GDB_ABS=\ + $(foreach script,$(DEBUGGER_BIN_SCRIPTS_GDB), \ + $(CFG_SRC_DIR)src/etc/$(script)) + + +## LLDB ## +DEBUGGER_RUSTLIB_ETC_SCRIPTS_LLDB=lldb_rust_formatters.py +DEBUGGER_RUSTLIB_ETC_SCRIPTS_LLDB_ABS=\ + $(foreach script,$(DEBUGGER_RUSTLIB_ETC_SCRIPTS_LLDB), \ + $(CFG_SRC_DIR)src/etc/$(script)) + +DEBUGGER_BIN_SCRIPTS_LLDB=rust-lldb +DEBUGGER_BIN_SCRIPTS_LLDB_ABS=\ + $(foreach script,$(DEBUGGER_BIN_SCRIPTS_LLDB), \ + $(CFG_SRC_DIR)src/etc/$(script)) + + +## ALL ## +DEBUGGER_RUSTLIB_ETC_SCRIPTS_ALL=$(DEBUGGER_RUSTLIB_ETC_SCRIPTS_GDB) \ + $(DEBUGGER_RUSTLIB_ETC_SCRIPTS_LLDB) +DEBUGGER_RUSTLIB_ETC_SCRIPTS_ALL_ABS=$(DEBUGGER_RUSTLIB_ETC_SCRIPTS_GDB_ABS) \ + $(DEBUGGER_RUSTLIB_ETC_SCRIPTS_LLDB_ABS) +DEBUGGER_BIN_SCRIPTS_ALL=$(DEBUGGER_BIN_SCRIPTS_GDB) \ + $(DEBUGGER_BIN_SCRIPTS_LLDB) +DEBUGGER_BIN_SCRIPTS_ALL_ABS=$(DEBUGGER_BIN_SCRIPTS_GDB_ABS) \ + $(DEBUGGER_BIN_SCRIPTS_LLDB_ABS) -DEBUGGER_SCRIPTS_ALL=$(DEBUGGER_RUSTLIB_ETC_SCRIPTS_ABS) $(DEBUGGER_BIN_SCRIPTS_ABS) # $(1) - the stage to copy to # $(2) - the host triple define DEF_INSTALL_DEBUGGER_SCRIPTS_HOST -tmp/install-debugger-scripts$(1)_H_$(2).done: $$(DEBUGGER_SCRIPTS_ALL) +tmp/install-debugger-scripts$(1)_H_$(2)-gdb.done: \ + $$(DEBUGGER_RUSTLIB_ETC_SCRIPTS_GDB_ABS) \ + $$(DEBUGGER_BIN_SCRIPTS_GDB_ABS) + $(Q)mkdir -p $$(HBIN$(1)_H_$(2)) + $(Q)mkdir -p $$(HLIB$(1)_H_$(2))/rustlib/etc + $(Q)install $$(DEBUGGER_BIN_SCRIPTS_GDB_ABS) $$(HBIN$(1)_H_$(2)) + $(Q)install $$(DEBUGGER_RUSTLIB_ETC_SCRIPTS_GDB_ABS) $$(HLIB$(1)_H_$(2))/rustlib/etc + $(Q)touch $$@ + +tmp/install-debugger-scripts$(1)_H_$(2)-lldb.done: \ + $$(DEBUGGER_RUSTLIB_ETC_SCRIPTS_LLDB_ABS) \ + $$(DEBUGGER_BIN_SCRIPTS_LLDB_ABS) + $(Q)mkdir -p $$(HBIN$(1)_H_$(2)) + $(Q)mkdir -p $$(HLIB$(1)_H_$(2))/rustlib/etc + $(Q)install $$(DEBUGGER_BIN_SCRIPTS_LLDB_ABS) $$(HBIN$(1)_H_$(2)) + $(Q)install $$(DEBUGGER_RUSTLIB_ETC_SCRIPTS_LLDB_ABS) $$(HLIB$(1)_H_$(2))/rustlib/etc + $(Q)touch $$@ + +tmp/install-debugger-scripts$(1)_H_$(2)-all.done: \ + $$(DEBUGGER_RUSTLIB_ETC_SCRIPTS_ALL_ABS) \ + $$(DEBUGGER_BIN_SCRIPTS_ALL_ABS) $(Q)mkdir -p $$(HBIN$(1)_H_$(2)) $(Q)mkdir -p $$(HLIB$(1)_H_$(2))/rustlib/etc - $(Q)install $(DEBUGGER_BIN_SCRIPTS_ABS) $$(HBIN$(1)_H_$(2)) - $(Q)install $(DEBUGGER_RUSTLIB_ETC_SCRIPTS_ABS) $$(HLIB$(1)_H_$(2))/rustlib/etc + $(Q)install $$(DEBUGGER_BIN_SCRIPTS_ALL_ABS) $$(HBIN$(1)_H_$(2)) + $(Q)install $$(DEBUGGER_RUSTLIB_ETC_SCRIPTS_ALL_ABS) $$(HLIB$(1)_H_$(2))/rustlib/etc $(Q)touch $$@ + +tmp/install-debugger-scripts$(1)_H_$(2)-none.done: + $(Q)touch $$@ + endef # Expand host make-targets for all stages @@ -44,12 +95,36 @@ $(foreach stage,$(STAGES), \ # $(3) is the host triple define DEF_INSTALL_DEBUGGER_SCRIPTS_TARGET -tmp/install-debugger-scripts$(1)_T_$(2)_H_$(3).done: $$(DEBUGGER_SCRIPTS_ALL) +tmp/install-debugger-scripts$(1)_T_$(2)_H_$(3)-gdb.done: \ + $$(DEBUGGER_RUSTLIB_ETC_SCRIPTS_GDB_ABS) \ + $$(DEBUGGER_BIN_SCRIPTS_GDB_ABS) + $(Q)mkdir -p $$(TBIN$(1)_T_$(2)_H_$(3)) + $(Q)mkdir -p $$(TLIB$(1)_T_$(2)_H_$(3))/rustlib/etc + $(Q)install $(DEBUGGER_BIN_SCRIPTS_GDB_ABS) $$(TBIN$(1)_T_$(2)_H_$(3)) + $(Q)install $(DEBUGGER_RUSTLIB_ETC_SCRIPTS_GDB_ABS) $$(TLIB$(1)_T_$(2)_H_$(3))/rustlib/etc + $(Q)touch $$@ + +tmp/install-debugger-scripts$(1)_T_$(2)_H_$(3)-lldb.done: \ + $$(DEBUGGER_RUSTLIB_ETC_SCRIPTS_LLDB_ABS) \ + $$(DEBUGGER_BIN_SCRIPTS_LLDB_ABS) $(Q)mkdir -p $$(TBIN$(1)_T_$(2)_H_$(3)) $(Q)mkdir -p $$(TLIB$(1)_T_$(2)_H_$(3))/rustlib/etc - $(Q)install $(DEBUGGER_BIN_SCRIPTS_ABS) $$(TBIN$(1)_T_$(2)_H_$(3)) - $(Q)install $(DEBUGGER_RUSTLIB_ETC_SCRIPTS_ABS) $$(TLIB$(1)_T_$(2)_H_$(3))/rustlib/etc + $(Q)install $(DEBUGGER_BIN_SCRIPTS_LLDB_ABS) $$(TBIN$(1)_T_$(2)_H_$(3)) + $(Q)install $(DEBUGGER_RUSTLIB_ETC_SCRIPTS_LLDB_ABS) $$(TLIB$(1)_T_$(2)_H_$(3))/rustlib/etc $(Q)touch $$@ + +tmp/install-debugger-scripts$(1)_T_$(2)_H_$(3)-all.done: \ + $$(DEBUGGER_RUSTLIB_ETC_SCRIPTS_ALL_ABS) \ + $$(DEBUGGER_BIN_SCRIPTS_ALL_ABS) + $(Q)mkdir -p $$(TBIN$(1)_T_$(2)_H_$(3)) + $(Q)mkdir -p $$(TLIB$(1)_T_$(2)_H_$(3))/rustlib/etc + $(Q)install $(DEBUGGER_BIN_SCRIPTS_ALL_ABS) $$(TBIN$(1)_T_$(2)_H_$(3)) + $(Q)install $(DEBUGGER_RUSTLIB_ETC_SCRIPTS_ALL_ABS) $$(TLIB$(1)_T_$(2)_H_$(3))/rustlib/etc + $(Q)touch $$@ + +tmp/install-debugger-scripts$(1)_T_$(2)_H_$(3)-none.done: + $(Q)touch $$@ + endef # Expand target make-targets for all stages diff --git a/mk/dist.mk b/mk/dist.mk index 963627dbe0997..a8b331c6cc239 100644 --- a/mk/dist.mk +++ b/mk/dist.mk @@ -35,7 +35,7 @@ LICENSE.txt: $(S)COPYRIGHT $(S)LICENSE-APACHE $(S)LICENSE-MIT # Source tarball ###################################################################### -PKG_TAR = dist/$(PKG_NAME).tar.gz +PKG_TAR = dist/$(PKG_NAME)-src.tar.gz PKG_GITMODULES := $(S)src/llvm $(S)src/compiler-rt \ $(S)src/rt/hoedown $(S)src/jemalloc @@ -241,8 +241,8 @@ dist/$$(PKG_NAME)-$(1).tar.gz: dist-install-dir-$(1) @$(call E, build: $$@) # Copy essential gcc components into installer ifdef CFG_WINDOWSY_$(1) - $$(Q)rm -Rf dist/win-rust-gcc-$(1) - $$(Q)$$(CFG_PYTHON) $$(S)src/etc/make-win-dist.py tmp/dist/$$(PKG_NAME)-$(1)-image dist/win-rust-gcc-$(1) $(1) + $$(Q)rm -Rf tmp/dist/win-rust-gcc-$(1) + $$(Q)$$(CFG_PYTHON) $$(S)src/etc/make-win-dist.py tmp/dist/$$(PKG_NAME)-$(1)-image tmp/dist/win-rust-gcc-$(1) $(1) $$(Q)cp -r $$(S)src/etc/third-party tmp/dist/$$(PKG_NAME)-$(1)-image/share/doc/ endif $$(Q)$$(S)src/rust-installer/gen-installer.sh \ diff --git a/mk/main.mk b/mk/main.mk index 4aed1cea9ca09..32167dfd89990 100644 --- a/mk/main.mk +++ b/mk/main.mk @@ -15,6 +15,9 @@ # The version number CFG_RELEASE_NUM=0.13.0 +# An optional number to put after the label, e.g. '2' -> '-beta2' +CFG_BETA_CYCLE= + CFG_FILENAME_EXTRA=4e7c5e5c ifeq ($(CFG_RELEASE_CHANNEL),stable) @@ -24,12 +27,13 @@ CFG_RELEASE=$(CFG_RELEASE_NUM) CFG_PACKAGE_VERS=$(CFG_RELEASE_NUM) endif ifeq ($(CFG_RELEASE_CHANNEL),beta) -CFG_RELEASE=$(CFG_RELEASE_NUM)-beta +# The beta channel is temporarily called 'alpha' +CFG_RELEASE=$(CFG_RELEASE_NUM)-alpha$(CFG_BETA_CYCLE) # When building beta/nightly distributables just reuse the same "beta" # name so when we upload we'll always override the previous # nighly. This doesn't actually impact the version reported by rustc - # it's just for file naming. -CFG_PACKAGE_VERS=beta +CFG_PACKAGE_VERS=alpha endif ifeq ($(CFG_RELEASE_CHANNEL),nightly) CFG_RELEASE=$(CFG_RELEASE_NUM)-nightly @@ -325,6 +329,12 @@ export CFG_DISABLE_INJECT_STD_VERSION # Per-stage targets and runner ###################################################################### +# Valid setting-strings are 'all', 'none', 'gdb', 'lldb' +# This 'function' will determine which debugger scripts to copy based on a +# target triple. See debuggers.mk for more information. +TRIPLE_TO_DEBUGGER_SCRIPT_SETTING=\ + $(if $(findstring windows,$(1)),none,$(if $(findstring darwin,$(1)),lldb,gdb)) + STAGES = 0 1 2 3 define SREQ @@ -357,7 +367,7 @@ else HSREQ$(1)_H_$(3) = \ $$(HBIN$(1)_H_$(3))/rustc$$(X_$(3)) \ $$(MKFILE_DEPS) \ - tmp/install-debugger-scripts$(1)_H_$(3).done + tmp/install-debugger-scripts$(1)_H_$(3)-$$(call TRIPLE_TO_DEBUGGER_SCRIPT_SETTING,$(3)).done endif # Prerequisites for using the stageN compiler to build target artifacts @@ -372,7 +382,7 @@ SREQ$(1)_T_$(2)_H_$(3) = \ $$(TSREQ$(1)_T_$(2)_H_$(3)) \ $$(foreach dep,$$(TARGET_CRATES), \ $$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$$(dep)) \ - tmp/install-debugger-scripts$(1)_T_$(2)_H_$(3).done + tmp/install-debugger-scripts$(1)_T_$(2)_H_$(3)-$$(call TRIPLE_TO_DEBUGGER_SCRIPT_SETTING,$(2)).done # Prerequisites for a working stageN compiler and complete set of target # libraries diff --git a/mk/prepare.mk b/mk/prepare.mk index d404d3d2950e0..52fbbef81bd78 100644 --- a/mk/prepare.mk +++ b/mk/prepare.mk @@ -144,6 +144,27 @@ prepare-target-$(2)-host-$(3)-$(1)-$(4): prepare-maybe-clean-$(4) \ $$(call PREPARE_LIB,libcompiler-rt.a),),),) endef +define INSTALL_GDB_DEBUGGER_SCRIPTS_COMMANDS + $(Q)$(PREPARE_BIN_CMD) $(DEBUGGER_BIN_SCRIPTS_GDB_ABS) $(PREPARE_DEST_BIN_DIR) + $(Q)$(PREPARE_LIB_CMD) $(DEBUGGER_RUSTLIB_ETC_SCRIPTS_GDB_ABS) $(PREPARE_DEST_LIB_DIR)/rustlib/etc +endef + +define INSTALL_LLDB_DEBUGGER_SCRIPTS_COMMANDS + $(Q)$(PREPARE_BIN_CMD) $(DEBUGGER_BIN_SCRIPTS_LLDB_ABS) $(PREPARE_DEST_BIN_DIR) + $(Q)$(PREPARE_LIB_CMD) $(DEBUGGER_RUSTLIB_ETC_SCRIPTS_LLDB_ABS) $(PREPARE_DEST_LIB_DIR)/rustlib/etc +endef + +define INSTALL_NO_DEBUGGER_SCRIPTS_COMMANDS + $(Q)echo "No debugger scripts will be installed for host $(PREPARE_HOST)" +endef + +# $(1) is PREPARE_HOST +INSTALL_DEBUGGER_SCRIPT_COMMANDS=$(if $(findstring windows,$(1)),\ + $(INSTALL_NO_DEBUGGER_SCRIPTS_COMMANDS),\ + $(if $(findstring darwin,$(1)),\ + $(INSTALL_LLDB_DEBUGGER_SCRIPTS_COMMANDS),\ + $(INSTALL_GDB_DEBUGGER_SCRIPTS_COMMANDS))) + define DEF_PREPARE prepare-base-$(1): PREPARE_SOURCE_DIR=$$(PREPARE_HOST)/stage$$(PREPARE_STAGE) @@ -170,9 +191,10 @@ prepare-host-dirs-$(1): prepare-maybe-clean-$(1) $$(call PREPARE_DIR,$$(PREPARE_DEST_LIB_DIR)/rustlib/etc) $$(call PREPARE_DIR,$$(PREPARE_DEST_MAN_DIR)) -prepare-debugger-scripts-$(1): prepare-host-dirs-$(1) $(DEBUGGER_SCRIPTS_ALL) - $$(Q)$$(PREPARE_BIN_CMD) $(DEBUGGER_BIN_SCRIPTS_ABS) $$(PREPARE_DEST_BIN_DIR) - $$(Q)$$(PREPARE_LIB_CMD) $(DEBUGGER_RUSTLIB_ETC_SCRIPTS_ABS) $$(PREPARE_DEST_LIB_DIR)/rustlib/etc +prepare-debugger-scripts-$(1): prepare-host-dirs-$(1) \ + $$(DEBUGGER_BIN_SCRIPTS_ALL_ABS) \ + $$(DEBUGGER_RUSTLIB_ETC_SCRIPTS_ALL_ABS) + $$(call INSTALL_DEBUGGER_SCRIPT_COMMANDS,$$(PREPARE_HOST)) $$(foreach tool,$$(PREPARE_TOOLS), \ $$(foreach host,$$(CFG_HOST), \ diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs index 1abcd8bd21407..c513aec0b843a 100644 --- a/src/compiletest/runtest.rs +++ b/src/compiletest/runtest.rs @@ -32,6 +32,7 @@ use std::io::process; use std::io::timer; use std::io; use std::os; +use std::iter::repeat; use std::str; use std::string::String; use std::thread::Thread; @@ -367,7 +368,6 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) { let DebuggerCommands { commands, check_lines, - use_gdb_pretty_printer, breakpoint_lines } = parse_debugger_commands(testfile, "gdb"); let mut cmds = commands.connect("\n"); @@ -521,16 +521,11 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) { 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 ... + // GDB's script auto loading safe path script_str.push_str( format!("add-auto-load-safe-path {}\n", rust_pp_module_abs_path.replace("\\", "\\\\").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().replace("\\", "\\\\")) - .as_slice()); } } _ => { @@ -543,6 +538,9 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) { // pretty printing, it just tells GDB to print values on one line: script_str.push_str("set print pretty off\n"); + // Add the pretty printer directory to GDB's source-file search path + script_str.push_str(format!("directory {}\n", rust_pp_module_abs_path)[]); + // Load the target executable script_str.push_str(format!("file {}\n", exe_file.as_str().unwrap().replace("\\", "\\\\")) @@ -564,12 +562,6 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) { 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 { @@ -611,19 +603,6 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) { } 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 { @@ -781,7 +760,6 @@ struct DebuggerCommands { commands: Vec, check_lines: Vec, breakpoint_lines: Vec, - use_gdb_pretty_printer: bool } fn parse_debugger_commands(file_path: &Path, debugger_prefix: &str) @@ -794,7 +772,6 @@ 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() { @@ -804,10 +781,6 @@ 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| { @@ -832,7 +805,6 @@ fn parse_debugger_commands(file_path: &Path, debugger_prefix: &str) commands: commands, check_lines: check_lines, breakpoint_lines: breakpoint_lines, - use_gdb_pretty_printer: use_gdb_pretty_printer, } } @@ -976,8 +948,7 @@ fn check_expected_errors(expected_errors: Vec , proc_res: &ProcRes) { // true if we found the error in question - let mut found_flags = Vec::from_elem( - expected_errors.len(), false); + let mut found_flags: Vec<_> = repeat(false).take(expected_errors.len()).collect(); if proc_res.status.success() { fatal("process did not return an error status"); @@ -1337,7 +1308,7 @@ fn make_run_args(config: &Config, props: &TestProps, testfile: &Path) -> // Add the arguments in the run_flags directive args.extend(split_maybe_args(&props.run_flags).into_iter()); - let prog = args.remove(0).unwrap(); + let prog = args.remove(0); return ProcArgs { prog: prog, args: args, diff --git a/src/doc/guide.md b/src/doc/guide.md index d094c47da93bb..fe65f4bd7f53d 100644 --- a/src/doc/guide.md +++ b/src/doc/guide.md @@ -460,7 +460,7 @@ x = 10i; There is no single reason that bindings are immutable by default, but we can think about it through one of Rust's primary focuses: safety. If you forget to say `mut`, the compiler will catch it, and let you know that you have mutated -something you may not have cared to mutate. If bindings were mutable by +something you may not have intended to mutate. If bindings were mutable by default, the compiler would not be able to tell you this. If you _did_ intend mutation, then the solution is quite easy: add `mut`. @@ -889,9 +889,8 @@ fn hello(name: &str) { When writing doc comments, adding sections for any arguments, return values, and providing some examples of usage is very, very helpful. -You can use the `rustdoc` tool to generate HTML documentation from these doc -comments. We will talk more about `rustdoc` when we get to modules, as -generally, you want to export documentation for a full module. +You can use the [`rustdoc`](rustdoc.html) tool to generate HTML documentation +from these doc comments. # Compound Data Types diff --git a/src/etc/gdb_load_rust_pretty_printers.py b/src/etc/gdb_load_rust_pretty_printers.py new file mode 100644 index 0000000000000..755cac153d10d --- /dev/null +++ b/src/etc/gdb_load_rust_pretty_printers.py @@ -0,0 +1,12 @@ +# Copyright 2014 The Rust Project Developers. See the COPYRIGHT +# file at the top-level directory of this distribution and at +# http://rust-lang.org/COPYRIGHT. +# +# Licensed under the Apache License, Version 2.0 or the MIT license +# , at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + +import gdb_rust_pretty_printing +gdb_rust_pretty_printing.register_printers(gdb.current_objfile()) diff --git a/src/etc/rust-gdb b/src/etc/rust-gdb new file mode 100755 index 0000000000000..520a108da914c --- /dev/null +++ b/src/etc/rust-gdb @@ -0,0 +1,23 @@ +#!/bin/sh +# Copyright 2014 The Rust Project Developers. See the COPYRIGHT +# file at the top-level directory of this distribution and at +# http://rust-lang.org/COPYRIGHT. +# +# Licensed under the Apache License, Version 2.0 or the MIT license +# , at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + +# Exit if anything fails +set -e + +# Find out where the pretty printer Python module is +RUSTC_SYSROOT=`rustc --print=sysroot` +GDB_PYTHON_MODULE_DIRECTORY="$RUSTC_SYSROOT/lib/rustlib/etc" + +# Run GDB with the additional arguments that load the pretty printers +PYTHONPATH="$PYTHONPATH:$GDB_PYTHON_MODULE_DIRECTORY" gdb \ + -d "$GDB_PYTHON_MODULE_DIRECTORY" \ + -iex "add-auto-load-safe-path $GDB_PYTHON_MODULE_DIRECTORY" \ + "$@" diff --git a/src/grammar/README.md b/src/grammar/README.md index f5b872cdc7f67..1f7923e1caff2 100644 --- a/src/grammar/README.md +++ b/src/grammar/README.md @@ -1,7 +1,7 @@ Reference grammar. Uses [antlr4](http://www.antlr.org/) and a custom Rust tool to compare -ASTs/token streams generated. You can use the `check-syntax` make target to +ASTs/token streams generated. You can use the `check-lexer` make target to run all of the available tests. To use manually: @@ -12,7 +12,7 @@ javac *.java rustc -O verify.rs for file in ../*/**.rs; do echo $file; - grun RustLexer tokens -tokens < $file | ./verify $file || break + grun RustLexer tokens -tokens < $file | ./verify $file RustLexer.tokens || break done ``` diff --git a/src/grammar/RustLexer.g4 b/src/grammar/RustLexer.g4 index 00af6d358e5eb..88de5db41fe7b 100644 --- a/src/grammar/RustLexer.g4 +++ b/src/grammar/RustLexer.g4 @@ -112,8 +112,64 @@ LIT_INTEGER ; LIT_FLOAT - : [0-9][0-9_]* ( '.' {_input.LA(1) != '.'}? - | ('.' [0-9][0-9_]*)? ([eE] [-+]? [0-9][0-9_]*)? SUFFIX?) + : [0-9][0-9_]* ('.' { + /* dot followed by another dot is a range, no float */ + _input.LA(1) != '.' && + /* dot followed by an identifier is an integer with a function call, no float */ + _input.LA(1) != '_' && + _input.LA(1) != 'a' && + _input.LA(1) != 'b' && + _input.LA(1) != 'c' && + _input.LA(1) != 'd' && + _input.LA(1) != 'e' && + _input.LA(1) != 'f' && + _input.LA(1) != 'g' && + _input.LA(1) != 'h' && + _input.LA(1) != 'i' && + _input.LA(1) != 'j' && + _input.LA(1) != 'k' && + _input.LA(1) != 'l' && + _input.LA(1) != 'm' && + _input.LA(1) != 'n' && + _input.LA(1) != 'o' && + _input.LA(1) != 'p' && + _input.LA(1) != 'q' && + _input.LA(1) != 'r' && + _input.LA(1) != 's' && + _input.LA(1) != 't' && + _input.LA(1) != 'u' && + _input.LA(1) != 'v' && + _input.LA(1) != 'w' && + _input.LA(1) != 'x' && + _input.LA(1) != 'y' && + _input.LA(1) != 'z' && + _input.LA(1) != 'A' && + _input.LA(1) != 'B' && + _input.LA(1) != 'C' && + _input.LA(1) != 'D' && + _input.LA(1) != 'E' && + _input.LA(1) != 'F' && + _input.LA(1) != 'G' && + _input.LA(1) != 'H' && + _input.LA(1) != 'I' && + _input.LA(1) != 'J' && + _input.LA(1) != 'K' && + _input.LA(1) != 'L' && + _input.LA(1) != 'M' && + _input.LA(1) != 'N' && + _input.LA(1) != 'O' && + _input.LA(1) != 'P' && + _input.LA(1) != 'Q' && + _input.LA(1) != 'R' && + _input.LA(1) != 'S' && + _input.LA(1) != 'T' && + _input.LA(1) != 'U' && + _input.LA(1) != 'V' && + _input.LA(1) != 'W' && + _input.LA(1) != 'X' && + _input.LA(1) != 'Y' && + _input.LA(1) != 'Z' + }? | ('.' [0-9][0-9_]*)? ([eE] [-+]? [0-9][0-9_]*)? SUFFIX?) ; LIT_STR diff --git a/src/grammar/check.sh b/src/grammar/check.sh index f2836312437c9..cb269bbdb0ade 100755 --- a/src/grammar/check.sh +++ b/src/grammar/check.sh @@ -11,6 +11,10 @@ if [ "${VERBOSE}" == "1" ]; then set -x fi +passed=0 +failed=0 +skipped=0 + check() { grep --silent "// ignore-lexer-test" $1; @@ -21,14 +25,27 @@ check() { # seem to have anny effect. if $3 RustLexer tokens -tokens < $1 | $4 $1 $5; then echo "pass: $1" + passed=`expr $passed + 1` else echo "fail: $1" + failed=`expr $failed + 1` fi else echo "skip: $1" + skipped=`expr $skipped + 1` fi } for file in $(find $1 -iname '*.rs' ! -path '*/test/compile-fail*'); do check $file $2 $3 $4 $5 done + +printf "\ntest result: " + +if [ $failed -eq 0 ]; then + printf "ok. $passed passed; $failed failed; $skipped skipped\n\n" +else + printf "failed. $passed passed; $failed failed; $skipped skipped\n\n" + exit 1 +fi + diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index 21c47cdf3d752..820a3838978c0 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -68,6 +68,7 @@ //! ``` use core::atomic; +use core::atomic::Ordering::{Relaxed, Release, Acquire, SeqCst}; use core::borrow::BorrowFrom; use core::clone::Clone; use core::fmt::{mod, Show}; @@ -95,7 +96,7 @@ use heap::deallocate; /// use std::thread::Thread; /// /// fn main() { -/// let numbers = Vec::from_fn(100, |i| i as f32); +/// let numbers: Vec<_> = range(0, 100u32).map(|i| i as f32).collect(); /// let shared_numbers = Arc::new(numbers); /// /// for _ in range(0u, 10) { @@ -182,7 +183,7 @@ impl Arc { #[experimental = "Weak pointers may not belong in this module."] pub fn downgrade(&self) -> Weak { // See the clone() impl for why this is relaxed - self.inner().weak.fetch_add(1, atomic::Relaxed); + self.inner().weak.fetch_add(1, Relaxed); Weak { _ptr: self._ptr } } } @@ -201,12 +202,12 @@ impl Arc { /// Get the number of weak references to this value. #[inline] #[experimental] -pub fn weak_count(this: &Arc) -> uint { this.inner().weak.load(atomic::SeqCst) - 1 } +pub fn weak_count(this: &Arc) -> uint { this.inner().weak.load(SeqCst) - 1 } /// Get the number of strong references to this value. #[inline] #[experimental] -pub fn strong_count(this: &Arc) -> uint { this.inner().strong.load(atomic::SeqCst) } +pub fn strong_count(this: &Arc) -> uint { this.inner().strong.load(SeqCst) } #[stable] impl Clone for Arc { @@ -234,7 +235,7 @@ impl Clone for Arc { // must already provide any required synchronization. // // [1]: (www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html) - self.inner().strong.fetch_add(1, atomic::Relaxed); + self.inner().strong.fetch_add(1, Relaxed); Arc { _ptr: self._ptr } } } @@ -273,8 +274,8 @@ impl Arc { pub fn make_unique(&mut self) -> &mut T { // Note that we hold a strong reference, which also counts as a weak reference, so we only // clone if there is an additional reference of either kind. - if self.inner().strong.load(atomic::SeqCst) != 1 || - self.inner().weak.load(atomic::SeqCst) != 1 { + if self.inner().strong.load(SeqCst) != 1 || + self.inner().weak.load(SeqCst) != 1 { *self = Arc::new((**self).clone()) } // This unsafety is ok because we're guaranteed that the pointer returned is the *only* @@ -322,7 +323,7 @@ impl Drop for Arc { // Because `fetch_sub` is already atomic, we do not need to synchronize with other threads // unless we are going to delete the object. This same logic applies to the below // `fetch_sub` to the `weak` count. - if self.inner().strong.fetch_sub(1, atomic::Release) != 1 { return } + if self.inner().strong.fetch_sub(1, Release) != 1 { return } // This fence is needed to prevent reordering of use of the data and deletion of the data. // Because it is marked `Release`, the decreasing of the reference count synchronizes with @@ -339,14 +340,14 @@ impl Drop for Arc { // > operation before deleting the object. // // [1]: (www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html) - atomic::fence(atomic::Acquire); + atomic::fence(Acquire); // Destroy the data at this time, even though we may not free the box allocation itself // (there may still be weak pointers lying around). unsafe { drop(ptr::read(&self.inner().data)); } - if self.inner().weak.fetch_sub(1, atomic::Release) == 1 { - atomic::fence(atomic::Acquire); + if self.inner().weak.fetch_sub(1, Release) == 1 { + atomic::fence(Acquire); unsafe { deallocate(ptr as *mut u8, size_of::>(), min_align_of::>()) } } @@ -377,9 +378,9 @@ impl Weak { // count hits 0 is must never be above 0. let inner = self.inner(); loop { - let n = inner.strong.load(atomic::SeqCst); + let n = inner.strong.load(SeqCst); if n == 0 { return None } - let old = inner.strong.compare_and_swap(n, n + 1, atomic::SeqCst); + let old = inner.strong.compare_and_swap(n, n + 1, SeqCst); if old == n { return Some(Arc { _ptr: self._ptr }) } } } @@ -409,7 +410,7 @@ impl Clone for Weak { #[inline] fn clone(&self) -> Weak { // See comments in Arc::clone() for why this is relaxed - self.inner().weak.fetch_add(1, atomic::Relaxed); + self.inner().weak.fetch_add(1, Relaxed); Weak { _ptr: self._ptr } } } @@ -450,15 +451,15 @@ impl Drop for Weak { // If we find out that we were the last weak pointer, then its time to deallocate the data // entirely. See the discussion in Arc::drop() about the memory orderings - if self.inner().weak.fetch_sub(1, atomic::Release) == 1 { - atomic::fence(atomic::Acquire); + if self.inner().weak.fetch_sub(1, Release) == 1 { + atomic::fence(Acquire); unsafe { deallocate(ptr as *mut u8, size_of::>(), min_align_of::>()) } } } } -#[unstable = "waiting on PartialEq"] +#[stable] impl PartialEq for Arc { /// Equality for two `Arc`s. /// @@ -490,7 +491,7 @@ impl PartialEq for Arc { /// ``` fn ne(&self, other: &Arc) -> bool { *(*self) != *(*other) } } -#[unstable = "waiting on PartialOrd"] +#[stable] impl PartialOrd for Arc { /// Partial comparison for two `Arc`s. /// @@ -569,11 +570,11 @@ impl PartialOrd for Arc { /// ``` fn ge(&self, other: &Arc) -> bool { *(*self) >= *(*other) } } -#[unstable = "waiting on Ord"] +#[stable] impl Ord for Arc { fn cmp(&self, other: &Arc) -> Ordering { (**self).cmp(&**other) } } -#[unstable = "waiting on Eq"] +#[stable] impl Eq for Arc {} impl fmt::Show for Arc { @@ -599,6 +600,7 @@ mod tests { use std::option::Option::{Some, None}; use std::str::Str; use std::sync::atomic; + use std::sync::atomic::Ordering::{Acquire, SeqCst}; use std::task; use std::kinds::Send; use std::vec::Vec; @@ -613,7 +615,7 @@ mod tests { unsafe { match *self { Canary(c) => { - (*c).fetch_add(1, atomic::SeqCst); + (*c).fetch_add(1, SeqCst); } } } @@ -732,7 +734,7 @@ mod tests { let mut canary = atomic::AtomicUint::new(0); let x = Arc::new(Canary(&mut canary as *mut atomic::AtomicUint)); drop(x); - assert!(canary.load(atomic::Acquire) == 1); + assert!(canary.load(Acquire) == 1); } #[test] @@ -740,9 +742,9 @@ mod tests { let mut canary = atomic::AtomicUint::new(0); let arc = Arc::new(Canary(&mut canary as *mut atomic::AtomicUint)); let arc_weak = arc.downgrade(); - assert!(canary.load(atomic::Acquire) == 0); + assert!(canary.load(Acquire) == 0); drop(arc); - assert!(canary.load(atomic::Acquire) == 1); + assert!(canary.load(Acquire) == 1); drop(arc_weak); } diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 3c6b2d2cbc068..74f0599e486e1 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -72,12 +72,14 @@ impl Clone for Box { } } +#[stable] impl PartialEq for Box { #[inline] fn eq(&self, other: &Box) -> bool { PartialEq::eq(&**self, &**other) } #[inline] fn ne(&self, other: &Box) -> bool { PartialEq::ne(&**self, &**other) } } +#[stable] impl PartialOrd for Box { #[inline] fn partial_cmp(&self, other: &Box) -> Option { @@ -92,12 +94,14 @@ impl PartialOrd for Box { #[inline] fn gt(&self, other: &Box) -> bool { PartialOrd::gt(&**self, &**other) } } +#[stable] impl Ord for Box { #[inline] fn cmp(&self, other: &Box) -> Ordering { Ord::cmp(&**self, &**other) } -} + +#[stable]} impl Eq for Box {} impl> Hash for Box { diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 214fae02ce272..75d4342083b98 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -452,7 +452,7 @@ impl Default for Rc { } } -#[unstable = "PartialEq is unstable."] +#[stable] impl PartialEq for Rc { /// Equality for two `Rc`s. /// @@ -487,10 +487,10 @@ impl PartialEq for Rc { fn ne(&self, other: &Rc) -> bool { **self != **other } } -#[unstable = "Eq is unstable."] +#[stable] impl Eq for Rc {} -#[unstable = "PartialOrd is unstable."] +#[stable] impl PartialOrd for Rc { /// Partial comparison for two `Rc`s. /// @@ -575,7 +575,7 @@ impl PartialOrd for Rc { fn ge(&self, other: &Rc) -> bool { **self >= **other } } -#[unstable = "Ord is unstable."] +#[stable] impl Ord for Rc { /// Comparison for two `Rc`s. /// diff --git a/src/libcollections/binary_heap.rs b/src/libcollections/binary_heap.rs index a2f38bb667447..2427422f74320 100644 --- a/src/libcollections/binary_heap.rs +++ b/src/libcollections/binary_heap.rs @@ -66,7 +66,7 @@ //! // for a simpler implementation. //! fn shortest_path(adj_list: &Vec>, start: uint, goal: uint) -> uint { //! // dist[node] = current shortest distance from `start` to `node` -//! let mut dist = Vec::from_elem(adj_list.len(), uint::MAX); +//! let mut dist: Vec<_> = range(0, adj_list.len()).map(|_| uint::MAX).collect(); //! //! let mut heap = BinaryHeap::new(); //! @@ -563,6 +563,13 @@ pub struct Iter <'a, T: 'a> { iter: slice::Iter<'a, T>, } +// FIXME(#19839) Remove in favor of `#[deriving(Clone)]` +impl<'a, T> Clone for Iter<'a, T> { + fn clone(&self) -> Iter<'a, T> { + Iter { iter: self.iter.clone() } + } +} + impl<'a, T> Iterator<&'a T> for Iter<'a, T> { #[inline] fn next(&mut self) -> Option<&'a T> { self.iter.next() } diff --git a/src/libcollections/bit.rs b/src/libcollections/bit.rs index 430d7210bf69b..e29f19bbed369 100644 --- a/src/libcollections/bit.rs +++ b/src/libcollections/bit.rs @@ -85,7 +85,7 @@ use core::prelude::*; use core::cmp; use core::default::Default; use core::fmt; -use core::iter::{Cloned, Chain, Enumerate, Repeat, Skip, Take}; +use core::iter::{Cloned, Chain, Enumerate, Repeat, Skip, Take, repeat}; use core::iter; use core::num::Int; use core::slice::{Iter, IterMut}; @@ -267,7 +267,7 @@ impl Bitv { pub fn from_elem(nbits: uint, bit: bool) -> Bitv { let nblocks = blocks_for_bits(nbits); let mut bitv = Bitv { - storage: Vec::from_elem(nblocks, if bit { !0u32 } else { 0u32 }), + storage: repeat(if bit { !0u32 } else { 0u32 }).take(nblocks).collect(), nbits: nbits }; bitv.fix_last_block(); @@ -651,7 +651,7 @@ impl Bitv { let len = self.nbits/8 + if self.nbits % 8 == 0 { 0 } else { 1 }; - Vec::from_fn(len, |i| + range(0, len).map(|i| bit(self, i, 0) | bit(self, i, 1) | bit(self, i, 2) | @@ -660,7 +660,7 @@ impl Bitv { bit(self, i, 5) | bit(self, i, 6) | bit(self, i, 7) - ) + ).collect() } /// Deprecated: Use `iter().collect()`. @@ -834,7 +834,7 @@ impl Bitv { // Allocate new words, if needed if new_nblocks > self.storage.len() { let to_add = new_nblocks - self.storage.len(); - self.storage.grow(to_add, full_value); + self.storage.extend(repeat(full_value).take(to_add)); } // Adjust internal bit count @@ -965,6 +965,7 @@ impl Clone for Bitv { } } +#[stable] impl PartialOrd for Bitv { #[inline] fn partial_cmp(&self, other: &Bitv) -> Option { @@ -972,6 +973,7 @@ impl PartialOrd for Bitv { } } +#[stable] impl Ord for Bitv { #[inline] fn cmp(&self, other: &Bitv) -> Ordering { @@ -997,6 +999,7 @@ impl hash::Hash for Bitv { } } +#[stable] impl cmp::PartialEq for Bitv { #[inline] fn eq(&self, other: &Bitv) -> bool { @@ -1007,9 +1010,11 @@ impl cmp::PartialEq for Bitv { } } +#[stable] impl cmp::Eq for Bitv {} /// An iterator for `Bitv`. +#[deriving(Clone)] pub struct Bits<'a> { bitv: &'a Bitv, next_idx: uint, @@ -1129,6 +1134,7 @@ impl Extend for BitvSet { } } +#[stable] impl PartialOrd for BitvSet { #[inline] fn partial_cmp(&self, other: &BitvSet) -> Option { @@ -1137,6 +1143,7 @@ impl PartialOrd for BitvSet { } } +#[stable] impl Ord for BitvSet { #[inline] fn cmp(&self, other: &BitvSet) -> Ordering { @@ -1145,6 +1152,7 @@ impl Ord for BitvSet { } } +#[stable] impl cmp::PartialEq for BitvSet { #[inline] fn eq(&self, other: &BitvSet) -> bool { @@ -1153,6 +1161,7 @@ impl cmp::PartialEq for BitvSet { } } +#[stable] impl cmp::Eq for BitvSet {} impl BitvSet { @@ -1739,12 +1748,14 @@ impl hash::Hash for BitvSet { } /// An iterator for `BitvSet`. +#[deriving(Clone)] pub struct BitPositions<'a> { set: &'a BitvSet, next_idx: uint } /// An iterator combining two `BitvSet` iterators. +#[deriving(Clone)] pub struct TwoBitPositions<'a> { set: &'a BitvSet, other: &'a BitvSet, diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index 65c644da3d892..a3dff3e870658 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -843,6 +843,7 @@ impl Default for BTreeMap { } } +#[stable] impl PartialEq for BTreeMap { fn eq(&self, other: &BTreeMap) -> bool { self.len() == other.len() && @@ -850,8 +851,10 @@ impl PartialEq for BTreeMap { } } +#[stable] impl Eq for BTreeMap {} +#[stable] impl PartialOrd for BTreeMap { #[inline] fn partial_cmp(&self, other: &BTreeMap) -> Option { @@ -859,6 +862,7 @@ impl PartialOrd for BTreeMap { } } +#[stable] impl Ord for BTreeMap { #[inline] fn cmp(&self, other: &BTreeMap) -> Ordering { diff --git a/src/libcollections/btree/node.rs b/src/libcollections/btree/node.rs index 2c3c546fdb7ff..3907f28092a37 100644 --- a/src/libcollections/btree/node.rs +++ b/src/libcollections/btree/node.rs @@ -21,6 +21,7 @@ use core::prelude::*; use core::{slice, mem, ptr, cmp, num, raw}; use core::iter::Zip; use core::borrow::BorrowFrom; +use core::ptr::Unique; use alloc::heap; /// Represents the result of an Insertion: either the item fit, or the node had to split @@ -51,11 +52,11 @@ pub struct Node { // These will never be null during normal usage of a `Node`. However, to avoid the need for a // drop flag, `Node::drop` zeroes `keys`, signaling that the `Node` has already been cleaned // up. - keys: *mut K, - vals: *mut V, + keys: Unique, + vals: Unique, // In leaf nodes, this will be null, and no space will be allocated for edges. - edges: *mut Node, + edges: Unique>, // At any given time, there will be `_len` keys, `_len` values, and (in an internal node) // `_len + 1` edges. In a leaf node, there will never be any edges. @@ -255,7 +256,7 @@ impl Drop for RawItems { #[unsafe_destructor] impl Drop for Node { fn drop(&mut self) { - if self.keys.is_null() { + if self.keys.0.is_null() { // We have already cleaned up this node. return; } @@ -269,7 +270,7 @@ impl Drop for Node { self.destroy(); } - self.keys = ptr::null_mut(); + self.keys.0 = ptr::null_mut(); } } @@ -285,9 +286,9 @@ impl Node { let (vals_offset, edges_offset) = calculate_offsets_generic::(capacity, false); Node { - keys: buffer as *mut K, - vals: buffer.offset(vals_offset as int) as *mut V, - edges: buffer.offset(edges_offset as int) as *mut Node, + keys: Unique(buffer as *mut K), + vals: Unique(buffer.offset(vals_offset as int) as *mut V), + edges: Unique(buffer.offset(edges_offset as int) as *mut Node), _len: 0, _capacity: capacity, } @@ -303,9 +304,9 @@ impl Node { let (vals_offset, _) = calculate_offsets_generic::(capacity, true); Node { - keys: buffer as *mut K, - vals: unsafe { buffer.offset(vals_offset as int) as *mut V }, - edges: ptr::null_mut(), + keys: Unique(buffer as *mut K), + vals: Unique(unsafe { buffer.offset(vals_offset as int) as *mut V }), + edges: Unique(ptr::null_mut()), _len: 0, _capacity: capacity, } @@ -314,18 +315,18 @@ impl Node { unsafe fn destroy(&mut self) { let (alignment, size) = calculate_allocation_generic::(self.capacity(), self.is_leaf()); - heap::deallocate(self.keys as *mut u8, size, alignment); + heap::deallocate(self.keys.0 as *mut u8, size, alignment); } #[inline] pub fn as_slices<'a>(&'a self) -> (&'a [K], &'a [V]) { unsafe {( mem::transmute(raw::Slice { - data: self.keys as *const K, + data: self.keys.0 as *const K, len: self.len() }), mem::transmute(raw::Slice { - data: self.vals as *const V, + data: self.vals.0 as *const V, len: self.len() }) )} @@ -344,7 +345,7 @@ impl Node { } else { unsafe { mem::transmute(raw::Slice { - data: self.edges as *const Node, + data: self.edges.0 as *const Node, len: self.len() + 1 }) } @@ -554,10 +555,10 @@ impl Node { let node = mem::replace(left_and_out, unsafe { Node::new_internal(capacity_from_b(b)) }); left_and_out._len = 1; unsafe { - ptr::write(left_and_out.keys_mut().unsafe_mut(0), key); - ptr::write(left_and_out.vals_mut().unsafe_mut(0), value); - ptr::write(left_and_out.edges_mut().unsafe_mut(0), node); - ptr::write(left_and_out.edges_mut().unsafe_mut(1), right); + ptr::write(left_and_out.keys_mut().get_unchecked_mut(0), key); + ptr::write(left_and_out.vals_mut().get_unchecked_mut(0), value); + ptr::write(left_and_out.edges_mut().get_unchecked_mut(0), node); + ptr::write(left_and_out.edges_mut().get_unchecked_mut(1), right); } } @@ -573,7 +574,7 @@ impl Node { /// If the node has any children pub fn is_leaf(&self) -> bool { - self.edges.is_null() + self.edges.0.is_null() } /// if the node has too few elements @@ -636,7 +637,7 @@ impl<'a, K: 'a, V: 'a> Handle<&'a Node, handle::Edge, handle::Internal> { /// making it more suitable for moving down a chain of nodes. pub fn into_edge(self) -> &'a Node { unsafe { - self.node.edges().unsafe_get(self.index) + self.node.edges().get_unchecked(self.index) } } } @@ -647,7 +648,7 @@ impl<'a, K: 'a, V: 'a> Handle<&'a mut Node, handle::Edge, handle::Internal /// `edge_mut`, making it more suitable for moving down a chain of nodes. pub fn into_edge_mut(self) -> &'a mut Node { unsafe { - self.node.edges_mut().unsafe_mut(self.index) + self.node.edges_mut().get_unchecked_mut(self.index) } } } @@ -721,7 +722,7 @@ impl>> Handle &mut Node { unsafe { - self.node.edges_mut().unsafe_mut(self.index) + self.node.edges_mut().get_unchecked_mut(self.index) } } @@ -829,8 +830,8 @@ impl<'a, K: 'a, V: 'a, NodeType> Handle<&'a Node, handle::KV, NodeType> { let (keys, vals) = self.node.as_slices(); unsafe { ( - keys.unsafe_get(self.index), - vals.unsafe_get(self.index) + keys.get_unchecked(self.index), + vals.get_unchecked(self.index) ) } } @@ -844,8 +845,8 @@ impl<'a, K: 'a, V: 'a, NodeType> Handle<&'a mut Node, handle::KV, NodeType let (keys, vals) = self.node.as_slices_mut(); unsafe { ( - keys.unsafe_mut(self.index), - vals.unsafe_mut(self.index) + keys.get_unchecked_mut(self.index), + vals.get_unchecked_mut(self.index) ) } } @@ -869,14 +870,14 @@ impl<'a, K: 'a, V: 'a, NodeRef: Deref> + 'a, NodeType> Handle &'a K { - // unsafe { self.node.keys().unsafe_get(self.index) } + // unsafe { self.node.keys().get_unchecked(self.index) } // } // // /// Returns a reference to the value pointed-to by this handle. This doesn't return a // /// reference with a lifetime as large as `into_kv_mut`, but it also does not consume the // /// handle. // pub fn val(&'a self) -> &'a V { - // unsafe { self.node.vals().unsafe_get(self.index) } + // unsafe { self.node.vals().get_unchecked(self.index) } // } } @@ -886,14 +887,14 @@ impl<'a, K: 'a, V: 'a, NodeRef: DerefMut> + 'a, NodeType> Handle &'a mut K { - unsafe { self.node.keys_mut().unsafe_mut(self.index) } + unsafe { self.node.keys_mut().get_unchecked_mut(self.index) } } /// Returns a mutable reference to the value pointed-to by this handle. This doesn't return a /// reference with a lifetime as large as `into_kv_mut`, but it also does not consume the /// handle. pub fn val_mut(&'a mut self) -> &'a mut V { - unsafe { self.node.vals_mut().unsafe_mut(self.index) } + unsafe { self.node.vals_mut().get_unchecked_mut(self.index) } } } @@ -1057,7 +1058,7 @@ impl Node { vals: RawItems::from_slice(self.vals()), edges: RawItems::from_slice(self.edges()), - ptr: self.keys as *mut u8, + ptr: self.keys.0 as *mut u8, capacity: self.capacity(), is_leaf: self.is_leaf() }, @@ -1077,7 +1078,7 @@ impl Node { debug_assert!(!self.is_leaf()); unsafe { - let ret = ptr::read(self.edges().unsafe_get(0)); + let ret = ptr::read(self.edges().get_unchecked(0)); self.destroy(); ptr::write(self, ret); } @@ -1091,8 +1092,8 @@ impl Node { unsafe fn push_kv(&mut self, key: K, val: V) { let len = self.len(); - ptr::write(self.keys_mut().unsafe_mut(len), key); - ptr::write(self.vals_mut().unsafe_mut(len), val); + ptr::write(self.keys_mut().get_unchecked_mut(len), key); + ptr::write(self.vals_mut().get_unchecked_mut(len), val); self._len += 1; } @@ -1102,7 +1103,7 @@ impl Node { unsafe fn push_edge(&mut self, edge: Node) { let len = self.len(); - ptr::write(self.edges_mut().unsafe_mut(len), edge); + ptr::write(self.edges_mut().get_unchecked_mut(len), edge); } // This must be followed by insert_edge on an internal node. @@ -1119,12 +1120,12 @@ impl Node { self.len() - index ); - ptr::write(self.keys_mut().unsafe_mut(index), key); - ptr::write(self.vals_mut().unsafe_mut(index), val); + ptr::write(self.keys_mut().get_unchecked_mut(index), key); + ptr::write(self.vals_mut().get_unchecked_mut(index), val); self._len += 1; - self.vals_mut().unsafe_mut(index) + self.vals_mut().get_unchecked_mut(index) } // This can only be called immediately after a call to insert_kv. @@ -1135,14 +1136,14 @@ impl Node { self.edges().as_ptr().offset(index as int), self.len() - index ); - ptr::write(self.edges_mut().unsafe_mut(index), edge); + ptr::write(self.edges_mut().get_unchecked_mut(index), edge); } // This must be followed by pop_edge on an internal node. #[inline] unsafe fn pop_kv(&mut self) -> (K, V) { - let key = ptr::read(self.keys().unsafe_get(self.len() - 1)); - let val = ptr::read(self.vals().unsafe_get(self.len() - 1)); + let key = ptr::read(self.keys().get_unchecked(self.len() - 1)); + let val = ptr::read(self.vals().get_unchecked(self.len() - 1)); self._len -= 1; @@ -1152,7 +1153,7 @@ impl Node { // This can only be called immediately after a call to pop_kv. #[inline] unsafe fn pop_edge(&mut self) -> Node { - let edge = ptr::read(self.edges().unsafe_get(self.len() + 1)); + let edge = ptr::read(self.edges().get_unchecked(self.len() + 1)); edge } @@ -1160,8 +1161,8 @@ impl Node { // This must be followed by remove_edge on an internal node. #[inline] unsafe fn remove_kv(&mut self, index: uint) -> (K, V) { - let key = ptr::read(self.keys().unsafe_get(index)); - let val = ptr::read(self.vals().unsafe_get(index)); + let key = ptr::read(self.keys().get_unchecked(index)); + let val = ptr::read(self.vals().get_unchecked(index)); ptr::copy_memory( self.keys_mut().as_mut_ptr().offset(index as int), @@ -1182,7 +1183,7 @@ impl Node { // This can only be called immediately after a call to remove_kv. #[inline] unsafe fn remove_edge(&mut self, index: uint) -> Node { - let edge = ptr::read(self.edges().unsafe_get(index)); + let edge = ptr::read(self.edges().get_unchecked(index)); ptr::copy_memory( self.edges_mut().as_mut_ptr().offset(index as int), @@ -1229,8 +1230,8 @@ impl Node { ); } - let key = ptr::read(self.keys().unsafe_get(right_offset - 1)); - let val = ptr::read(self.vals().unsafe_get(right_offset - 1)); + let key = ptr::read(self.keys().get_unchecked(right_offset - 1)); + let val = ptr::read(self.vals().get_unchecked(right_offset - 1)); self._len = right_offset - 1; @@ -1249,8 +1250,8 @@ impl Node { let old_len = self.len(); self._len += right.len() + 1; - ptr::write(self.keys_mut().unsafe_mut(old_len), key); - ptr::write(self.vals_mut().unsafe_mut(old_len), val); + ptr::write(self.keys_mut().get_unchecked_mut(old_len), key); + ptr::write(self.vals_mut().get_unchecked_mut(old_len), val); ptr::copy_nonoverlapping_memory( self.keys_mut().as_mut_ptr().offset(old_len as int + 1), diff --git a/src/libcollections/dlist.rs b/src/libcollections/dlist.rs index d8ce79f4fe90d..82dabedd871a4 100644 --- a/src/libcollections/dlist.rs +++ b/src/libcollections/dlist.rs @@ -770,6 +770,7 @@ impl Extend for DList { } } +#[stable] impl PartialEq for DList { fn eq(&self, other: &DList) -> bool { self.len() == other.len() && @@ -782,14 +783,17 @@ impl PartialEq for DList { } } +#[stable] impl Eq for DList {} +#[stable] impl PartialOrd for DList { fn partial_cmp(&self, other: &DList) -> Option { iter::order::partial_cmp(self.iter(), other.iter()) } } +#[stable] impl Ord for DList { #[inline] fn cmp(&self, other: &DList) -> Ordering { @@ -1290,8 +1294,10 @@ mod tests { v.pop(); } 1 => { - m.pop_front(); - v.remove(0); + if !v.is_empty() { + m.pop_front(); + v.remove(0); + } } 2 | 4 => { m.push_front(-i); diff --git a/src/libcollections/enum_set.rs b/src/libcollections/enum_set.rs index fd04ce94247b7..b484fc41ff6e5 100644 --- a/src/libcollections/enum_set.rs +++ b/src/libcollections/enum_set.rs @@ -213,6 +213,16 @@ pub struct Iter { bits: uint, } +// FIXME(#19839) Remove in favor of `#[deriving(Clone)]` +impl Clone for Iter { + fn clone(&self) -> Iter { + Iter { + index: self.index, + bits: self.bits, + } + } +} + impl Iter { fn new(bits: uint) -> Iter { Iter { index: 0, bits: bits } diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index fe9d8de440a17..688214140c1be 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -128,8 +128,8 @@ mod prelude { pub use unicode::char::UnicodeChar; // from collections. - pub use slice::{CloneSliceExt, VectorVector}; - pub use str::{IntoMaybeOwned, StrVector}; + pub use slice::{CloneSliceExt, SliceConcatExt}; + pub use str::IntoMaybeOwned; pub use string::{String, ToString}; pub use vec::Vec; } diff --git a/src/libcollections/ring_buf.rs b/src/libcollections/ring_buf.rs index df8e08f07a321..aeda7309064f7 100644 --- a/src/libcollections/ring_buf.rs +++ b/src/libcollections/ring_buf.rs @@ -48,6 +48,12 @@ pub struct RingBuf { ptr: *mut T } +#[stable] +unsafe impl Send for RingBuf {} + +#[stable] +unsafe impl Sync for RingBuf {} + #[stable] impl Clone for RingBuf { fn clone(&self) -> RingBuf { @@ -1129,6 +1135,17 @@ pub struct Iter<'a, T:'a> { head: uint } +// FIXME(#19839) Remove in favor of `#[deriving(Clone)]` +impl<'a, T> Clone for Iter<'a, T> { + fn clone(&self) -> Iter<'a, T> { + Iter { + ring: self.ring, + tail: self.tail, + head: self.head + } + } +} + impl<'a, T> Iterator<&'a T> for Iter<'a, T> { #[inline] fn next(&mut self) -> Option<&'a T> { @@ -1137,7 +1154,7 @@ impl<'a, T> Iterator<&'a T> for Iter<'a, T> { } let tail = self.tail; self.tail = wrap_index(self.tail + 1, self.ring.len()); - unsafe { Some(self.ring.unsafe_get(tail)) } + unsafe { Some(self.ring.get_unchecked(tail)) } } #[inline] @@ -1154,7 +1171,7 @@ impl<'a, T> DoubleEndedIterator<&'a T> for Iter<'a, T> { return None; } self.head = wrap_index(self.head - 1, self.ring.len()); - unsafe { Some(self.ring.unsafe_get(self.head)) } + unsafe { Some(self.ring.get_unchecked(self.head)) } } } @@ -1173,7 +1190,7 @@ impl<'a, T> RandomAccessIterator<&'a T> for Iter<'a, T> { None } else { let idx = wrap_index(self.tail + j, self.ring.len()); - unsafe { Some(self.ring.unsafe_get(idx)) } + unsafe { Some(self.ring.get_unchecked(idx)) } } } } @@ -1290,6 +1307,7 @@ impl<'a, T: 'a> DoubleEndedIterator for Drain<'a, T> { impl<'a, T: 'a> ExactSizeIterator for Drain<'a, T> {} +#[stable] impl PartialEq for RingBuf { fn eq(&self, other: &RingBuf) -> bool { self.len() == other.len() && @@ -1297,14 +1315,17 @@ impl PartialEq for RingBuf { } } +#[stable] impl Eq for RingBuf {} +#[stable] impl PartialOrd for RingBuf { fn partial_cmp(&self, other: &RingBuf) -> Option { iter::order::partial_cmp(self.iter(), other.iter()) } } +#[stable] impl Ord for RingBuf { #[inline] fn cmp(&self, other: &RingBuf) -> Ordering { diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index c55a8ba104ebe..02b70c0f169d8 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -96,1245 +96,1318 @@ use core::mem::size_of; use core::mem; use core::ops::{FnMut,SliceMut}; use core::prelude::{Clone, Greater, Iterator, IteratorExt, Less, None, Option}; -use core::prelude::{Ord, Ordering, PtrExt, Some, range}; +use core::prelude::{Ord, Ordering, PtrExt, Some, range, IteratorCloneExt, Result}; use core::ptr; use core::slice as core_slice; use self::Direction::*; use vec::Vec; -pub use core::slice::{Chunks, AsSlice, SplitsN, Windows}; +pub use core::slice::{Chunks, AsSlice, Windows}; pub use core::slice::{Iter, IterMut, PartialEqSliceExt}; -pub use core::slice::{ImmutableIntSlice, MutableIntSlice}; -pub use core::slice::{MutSplits, MutChunks, Splits}; +pub use core::slice::{IntSliceExt, SplitMut, ChunksMut, Split}; +pub use core::slice::{SplitN, RSplitN, SplitNMut, RSplitNMut}; pub use core::slice::{bytes, mut_ref_slice, ref_slice}; -pub use core::slice::{from_raw_buf, from_raw_mut_buf, BinarySearchResult}; +pub use core::slice::{from_raw_buf, from_raw_mut_buf}; -// Functional utilities +#[deprecated = "use Iter instead"] +pub type Items<'a, T:'a> = Iter<'a, T>; -#[allow(missing_docs)] -pub trait VectorVector for Sized? { - // FIXME #5898: calling these .concat and .connect conflicts with - // StrVector::con{cat,nect}, since they have generic contents. - /// Flattens a vector of vectors of `T` into a single `Vec`. - fn concat_vec(&self) -> Vec; +#[deprecated = "use IterMut instead"] +pub type MutItems<'a, T:'a> = IterMut<'a, T>; - /// Concatenate a vector of vectors, placing a given separator between each. - fn connect_vec(&self, sep: &T) -> Vec; -} +//////////////////////////////////////////////////////////////////////////////// +// Basic slice extension methods +//////////////////////////////////////////////////////////////////////////////// -impl<'a, T: Clone, V: AsSlice> VectorVector for [V] { - fn concat_vec(&self) -> Vec { - let size = self.iter().fold(0u, |acc, v| acc + v.as_slice().len()); - let mut result = Vec::with_capacity(size); - for v in self.iter() { - result.push_all(v.as_slice()) - } - result - } +/// Allocating extension methods for slices. +#[unstable = "needs associated types, may merge with other traits"] +pub trait SliceExt for Sized? { + /// Sorts the slice, in place, using `compare` to compare + /// elements. + /// + /// This sort is `O(n log n)` worst-case and stable, but allocates + /// approximately `2 * n`, where `n` is the length of `self`. + /// + /// # Examples + /// + /// ```rust + /// let mut v = [5i, 4, 1, 3, 2]; + /// v.sort_by(|a, b| a.cmp(b)); + /// assert!(v == [1, 2, 3, 4, 5]); + /// + /// // reverse sorting + /// v.sort_by(|a, b| b.cmp(a)); + /// assert!(v == [5, 4, 3, 2, 1]); + /// ``` + #[stable] + fn sort_by(&mut self, compare: F) where F: FnMut(&T, &T) -> Ordering; - fn connect_vec(&self, sep: &T) -> Vec { - let size = self.iter().fold(0u, |acc, v| acc + v.as_slice().len()); - let mut result = Vec::with_capacity(size + self.len()); - let mut first = true; - for v in self.iter() { - if first { first = false } else { result.push(sep.clone()) } - result.push_all(v.as_slice()) - } - result - } -} + /// Consumes `src` and moves as many elements as it can into `self` + /// from the range [start,end). + /// + /// Returns the number of elements copied (the shorter of `self.len()` + /// and `end - start`). + /// + /// # Arguments + /// + /// * src - A mutable vector of `T` + /// * start - The index into `src` to start copying from + /// * end - The index into `src` to stop copying from + /// + /// # Examples + /// + /// ```rust + /// let mut a = [1i, 2, 3, 4, 5]; + /// let b = vec![6i, 7, 8]; + /// let num_moved = a.move_from(b, 0, 3); + /// assert_eq!(num_moved, 3); + /// assert!(a == [6i, 7, 8, 4, 5]); + /// ``` + #[experimental = "uncertain about this API approach"] + fn move_from(&mut self, src: Vec, start: uint, end: uint) -> uint; -/// An iterator that yields the element swaps needed to produce -/// a sequence of all possible permutations for an indexed sequence of -/// elements. Each permutation is only a single swap apart. -/// -/// The Steinhaus-Johnson-Trotter algorithm is used. -/// -/// Generates even and odd permutations alternately. -/// -/// The last generated swap is always (0, 1), and it returns the -/// sequence to its initial order. -pub struct ElementSwaps { - sdir: Vec, - /// If `true`, emit the last swap that returns the sequence to initial - /// state. - emit_reset: bool, - swaps_made : uint, -} + /// Returns a subslice spanning the interval [`start`, `end`). + /// + /// Panics when the end of the new slice lies beyond the end of the + /// original slice (i.e. when `end > self.len()`) or when `start > end`. + /// + /// Slicing with `start` equal to `end` yields an empty slice. + #[experimental = "will be replaced by slice syntax"] + fn slice(&self, start: uint, end: uint) -> &[T]; -impl ElementSwaps { - /// Creates an `ElementSwaps` iterator for a sequence of `length` elements. - pub fn new(length: uint) -> ElementSwaps { - // Initialize `sdir` with a direction that position should move in - // (all negative at the beginning) and the `size` of the - // element (equal to the original index). - ElementSwaps{ - emit_reset: true, - sdir: range(0, length).map(|i| SizeDirection{ size: i, dir: Neg }).collect(), - swaps_made: 0 - } - } -} + /// Returns a subslice from `start` to the end of the slice. + /// + /// Panics when `start` is strictly greater than the length of the original slice. + /// + /// Slicing from `self.len()` yields an empty slice. + #[experimental = "will be replaced by slice syntax"] + fn slice_from(&self, start: uint) -> &[T]; -#[deriving(Copy)] -enum Direction { Pos, Neg } + /// Returns a subslice from the start of the slice to `end`. + /// + /// Panics when `end` is strictly greater than the length of the original slice. + /// + /// Slicing to `0` yields an empty slice. + #[experimental = "will be replaced by slice syntax"] + fn slice_to(&self, end: uint) -> &[T]; -/// An `Index` and `Direction` together. -#[deriving(Copy)] -struct SizeDirection { - size: uint, - dir: Direction, -} + /// Divides one slice into two at an index. + /// + /// The first will contain all indices from `[0, mid)` (excluding + /// the index `mid` itself) and the second will contain all + /// indices from `[mid, len)` (excluding the index `len` itself). + /// + /// Panics if `mid > len`. + #[stable] + fn split_at(&self, mid: uint) -> (&[T], &[T]); -impl Iterator<(uint, uint)> for ElementSwaps { - #[inline] - fn next(&mut self) -> Option<(uint, uint)> { - fn new_pos(i: uint, s: Direction) -> uint { - i + match s { Pos => 1, Neg => -1 } - } + /// Returns an iterator over the slice + #[stable] + fn iter(&self) -> Iter; - // Find the index of the largest mobile element: - // The direction should point into the vector, and the - // swap should be with a smaller `size` element. - let max = self.sdir.iter().map(|&x| x).enumerate() - .filter(|&(i, sd)| - new_pos(i, sd.dir) < self.sdir.len() && - self.sdir[new_pos(i, sd.dir)].size < sd.size) - .max_by(|&(_, sd)| sd.size); - match max { - Some((i, sd)) => { - let j = new_pos(i, sd.dir); - self.sdir.swap(i, j); + /// Returns an iterator over subslices separated by elements that match + /// `pred`. The matched element is not contained in the subslices. + #[stable] + fn split(&self, pred: F) -> Split + where F: FnMut(&T) -> bool; - // Swap the direction of each larger SizeDirection - for x in self.sdir.iter_mut() { - if x.size > sd.size { - x.dir = match x.dir { Pos => Neg, Neg => Pos }; - } - } - self.swaps_made += 1; - Some((i, j)) - }, - None => if self.emit_reset { - self.emit_reset = false; - if self.sdir.len() > 1 { - // The last swap - self.swaps_made += 1; - Some((0, 1)) - } else { - // Vector is of the form [] or [x], and the only permutation is itself - self.swaps_made += 1; - Some((0,0)) - } - } else { None } - } - } + /// Returns an iterator over subslices separated by elements that match + /// `pred`, limited to splitting at most `n` times. The matched element is + /// not contained in the subslices. + #[stable] + fn splitn(&self, n: uint, pred: F) -> SplitN + where F: FnMut(&T) -> bool; - #[inline] - fn size_hint(&self) -> (uint, Option) { - // For a vector of size n, there are exactly n! permutations. - let n = range(2, self.sdir.len() + 1).product(); - (n - self.swaps_made, Some(n - self.swaps_made)) - } -} + /// Returns an iterator over subslices separated by elements that match + /// `pred` limited to splitting at most `n` times. This starts at the end of + /// the slice and works backwards. The matched element is not contained in + /// the subslices. + #[stable] + fn rsplitn(&self, n: uint, pred: F) -> RSplitN + where F: FnMut(&T) -> bool; -/// An iterator that uses `ElementSwaps` to iterate through -/// all possible permutations of a vector. -/// -/// The first iteration yields a clone of the vector as it is, -/// then each successive element is the vector with one -/// swap applied. -/// -/// Generates even and odd permutations alternately. -pub struct Permutations { - swaps: ElementSwaps, - v: Vec, -} + /// Returns an iterator over all contiguous windows of length + /// `size`. The windows overlap. If the slice is shorter than + /// `size`, the iterator returns no values. + /// + /// # Panics + /// + /// Panics if `size` is 0. + /// + /// # Example + /// + /// Print the adjacent pairs of a slice (i.e. `[1,2]`, `[2,3]`, + /// `[3,4]`): + /// + /// ```rust + /// let v = &[1i, 2, 3, 4]; + /// for win in v.windows(2) { + /// println!("{}", win); + /// } + /// ``` + #[stable] + fn windows(&self, size: uint) -> Windows; -impl Iterator> for Permutations { - #[inline] - fn next(&mut self) -> Option> { - match self.swaps.next() { - None => None, - Some((0,0)) => Some(self.v.clone()), - Some((a, b)) => { - let elt = self.v.clone(); - self.v.swap(a, b); - Some(elt) - } - } - } + /// Returns an iterator over `size` elements of the slice at a + /// time. The chunks do not overlap. If `size` does not divide the + /// length of the slice, then the last chunk will not have length + /// `size`. + /// + /// # Panics + /// + /// Panics if `size` is 0. + /// + /// # Example + /// + /// Print the slice two elements at a time (i.e. `[1,2]`, + /// `[3,4]`, `[5]`): + /// + /// ```rust + /// let v = &[1i, 2, 3, 4, 5]; + /// for win in v.chunks(2) { + /// println!("{}", win); + /// } + /// ``` + #[stable] + fn chunks(&self, size: uint) -> Chunks; - #[inline] - fn size_hint(&self) -> (uint, Option) { - self.swaps.size_hint() - } -} + /// Returns the element of a slice at the given index, or `None` if the + /// index is out of bounds. + #[stable] + fn get(&self, index: uint) -> Option<&T>; -/// Extension methods for boxed slices. -pub trait BoxedSliceExt { - /// Convert `self` into a vector without clones or allocation. - fn into_vec(self) -> Vec; -} + /// Returns the first element of a slice, or `None` if it is empty. + #[stable] + fn first(&self) -> Option<&T>; + + /// Deprecated: renamed to `first`. + #[deprecated = "renamed to `first`"] + fn head(&self) -> Option<&T> { self.first() } + + /// Returns all but the first element of a slice. + #[experimental = "likely to be renamed"] + fn tail(&self) -> &[T]; + + /// Returns all but the last element of a slice. + #[experimental = "likely to be renamed"] + fn init(&self) -> &[T]; + + /// Returns the last element of a slice, or `None` if it is empty. + #[stable] + fn last(&self) -> Option<&T>; + + /// Returns a pointer to the element at the given index, without doing + /// bounds checking. + #[stable] + unsafe fn get_unchecked(&self, index: uint) -> &T; -impl BoxedSliceExt for Box<[T]> { - #[experimental] - fn into_vec(mut self) -> Vec { - unsafe { - let xs = Vec::from_raw_parts(self.as_mut_ptr(), self.len(), self.len()); - mem::forget(self); - xs - } + /// Deprecated: renamed to `get_unchecked`. + #[deprecated = "renamed to get_unchecked"] + unsafe fn unsafe_get(&self, index: uint) -> &T { + self.get_unchecked(index) } -} - -/// Allocating extension methods for slices containing `Clone` elements. -pub trait CloneSliceExt for Sized? { - /// Copies `self` into a new `Vec`. - fn to_vec(&self) -> Vec; - /// Partitions the vector into two vectors `(a, b)`, where all - /// elements of `a` satisfy `f` and all elements of `b` do not. - fn partitioned(&self, f: F) -> (Vec, Vec) where F: FnMut(&T) -> bool; + /// Returns an unsafe pointer to the slice's buffer + /// + /// The caller must ensure that the slice outlives the pointer this + /// function returns, or else it will end up pointing to garbage. + /// + /// Modifying the slice may cause its buffer to be reallocated, which + /// would also make any pointers to it invalid. + #[stable] + fn as_ptr(&self) -> *const T; - /// Creates an iterator that yields every possible permutation of the - /// vector in succession. + /// Binary search a sorted slice with a comparator function. /// - /// # Examples + /// The comparator function should implement an order consistent + /// with the sort order of the underlying slice, returning an + /// order code that indicates whether its argument is `Less`, + /// `Equal` or `Greater` the desired target. /// - /// ```rust - /// let v = [1i, 2, 3]; - /// let mut perms = v.permutations(); + /// If a matching value is found then returns `Ok`, containing + /// the index for the matched element; if no match is found then + /// `Err` is returned, containing the index where a matching + /// element could be inserted while maintaining sorted order. /// - /// for p in perms { - /// println!("{}", p); - /// } - /// ``` + /// # Example /// - /// Iterating through permutations one by one. + /// Looks up a series of four elements. The first is found, with a + /// uniquely determined position; the second and third are not + /// found; the fourth could match any position in `[1,4]`. /// /// ```rust - /// let v = [1i, 2, 3]; - /// let mut perms = v.permutations(); + /// let s = [0i, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; + /// let s = s.as_slice(); /// - /// assert_eq!(Some(vec![1i, 2, 3]), perms.next()); - /// assert_eq!(Some(vec![1i, 3, 2]), perms.next()); - /// assert_eq!(Some(vec![3i, 1, 2]), perms.next()); + /// let seek = 13; + /// assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Ok(9)); + /// let seek = 4; + /// assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Err(7)); + /// let seek = 100; + /// assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Err(13)); + /// let seek = 1; + /// let r = s.binary_search_by(|probe| probe.cmp(&seek)); + /// assert!(match r { Ok(1...4) => true, _ => false, }); /// ``` - fn permutations(&self) -> Permutations; + #[stable] + fn binary_search_by(&self, f: F) -> Result where + F: FnMut(&T) -> Ordering; - /// Copies as many elements from `src` as it can into `self` (the - /// shorter of `self.len()` and `src.len()`). Returns the number - /// of elements copied. + /// Return the number of elements in the slice /// /// # Example /// - /// ```rust - /// let mut dst = [0i, 0, 0]; - /// let src = [1i, 2]; + /// ``` + /// let a = [1i, 2, 3]; + /// assert_eq!(a.len(), 3); + /// ``` + #[stable] + fn len(&self) -> uint; + + /// Returns true if the slice has a length of 0 /// - /// assert!(dst.clone_from_slice(&src) == 2); - /// assert!(dst == [1, 2, 0]); + /// # Example /// - /// let src2 = [3i, 4, 5, 6]; - /// assert!(dst.clone_from_slice(&src2) == 3); - /// assert!(dst == [3i, 4, 5]); /// ``` - fn clone_from_slice(&mut self, &[T]) -> uint; -} - -impl CloneSliceExt for [T] { - /// Returns a copy of `v`. + /// let a = [1i, 2, 3]; + /// assert!(!a.is_empty()); + /// ``` #[inline] - fn to_vec(&self) -> Vec { - let mut vector = Vec::with_capacity(self.len()); - vector.push_all(self); - vector - } + #[stable] + fn is_empty(&self) -> bool { self.len() == 0 } + /// Returns a mutable reference to the element at the given index, + /// or `None` if the index is out of bounds + #[stable] + fn get_mut(&mut self, index: uint) -> Option<&mut T>; + /// Work with `self` as a mut slice. + /// Primarily intended for getting a &mut [T] from a [T, ..N]. + #[stable] + fn as_mut_slice(&mut self) -> &mut [T]; - #[inline] - fn partitioned(&self, mut f: F) -> (Vec, Vec) where F: FnMut(&T) -> bool { - let mut lefts = Vec::new(); - let mut rights = Vec::new(); - - for elt in self.iter() { - if f(elt) { - lefts.push((*elt).clone()); - } else { - rights.push((*elt).clone()); - } - } + /// Returns a mutable subslice spanning the interval [`start`, `end`). + /// + /// Panics when the end of the new slice lies beyond the end of the + /// original slice (i.e. when `end > self.len()`) or when `start > end`. + /// + /// Slicing with `start` equal to `end` yields an empty slice. + #[experimental = "will be replaced by slice syntax"] + fn slice_mut(&mut self, start: uint, end: uint) -> &mut [T]; - (lefts, rights) - } + /// Returns a mutable subslice from `start` to the end of the slice. + /// + /// Panics when `start` is strictly greater than the length of the original slice. + /// + /// Slicing from `self.len()` yields an empty slice. + #[experimental = "will be replaced by slice syntax"] + fn slice_from_mut(&mut self, start: uint) -> &mut [T]; - /// Returns an iterator over all permutations of a vector. - fn permutations(&self) -> Permutations { - Permutations{ - swaps: ElementSwaps::new(self.len()), - v: self.to_vec(), - } - } + /// Returns a mutable subslice from the start of the slice to `end`. + /// + /// Panics when `end` is strictly greater than the length of the original slice. + /// + /// Slicing to `0` yields an empty slice. + #[experimental = "will be replaced by slice syntax"] + fn slice_to_mut(&mut self, end: uint) -> &mut [T]; - fn clone_from_slice(&mut self, src: &[T]) -> uint { - core_slice::CloneSliceExt::clone_from_slice(self, src) + /// Returns an iterator that allows modifying each value + #[stable] + fn iter_mut(&mut self) -> IterMut; + + /// Returns a mutable pointer to the first element of a slice, or `None` if it is empty + #[stable] + fn first_mut(&mut self) -> Option<&mut T>; + + /// Depreated: renamed to `first_mut`. + #[deprecated = "renamed to first_mut"] + fn head_mut(&mut self) -> Option<&mut T> { + self.first_mut() } -} -fn insertion_sort(v: &mut [T], mut compare: F) where F: FnMut(&T, &T) -> Ordering { - let len = v.len() as int; - let buf_v = v.as_mut_ptr(); + /// Returns all but the first element of a mutable slice + #[experimental = "likely to be renamed or removed"] + fn tail_mut(&mut self) -> &mut [T]; - // 1 <= i < len; - for i in range(1, len) { - // j satisfies: 0 <= j <= i; - let mut j = i; - unsafe { - // `i` is in bounds. - let read_ptr = buf_v.offset(i) as *const T; + /// Returns all but the last element of a mutable slice + #[experimental = "likely to be renamed or removed"] + fn init_mut(&mut self) -> &mut [T]; - // find where to insert, we need to do strict <, - // rather than <=, to maintain stability. + /// Returns a mutable pointer to the last item in the slice. + #[stable] + fn last_mut(&mut self) -> Option<&mut T>; - // 0 <= j - 1 < len, so .offset(j - 1) is in bounds. - while j > 0 && - compare(&*read_ptr, &*buf_v.offset(j - 1)) == Less { - j -= 1; - } + /// Returns an iterator over mutable subslices separated by elements that + /// match `pred`. The matched element is not contained in the subslices. + #[stable] + fn split_mut(&mut self, pred: F) -> SplitMut + where F: FnMut(&T) -> bool; - // shift everything to the right, to make space to - // insert this value. + /// Returns an iterator over subslices separated by elements that match + /// `pred`, limited to splitting at most `n` times. The matched element is + /// not contained in the subslices. + #[stable] + fn splitn_mut(&mut self, n: uint, pred: F) -> SplitNMut + where F: FnMut(&T) -> bool; - // j + 1 could be `len` (for the last `i`), but in - // that case, `i == j` so we don't copy. The - // `.offset(j)` is always in bounds. + /// Returns an iterator over subslices separated by elements that match + /// `pred` limited to splitting at most `n` times. This starts at the end of + /// the slice and works backwards. The matched element is not contained in + /// the subslices. + #[stable] + fn rsplitn_mut(&mut self, n: uint, pred: F) -> RSplitNMut + where F: FnMut(&T) -> bool; - if i != j { - let tmp = ptr::read(read_ptr); - ptr::copy_memory(buf_v.offset(j + 1), - &*buf_v.offset(j), - (i - j) as uint); - ptr::copy_nonoverlapping_memory(buf_v.offset(j), - &tmp as *const T, - 1); - mem::forget(tmp); - } - } - } -} + /// Returns an iterator over `chunk_size` elements of the slice at a time. + /// The chunks are mutable and do not overlap. If `chunk_size` does + /// not divide the length of the slice, then the last chunk will not + /// have length `chunk_size`. + /// + /// # Panics + /// + /// Panics if `chunk_size` is 0. + #[stable] + fn chunks_mut(&mut self, chunk_size: uint) -> ChunksMut; -fn merge_sort(v: &mut [T], mut compare: F) where F: FnMut(&T, &T) -> Ordering { - // warning: this wildly uses unsafe. - static BASE_INSERTION: uint = 32; - static LARGE_INSERTION: uint = 16; + /// Swaps two elements in a slice. + /// + /// # Arguments + /// + /// * a - The index of the first element + /// * b - The index of the second element + /// + /// # Panics + /// + /// Panics if `a` or `b` are out of bounds. + /// + /// # Example + /// + /// ```rust + /// let mut v = ["a", "b", "c", "d"]; + /// v.swap(1, 3); + /// assert!(v == ["a", "d", "c", "b"]); + /// ``` + #[stable] + fn swap(&mut self, a: uint, b: uint); - // FIXME #12092: smaller insertion runs seems to make sorting - // vectors of large elements a little faster on some platforms, - // but hasn't been tested/tuned extensively - let insertion = if size_of::() <= 16 { - BASE_INSERTION - } else { - LARGE_INSERTION - }; + /// Divides one `&mut` into two at an index. + /// + /// The first will contain all indices from `[0, mid)` (excluding + /// the index `mid` itself) and the second will contain all + /// indices from `[mid, len)` (excluding the index `len` itself). + /// + /// # Panics + /// + /// Panics if `mid > len`. + /// + /// # Example + /// + /// ```rust + /// let mut v = [1i, 2, 3, 4, 5, 6]; + /// + /// // scoped to restrict the lifetime of the borrows + /// { + /// let (left, right) = v.split_at_mut(0); + /// assert!(left == []); + /// assert!(right == [1i, 2, 3, 4, 5, 6]); + /// } + /// + /// { + /// let (left, right) = v.split_at_mut(2); + /// assert!(left == [1i, 2]); + /// assert!(right == [3i, 4, 5, 6]); + /// } + /// + /// { + /// let (left, right) = v.split_at_mut(6); + /// assert!(left == [1i, 2, 3, 4, 5, 6]); + /// assert!(right == []); + /// } + /// ``` + #[stable] + fn split_at_mut(&mut self, mid: uint) -> (&mut [T], &mut [T]); - let len = v.len(); + /// Reverse the order of elements in a slice, in place. + /// + /// # Example + /// + /// ```rust + /// let mut v = [1i, 2, 3]; + /// v.reverse(); + /// assert!(v == [3i, 2, 1]); + /// ``` + #[stable] + fn reverse(&mut self); - // short vectors get sorted in-place via insertion sort to avoid allocations - if len <= insertion { - insertion_sort(v, compare); - return; - } + /// Returns an unsafe mutable pointer to the element in index + #[stable] + unsafe fn get_unchecked_mut(&mut self, index: uint) -> &mut T; - // allocate some memory to use as scratch memory, we keep the - // length 0 so we can keep shallow copies of the contents of `v` - // without risking the dtors running on an object twice if - // `compare` panics. - let mut working_space = Vec::with_capacity(2 * len); - // these both are buffers of length `len`. - let mut buf_dat = working_space.as_mut_ptr(); - let mut buf_tmp = unsafe {buf_dat.offset(len as int)}; + /// Deprecated: renamed to `get_unchecked_mut`. + #[deprecated = "renamed to get_unchecked_mut"] + unsafe fn unchecked_mut(&mut self, index: uint) -> &mut T { + self.get_unchecked_mut(index) + } - // length `len`. - let buf_v = v.as_ptr(); + /// Return an unsafe mutable pointer to the slice's buffer. + /// + /// The caller must ensure that the slice outlives the pointer this + /// function returns, or else it will end up pointing to garbage. + /// + /// Modifying the slice may cause its buffer to be reallocated, which + /// would also make any pointers to it invalid. + #[inline] + #[stable] + fn as_mut_ptr(&mut self) -> *mut T; +} - // step 1. sort short runs with insertion sort. This takes the - // values from `v` and sorts them into `buf_dat`, leaving that - // with sorted runs of length INSERTION. +#[unstable = "trait is unstable"] +impl SliceExt for [T] { + #[inline] + fn sort_by(&mut self, compare: F) where F: FnMut(&T, &T) -> Ordering { + merge_sort(self, compare) + } - // We could hardcode the sorting comparisons here, and we could - // manipulate/step the pointers themselves, rather than repeatedly - // .offset-ing. - for start in range_step(0, len, insertion) { - // start <= i < len; - for i in range(start, cmp::min(start + insertion, len)) { - // j satisfies: start <= j <= i; - let mut j = i as int; - unsafe { - // `i` is in bounds. - let read_ptr = buf_v.offset(i as int); + #[inline] + fn move_from(&mut self, mut src: Vec, start: uint, end: uint) -> uint { + for (a, b) in self.iter_mut().zip(src.slice_mut(start, end).iter_mut()) { + mem::swap(a, b); + } + cmp::min(self.len(), end-start) + } - // find where to insert, we need to do strict <, - // rather than <=, to maintain stability. + #[inline] + fn slice<'a>(&'a self, start: uint, end: uint) -> &'a [T] { + core_slice::SliceExt::slice(self, start, end) + } - // start <= j - 1 < len, so .offset(j - 1) is in - // bounds. - while j > start as int && - compare(&*read_ptr, &*buf_dat.offset(j - 1)) == Less { - j -= 1; - } + #[inline] + fn slice_from<'a>(&'a self, start: uint) -> &'a [T] { + core_slice::SliceExt::slice_from(self, start) + } - // shift everything to the right, to make space to - // insert this value. + #[inline] + fn slice_to<'a>(&'a self, end: uint) -> &'a [T] { + core_slice::SliceExt::slice_to(self, end) + } - // j + 1 could be `len` (for the last `i`), but in - // that case, `i == j` so we don't copy. The - // `.offset(j)` is always in bounds. - ptr::copy_memory(buf_dat.offset(j + 1), - &*buf_dat.offset(j), - i - j as uint); - ptr::copy_nonoverlapping_memory(buf_dat.offset(j), read_ptr, 1); - } - } + #[inline] + fn split_at<'a>(&'a self, mid: uint) -> (&'a [T], &'a [T]) { + core_slice::SliceExt::split_at(self, mid) } - // step 2. merge the sorted runs. - let mut width = insertion; - while width < len { - // merge the sorted runs of length `width` in `buf_dat` two at - // a time, placing the result in `buf_tmp`. + #[inline] + fn iter<'a>(&'a self) -> Iter<'a, T> { + core_slice::SliceExt::iter(self) + } - // 0 <= start <= len. - for start in range_step(0, len, 2 * width) { - // manipulate pointers directly for speed (rather than - // using a `for` loop with `range` and `.offset` inside - // that loop). - unsafe { - // the end of the first run & start of the - // second. Offset of `len` is defined, since this is - // precisely one byte past the end of the object. - let right_start = buf_dat.offset(cmp::min(start + width, len) as int); - // end of the second. Similar reasoning to the above re safety. - let right_end_idx = cmp::min(start + 2 * width, len); - let right_end = buf_dat.offset(right_end_idx as int); + #[inline] + fn split(&self, pred: F) -> Split + where F: FnMut(&T) -> bool { + core_slice::SliceExt::split(self, pred) + } - // the pointers to the elements under consideration - // from the two runs. + #[inline] + fn splitn(&self, n: uint, pred: F) -> SplitN + where F: FnMut(&T) -> bool { + core_slice::SliceExt::splitn(self, n, pred) + } - // both of these are in bounds. - let mut left = buf_dat.offset(start as int); - let mut right = right_start; + #[inline] + fn rsplitn(&self, n: uint, pred: F) -> RSplitN + where F: FnMut(&T) -> bool { + core_slice::SliceExt::rsplitn(self, n, pred) + } - // where we're putting the results, it is a run of - // length `2*width`, so we step it once for each step - // of either `left` or `right`. `buf_tmp` has length - // `len`, so these are in bounds. - let mut out = buf_tmp.offset(start as int); - let out_end = buf_tmp.offset(right_end_idx as int); + #[inline] + fn windows<'a>(&'a self, size: uint) -> Windows<'a, T> { + core_slice::SliceExt::windows(self, size) + } - while out < out_end { - // Either the left or the right run are exhausted, - // so just copy the remainder from the other run - // and move on; this gives a huge speed-up (order - // of 25%) for mostly sorted vectors (the best - // case). - if left == right_start { - // the number remaining in this run. - let elems = (right_end as uint - right as uint) / mem::size_of::(); - ptr::copy_nonoverlapping_memory(out, &*right, elems); - break; - } else if right == right_end { - let elems = (right_start as uint - left as uint) / mem::size_of::(); - ptr::copy_nonoverlapping_memory(out, &*left, elems); - break; - } + #[inline] + fn chunks<'a>(&'a self, size: uint) -> Chunks<'a, T> { + core_slice::SliceExt::chunks(self, size) + } - // check which side is smaller, and that's the - // next element for the new run. + #[inline] + fn get<'a>(&'a self, index: uint) -> Option<&'a T> { + core_slice::SliceExt::get(self, index) + } - // `left < right_start` and `right < right_end`, - // so these are valid. - let to_copy = if compare(&*left, &*right) == Greater { - step(&mut right) - } else { - step(&mut left) - }; - ptr::copy_nonoverlapping_memory(out, &*to_copy, 1); - step(&mut out); - } - } - } + #[inline] + fn first<'a>(&'a self) -> Option<&'a T> { + core_slice::SliceExt::first(self) + } - mem::swap(&mut buf_dat, &mut buf_tmp); + #[inline] + fn tail<'a>(&'a self) -> &'a [T] { + core_slice::SliceExt::tail(self) + } - width *= 2; + #[inline] + fn init<'a>(&'a self) -> &'a [T] { + core_slice::SliceExt::init(self) } - // write the result to `v` in one go, so that there are never two copies - // of the same object in `v`. - unsafe { - ptr::copy_nonoverlapping_memory(v.as_mut_ptr(), &*buf_dat, len); + #[inline] + fn last<'a>(&'a self) -> Option<&'a T> { + core_slice::SliceExt::last(self) } - // increment the pointer, returning the old pointer. - #[inline(always)] - unsafe fn step(ptr: &mut *mut T) -> *mut T { - let old = *ptr; - *ptr = ptr.offset(1); - old + #[inline] + unsafe fn get_unchecked<'a>(&'a self, index: uint) -> &'a T { + core_slice::SliceExt::get_unchecked(self, index) } -} -/// Allocating extension methods for slices on Ord values. -#[experimental = "likely to merge with other traits"] -pub trait OrdSliceExt for Sized? { - /// Sorts the slice, in place. - /// - /// This is equivalent to `self.sort_by(|a, b| a.cmp(b))`. - /// - /// # Examples - /// - /// ```rust - /// let mut v = [-5i, 4, 1, -3, 2]; - /// - /// v.sort(); - /// assert!(v == [-5i, -3, 1, 2, 4]); - /// ``` - #[experimental] - fn sort(&mut self); + #[inline] + fn as_ptr(&self) -> *const T { + core_slice::SliceExt::as_ptr(self) + } - /// Binary search a sorted slice for a given element. - /// - /// If the value is found then `Found` is returned, containing the - /// index of the matching element; if the value is not found then - /// `NotFound` is returned, containing the index where a matching - /// element could be inserted while maintaining sorted order. - /// - /// # Example - /// - /// Looks up a series of four elements. The first is found, with a - /// uniquely determined position; the second and third are not - /// found; the fourth could match any position in `[1,4]`. - /// - /// ```rust - /// use std::slice::BinarySearchResult::{Found, NotFound}; - /// let s = [0i, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; - /// let s = s.as_slice(); - /// - /// assert_eq!(s.binary_search_elem(&13), Found(9)); - /// assert_eq!(s.binary_search_elem(&4), NotFound(7)); - /// assert_eq!(s.binary_search_elem(&100), NotFound(13)); - /// let r = s.binary_search_elem(&1); - /// assert!(match r { Found(1...4) => true, _ => false, }); - /// ``` - #[unstable = "name likely to change"] - fn binary_search_elem(&self, x: &T) -> BinarySearchResult; + #[inline] + fn binary_search_by(&self, f: F) -> Result + where F: FnMut(&T) -> Ordering { + core_slice::SliceExt::binary_search_by(self, f) + } - /// Mutates the slice to the next lexicographic permutation. - /// - /// Returns `true` if successful and `false` if the slice is at the - /// last-ordered permutation. - /// - /// # Example - /// - /// ```rust - /// let v: &mut [_] = &mut [0i, 1, 2]; - /// v.next_permutation(); - /// let b: &mut [_] = &mut [0i, 2, 1]; - /// assert!(v == b); - /// v.next_permutation(); - /// let b: &mut [_] = &mut [1i, 0, 2]; - /// assert!(v == b); - /// ``` - #[experimental] - fn next_permutation(&mut self) -> bool; + #[inline] + fn len(&self) -> uint { + core_slice::SliceExt::len(self) + } - /// Mutates the slice to the previous lexicographic permutation. - /// - /// Returns `true` if successful and `false` if the slice is at the - /// first-ordered permutation. - /// - /// # Example - /// - /// ```rust - /// let v: &mut [_] = &mut [1i, 0, 2]; - /// v.prev_permutation(); - /// let b: &mut [_] = &mut [0i, 2, 1]; - /// assert!(v == b); - /// v.prev_permutation(); - /// let b: &mut [_] = &mut [0i, 1, 2]; - /// assert!(v == b); - /// ``` - #[experimental] - fn prev_permutation(&mut self) -> bool; -} + #[inline] + fn is_empty(&self) -> bool { + core_slice::SliceExt::is_empty(self) + } -impl OrdSliceExt for [T] { #[inline] - fn sort(&mut self) { - self.sort_by(|a, b| a.cmp(b)) + fn get_mut<'a>(&'a mut self, index: uint) -> Option<&'a mut T> { + core_slice::SliceExt::get_mut(self, index) } - fn binary_search_elem(&self, x: &T) -> BinarySearchResult { - core_slice::OrdSliceExt::binary_search_elem(self, x) + #[inline] + fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] { + core_slice::SliceExt::as_mut_slice(self) } - fn next_permutation(&mut self) -> bool { - core_slice::OrdSliceExt::next_permutation(self) + #[inline] + fn slice_mut<'a>(&'a mut self, start: uint, end: uint) -> &'a mut [T] { + core_slice::SliceExt::slice_mut(self, start, end) } - fn prev_permutation(&mut self) -> bool { - core_slice::OrdSliceExt::prev_permutation(self) + #[inline] + fn slice_from_mut<'a>(&'a mut self, start: uint) -> &'a mut [T] { + core_slice::SliceExt::slice_from_mut(self, start) } -} -/// Allocating extension methods for slices. -#[experimental = "likely to merge with other traits"] -pub trait SliceExt for Sized? { - /// Sorts the slice, in place, using `compare` to compare - /// elements. - /// - /// This sort is `O(n log n)` worst-case and stable, but allocates - /// approximately `2 * n`, where `n` is the length of `self`. - /// - /// # Examples - /// - /// ```rust - /// let mut v = [5i, 4, 1, 3, 2]; - /// v.sort_by(|a, b| a.cmp(b)); - /// assert!(v == [1, 2, 3, 4, 5]); - /// - /// // reverse sorting - /// v.sort_by(|a, b| b.cmp(a)); - /// assert!(v == [5, 4, 3, 2, 1]); - /// ``` - fn sort_by(&mut self, compare: F) where F: FnMut(&T, &T) -> Ordering; + #[inline] + fn slice_to_mut<'a>(&'a mut self, end: uint) -> &'a mut [T] { + core_slice::SliceExt::slice_to_mut(self, end) + } - /// Consumes `src` and moves as many elements as it can into `self` - /// from the range [start,end). - /// - /// Returns the number of elements copied (the shorter of `self.len()` - /// and `end - start`). - /// - /// # Arguments - /// - /// * src - A mutable vector of `T` - /// * start - The index into `src` to start copying from - /// * end - The index into `src` to stop copying from - /// - /// # Examples - /// - /// ```rust - /// let mut a = [1i, 2, 3, 4, 5]; - /// let b = vec![6i, 7, 8]; - /// let num_moved = a.move_from(b, 0, 3); - /// assert_eq!(num_moved, 3); - /// assert!(a == [6i, 7, 8, 4, 5]); - /// ``` - fn move_from(&mut self, src: Vec, start: uint, end: uint) -> uint; + #[inline] + fn iter_mut<'a>(&'a mut self) -> IterMut<'a, T> { + core_slice::SliceExt::iter_mut(self) + } - /// Returns a subslice spanning the interval [`start`, `end`). - /// - /// Panics when the end of the new slice lies beyond the end of the - /// original slice (i.e. when `end > self.len()`) or when `start > end`. - /// - /// Slicing with `start` equal to `end` yields an empty slice. - #[unstable = "waiting on final error conventions/slicing syntax"] - fn slice(&self, start: uint, end: uint) -> &[T]; + #[inline] + fn first_mut<'a>(&'a mut self) -> Option<&'a mut T> { + core_slice::SliceExt::first_mut(self) + } - /// Returns a subslice from `start` to the end of the slice. - /// - /// Panics when `start` is strictly greater than the length of the original slice. - /// - /// Slicing from `self.len()` yields an empty slice. - #[unstable = "waiting on final error conventions/slicing syntax"] - fn slice_from(&self, start: uint) -> &[T]; + #[inline] + fn tail_mut<'a>(&'a mut self) -> &'a mut [T] { + core_slice::SliceExt::tail_mut(self) + } - /// Returns a subslice from the start of the slice to `end`. - /// - /// Panics when `end` is strictly greater than the length of the original slice. - /// - /// Slicing to `0` yields an empty slice. - #[unstable = "waiting on final error conventions/slicing syntax"] - fn slice_to(&self, end: uint) -> &[T]; + #[inline] + fn init_mut<'a>(&'a mut self) -> &'a mut [T] { + core_slice::SliceExt::init_mut(self) + } - /// Divides one slice into two at an index. - /// - /// The first will contain all indices from `[0, mid)` (excluding - /// the index `mid` itself) and the second will contain all - /// indices from `[mid, len)` (excluding the index `len` itself). - /// - /// Panics if `mid > len`. - #[unstable = "waiting on final error conventions"] - fn split_at(&self, mid: uint) -> (&[T], &[T]); + #[inline] + fn last_mut<'a>(&'a mut self) -> Option<&'a mut T> { + core_slice::SliceExt::last_mut(self) + } - /// Returns an iterator over the slice - #[unstable = "iterator type may change"] - fn iter(&self) -> Iter; + #[inline] + fn split_mut(&mut self, pred: F) -> SplitMut + where F: FnMut(&T) -> bool { + core_slice::SliceExt::split_mut(self, pred) + } - /// Returns an iterator over subslices separated by elements that match - /// `pred`. The matched element is not contained in the subslices. - #[unstable = "iterator type may change, waiting on unboxed closures"] - fn split(&self, pred: F) -> Splits - where F: FnMut(&T) -> bool; + #[inline] + fn splitn_mut(&mut self, n: uint, pred: F) -> SplitNMut + where F: FnMut(&T) -> bool { + core_slice::SliceExt::splitn_mut(self, n, pred) + } - /// Returns an iterator over subslices separated by elements that match - /// `pred`, limited to splitting at most `n` times. The matched element is - /// not contained in the subslices. - #[unstable = "iterator type may change"] - fn splitn(&self, n: uint, pred: F) -> SplitsN> - where F: FnMut(&T) -> bool; + #[inline] + fn rsplitn_mut(&mut self, n: uint, pred: F) -> RSplitNMut + where F: FnMut(&T) -> bool { + core_slice::SliceExt::rsplitn_mut(self, n, pred) + } - /// Returns an iterator over subslices separated by elements that match - /// `pred` limited to splitting at most `n` times. This starts at the end of - /// the slice and works backwards. The matched element is not contained in - /// the subslices. - #[unstable = "iterator type may change"] - fn rsplitn(&self, n: uint, pred: F) -> SplitsN> - where F: FnMut(&T) -> bool; + #[inline] + fn chunks_mut<'a>(&'a mut self, chunk_size: uint) -> ChunksMut<'a, T> { + core_slice::SliceExt::chunks_mut(self, chunk_size) + } - /// Returns an iterator over all contiguous windows of length - /// `size`. The windows overlap. If the slice is shorter than - /// `size`, the iterator returns no values. - /// - /// # Panics - /// - /// Panics if `size` is 0. - /// - /// # Example - /// - /// Print the adjacent pairs of a slice (i.e. `[1,2]`, `[2,3]`, - /// `[3,4]`): - /// - /// ```rust - /// let v = &[1i, 2, 3, 4]; - /// for win in v.windows(2) { - /// println!("{}", win); - /// } - /// ``` - #[unstable = "iterator type may change"] - fn windows(&self, size: uint) -> Windows; + #[inline] + fn swap(&mut self, a: uint, b: uint) { + core_slice::SliceExt::swap(self, a, b) + } - /// Returns an iterator over `size` elements of the slice at a - /// time. The chunks do not overlap. If `size` does not divide the - /// length of the slice, then the last chunk will not have length - /// `size`. - /// - /// # Panics - /// - /// Panics if `size` is 0. - /// - /// # Example - /// - /// Print the slice two elements at a time (i.e. `[1,2]`, - /// `[3,4]`, `[5]`): - /// - /// ```rust - /// let v = &[1i, 2, 3, 4, 5]; - /// for win in v.chunks(2) { - /// println!("{}", win); - /// } - /// ``` - #[unstable = "iterator type may change"] - fn chunks(&self, size: uint) -> Chunks; + #[inline] + fn split_at_mut<'a>(&'a mut self, mid: uint) -> (&'a mut [T], &'a mut [T]) { + core_slice::SliceExt::split_at_mut(self, mid) + } - /// Returns the element of a slice at the given index, or `None` if the - /// index is out of bounds. - #[unstable = "waiting on final collection conventions"] - fn get(&self, index: uint) -> Option<&T>; + #[inline] + fn reverse(&mut self) { + core_slice::SliceExt::reverse(self) + } - /// Returns the first element of a slice, or `None` if it is empty. - #[unstable = "name may change"] - fn head(&self) -> Option<&T>; + #[inline] + unsafe fn get_unchecked_mut<'a>(&'a mut self, index: uint) -> &'a mut T { + core_slice::SliceExt::get_unchecked_mut(self, index) + } - /// Returns all but the first element of a slice. - #[unstable = "name may change"] - fn tail(&self) -> &[T]; + #[inline] + fn as_mut_ptr(&mut self) -> *mut T { + core_slice::SliceExt::as_mut_ptr(self) + } +} - /// Returns all but the last element of a slice. - #[unstable = "name may change"] - fn init(&self) -> &[T]; +//////////////////////////////////////////////////////////////////////////////// +// Extension traits for slices over specifc kinds of data +//////////////////////////////////////////////////////////////////////////////// + +/// Extension methods for boxed slices. +#[experimental = "likely to merge into SliceExt if it survives"] +pub trait BoxedSliceExt { + /// Convert `self` into a vector without clones or allocation. + #[experimental] + fn into_vec(self) -> Vec; +} - /// Returns the last element of a slice, or `None` if it is empty. - #[unstable = "name may change"] - fn last(&self) -> Option<&T>; +#[experimental = "trait is experimental"] +impl BoxedSliceExt for Box<[T]> { + fn into_vec(mut self) -> Vec { + unsafe { + let xs = Vec::from_raw_parts(self.as_mut_ptr(), self.len(), self.len()); + mem::forget(self); + xs + } + } +} - /// Returns a pointer to the element at the given index, without doing - /// bounds checking. - #[unstable] - unsafe fn unsafe_get(&self, index: uint) -> &T; +/// Allocating extension methods for slices containing `Clone` elements. +#[unstable = "likely to be merged into SliceExt"] +pub trait CloneSliceExt for Sized? { + /// Copies `self` into a new `Vec`. + #[stable] + fn to_vec(&self) -> Vec; - /// Returns an unsafe pointer to the slice's buffer - /// - /// The caller must ensure that the slice outlives the pointer this - /// function returns, or else it will end up pointing to garbage. - /// - /// Modifying the slice may cause its buffer to be reallocated, which - /// would also make any pointers to it invalid. - #[unstable] - fn as_ptr(&self) -> *const T; + /// Deprecated: use `iter().cloned().partition(f)` instead. + #[deprecated = "use iter().cloned().partition(f) instead"] + fn partitioned(&self, f: F) -> (Vec, Vec) where F: FnMut(&T) -> bool; - /// Binary search a sorted slice with a comparator function. + /// Creates an iterator that yields every possible permutation of the + /// vector in succession. /// - /// The comparator function should implement an order consistent - /// with the sort order of the underlying slice, returning an - /// order code that indicates whether its argument is `Less`, - /// `Equal` or `Greater` the desired target. + /// # Examples /// - /// If a matching value is found then returns `Found`, containing - /// the index for the matched element; if no match is found then - /// `NotFound` is returned, containing the index where a matching - /// element could be inserted while maintaining sorted order. + /// ```rust + /// let v = [1i, 2, 3]; + /// let mut perms = v.permutations(); /// - /// # Example + /// for p in perms { + /// println!("{}", p); + /// } + /// ``` /// - /// Looks up a series of four elements. The first is found, with a - /// uniquely determined position; the second and third are not - /// found; the fourth could match any position in `[1,4]`. + /// Iterating through permutations one by one. /// /// ```rust - /// use std::slice::BinarySearchResult::{Found, NotFound}; - /// let s = [0i, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; - /// let s = s.as_slice(); + /// let v = [1i, 2, 3]; + /// let mut perms = v.permutations(); /// - /// let seek = 13; - /// assert_eq!(s.binary_search(|probe| probe.cmp(&seek)), Found(9)); - /// let seek = 4; - /// assert_eq!(s.binary_search(|probe| probe.cmp(&seek)), NotFound(7)); - /// let seek = 100; - /// assert_eq!(s.binary_search(|probe| probe.cmp(&seek)), NotFound(13)); - /// let seek = 1; - /// let r = s.binary_search(|probe| probe.cmp(&seek)); - /// assert!(match r { Found(1...4) => true, _ => false, }); + /// assert_eq!(Some(vec![1i, 2, 3]), perms.next()); + /// assert_eq!(Some(vec![1i, 3, 2]), perms.next()); + /// assert_eq!(Some(vec![3i, 1, 2]), perms.next()); /// ``` - #[unstable = "waiting on unboxed closures"] - fn binary_search(&self, f: F) -> BinarySearchResult - where F: FnMut(&T) -> Ordering; + #[unstable] + fn permutations(&self) -> Permutations; - /// Return the number of elements in the slice + /// Copies as many elements from `src` as it can into `self` (the + /// shorter of `self.len()` and `src.len()`). Returns the number + /// of elements copied. /// /// # Example /// - /// ``` - /// let a = [1i, 2, 3]; - /// assert_eq!(a.len(), 3); - /// ``` - #[experimental = "not triaged yet"] - fn len(&self) -> uint; - - /// Returns true if the slice has a length of 0 + /// ```rust + /// let mut dst = [0i, 0, 0]; + /// let src = [1i, 2]; /// - /// # Example + /// assert!(dst.clone_from_slice(&src) == 2); + /// assert!(dst == [1, 2, 0]); /// + /// let src2 = [3i, 4, 5, 6]; + /// assert!(dst.clone_from_slice(&src2) == 3); + /// assert!(dst == [3i, 4, 5]); /// ``` - /// let a = [1i, 2, 3]; - /// assert!(!a.is_empty()); - /// ``` - #[inline] - #[experimental = "not triaged yet"] - fn is_empty(&self) -> bool { self.len() == 0 } - /// Returns a mutable reference to the element at the given index, - /// or `None` if the index is out of bounds - #[unstable = "waiting on final error conventions"] - fn get_mut(&mut self, index: uint) -> Option<&mut T>; - - /// Work with `self` as a mut slice. - /// Primarily intended for getting a &mut [T] from a [T, ..N]. - fn as_mut_slice(&mut self) -> &mut [T]; - - /// Returns a mutable subslice spanning the interval [`start`, `end`). - /// - /// Panics when the end of the new slice lies beyond the end of the - /// original slice (i.e. when `end > self.len()`) or when `start > end`. - /// - /// Slicing with `start` equal to `end` yields an empty slice. - #[unstable = "waiting on final error conventions"] - fn slice_mut(&mut self, start: uint, end: uint) -> &mut [T]; - - /// Returns a mutable subslice from `start` to the end of the slice. - /// - /// Panics when `start` is strictly greater than the length of the original slice. - /// - /// Slicing from `self.len()` yields an empty slice. - #[unstable = "waiting on final error conventions"] - fn slice_from_mut(&mut self, start: uint) -> &mut [T]; - - /// Returns a mutable subslice from the start of the slice to `end`. - /// - /// Panics when `end` is strictly greater than the length of the original slice. - /// - /// Slicing to `0` yields an empty slice. - #[unstable = "waiting on final error conventions"] - fn slice_to_mut(&mut self, end: uint) -> &mut [T]; - - /// Returns an iterator that allows modifying each value - #[unstable = "waiting on iterator type name conventions"] - fn iter_mut(&mut self) -> IterMut; - - /// Returns a mutable pointer to the first element of a slice, or `None` if it is empty - #[unstable = "name may change"] - fn head_mut(&mut self) -> Option<&mut T>; - - /// Returns all but the first element of a mutable slice - #[unstable = "name may change"] - fn tail_mut(&mut self) -> &mut [T]; - - /// Returns all but the last element of a mutable slice - #[unstable = "name may change"] - fn init_mut(&mut self) -> &mut [T]; + #[experimental] + fn clone_from_slice(&mut self, &[T]) -> uint; +} - /// Returns a mutable pointer to the last item in the slice. - #[unstable = "name may change"] - fn last_mut(&mut self) -> Option<&mut T>; +#[unstable = "trait is unstable"] +impl CloneSliceExt for [T] { + /// Returns a copy of `v`. + #[inline] + fn to_vec(&self) -> Vec { + let mut vector = Vec::with_capacity(self.len()); + vector.push_all(self); + vector + } - /// Returns an iterator over mutable subslices separated by elements that - /// match `pred`. The matched element is not contained in the subslices. - #[unstable = "waiting on unboxed closures, iterator type name conventions"] - fn split_mut(&mut self, pred: F) -> MutSplits - where F: FnMut(&T) -> bool; - /// Returns an iterator over subslices separated by elements that match - /// `pred`, limited to splitting at most `n` times. The matched element is - /// not contained in the subslices. - #[unstable = "waiting on unboxed closures, iterator type name conventions"] - fn splitn_mut(&mut self, n: uint, pred: F) -> SplitsN> - where F: FnMut(&T) -> bool; + #[inline] + fn partitioned(&self, f: F) -> (Vec, Vec) where F: FnMut(&T) -> bool { + self.iter().cloned().partition(f) + } - /// Returns an iterator over subslices separated by elements that match - /// `pred` limited to splitting at most `n` times. This starts at the end of - /// the slice and works backwards. The matched element is not contained in - /// the subslices. - #[unstable = "waiting on unboxed closures, iterator type name conventions"] - fn rsplitn_mut(&mut self, n: uint, pred: F) -> SplitsN> - where F: FnMut(&T) -> bool; + /// Returns an iterator over all permutations of a vector. + fn permutations(&self) -> Permutations { + Permutations{ + swaps: ElementSwaps::new(self.len()), + v: self.to_vec(), + } + } - /// Returns an iterator over `chunk_size` elements of the slice at a time. - /// The chunks are mutable and do not overlap. If `chunk_size` does - /// not divide the length of the slice, then the last chunk will not - /// have length `chunk_size`. - /// - /// # Panics - /// - /// Panics if `chunk_size` is 0. - #[unstable = "waiting on iterator type name conventions"] - fn chunks_mut(&mut self, chunk_size: uint) -> MutChunks; + fn clone_from_slice(&mut self, src: &[T]) -> uint { + core_slice::CloneSliceExt::clone_from_slice(self, src) + } +} - /// Swaps two elements in a slice. - /// - /// Panics if `a` or `b` are out of bounds. - /// - /// # Arguments +/// Allocating extension methods for slices on Ord values. +#[unstable = "likely to merge with SliceExt"] +pub trait OrdSliceExt for Sized? { + /// Sorts the slice, in place. /// - /// * a - The index of the first element - /// * b - The index of the second element + /// This is equivalent to `self.sort_by(|a, b| a.cmp(b))`. /// - /// # Example + /// # Examples /// /// ```rust - /// let mut v = ["a", "b", "c", "d"]; - /// v.swap(1, 3); - /// assert!(v == ["a", "d", "c", "b"]); + /// let mut v = [-5i, 4, 1, -3, 2]; + /// + /// v.sort(); + /// assert!(v == [-5i, -3, 1, 2, 4]); /// ``` - #[unstable = "waiting on final error conventions"] - fn swap(&mut self, a: uint, b: uint); + #[stable] + fn sort(&mut self); - /// Divides one `&mut` into two at an index. - /// - /// The first will contain all indices from `[0, mid)` (excluding - /// the index `mid` itself) and the second will contain all - /// indices from `[mid, len)` (excluding the index `len` itself). + /// Binary search a sorted slice for a given element. /// - /// Panics if `mid > len`. + /// If the value is found then `Ok` is returned, containing the + /// index of the matching element; if the value is not found then + /// `Err` is returned, containing the index where a matching + /// element could be inserted while maintaining sorted order. /// /// # Example /// - /// ```rust - /// let mut v = [1i, 2, 3, 4, 5, 6]; - /// - /// // scoped to restrict the lifetime of the borrows - /// { - /// let (left, right) = v.split_at_mut(0); - /// assert!(left == []); - /// assert!(right == [1i, 2, 3, 4, 5, 6]); - /// } + /// Looks up a series of four elements. The first is found, with a + /// uniquely determined position; the second and third are not + /// found; the fourth could match any position in `[1,4]`. /// - /// { - /// let (left, right) = v.split_at_mut(2); - /// assert!(left == [1i, 2]); - /// assert!(right == [3i, 4, 5, 6]); - /// } + /// ```rust + /// let s = [0i, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; + /// let s = s.as_slice(); /// - /// { - /// let (left, right) = v.split_at_mut(6); - /// assert!(left == [1i, 2, 3, 4, 5, 6]); - /// assert!(right == []); - /// } + /// assert_eq!(s.binary_search(&13), Ok(9)); + /// assert_eq!(s.binary_search(&4), Err(7)); + /// assert_eq!(s.binary_search(&100), Err(13)); + /// let r = s.binary_search(&1); + /// assert!(match r { Ok(1...4) => true, _ => false, }); /// ``` - #[unstable = "waiting on final error conventions"] - fn split_at_mut(&mut self, mid: uint) -> (&mut [T], &mut [T]); + #[stable] + fn binary_search(&self, x: &T) -> Result; - /// Reverse the order of elements in a slice, in place. + /// Deprecated: use `binary_search` instead. + #[deprecated = "use binary_search instead"] + fn binary_search_elem(&self, x: &T) -> Result { + self.binary_search(x) + } + + /// Mutates the slice to the next lexicographic permutation. + /// + /// Returns `true` if successful and `false` if the slice is at the + /// last-ordered permutation. /// /// # Example /// /// ```rust - /// let mut v = [1i, 2, 3]; - /// v.reverse(); - /// assert!(v == [3i, 2, 1]); + /// let v: &mut [_] = &mut [0i, 1, 2]; + /// v.next_permutation(); + /// let b: &mut [_] = &mut [0i, 2, 1]; + /// assert!(v == b); + /// v.next_permutation(); + /// let b: &mut [_] = &mut [1i, 0, 2]; + /// assert!(v == b); /// ``` - #[experimental = "may be moved to iterators instead"] - fn reverse(&mut self); - - /// Returns an unsafe mutable pointer to the element in index - #[experimental = "waiting on unsafe conventions"] - unsafe fn unsafe_mut(&mut self, index: uint) -> &mut T; + #[unstable = "uncertain if this merits inclusion in std"] + fn next_permutation(&mut self) -> bool; - /// Return an unsafe mutable pointer to the slice's buffer. + /// Mutates the slice to the previous lexicographic permutation. /// - /// The caller must ensure that the slice outlives the pointer this - /// function returns, or else it will end up pointing to garbage. + /// Returns `true` if successful and `false` if the slice is at the + /// first-ordered permutation. /// - /// Modifying the slice may cause its buffer to be reallocated, which - /// would also make any pointers to it invalid. - #[inline] - #[unstable] - fn as_mut_ptr(&mut self) -> *mut T; + /// # Example + /// + /// ```rust + /// let v: &mut [_] = &mut [1i, 0, 2]; + /// v.prev_permutation(); + /// let b: &mut [_] = &mut [0i, 2, 1]; + /// assert!(v == b); + /// v.prev_permutation(); + /// let b: &mut [_] = &mut [0i, 1, 2]; + /// assert!(v == b); + /// ``` + #[unstable = "uncertain if this merits inclusion in std"] + fn prev_permutation(&mut self) -> bool; } -impl SliceExt for [T] { +#[unstable = "trait is unstable"] +impl OrdSliceExt for [T] { #[inline] - fn sort_by(&mut self, compare: F) where F: FnMut(&T, &T) -> Ordering { - merge_sort(self, compare) + fn sort(&mut self) { + self.sort_by(|a, b| a.cmp(b)) } - #[inline] - fn move_from(&mut self, mut src: Vec, start: uint, end: uint) -> uint { - for (a, b) in self.iter_mut().zip(src.slice_mut(start, end).iter_mut()) { - mem::swap(a, b); - } - cmp::min(self.len(), end-start) + fn binary_search(&self, x: &T) -> Result { + core_slice::OrdSliceExt::binary_search(self, x) } - #[inline] - fn slice<'a>(&'a self, start: uint, end: uint) -> &'a [T] { - core_slice::SliceExt::slice(self, start, end) + fn next_permutation(&mut self) -> bool { + core_slice::OrdSliceExt::next_permutation(self) } - #[inline] - fn slice_from<'a>(&'a self, start: uint) -> &'a [T] { - core_slice::SliceExt::slice_from(self, start) + fn prev_permutation(&mut self) -> bool { + core_slice::OrdSliceExt::prev_permutation(self) } +} - #[inline] - fn slice_to<'a>(&'a self, end: uint) -> &'a [T] { - core_slice::SliceExt::slice_to(self, end) - } +#[unstable = "U should be an associated type"] +/// An extension trait for concatenating slices +pub trait SliceConcatExt for Sized? { + /// Flattens a slice of `T` into a single value `U`. + #[stable] + fn concat(&self) -> U; - #[inline] - fn split_at<'a>(&'a self, mid: uint) -> (&'a [T], &'a [T]) { - core_slice::SliceExt::split_at(self, mid) + #[deprecated = "renamed to concat"] + fn concat_vec(&self) -> U { + self.concat() } - #[inline] - fn iter<'a>(&'a self) -> Iter<'a, T> { - core_slice::SliceExt::iter(self) - } + /// Flattens a slice of `T` into a single value `U`, placing a + /// given seperator between each. + #[stable] + fn connect(&self, sep: &T) -> U; - #[inline] - fn split(&self, pred: F) -> Splits - where F: FnMut(&T) -> bool { - core_slice::SliceExt::split(self, pred) + #[deprecated = "renamed to connect"] + fn connect_vec(&self, sep: &T) -> U { + self.connect(sep) } +} - #[inline] - fn splitn(&self, n: uint, pred: F) -> SplitsN> - where F: FnMut(&T) -> bool { - core_slice::SliceExt::splitn(self, n, pred) +impl> SliceConcatExt> for [V] { + fn concat(&self) -> Vec { + let size = self.iter().fold(0u, |acc, v| acc + v.as_slice().len()); + let mut result = Vec::with_capacity(size); + for v in self.iter() { + result.push_all(v.as_slice()) + } + result } - #[inline] - fn rsplitn(&self, n: uint, pred: F) -> SplitsN> - where F: FnMut(&T) -> bool { - core_slice::SliceExt::rsplitn(self, n, pred) + fn connect(&self, sep: &T) -> Vec { + let size = self.iter().fold(0u, |acc, v| acc + v.as_slice().len()); + let mut result = Vec::with_capacity(size + self.len()); + let mut first = true; + for v in self.iter() { + if first { first = false } else { result.push(sep.clone()) } + result.push_all(v.as_slice()) + } + result } +} - #[inline] - fn windows<'a>(&'a self, size: uint) -> Windows<'a, T> { - core_slice::SliceExt::windows(self, size) - } +/// An iterator that yields the element swaps needed to produce +/// a sequence of all possible permutations for an indexed sequence of +/// elements. Each permutation is only a single swap apart. +/// +/// The Steinhaus-Johnson-Trotter algorithm is used. +/// +/// Generates even and odd permutations alternately. +/// +/// The last generated swap is always (0, 1), and it returns the +/// sequence to its initial order. +#[experimental] +#[deriving(Clone)] +pub struct ElementSwaps { + sdir: Vec, + /// If `true`, emit the last swap that returns the sequence to initial + /// state. + emit_reset: bool, + swaps_made : uint, +} - #[inline] - fn chunks<'a>(&'a self, size: uint) -> Chunks<'a, T> { - core_slice::SliceExt::chunks(self, size) +impl ElementSwaps { + /// Creates an `ElementSwaps` iterator for a sequence of `length` elements. + #[experimental] + pub fn new(length: uint) -> ElementSwaps { + // Initialize `sdir` with a direction that position should move in + // (all negative at the beginning) and the `size` of the + // element (equal to the original index). + ElementSwaps{ + emit_reset: true, + sdir: range(0, length).map(|i| SizeDirection{ size: i, dir: Neg }).collect(), + swaps_made: 0 + } } +} - #[inline] - fn get<'a>(&'a self, index: uint) -> Option<&'a T> { - core_slice::SliceExt::get(self, index) - } +//////////////////////////////////////////////////////////////////////////////// +// Standard trait implementations for slices +//////////////////////////////////////////////////////////////////////////////// + +#[unstable = "trait is unstable"] +impl BorrowFrom> for [T] { + fn borrow_from(owned: &Vec) -> &[T] { owned[] } +} + +#[unstable = "trait is unstable"] +impl BorrowFromMut> for [T] { + fn borrow_from_mut(owned: &mut Vec) -> &mut [T] { owned.as_mut_slice_() } +} + +#[unstable = "trait is unstable"] +impl ToOwned> for [T] { + fn to_owned(&self) -> Vec { self.to_vec() } +} + +//////////////////////////////////////////////////////////////////////////////// +// Iterators +//////////////////////////////////////////////////////////////////////////////// + +#[deriving(Copy, Clone)] +enum Direction { Pos, Neg } + +/// An `Index` and `Direction` together. +#[deriving(Copy, Clone)] +struct SizeDirection { + size: uint, + dir: Direction, +} +impl Iterator<(uint, uint)> for ElementSwaps { #[inline] - fn head<'a>(&'a self) -> Option<&'a T> { - core_slice::SliceExt::head(self) + fn next(&mut self) -> Option<(uint, uint)> { + fn new_pos(i: uint, s: Direction) -> uint { + i + match s { Pos => 1, Neg => -1 } + } + + // Find the index of the largest mobile element: + // The direction should point into the vector, and the + // swap should be with a smaller `size` element. + let max = self.sdir.iter().map(|&x| x).enumerate() + .filter(|&(i, sd)| + new_pos(i, sd.dir) < self.sdir.len() && + self.sdir[new_pos(i, sd.dir)].size < sd.size) + .max_by(|&(_, sd)| sd.size); + match max { + Some((i, sd)) => { + let j = new_pos(i, sd.dir); + self.sdir.swap(i, j); + + // Swap the direction of each larger SizeDirection + for x in self.sdir.iter_mut() { + if x.size > sd.size { + x.dir = match x.dir { Pos => Neg, Neg => Pos }; + } + } + self.swaps_made += 1; + Some((i, j)) + }, + None => if self.emit_reset { + self.emit_reset = false; + if self.sdir.len() > 1 { + // The last swap + self.swaps_made += 1; + Some((0, 1)) + } else { + // Vector is of the form [] or [x], and the only permutation is itself + self.swaps_made += 1; + Some((0,0)) + } + } else { None } + } } #[inline] - fn tail<'a>(&'a self) -> &'a [T] { - core_slice::SliceExt::tail(self) + fn size_hint(&self) -> (uint, Option) { + // For a vector of size n, there are exactly n! permutations. + let n = range(2, self.sdir.len() + 1).product(); + (n - self.swaps_made, Some(n - self.swaps_made)) } +} + +/// An iterator that uses `ElementSwaps` to iterate through +/// all possible permutations of a vector. +/// +/// The first iteration yields a clone of the vector as it is, +/// then each successive element is the vector with one +/// swap applied. +/// +/// Generates even and odd permutations alternately. +#[unstable] +pub struct Permutations { + swaps: ElementSwaps, + v: Vec, +} +#[unstable = "trait is unstable"] +impl Iterator> for Permutations { #[inline] - fn init<'a>(&'a self) -> &'a [T] { - core_slice::SliceExt::init(self) + fn next(&mut self) -> Option> { + match self.swaps.next() { + None => None, + Some((0,0)) => Some(self.v.clone()), + Some((a, b)) => { + let elt = self.v.clone(); + self.v.swap(a, b); + Some(elt) + } + } } #[inline] - fn last<'a>(&'a self) -> Option<&'a T> { - core_slice::SliceExt::last(self) + fn size_hint(&self) -> (uint, Option) { + self.swaps.size_hint() } +} + +//////////////////////////////////////////////////////////////////////////////// +// Sorting +//////////////////////////////////////////////////////////////////////////////// + +fn insertion_sort(v: &mut [T], mut compare: F) where F: FnMut(&T, &T) -> Ordering { + let len = v.len() as int; + let buf_v = v.as_mut_ptr(); + + // 1 <= i < len; + for i in range(1, len) { + // j satisfies: 0 <= j <= i; + let mut j = i; + unsafe { + // `i` is in bounds. + let read_ptr = buf_v.offset(i) as *const T; + + // find where to insert, we need to do strict <, + // rather than <=, to maintain stability. + + // 0 <= j - 1 < len, so .offset(j - 1) is in bounds. + while j > 0 && + compare(&*read_ptr, &*buf_v.offset(j - 1)) == Less { + j -= 1; + } + + // shift everything to the right, to make space to + // insert this value. + + // j + 1 could be `len` (for the last `i`), but in + // that case, `i == j` so we don't copy. The + // `.offset(j)` is always in bounds. - #[inline] - unsafe fn unsafe_get<'a>(&'a self, index: uint) -> &'a T { - core_slice::SliceExt::unsafe_get(self, index) + if i != j { + let tmp = ptr::read(read_ptr); + ptr::copy_memory(buf_v.offset(j + 1), + &*buf_v.offset(j), + (i - j) as uint); + ptr::copy_nonoverlapping_memory(buf_v.offset(j), + &tmp as *const T, + 1); + mem::forget(tmp); + } + } } +} - #[inline] - fn as_ptr(&self) -> *const T { - core_slice::SliceExt::as_ptr(self) - } +fn merge_sort(v: &mut [T], mut compare: F) where F: FnMut(&T, &T) -> Ordering { + // warning: this wildly uses unsafe. + static BASE_INSERTION: uint = 32; + static LARGE_INSERTION: uint = 16; - #[inline] - fn binary_search(&self, f: F) -> BinarySearchResult - where F: FnMut(&T) -> Ordering { - core_slice::SliceExt::binary_search(self, f) - } + // FIXME #12092: smaller insertion runs seems to make sorting + // vectors of large elements a little faster on some platforms, + // but hasn't been tested/tuned extensively + let insertion = if size_of::() <= 16 { + BASE_INSERTION + } else { + LARGE_INSERTION + }; - #[inline] - fn len(&self) -> uint { - core_slice::SliceExt::len(self) - } + let len = v.len(); - #[inline] - fn is_empty(&self) -> bool { - core_slice::SliceExt::is_empty(self) + // short vectors get sorted in-place via insertion sort to avoid allocations + if len <= insertion { + insertion_sort(v, compare); + return; } - #[inline] - fn get_mut<'a>(&'a mut self, index: uint) -> Option<&'a mut T> { - core_slice::SliceExt::get_mut(self, index) - } + // allocate some memory to use as scratch memory, we keep the + // length 0 so we can keep shallow copies of the contents of `v` + // without risking the dtors running on an object twice if + // `compare` panics. + let mut working_space = Vec::with_capacity(2 * len); + // these both are buffers of length `len`. + let mut buf_dat = working_space.as_mut_ptr(); + let mut buf_tmp = unsafe {buf_dat.offset(len as int)}; - #[inline] - fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] { - core_slice::SliceExt::as_mut_slice(self) - } + // length `len`. + let buf_v = v.as_ptr(); - #[inline] - fn slice_mut<'a>(&'a mut self, start: uint, end: uint) -> &'a mut [T] { - core_slice::SliceExt::slice_mut(self, start, end) - } + // step 1. sort short runs with insertion sort. This takes the + // values from `v` and sorts them into `buf_dat`, leaving that + // with sorted runs of length INSERTION. - #[inline] - fn slice_from_mut<'a>(&'a mut self, start: uint) -> &'a mut [T] { - core_slice::SliceExt::slice_from_mut(self, start) - } + // We could hardcode the sorting comparisons here, and we could + // manipulate/step the pointers themselves, rather than repeatedly + // .offset-ing. + for start in range_step(0, len, insertion) { + // start <= i < len; + for i in range(start, cmp::min(start + insertion, len)) { + // j satisfies: start <= j <= i; + let mut j = i as int; + unsafe { + // `i` is in bounds. + let read_ptr = buf_v.offset(i as int); - #[inline] - fn slice_to_mut<'a>(&'a mut self, end: uint) -> &'a mut [T] { - core_slice::SliceExt::slice_to_mut(self, end) - } + // find where to insert, we need to do strict <, + // rather than <=, to maintain stability. - #[inline] - fn iter_mut<'a>(&'a mut self) -> IterMut<'a, T> { - core_slice::SliceExt::iter_mut(self) - } + // start <= j - 1 < len, so .offset(j - 1) is in + // bounds. + while j > start as int && + compare(&*read_ptr, &*buf_dat.offset(j - 1)) == Less { + j -= 1; + } - #[inline] - fn head_mut<'a>(&'a mut self) -> Option<&'a mut T> { - core_slice::SliceExt::head_mut(self) - } + // shift everything to the right, to make space to + // insert this value. - #[inline] - fn tail_mut<'a>(&'a mut self) -> &'a mut [T] { - core_slice::SliceExt::tail_mut(self) + // j + 1 could be `len` (for the last `i`), but in + // that case, `i == j` so we don't copy. The + // `.offset(j)` is always in bounds. + ptr::copy_memory(buf_dat.offset(j + 1), + &*buf_dat.offset(j), + i - j as uint); + ptr::copy_nonoverlapping_memory(buf_dat.offset(j), read_ptr, 1); + } + } } - #[inline] - fn init_mut<'a>(&'a mut self) -> &'a mut [T] { - core_slice::SliceExt::init_mut(self) - } + // step 2. merge the sorted runs. + let mut width = insertion; + while width < len { + // merge the sorted runs of length `width` in `buf_dat` two at + // a time, placing the result in `buf_tmp`. - #[inline] - fn last_mut<'a>(&'a mut self) -> Option<&'a mut T> { - core_slice::SliceExt::last_mut(self) - } + // 0 <= start <= len. + for start in range_step(0, len, 2 * width) { + // manipulate pointers directly for speed (rather than + // using a `for` loop with `range` and `.offset` inside + // that loop). + unsafe { + // the end of the first run & start of the + // second. Offset of `len` is defined, since this is + // precisely one byte past the end of the object. + let right_start = buf_dat.offset(cmp::min(start + width, len) as int); + // end of the second. Similar reasoning to the above re safety. + let right_end_idx = cmp::min(start + 2 * width, len); + let right_end = buf_dat.offset(right_end_idx as int); - #[inline] - fn split_mut(&mut self, pred: F) -> MutSplits - where F: FnMut(&T) -> bool { - core_slice::SliceExt::split_mut(self, pred) - } + // the pointers to the elements under consideration + // from the two runs. - #[inline] - fn splitn_mut(&mut self, n: uint, pred: F) -> SplitsN> - where F: FnMut(&T) -> bool { - core_slice::SliceExt::splitn_mut(self, n, pred) - } + // both of these are in bounds. + let mut left = buf_dat.offset(start as int); + let mut right = right_start; - #[inline] - fn rsplitn_mut(&mut self, n: uint, pred: F) -> SplitsN> - where F: FnMut(&T) -> bool { - core_slice::SliceExt::rsplitn_mut(self, n, pred) - } + // where we're putting the results, it is a run of + // length `2*width`, so we step it once for each step + // of either `left` or `right`. `buf_tmp` has length + // `len`, so these are in bounds. + let mut out = buf_tmp.offset(start as int); + let out_end = buf_tmp.offset(right_end_idx as int); - #[inline] - fn chunks_mut<'a>(&'a mut self, chunk_size: uint) -> MutChunks<'a, T> { - core_slice::SliceExt::chunks_mut(self, chunk_size) - } + while out < out_end { + // Either the left or the right run are exhausted, + // so just copy the remainder from the other run + // and move on; this gives a huge speed-up (order + // of 25%) for mostly sorted vectors (the best + // case). + if left == right_start { + // the number remaining in this run. + let elems = (right_end as uint - right as uint) / mem::size_of::(); + ptr::copy_nonoverlapping_memory(out, &*right, elems); + break; + } else if right == right_end { + let elems = (right_start as uint - left as uint) / mem::size_of::(); + ptr::copy_nonoverlapping_memory(out, &*left, elems); + break; + } - #[inline] - fn swap(&mut self, a: uint, b: uint) { - core_slice::SliceExt::swap(self, a, b) - } + // check which side is smaller, and that's the + // next element for the new run. - #[inline] - fn split_at_mut<'a>(&'a mut self, mid: uint) -> (&'a mut [T], &'a mut [T]) { - core_slice::SliceExt::split_at_mut(self, mid) - } + // `left < right_start` and `right < right_end`, + // so these are valid. + let to_copy = if compare(&*left, &*right) == Greater { + step(&mut right) + } else { + step(&mut left) + }; + ptr::copy_nonoverlapping_memory(out, &*to_copy, 1); + step(&mut out); + } + } + } - #[inline] - fn reverse(&mut self) { - core_slice::SliceExt::reverse(self) - } + mem::swap(&mut buf_dat, &mut buf_tmp); - #[inline] - unsafe fn unsafe_mut<'a>(&'a mut self, index: uint) -> &'a mut T { - core_slice::SliceExt::unsafe_mut(self, index) + width *= 2; } - #[inline] - fn as_mut_ptr(&mut self) -> *mut T { - core_slice::SliceExt::as_mut_ptr(self) + // write the result to `v` in one go, so that there are never two copies + // of the same object in `v`. + unsafe { + ptr::copy_nonoverlapping_memory(v.as_mut_ptr(), &*buf_dat, len); } -} - -#[unstable = "trait is unstable"] -impl BorrowFrom> for [T] { - fn borrow_from(owned: &Vec) -> &[T] { owned[] } -} - -#[unstable = "trait is unstable"] -impl BorrowFromMut> for [T] { - fn borrow_from_mut(owned: &mut Vec) -> &mut [T] { owned.as_mut_slice_() } -} -#[unstable = "trait is unstable"] -impl ToOwned> for [T] { - fn to_owned(&self) -> Vec { self.to_vec() } + // increment the pointer, returning the old pointer. + #[inline(always)] + unsafe fn step(ptr: &mut *mut T) -> *mut T { + let old = *ptr; + *ptr = ptr.offset(1); + old + } } -/// Unsafe operations +/// Deprecated, unsafe operations +#[deprecated] pub mod raw { pub use core::slice::raw::{buf_as_slice, mut_buf_as_slice}; pub use core::slice::raw::{shift_ptr, pop_ptr}; @@ -1346,7 +1419,7 @@ mod tests { use prelude::{Some, None, range, Vec, ToString, Clone, Greater, Less, Equal}; use prelude::{SliceExt, Iterator, IteratorExt, DoubleEndedIteratorExt}; use prelude::{OrdSliceExt, CloneSliceExt, PartialEqSliceExt, AsSlice}; - use prelude::{RandomAccessIterator, Ord, VectorVector}; + use prelude::{RandomAccessIterator, Ord, SliceConcatExt}; use core::cell::Cell; use core::default::Default; use core::mem; @@ -1612,15 +1685,19 @@ mod tests { fn test_swap_remove() { let mut v = vec![1i, 2, 3, 4, 5]; let mut e = v.swap_remove(0); - assert_eq!(e, Some(1)); + assert_eq!(e, 1); assert_eq!(v, vec![5i, 2, 3, 4]); e = v.swap_remove(3); - assert_eq!(e, Some(4)); + assert_eq!(e, 4); assert_eq!(v, vec![5i, 2, 3]); + } - e = v.swap_remove(3); - assert_eq!(e, None); - assert_eq!(v, vec![5i, 2, 3]); + #[test] + #[should_fail] + fn test_swap_remove_fail() { + let mut v = vec![1i]; + let _ = v.swap_remove(0); + let _ = v.swap_remove(0); } #[test] @@ -1904,48 +1981,48 @@ mod tests { } #[test] - fn test_binary_search_elem() { - assert_eq!([1i,2,3,4,5].binary_search_elem(&5).found(), Some(4)); - assert_eq!([1i,2,3,4,5].binary_search_elem(&4).found(), Some(3)); - assert_eq!([1i,2,3,4,5].binary_search_elem(&3).found(), Some(2)); - assert_eq!([1i,2,3,4,5].binary_search_elem(&2).found(), Some(1)); - assert_eq!([1i,2,3,4,5].binary_search_elem(&1).found(), Some(0)); + fn test_binary_search() { + assert_eq!([1i,2,3,4,5].binary_search(&5).ok(), Some(4)); + assert_eq!([1i,2,3,4,5].binary_search(&4).ok(), Some(3)); + assert_eq!([1i,2,3,4,5].binary_search(&3).ok(), Some(2)); + assert_eq!([1i,2,3,4,5].binary_search(&2).ok(), Some(1)); + assert_eq!([1i,2,3,4,5].binary_search(&1).ok(), Some(0)); - assert_eq!([2i,4,6,8,10].binary_search_elem(&1).found(), None); - assert_eq!([2i,4,6,8,10].binary_search_elem(&5).found(), None); - assert_eq!([2i,4,6,8,10].binary_search_elem(&4).found(), Some(1)); - assert_eq!([2i,4,6,8,10].binary_search_elem(&10).found(), Some(4)); + assert_eq!([2i,4,6,8,10].binary_search(&1).ok(), None); + assert_eq!([2i,4,6,8,10].binary_search(&5).ok(), None); + assert_eq!([2i,4,6,8,10].binary_search(&4).ok(), Some(1)); + assert_eq!([2i,4,6,8,10].binary_search(&10).ok(), Some(4)); - assert_eq!([2i,4,6,8].binary_search_elem(&1).found(), None); - assert_eq!([2i,4,6,8].binary_search_elem(&5).found(), None); - assert_eq!([2i,4,6,8].binary_search_elem(&4).found(), Some(1)); - assert_eq!([2i,4,6,8].binary_search_elem(&8).found(), Some(3)); + assert_eq!([2i,4,6,8].binary_search(&1).ok(), None); + assert_eq!([2i,4,6,8].binary_search(&5).ok(), None); + assert_eq!([2i,4,6,8].binary_search(&4).ok(), Some(1)); + assert_eq!([2i,4,6,8].binary_search(&8).ok(), Some(3)); - assert_eq!([2i,4,6].binary_search_elem(&1).found(), None); - assert_eq!([2i,4,6].binary_search_elem(&5).found(), None); - assert_eq!([2i,4,6].binary_search_elem(&4).found(), Some(1)); - assert_eq!([2i,4,6].binary_search_elem(&6).found(), Some(2)); + assert_eq!([2i,4,6].binary_search(&1).ok(), None); + assert_eq!([2i,4,6].binary_search(&5).ok(), None); + assert_eq!([2i,4,6].binary_search(&4).ok(), Some(1)); + assert_eq!([2i,4,6].binary_search(&6).ok(), Some(2)); - assert_eq!([2i,4].binary_search_elem(&1).found(), None); - assert_eq!([2i,4].binary_search_elem(&5).found(), None); - assert_eq!([2i,4].binary_search_elem(&2).found(), Some(0)); - assert_eq!([2i,4].binary_search_elem(&4).found(), Some(1)); + assert_eq!([2i,4].binary_search(&1).ok(), None); + assert_eq!([2i,4].binary_search(&5).ok(), None); + assert_eq!([2i,4].binary_search(&2).ok(), Some(0)); + assert_eq!([2i,4].binary_search(&4).ok(), Some(1)); - assert_eq!([2i].binary_search_elem(&1).found(), None); - assert_eq!([2i].binary_search_elem(&5).found(), None); - assert_eq!([2i].binary_search_elem(&2).found(), Some(0)); + assert_eq!([2i].binary_search(&1).ok(), None); + assert_eq!([2i].binary_search(&5).ok(), None); + assert_eq!([2i].binary_search(&2).ok(), Some(0)); - assert_eq!([].binary_search_elem(&1i).found(), None); - assert_eq!([].binary_search_elem(&5i).found(), None); + assert_eq!([].binary_search(&1i).ok(), None); + assert_eq!([].binary_search(&5i).ok(), None); - assert!([1i,1,1,1,1].binary_search_elem(&1).found() != None); - assert!([1i,1,1,1,2].binary_search_elem(&1).found() != None); - assert!([1i,1,1,2,2].binary_search_elem(&1).found() != None); - assert!([1i,1,2,2,2].binary_search_elem(&1).found() != None); - assert_eq!([1i,2,2,2,2].binary_search_elem(&1).found(), Some(0)); + assert!([1i,1,1,1,1].binary_search(&1).ok() != None); + assert!([1i,1,1,1,2].binary_search(&1).ok() != None); + assert!([1i,1,1,2,2].binary_search(&1).ok() != None); + assert!([1i,1,2,2,2].binary_search(&1).ok() != None); + assert_eq!([1i,2,2,2,2].binary_search(&1).ok(), Some(0)); - assert_eq!([1i,2,3,4,5].binary_search_elem(&6).found(), None); - assert_eq!([1i,2,3,4,5].binary_search_elem(&0).found(), None); + assert_eq!([1i,2,3,4,5].binary_search(&6).ok(), None); + assert_eq!([1i,2,3,4,5].binary_search(&0).ok(), None); } #[test] @@ -2040,13 +2117,15 @@ mod tests { #[test] fn test_concat() { let v: [Vec, ..0] = []; - assert_eq!(v.concat_vec(), vec![]); - assert_eq!([vec![1i], vec![2i,3i]].concat_vec(), vec![1, 2, 3]); + let c: Vec = v.concat(); + assert_eq!(c, []); + let d: Vec = [vec![1i], vec![2i,3i]].concat(); + assert_eq!(d, vec![1i, 2, 3]); let v: [&[int], ..2] = [&[1], &[2, 3]]; - assert_eq!(v.connect_vec(&0), vec![1, 0, 2, 3]); - let v: [&[int], ..3] = [&[1], &[2], &[3]]; - assert_eq!(v.connect_vec(&0), vec![1, 0, 2, 0, 3]); + assert_eq!(v.connect(&0), vec![1i, 0, 2, 3]); + let v: [&[int], ..3] = [&[1i], &[2], &[3]]; + assert_eq!(v.connect(&0), vec![1i, 0, 2, 0, 3]); } #[test] @@ -2092,23 +2171,25 @@ mod tests { fn test_remove() { let mut a = vec![1i,2,3,4]; - assert_eq!(a.remove(2), Some(3)); + assert_eq!(a.remove(2), 3); assert_eq!(a, vec![1i,2,4]); - assert_eq!(a.remove(2), Some(4)); - assert_eq!(a, vec![1i,2]); - - assert_eq!(a.remove(2), None); + assert_eq!(a.remove(2), 4); assert_eq!(a, vec![1i,2]); - assert_eq!(a.remove(0), Some(1)); + assert_eq!(a.remove(0), 1); assert_eq!(a, vec![2i]); - assert_eq!(a.remove(0), Some(2)); + assert_eq!(a.remove(0), 2); assert_eq!(a, vec![]); + } - assert_eq!(a.remove(0), None); - assert_eq!(a.remove(10), None); + #[test] + #[should_fail] + fn test_remove_fail() { + let mut a = vec![1i]; + let _ = a.remove(0); + let _ = a.remove(0); } #[test] @@ -2804,7 +2885,7 @@ mod bench { let xss: Vec> = Vec::from_fn(100, |i| range(0u, i).collect()); b.iter(|| { - xss.as_slice().concat_vec() + xss.as_slice().concat(); }); } diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index 7c7a7e19a2f18..8d5d76f9598f4 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -77,6 +77,7 @@ use slice::SliceExt; use string::String; use unicode; use vec::Vec; +use slice::SliceConcatExt; pub use core::str::{from_utf8, CharEq, Chars, CharIndices}; pub use core::str::{Bytes, CharSplits, is_utf8}; @@ -93,71 +94,45 @@ pub use core::str::{SplitN, RSplitN}; Section: Creating a string */ -/// Methods for vectors of strings. -#[unstable = "functionality may be replaced with iterators"] -pub trait StrVector for Sized? { - /// Concatenates a vector of strings. - /// - /// # Examples - /// - /// ```rust - /// let first = "Restaurant at the End of the".to_string(); - /// let second = " Universe".to_string(); - /// let string_vec = vec![first, second]; - /// assert_eq!(string_vec.concat(), "Restaurant at the End of the Universe".to_string()); - /// ``` - fn concat(&self) -> String; - - /// Concatenates a vector of strings, placing a given separator between each. - /// - /// # Examples - /// - /// ```rust - /// let first = "Roast".to_string(); - /// let second = "Sirloin Steak".to_string(); - /// let string_vec = vec![first, second]; - /// assert_eq!(string_vec.connect(", "), "Roast, Sirloin Steak".to_string()); - /// ``` - fn connect(&self, sep: &str) -> String; -} - -#[allow(deprecated)] -impl StrVector for [S] { +impl SliceConcatExt for [S] { fn concat(&self) -> String { - if self.is_empty() { + let s = self.as_slice(); + + if s.is_empty() { return String::new(); } // `len` calculation may overflow but push_str will check boundaries - let len = self.iter().map(|s| s.as_slice().len()).sum(); - + let len = s.iter().map(|s| s.as_slice().len()).sum(); let mut result = String::with_capacity(len); - for s in self.iter() { - result.push_str(s.as_slice()); + for s in s.iter() { + result.push_str(s.as_slice()) } result } fn connect(&self, sep: &str) -> String { - if self.is_empty() { + let s = self.as_slice(); + + if s.is_empty() { return String::new(); } // concat is faster if sep.is_empty() { - return self.concat(); + return s.concat(); } // this is wrong without the guarantee that `self` is non-empty // `len` calculation may overflow but push_str but will check boundaries - let len = sep.len() * (self.len() - 1) - + self.iter().map(|s| s.as_slice().len()).sum(); + let len = sep.len() * (s.len() - 1) + + s.iter().map(|s| s.as_slice().len()).sum(); let mut result = String::with_capacity(len); let mut first = true; - for s in self.iter() { + for s in s.iter() { if first { first = false; } else { @@ -169,18 +144,6 @@ impl StrVector for [S] { } } -impl> StrVector for T { - #[inline] - fn concat(&self) -> String { - self.as_slice().concat() - } - - #[inline] - fn connect(&self, sep: &str) -> String { - self.as_slice().connect(sep) - } -} - /* Section: Iterators */ @@ -221,7 +184,7 @@ pub struct Decompositions<'a> { impl<'a> Iterator for Decompositions<'a> { #[inline] fn next(&mut self) -> Option { - match self.buffer.head() { + match self.buffer.first() { Some(&(c, 0)) => { self.sorted = false; self.buffer.remove(0); @@ -268,13 +231,16 @@ impl<'a> Iterator for Decompositions<'a> { self.sorted = true; } - match self.buffer.remove(0) { - Some((c, 0)) => { - self.sorted = false; - Some(c) + if self.buffer.is_empty() { + None + } else { + match self.buffer.remove(0) { + (c, 0) => { + self.sorted = false; + Some(c) + } + (c, _) => Some(c), } - Some((c, _)) => Some(c), - None => None } } @@ -747,7 +713,7 @@ pub trait StrExt for Sized?: ops::Slice { if me.is_empty() { return t.chars().count(); } if t.is_empty() { return me.chars().count(); } - let mut dcol = Vec::from_fn(t.len() + 1, |x| x); + let mut dcol: Vec<_> = range(0, t.len() + 1).collect(); let mut t_last = 0; for (i, sc) in me.chars().enumerate() { @@ -1892,22 +1858,12 @@ mod tests { assert_eq!("ะเทศไท", "ประเทศไทย中华Việt Nam".slice_chars(2, 8)); } - struct S { - x: [String, .. 2] - } - - impl AsSlice for S { - fn as_slice<'a> (&'a self) -> &'a [String] { - &self.x - } - } - fn s(x: &str) -> String { x.into_string() } macro_rules! test_concat { ($expected: expr, $string: expr) => { { - let s = $string.concat(); + let s: String = $string.concat(); assert_eq!($expected, s); } } @@ -1915,22 +1871,10 @@ mod tests { #[test] fn test_concat_for_different_types() { - test_concat!("ab", ["a", "b"]); - test_concat!("ab", [s("a"), s("b")]); + test_concat!("ab", vec![s("a"), s("b")]); test_concat!("ab", vec!["a", "b"]); test_concat!("ab", vec!["a", "b"].as_slice()); test_concat!("ab", vec![s("a"), s("b")]); - - let mut v0 = ["a", "b"]; - let mut v1 = [s("a"), s("b")]; - unsafe { - use std::c_vec::CVec; - - test_concat!("ab", CVec::new(v0.as_mut_ptr(), v0.len())); - test_concat!("ab", CVec::new(v1.as_mut_ptr(), v1.len())); - } - - test_concat!("ab", S { x: [s("a"), s("b")] }); } #[test] @@ -1959,17 +1903,6 @@ mod tests { test_connect!("a-b", vec!["a", "b"], hyphen.as_slice()); test_connect!("a-b", vec!["a", "b"].as_slice(), "-"); test_connect!("a-b", vec![s("a"), s("b")], "-"); - - let mut v0 = ["a", "b"]; - let mut v1 = [s("a"), s("b")]; - unsafe { - use std::c_vec::CVec; - - test_connect!("a-b", CVec::new(v0.as_mut_ptr(), v0.len()), "-"); - test_connect!("a-b", CVec::new(v1.as_mut_ptr(), v1.len()), hyphen.as_slice()); - } - - test_connect!("a-b", S { x: [s("a"), s("b")] }, "-"); } #[test] @@ -3339,7 +3272,7 @@ mod tests { #[cfg(test)] mod bench { use super::*; - use prelude::{SliceExt, IteratorExt, DoubleEndedIteratorExt}; + use prelude::{SliceExt, IteratorExt, DoubleEndedIteratorExt, SliceConcatExt}; use test::Bencher; use test::black_box; @@ -3502,7 +3435,7 @@ mod bench { fn bench_connect(b: &mut Bencher) { let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; let sep = "→"; - let v = [s, s, s, s, s, s, s, s, s, s]; + let v = vec![s, s, s, s, s, s, s, s, s, s]; b.iter(|| { assert_eq!(v.connect(sep).len(), s.len() * 10 + sep.len() * 9); }) diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index c6c19cae75f1e..f703ff99660c6 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -151,7 +151,7 @@ impl String { let mut i = 0; let total = v.len(); fn unsafe_get(xs: &[u8], i: uint) -> u8 { - unsafe { *xs.unsafe_get(i) } + unsafe { *xs.get_unchecked(i) } } fn safe_get(xs: &[u8], i: uint, total: uint) -> u8 { if i >= total { @@ -815,6 +815,7 @@ impl<'a> Extend<&'a str> for String { } } +#[stable] impl PartialEq for String { #[inline] fn eq(&self, other: &String) -> bool { PartialEq::eq(&**self, &**other) } @@ -824,6 +825,7 @@ impl PartialEq for String { macro_rules! impl_eq { ($lhs:ty, $rhs: ty) => { + #[stable] impl<'a> PartialEq<$rhs> for $lhs { #[inline] fn eq(&self, other: &$rhs) -> bool { PartialEq::eq(&**self, &**other) } @@ -831,6 +833,7 @@ macro_rules! impl_eq { fn ne(&self, other: &$rhs) -> bool { PartialEq::ne(&**self, &**other) } } + #[stable] impl<'a> PartialEq<$lhs> for $rhs { #[inline] fn eq(&self, other: &$lhs) -> bool { PartialEq::eq(&**self, &**other) } @@ -844,6 +847,7 @@ macro_rules! impl_eq { impl_eq! { String, &'a str } impl_eq! { CowString<'a>, String } +#[stable] impl<'a, 'b> PartialEq<&'b str> for CowString<'a> { #[inline] fn eq(&self, other: &&'b str) -> bool { PartialEq::eq(&**self, &**other) } @@ -851,6 +855,7 @@ impl<'a, 'b> PartialEq<&'b str> for CowString<'a> { fn ne(&self, other: &&'b str) -> bool { PartialEq::ne(&**self, &**other) } } +#[stable] impl<'a, 'b> PartialEq> for &'b str { #[inline] fn eq(&self, other: &CowString<'a>) -> bool { PartialEq::eq(&**self, &**other) } @@ -989,20 +994,11 @@ pub trait ToString { } impl ToString for T { - // NOTE(stage0): Remove cfg after a snapshot - #[cfg(not(stage0))] fn to_string(&self) -> String { let mut buf = Vec::::new(); let _ = fmt::write(&mut buf, format_args!("{}", *self)); String::from_utf8(buf).unwrap() } - // NOTE(stage0): Remove method after a snapshot - #[cfg(stage0)] - fn to_string(&self) -> String { - let mut buf = Vec::::new(); - let _ = format_args!(|args| fmt::write(&mut buf, args), "{}", self); - String::from_utf8(buf).unwrap() - } } impl IntoCow<'static, String, str> for String { diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index bf69980b49c8f..a1952352badfa 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -142,26 +142,9 @@ pub struct Vec { unsafe impl Send for Vec { } unsafe impl Sync for Vec { } -/// A clone-on-write vector -pub type CowVec<'a, T> = Cow<'a, Vec, [T]>; - -impl<'a, T> FromIterator for CowVec<'a, T> where T: Clone { - fn from_iter>(it: I) -> CowVec<'a, T> { - Cow::Owned(FromIterator::from_iter(it)) - } -} - -impl<'a, T: 'a> IntoCow<'a, Vec, [T]> for Vec where T: Clone { - fn into_cow(self) -> CowVec<'a, T> { - Cow::Owned(self) - } -} - -impl<'a, T> IntoCow<'a, Vec, [T]> for &'a [T] where T: Clone { - fn into_cow(self) -> CowVec<'a, T> { - Cow::Borrowed(self) - } -} +//////////////////////////////////////////////////////////////////////////////// +// Inherent methods +//////////////////////////////////////////////////////////////////////////////// impl Vec { /// Constructs a new, empty `Vec`. @@ -190,8 +173,7 @@ impl Vec { /// /// It is important to note that this function does not specify the *length* of the returned /// vector, but only the *capacity*. (For an explanation of the difference between length and - /// capacity, see the main `Vec` docs above, 'Capacity and reallocation'.) To create a - /// vector of a given length, use `Vec::from_elem` or `Vec::from_fn`. + /// capacity, see the main `Vec` docs above, 'Capacity and reallocation'.) /// /// # Examples /// @@ -225,30 +207,11 @@ impl Vec { } } - /// Creates and initializes a `Vec`. - /// - /// Creates a `Vec` of size `length` and initializes the elements to the value returned by - /// the closure `op`. - /// - /// # Examples - /// - /// ``` - /// let vec = Vec::from_fn(3, |idx| idx * 2); - /// assert_eq!(vec, vec![0, 2, 4]); - /// ``` + /// Deprecated: use `iter::range(0, length).map(op).collect()` instead #[inline] - #[unstable = "the naming is uncertain as well as this migrating to unboxed \ - closures in the future"] - pub fn from_fn(length: uint, mut op: F) -> Vec where F: FnMut(uint) -> T { - unsafe { - let mut xs = Vec::with_capacity(length); - while xs.len < length { - let len = xs.len; - ptr::write(xs.unsafe_mut(len), op(len)); - xs.len += 1; - } - xs - } + #[deprecated = "use iter::range(0, length).map(op).collect() instead"] + pub fn from_fn(length: uint, op: F) -> Vec where F: FnMut(uint) -> T { + range(0, length).map(op).collect() } /// Creates a `Vec` directly from the raw components of another vector. @@ -285,7 +248,7 @@ impl Vec { /// } /// } /// ``` - #[unstable = "needs finalization"] + #[stable] pub unsafe fn from_raw_parts(ptr: *mut T, length: uint, capacity: uint) -> Vec { Vec { ptr: NonZero::new(ptr), len: length, cap: capacity } @@ -297,7 +260,7 @@ impl Vec { /// owned by the returned `Vec`. The elements of the buffer are copied into the vector /// without cloning, as if `ptr::read()` were called on them. #[inline] - #[unstable = "just renamed from raw::from_buf"] + #[unstable = "may be better expressed via composition"] pub unsafe fn from_raw_buf(ptr: *const T, elts: uint) -> Vec { let mut dst = Vec::with_capacity(elts); dst.set_len(elts); @@ -305,945 +268,794 @@ impl Vec { dst } - /// Consumes the `Vec`, partitioning it based on a predicate. - /// - /// Partitions the `Vec` into two `Vec`s `(A,B)`, where all elements of `A` satisfy `f` - /// and all elements of `B` do not. The order of elements is preserved. + /// Deprecated: use `into_iter().partition(f)` instead. + #[inline] + #[deprecated = "use into_iter().partition(f) instead"] + pub fn partition(self, f: F) -> (Vec, Vec) where F: FnMut(&T) -> bool { + self.into_iter().partition(f) + } + + /// Returns the number of elements the vector can hold without + /// reallocating. /// /// # Examples /// /// ``` - /// let vec = vec![1i, 2i, 3i, 4i]; - /// let (even, odd) = vec.partition(|&n| n % 2 == 0); - /// assert_eq!(even, vec![2, 4]); - /// assert_eq!(odd, vec![1, 3]); + /// let vec: Vec = Vec::with_capacity(10); + /// assert_eq!(vec.capacity(), 10); /// ``` #[inline] - #[experimental] - pub fn partition(self, mut f: F) -> (Vec, Vec) where F: FnMut(&T) -> bool { - let mut lefts = Vec::new(); - let mut rights = Vec::new(); - - for elt in self.into_iter() { - if f(&elt) { - lefts.push(elt); - } else { - rights.push(elt); - } - } + #[stable] + pub fn capacity(&self) -> uint { + self.cap + } - (lefts, rights) + /// Deprecated: Renamed to `reserve`. + #[deprecated = "Renamed to `reserve`"] + pub fn reserve_additional(&mut self, extra: uint) { + self.reserve(extra) } -} -impl Vec { - /// Constructs a `Vec` with copies of a value. + /// Reserves capacity for at least `additional` more elements to be inserted in the given + /// `Vec`. The collection may reserve more space to avoid frequent reallocations. + /// + /// # Panics /// - /// Creates a `Vec` with `length` copies of `value`. + /// Panics if the new capacity overflows `uint`. /// /// # Examples /// /// ``` - /// let vec = Vec::from_elem(3, "hi"); - /// println!("{}", vec); // prints [hi, hi, hi] + /// let mut vec: Vec = vec![1]; + /// vec.reserve(10); + /// assert!(vec.capacity() >= 11); /// ``` - #[inline] - #[unstable = "this functionality may become more generic over all collections"] - pub fn from_elem(length: uint, value: T) -> Vec { - unsafe { - let mut xs = Vec::with_capacity(length); - while xs.len < length { - let len = xs.len; - ptr::write(xs.unsafe_mut(len), - value.clone()); - xs.len += 1; - } - xs + #[stable] + pub fn reserve(&mut self, additional: uint) { + if self.cap - self.len < additional { + let err_msg = "Vec::reserve: `uint` overflow"; + let new_cap = self.len.checked_add(additional).expect(err_msg) + .checked_next_power_of_two().expect(err_msg); + self.grow_capacity(new_cap); } } - /// Appends all elements in a slice to the `Vec`. + /// Reserves the minimum capacity for exactly `additional` more elements to + /// be inserted in the given `Vec`. Does nothing if the capacity is already + /// sufficient. /// - /// Iterates over the slice `other`, clones each element, and then appends - /// it to this `Vec`. The `other` vector is traversed in-order. + /// Note that the allocator may give the collection more space than it + /// requests. Therefore capacity can not be relied upon to be precisely + /// minimal. Prefer `reserve` if future insertions are expected. + /// + /// # Panics + /// + /// Panics if the new capacity overflows `uint`. /// /// # Examples /// /// ``` - /// let mut vec = vec![1i]; - /// vec.push_all(&[2i, 3, 4]); - /// assert_eq!(vec, vec![1, 2, 3, 4]); + /// let mut vec: Vec = vec![1]; + /// vec.reserve_exact(10); + /// assert!(vec.capacity() >= 11); /// ``` - #[inline] - #[experimental] - pub fn push_all(&mut self, other: &[T]) { - self.reserve(other.len()); - - for i in range(0, other.len()) { - let len = self.len(); - - // Unsafe code so this can be optimised to a memcpy (or something similarly - // fast) when T is Copy. LLVM is easily confused, so any extra operations - // during the loop can prevent this optimisation. - unsafe { - ptr::write( - self.unsafe_mut(len), - other.unsafe_get(i).clone()); - self.set_len(len + 1); + #[stable] + pub fn reserve_exact(&mut self, additional: uint) { + if self.cap - self.len < additional { + match self.len.checked_add(additional) { + None => panic!("Vec::reserve: `uint` overflow"), + Some(new_cap) => self.grow_capacity(new_cap) } } } - /// Grows the `Vec` in-place. + /// Shrinks the capacity of the vector as much as possible. /// - /// Adds `n` copies of `value` to the `Vec`. + /// It will drop down as close as possible to the length but the allocator + /// may still inform the vector that there is space for a few more elements. /// /// # Examples /// /// ``` - /// let mut vec = vec!["hello"]; - /// vec.grow(2, "world"); - /// assert_eq!(vec, vec!["hello", "world", "world"]); + /// let mut vec: Vec = Vec::with_capacity(10); + /// vec.push_all(&[1, 2, 3]); + /// assert_eq!(vec.capacity(), 10); + /// vec.shrink_to_fit(); + /// assert!(vec.capacity() >= 3); /// ``` #[stable] - pub fn grow(&mut self, n: uint, value: T) { - self.reserve(n); - let mut i: uint = 0u; + pub fn shrink_to_fit(&mut self) { + if mem::size_of::() == 0 { return } + + if self.len == 0 { + if self.cap != 0 { + unsafe { + dealloc(*self.ptr, self.cap) + } + self.cap = 0; + } + } else { + unsafe { + // Overflow check is unnecessary as the vector is already at + // least this large. + let ptr = reallocate(*self.ptr as *mut u8, + self.cap * mem::size_of::(), + self.len * mem::size_of::(), + mem::min_align_of::()) as *mut T; + if ptr.is_null() { ::alloc::oom() } + self.ptr = NonZero::new(ptr); + } + self.cap = self.len; + } + } - while i < n { - self.push(value.clone()); - i += 1u; + /// Convert the vector into Box<[T]>. + /// + /// Note that this will drop any excess capacity. Calling this and + /// converting back to a vector with `into_vec()` is equivalent to calling + /// `shrink_to_fit()`. + #[experimental] + pub fn into_boxed_slice(mut self) -> Box<[T]> { + self.shrink_to_fit(); + unsafe { + let xs: Box<[T]> = mem::transmute(self.as_mut_slice()); + mem::forget(self); + xs } } - /// Resizes the `Vec` in-place so that `len()` is equal to `new_len`. + /// Shorten a vector, dropping excess elements. /// - /// Calls either `extend()` or `truncate()` depending on whether `new_len` - /// is larger than the current value of `len()` or not. + /// If `len` is greater than the vector's current length, this has no + /// effect. /// /// # Examples /// /// ``` - /// let mut vec = vec!["hello"]; - /// vec.resize(3, "world"); - /// assert_eq!(vec, vec!["hello", "world", "world"]); - /// /// let mut vec = vec![1i, 2, 3, 4]; - /// vec.resize(2, 0); + /// vec.truncate(2); /// assert_eq!(vec, vec![1, 2]); /// ``` - #[unstable = "matches collection reform specification; waiting for dust to settle"] - pub fn resize(&mut self, new_len: uint, value: T) { - let len = self.len(); - - if new_len > len { - self.extend(repeat(value).take(new_len - len)); - } else { - self.truncate(new_len); + #[stable] + pub fn truncate(&mut self, len: uint) { + unsafe { + // drop any extra elements + while len < self.len { + // decrement len before the read(), so a panic on Drop doesn't + // re-drop the just-failed value. + self.len -= 1; + ptr::read(self.get_unchecked(self.len)); + } } } - /// Partitions a vector based on a predicate. - /// - /// Clones the elements of the vector, partitioning them into two `Vec`s - /// `(a, b)`, where all elements of `a` satisfy `f` and all elements of `b` - /// do not. The order of elements is preserved. + /// Returns a mutable slice of the elements of `self`. /// /// # Examples /// /// ``` - /// let vec = vec![1i, 2, 3, 4]; - /// let (even, odd) = vec.partitioned(|&n| n % 2 == 0); - /// assert_eq!(even, vec![2i, 4]); - /// assert_eq!(odd, vec![1i, 3]); + /// fn foo(slice: &mut [int]) {} + /// + /// let mut vec = vec![1i, 2]; + /// foo(vec.as_mut_slice()); /// ``` - #[experimental] - pub fn partitioned(&self, mut f: F) -> (Vec, Vec) where F: FnMut(&T) -> bool { - let mut lefts = Vec::new(); - let mut rights = Vec::new(); - - for elt in self.iter() { - if f(elt) { - lefts.push(elt.clone()); - } else { - rights.push(elt.clone()); - } + #[inline] + #[stable] + pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] { + unsafe { + mem::transmute(RawSlice { + data: *self.ptr as *const T, + len: self.len, + }) } - - (lefts, rights) } -} - -#[stable] -impl Clone for Vec { - fn clone(&self) -> Vec { self.as_slice().to_vec() } - - fn clone_from(&mut self, other: &Vec) { - // drop anything in self that will not be overwritten - if self.len() > other.len() { - self.truncate(other.len()) - } - // reuse the contained values' allocations/resources. - for (place, thing) in self.iter_mut().zip(other.iter()) { - place.clone_from(thing) + /// Creates a consuming iterator, that is, one that moves each value out of + /// the vector (from start to end). The vector cannot be used after calling + /// this. + /// + /// # Examples + /// + /// ``` + /// let v = vec!["a".to_string(), "b".to_string()]; + /// for s in v.into_iter() { + /// // s has type String, not &String + /// println!("{}", s); + /// } + /// ``` + #[inline] + #[stable] + pub fn into_iter(self) -> IntoIter { + unsafe { + let ptr = *self.ptr; + let cap = self.cap; + let begin = ptr as *const T; + let end = if mem::size_of::() == 0 { + (ptr as uint + self.len()) as *const T + } else { + ptr.offset(self.len() as int) as *const T + }; + mem::forget(self); + IntoIter { allocation: ptr, cap: cap, ptr: begin, end: end } } - - // self.len <= other.len due to the truncate above, so the - // slice here is always in-bounds. - let slice = other[self.len()..]; - self.push_all(slice); } -} -#[experimental = "waiting on Index stability"] -impl Index for Vec { + /// Sets the length of a vector. + /// + /// This will explicitly set the size of the vector, without actually + /// modifying its buffers, so it is up to the caller to ensure that the + /// vector is actually the specified size. + /// + /// # Examples + /// + /// ``` + /// let mut v = vec![1u, 2, 3, 4]; + /// unsafe { + /// v.set_len(1); + /// } + /// ``` #[inline] - fn index<'a>(&'a self, index: &uint) -> &'a T { - &self.as_slice()[*index] + #[stable] + pub unsafe fn set_len(&mut self, len: uint) { + self.len = len; } -} -impl IndexMut for Vec { - #[inline] - fn index_mut<'a>(&'a mut self, index: &uint) -> &'a mut T { - &mut self.as_mut_slice()[*index] - } -} - -impl ops::Slice for Vec { - #[inline] - fn as_slice_<'a>(&'a self) -> &'a [T] { - self.as_slice() - } - - #[inline] - fn slice_from_or_fail<'a>(&'a self, start: &uint) -> &'a [T] { - self.as_slice().slice_from_or_fail(start) - } - - #[inline] - fn slice_to_or_fail<'a>(&'a self, end: &uint) -> &'a [T] { - self.as_slice().slice_to_or_fail(end) - } - #[inline] - fn slice_or_fail<'a>(&'a self, start: &uint, end: &uint) -> &'a [T] { - self.as_slice().slice_or_fail(start, end) - } -} - -impl ops::SliceMut for Vec { - #[inline] - fn as_mut_slice_<'a>(&'a mut self) -> &'a mut [T] { - self.as_mut_slice() - } - - #[inline] - fn slice_from_or_fail_mut<'a>(&'a mut self, start: &uint) -> &'a mut [T] { - self.as_mut_slice().slice_from_or_fail_mut(start) - } - - #[inline] - fn slice_to_or_fail_mut<'a>(&'a mut self, end: &uint) -> &'a mut [T] { - self.as_mut_slice().slice_to_or_fail_mut(end) - } - #[inline] - fn slice_or_fail_mut<'a>(&'a mut self, start: &uint, end: &uint) -> &'a mut [T] { - self.as_mut_slice().slice_or_fail_mut(start, end) - } -} - -#[experimental = "waiting on Deref stability"] -impl ops::Deref<[T]> for Vec { - fn deref<'a>(&'a self) -> &'a [T] { self.as_slice() } -} - -#[experimental = "waiting on DerefMut stability"] -impl ops::DerefMut<[T]> for Vec { - fn deref_mut<'a>(&'a mut self) -> &'a mut [T] { self.as_mut_slice() } -} - -#[experimental = "waiting on FromIterator stability"] -impl FromIterator for Vec { - #[inline] - fn from_iter>(mut iterator: I) -> Vec { - let (lower, _) = iterator.size_hint(); - let mut vector = Vec::with_capacity(lower); - for element in iterator { - vector.push(element) - } - vector - } -} - -#[experimental = "waiting on Extend stability"] -impl Extend for Vec { - #[inline] - fn extend>(&mut self, mut iterator: I) { - let (lower, _) = iterator.size_hint(); - self.reserve(lower); - for element in iterator { - self.push(element) - } - } -} - -impl PartialEq> for Vec where A: PartialEq { - #[inline] - fn eq(&self, other: &Vec) -> bool { PartialEq::eq(&**self, &**other) } - #[inline] - fn ne(&self, other: &Vec) -> bool { PartialEq::ne(&**self, &**other) } -} - -macro_rules! impl_eq { - ($lhs:ty, $rhs:ty) => { - impl<'b, A, B> PartialEq<$rhs> for $lhs where A: PartialEq { - #[inline] - fn eq(&self, other: &$rhs) -> bool { PartialEq::eq(&**self, &**other) } - #[inline] - fn ne(&self, other: &$rhs) -> bool { PartialEq::ne(&**self, &**other) } - } - - impl<'b, A, B> PartialEq<$lhs> for $rhs where B: PartialEq { - #[inline] - fn eq(&self, other: &$lhs) -> bool { PartialEq::eq(&**self, &**other) } - #[inline] - fn ne(&self, other: &$lhs) -> bool { PartialEq::ne(&**self, &**other) } - } - } -} - -impl_eq! { Vec, &'b [B] } -impl_eq! { Vec, &'b mut [B] } - -impl<'a, A, B> PartialEq> for CowVec<'a, A> where A: PartialEq + Clone { - #[inline] - fn eq(&self, other: &Vec) -> bool { PartialEq::eq(&**self, &**other) } - #[inline] - fn ne(&self, other: &Vec) -> bool { PartialEq::ne(&**self, &**other) } -} - -impl<'a, A, B> PartialEq> for Vec where A: Clone, B: PartialEq { - #[inline] - fn eq(&self, other: &CowVec<'a, A>) -> bool { PartialEq::eq(&**self, &**other) } - #[inline] - fn ne(&self, other: &CowVec<'a, A>) -> bool { PartialEq::ne(&**self, &**other) } -} - -macro_rules! impl_eq_for_cowvec { - ($rhs:ty) => { - impl<'a, 'b, A, B> PartialEq<$rhs> for CowVec<'a, A> where A: PartialEq + Clone { - #[inline] - fn eq(&self, other: &$rhs) -> bool { PartialEq::eq(&**self, &**other) } - #[inline] - fn ne(&self, other: &$rhs) -> bool { PartialEq::ne(&**self, &**other) } - } - - impl<'a, 'b, A, B> PartialEq> for $rhs where A: Clone, B: PartialEq { - #[inline] - fn eq(&self, other: &CowVec<'a, A>) -> bool { PartialEq::eq(&**self, &**other) } - #[inline] - fn ne(&self, other: &CowVec<'a, A>) -> bool { PartialEq::ne(&**self, &**other) } - } - } -} - -impl_eq_for_cowvec! { &'b [B] } -impl_eq_for_cowvec! { &'b mut [B] } - -#[unstable = "waiting on PartialOrd stability"] -impl PartialOrd for Vec { - #[inline] - fn partial_cmp(&self, other: &Vec) -> Option { - self.as_slice().partial_cmp(other.as_slice()) - } -} - -#[unstable = "waiting on Eq stability"] -impl Eq for Vec {} - -#[allow(deprecated)] -#[deprecated = "Use overloaded `core::cmp::PartialEq`"] -impl> Equiv for Vec { - #[inline] - fn equiv(&self, other: &V) -> bool { self.as_slice() == other.as_slice() } -} - -#[unstable = "waiting on Ord stability"] -impl Ord for Vec { - #[inline] - fn cmp(&self, other: &Vec) -> Ordering { - self.as_slice().cmp(other.as_slice()) - } -} - -impl> Hash for Vec { - #[inline] - fn hash(&self, state: &mut S) { - self.as_slice().hash(state); - } -} - -// FIXME: #13996: need a way to mark the return value as `noalias` -#[inline(never)] -unsafe fn alloc_or_realloc(ptr: *mut T, old_size: uint, size: uint) -> *mut T { - if old_size == 0 { - allocate(size, mem::min_align_of::()) as *mut T - } else { - reallocate(ptr as *mut u8, old_size, size, mem::min_align_of::()) as *mut T - } -} - -#[inline] -unsafe fn dealloc(ptr: *mut T, len: uint) { - if mem::size_of::() != 0 { - deallocate(ptr as *mut u8, - len * mem::size_of::(), - mem::min_align_of::()) - } -} - -impl Vec { - /// Returns the number of elements the vector can hold without reallocating. + /// Removes an element from anywhere in the vector and return it, replacing + /// it with the last element. + /// + /// This does not preserve ordering, but is O(1). + /// + /// # Panics + /// + /// Panics if `index` is out of bounds. /// /// # Examples /// /// ``` - /// let vec: Vec = Vec::with_capacity(10); - /// assert_eq!(vec.capacity(), 10); + /// let mut v = vec!["foo", "bar", "baz", "qux"]; + /// + /// assert_eq!(v.swap_remove(1), "bar"); + /// assert_eq!(v, vec!["foo", "qux", "baz"]); + /// + /// assert_eq!(v.swap_remove(0), "foo"); + /// assert_eq!(v, vec!["baz", "qux"]); /// ``` #[inline] #[stable] - pub fn capacity(&self) -> uint { - self.cap - } - - /// Deprecated: Renamed to `reserve`. - #[deprecated = "Renamed to `reserve`"] - pub fn reserve_additional(&mut self, extra: uint) { - self.reserve(extra) + pub fn swap_remove(&mut self, index: uint) -> T { + let length = self.len(); + self.swap(index, length - 1); + self.pop().unwrap() } - /// Reserves capacity for at least `additional` more elements to be inserted in the given - /// `Vec`. The collection may reserve more space to avoid frequent reallocations. + /// Inserts an element at position `index` within the vector, shifting all + /// elements after position `i` one position to the right. /// /// # Panics /// - /// Panics if the new capacity overflows `uint`. + /// Panics if `index` is not between `0` and the vector's length (both + /// bounds inclusive). /// /// # Examples /// /// ``` - /// let mut vec: Vec = vec![1]; - /// vec.reserve(10); - /// assert!(vec.capacity() >= 11); + /// let mut vec = vec![1i, 2, 3]; + /// vec.insert(1, 4); + /// assert_eq!(vec, vec![1, 4, 2, 3]); + /// vec.insert(4, 5); + /// assert_eq!(vec, vec![1, 4, 2, 3, 5]); /// ``` - #[unstable = "matches collection reform specification, waiting for dust to settle"] - pub fn reserve(&mut self, additional: uint) { - if self.cap - self.len < additional { - let err_msg = "Vec::reserve: `uint` overflow"; - let new_cap = self.len.checked_add(additional).expect(err_msg) - .checked_next_power_of_two().expect(err_msg); - self.grow_capacity(new_cap); + #[stable] + pub fn insert(&mut self, index: uint, element: T) { + let len = self.len(); + assert!(index <= len); + // space for the new element + self.reserve(1); + + unsafe { // infallible + // The spot to put the new value + { + let p = self.as_mut_ptr().offset(index as int); + // Shift everything over to make space. (Duplicating the + // `index`th element into two consecutive places.) + ptr::copy_memory(p.offset(1), &*p, len - index); + // Write it in, overwriting the first copy of the `index`th + // element. + ptr::write(&mut *p, element); + } + self.set_len(len + 1); } } - /// Reserves the minimum capacity for exactly `additional` more elements to be inserted in the - /// given `Vec`. Does nothing if the capacity is already sufficient. - /// - /// Note that the allocator may give the collection more space than it requests. Therefore - /// capacity can not be relied upon to be precisely minimal. Prefer `reserve` if future - /// insertions are expected. + /// Removes and returns the element at position `index` within the vector, + /// shifting all elements after position `index` one position to the left. /// /// # Panics /// - /// Panics if the new capacity overflows `uint`. + /// Panics if `i` is out of bounds. /// /// # Examples /// /// ``` - /// let mut vec: Vec = vec![1]; - /// vec.reserve_exact(10); - /// assert!(vec.capacity() >= 11); + /// let mut v = vec![1i, 2, 3]; + /// assert_eq!(v.remove(1), 2); + /// assert_eq!(v, vec![1, 3]); /// ``` - #[unstable = "matches collection reform specification, waiting for dust to settle"] - pub fn reserve_exact(&mut self, additional: uint) { - if self.cap - self.len < additional { - match self.len.checked_add(additional) { - None => panic!("Vec::reserve: `uint` overflow"), - Some(new_cap) => self.grow_capacity(new_cap) + #[stable] + pub fn remove(&mut self, index: uint) -> T { + let len = self.len(); + assert!(index < len); + unsafe { // infallible + let ret; + { + // the place we are taking from. + let ptr = self.as_mut_ptr().offset(index as int); + // copy it out, unsafely having a copy of the value on + // the stack and in the vector at the same time. + ret = ptr::read(ptr as *const T); + + // Shift everything down to fill in that spot. + ptr::copy_memory(ptr, &*ptr.offset(1), len - index - 1); } + self.set_len(len - 1); + ret } } - /// Shrinks the capacity of the vector as much as possible. + /// Retains only the elements specified by the predicate. /// - /// It will drop down as close as possible to the length but the allocator may still inform the - /// vector that there is space for a few more elements. + /// In other words, remove all elements `e` such that `f(&e)` returns false. + /// This method operates in place and preserves the order of the retained + /// elements. /// /// # Examples /// /// ``` - /// let mut vec: Vec = Vec::with_capacity(10); - /// - /// vec.push_all(&[1, 2, 3]); - /// assert_eq!(vec.capacity(), 10); - /// - /// vec.shrink_to_fit(); - /// assert!(vec.capacity() >= 3); + /// let mut vec = vec![1i, 2, 3, 4]; + /// vec.retain(|&x| x%2 == 0); + /// assert_eq!(vec, vec![2, 4]); /// ``` #[stable] - pub fn shrink_to_fit(&mut self) { - if mem::size_of::() == 0 { return } + pub fn retain(&mut self, mut f: F) where F: FnMut(&T) -> bool { + let len = self.len(); + let mut del = 0u; + { + let v = self.as_mut_slice(); - if self.len == 0 { - if self.cap != 0 { - unsafe { - dealloc(*self.ptr, self.cap) + for i in range(0u, len) { + if !f(&v[i]) { + del += 1; + } else if del > 0 { + v.swap(i-del, i); } - self.cap = 0; - } - } else { - unsafe { - // Overflow check is unnecessary as the vector is already at - // least this large. - let ptr = reallocate(*self.ptr as *mut u8, - self.cap * mem::size_of::(), - self.len * mem::size_of::(), - mem::min_align_of::()) as *mut T; - if ptr.is_null() { ::alloc::oom() } - self.ptr = NonZero::new(ptr); } - self.cap = self.len; + } + if del > 0 { + self.truncate(len - del); } } - /// Convert the vector into Box<[T]>. - /// - /// Note that this will drop any excess capacity. Calling this and converting back to a vector - /// with `into_vec()` is equivalent to calling `shrink_to_fit()`. - #[experimental] - pub fn into_boxed_slice(mut self) -> Box<[T]> { - self.shrink_to_fit(); - unsafe { - let xs: Box<[T]> = mem::transmute(self.as_mut_slice()); - mem::forget(self); - xs - } + /// Deprecated: use `extend(range(0, n).map(f))` instead. + #[deprecated = "use extend(range(0, n).map(f)) instead"] + pub fn grow_fn(&mut self, n: uint, f: F) where F: FnMut(uint) -> T { + self.extend(range(0, n).map(f)); } - /// Shorten a vector, dropping excess elements. + /// Appends an element to the back of a collection. /// - /// If `len` is greater than the vector's current length, this has no - /// effect. + /// # Panics + /// + /// Panics if the number of elements in the vector overflows a `uint`. /// /// # Examples /// + /// ```rust + /// let mut vec = vec!(1i, 2); + /// vec.push(3); + /// assert_eq!(vec, vec!(1, 2, 3)); /// ``` - /// let mut vec = vec![1i, 2, 3, 4]; - /// vec.truncate(2); - /// assert_eq!(vec, vec![1, 2]); - /// ``` - #[unstable = "matches collection reform specification; waiting on panic semantics"] - pub fn truncate(&mut self, len: uint) { - unsafe { - // drop any extra elements - while len < self.len { - // decrement len before the read(), so a panic on Drop doesn't - // re-drop the just-failed value. - self.len -= 1; - ptr::read(self.unsafe_get(self.len)); + #[inline] + #[stable] + pub fn push(&mut self, value: T) { + if mem::size_of::() == 0 { + // zero-size types consume no memory, so we can't rely on the + // address space running out + self.len = self.len.checked_add(1).expect("length overflow"); + unsafe { mem::forget(value); } + return + } + if self.len == self.cap { + let old_size = self.cap * mem::size_of::(); + let size = max(old_size, 2 * mem::size_of::()) * 2; + if old_size > size { panic!("capacity overflow") } + unsafe { + let ptr = alloc_or_realloc(*self.ptr, old_size, size); + if ptr.is_null() { ::alloc::oom() } + self.ptr = NonZero::new(ptr); } + self.cap = max(self.cap, 2) * 2; + } + + unsafe { + let end = (*self.ptr).offset(self.len as int); + ptr::write(&mut *end, value); + self.len += 1; } } - /// Returns a mutable slice of the elements of `self`. + /// Removes the last element from a vector and returns it, or `None` if it is empty. /// /// # Examples /// - /// ``` - /// fn foo(slice: &mut [int]) {} - /// - /// let mut vec = vec![1i, 2]; - /// foo(vec.as_mut_slice()); + /// ```rust + /// let mut vec = vec![1i, 2, 3]; + /// assert_eq!(vec.pop(), Some(3)); + /// assert_eq!(vec, vec![1, 2]); /// ``` #[inline] #[stable] - pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] { - unsafe { - mem::transmute(RawSlice { - data: *self.ptr as *const T, - len: self.len, - }) + pub fn pop(&mut self) -> Option { + if self.len == 0 { + None + } else { + unsafe { + self.len -= 1; + Some(ptr::read(self.get_unchecked(self.len()))) + } } } - /// Creates a consuming iterator, that is, one that moves each value out of the vector (from - /// start to end). The vector cannot be used after calling this. + /// Creates a draining iterator that clears the `Vec` and iterates over + /// the removed items from start to end. /// /// # Examples /// /// ``` - /// let v = vec!["a".to_string(), "b".to_string()]; - /// - /// for s in v.into_iter() { + /// let mut v = vec!["a".to_string(), "b".to_string()]; + /// for s in v.drain() { /// // s has type String, not &String /// println!("{}", s); /// } + /// assert!(v.is_empty()); /// ``` #[inline] #[unstable = "matches collection reform specification, waiting for dust to settle"] - pub fn into_iter(self) -> IntoIter { + pub fn drain<'a>(&'a mut self) -> Drain<'a, T> { unsafe { - let ptr = *self.ptr; - let cap = self.cap; - let begin = ptr as *const T; + let begin = *self.ptr as *const T; let end = if mem::size_of::() == 0 { - (ptr as uint + self.len()) as *const T + (*self.ptr as uint + self.len()) as *const T } else { - ptr.offset(self.len() as int) as *const T + (*self.ptr).offset(self.len() as int) as *const T }; - mem::forget(self); - IntoIter { allocation: ptr, cap: cap, ptr: begin, end: end } + self.set_len(0); + Drain { + ptr: begin, + end: end, + marker: ContravariantLifetime, + } } } - /// Sets the length of a vector. - /// - /// This will explicitly set the size of the vector, without actually modifying its buffers, so - /// it is up to the caller to ensure that the vector is actually the specified size. + /// Clears the vector, removing all values. /// /// # Examples /// /// ``` - /// let mut v = vec![1u, 2, 3, 4]; - /// unsafe { - /// v.set_len(1); - /// } + /// let mut v = vec![1i, 2, 3]; + /// + /// v.clear(); + /// + /// assert!(v.is_empty()); /// ``` #[inline] #[stable] - pub unsafe fn set_len(&mut self, len: uint) { - self.len = len; + pub fn clear(&mut self) { + self.truncate(0) } - /// Removes an element from anywhere in the vector and return it, replacing it with the last - /// element. - /// - /// This does not preserve ordering, but is O(1). - /// - /// Returns `None` if `index` is out of bounds. + /// Returns the number of elements in the vector. /// /// # Examples /// /// ``` - /// let mut v = vec!["foo", "bar", "baz", "qux"]; - /// - /// assert_eq!(v.swap_remove(1), Some("bar")); - /// assert_eq!(v, vec!["foo", "qux", "baz"]); - /// - /// assert_eq!(v.swap_remove(0), Some("foo")); - /// assert_eq!(v, vec!["baz", "qux"]); - /// - /// assert_eq!(v.swap_remove(2), None); + /// let a = vec![1i, 2, 3]; + /// assert_eq!(a.len(), 3); /// ``` #[inline] - #[unstable = "the naming of this function may be altered"] - pub fn swap_remove(&mut self, index: uint) -> Option { - let length = self.len(); - if length > 0 && index < length - 1 { - self.swap(index, length - 1); - } else if index >= length { - return None - } - self.pop() - } + #[stable] + pub fn len(&self) -> uint { self.len } - /// Inserts an element at position `index` within the vector, shifting all elements after - /// position `i` one position to the right. - /// - /// # Panics - /// - /// Panics if `index` is not between `0` and the vector's length (both bounds inclusive). + /// Returns `true` if the vector contains no elements. /// /// # Examples /// /// ``` - /// let mut vec = vec![1i, 2, 3]; - /// vec.insert(1, 4); - /// assert_eq!(vec, vec![1, 4, 2, 3]); - /// vec.insert(4, 5); - /// assert_eq!(vec, vec![1, 4, 2, 3, 5]); + /// let mut v = Vec::new(); + /// assert!(v.is_empty()); + /// + /// v.push(1i); + /// assert!(!v.is_empty()); /// ``` - #[unstable = "panic semantics need settling"] - pub fn insert(&mut self, index: uint, element: T) { - let len = self.len(); - assert!(index <= len); - // space for the new element - self.reserve(1); - - unsafe { // infallible - // The spot to put the new value - { - let p = self.as_mut_ptr().offset(index as int); - // Shift everything over to make space. (Duplicating the - // `index`th element into two consecutive places.) - ptr::copy_memory(p.offset(1), &*p, len - index); - // Write it in, overwriting the first copy of the `index`th - // element. - ptr::write(&mut *p, element); - } - self.set_len(len + 1); - } - } + #[stable] + pub fn is_empty(&self) -> bool { self.len() == 0 } - /// Removes and returns the element at position `index` within the vector, shifting all - /// elements after position `index` one position to the left. Returns `None` if `i` is out of - /// bounds. + /// Converts a `Vec` to a `Vec` where `T` and `U` have the same + /// size and in case they are not zero-sized the same minimal alignment. + /// + /// # Panics + /// + /// Panics if `T` and `U` have differing sizes or are not zero-sized and + /// have differing minimal alignments. /// /// # Examples /// /// ``` - /// let mut v = vec![1i, 2, 3]; - /// assert_eq!(v.remove(1), Some(2)); - /// assert_eq!(v, vec![1, 3]); + /// let v = vec![0u, 1, 2]; + /// let w = v.map_in_place(|i| i + 3); + /// assert_eq!(w.as_slice(), [3, 4, 5].as_slice()); /// - /// assert_eq!(v.remove(4), None); - /// // v is unchanged: - /// assert_eq!(v, vec![1, 3]); + /// #[deriving(PartialEq, Show)] + /// struct Newtype(u8); + /// let bytes = vec![0x11, 0x22]; + /// let newtyped_bytes = bytes.map_in_place(|x| Newtype(x)); + /// assert_eq!(newtyped_bytes.as_slice(), [Newtype(0x11), Newtype(0x22)].as_slice()); /// ``` - #[unstable = "panic semantics need settling"] - pub fn remove(&mut self, index: uint) -> Option { - let len = self.len(); - if index < len { - unsafe { // infallible - let ret; - { - // the place we are taking from. - let ptr = self.as_mut_ptr().offset(index as int); - // copy it out, unsafely having a copy of the value on - // the stack and in the vector at the same time. - ret = Some(ptr::read(ptr as *const T)); - - // Shift everything down to fill in that spot. - ptr::copy_memory(ptr, &*ptr.offset(1), len - index - 1); + #[experimental = "API may change to provide stronger guarantees"] + pub fn map_in_place(self, mut f: F) -> Vec where F: FnMut(T) -> U { + // FIXME: Assert statically that the types `T` and `U` have the same + // size. + assert!(mem::size_of::() == mem::size_of::()); + + let mut vec = self; + + if mem::size_of::() != 0 { + // FIXME: Assert statically that the types `T` and `U` have the + // same minimal alignment in case they are not zero-sized. + + // These asserts are necessary because the `min_align_of` of the + // types are passed to the allocator by `Vec`. + assert!(mem::min_align_of::() == mem::min_align_of::()); + + // This `as int` cast is safe, because the size of the elements of the + // vector is not 0, and: + // + // 1) If the size of the elements in the vector is 1, the `int` may + // overflow, but it has the correct bit pattern so that the + // `.offset()` function will work. + // + // Example: + // Address space 0x0-0xF. + // `u8` array at: 0x1. + // Size of `u8` array: 0x8. + // Calculated `offset`: -0x8. + // After `array.offset(offset)`: 0x9. + // (0x1 + 0x8 = 0x1 - 0x8) + // + // 2) If the size of the elements in the vector is >1, the `uint` -> + // `int` conversion can't overflow. + let offset = vec.len() as int; + let start = vec.as_mut_ptr(); + + let mut pv = PartialVecNonZeroSized { + vec: vec, + + start_t: start, + // This points inside the vector, as the vector has length + // `offset`. + end_t: unsafe { start.offset(offset) }, + start_u: start as *mut U, + end_u: start as *mut U, + }; + // start_t + // start_u + // | + // +-+-+-+-+-+-+ + // |T|T|T|...|T| + // +-+-+-+-+-+-+ + // | | + // end_u end_t + + while pv.end_u as *mut T != pv.end_t { + unsafe { + // start_u start_t + // | | + // +-+-+-+-+-+-+-+-+-+ + // |U|...|U|T|T|...|T| + // +-+-+-+-+-+-+-+-+-+ + // | | + // end_u end_t + + let t = ptr::read(pv.start_t as *const T); + // start_u start_t + // | | + // +-+-+-+-+-+-+-+-+-+ + // |U|...|U|X|T|...|T| + // +-+-+-+-+-+-+-+-+-+ + // | | + // end_u end_t + // We must not panic here, one cell is marked as `T` + // although it is not `T`. + + pv.start_t = pv.start_t.offset(1); + // start_u start_t + // | | + // +-+-+-+-+-+-+-+-+-+ + // |U|...|U|X|T|...|T| + // +-+-+-+-+-+-+-+-+-+ + // | | + // end_u end_t + // We may panic again. + + // The function given by the user might panic. + let u = f(t); + + ptr::write(pv.end_u, u); + // start_u start_t + // | | + // +-+-+-+-+-+-+-+-+-+ + // |U|...|U|U|T|...|T| + // +-+-+-+-+-+-+-+-+-+ + // | | + // end_u end_t + // We should not panic here, because that would leak the `U` + // pointed to by `end_u`. + + pv.end_u = pv.end_u.offset(1); + // start_u start_t + // | | + // +-+-+-+-+-+-+-+-+-+ + // |U|...|U|U|T|...|T| + // +-+-+-+-+-+-+-+-+-+ + // | | + // end_u end_t + // We may panic again. } - self.set_len(len - 1); - ret + } + + // start_u start_t + // | | + // +-+-+-+-+-+-+ + // |U|...|U|U|U| + // +-+-+-+-+-+-+ + // | + // end_t + // end_u + // Extract `vec` and prevent the destructor of + // `PartialVecNonZeroSized` from running. Note that none of the + // function calls can panic, thus no resources can be leaked (as the + // `vec` member of `PartialVec` is the only one which holds + // allocations -- and it is returned from this function. None of + // this can panic. + unsafe { + let vec_len = pv.vec.len(); + let vec_cap = pv.vec.capacity(); + let vec_ptr = pv.vec.as_mut_ptr() as *mut U; + mem::forget(pv); + Vec::from_raw_parts(vec_ptr, vec_len, vec_cap) } } else { - None - } - } + // Put the `Vec` into the `PartialVecZeroSized` structure and + // prevent the destructor of the `Vec` from running. Since the + // `Vec` contained zero-sized objects, it did not allocate, so we + // are not leaking memory here. + let mut pv = PartialVecZeroSized:: { + num_t: vec.len(), + num_u: 0, + marker_t: InvariantType, + marker_u: InvariantType, + }; + unsafe { mem::forget(vec); } - /// Retains only the elements specified by the predicate. - /// - /// In other words, remove all elements `e` such that `f(&e)` returns false. This method - /// operates in place and preserves the order of the retained elements. - /// - /// # Examples - /// - /// ``` - /// let mut vec = vec![1i, 2, 3, 4]; - /// vec.retain(|&x| x%2 == 0); - /// assert_eq!(vec, vec![2, 4]); - /// ``` - #[unstable = "the closure argument may become an unboxed closure"] - pub fn retain(&mut self, mut f: F) where F: FnMut(&T) -> bool { - let len = self.len(); - let mut del = 0u; - { - let v = self.as_mut_slice(); + while pv.num_t != 0 { + unsafe { + // Create a `T` out of thin air and decrement `num_t`. This + // must not panic between these steps, as otherwise a + // destructor of `T` which doesn't exist runs. + let t = mem::uninitialized(); + pv.num_t -= 1; - for i in range(0u, len) { - if !f(&v[i]) { - del += 1; - } else if del > 0 { - v.swap(i-del, i); + // The function given by the user might panic. + let u = f(t); + + // Forget the `U` and increment `num_u`. This increment + // cannot overflow the `uint` as we only do this for a + // number of times that fits into a `uint` (and start with + // `0`). Again, we should not panic between these steps. + mem::forget(u); + pv.num_u += 1; } } - } - if del > 0 { - self.truncate(len - del); + // Create a `Vec` from our `PartialVecZeroSized` and make sure the + // destructor of the latter will not run. None of this can panic. + let mut result = Vec::new(); + unsafe { + result.set_len(pv.num_u); + mem::forget(pv); + } + result } } +} - /// Expands a vector in place, initializing the new elements to the result of a function. - /// - /// The vector is grown by `n` elements. The i-th new element are initialized to the value - /// returned by `f(i)` where `i` is in the range [0, n). - /// - /// # Examples - /// - /// ``` - /// let mut vec = vec![0u, 1]; - /// vec.grow_fn(3, |i| i); - /// assert_eq!(vec, vec![0, 1, 0, 1, 2]); - /// ``` - #[unstable = "this function may be renamed or change to unboxed closures"] - pub fn grow_fn(&mut self, n: uint, mut f: F) where F: FnMut(uint) -> T { - self.reserve(n); - for i in range(0u, n) { - self.push(f(i)); - } +impl Vec { + /// Deprecated: use `repeat(value).take(length).collect()` instead. + #[inline] + #[deprecated = "use repeat(value).take(length).collect() instead"] + pub fn from_elem(length: uint, value: T) -> Vec { + repeat(value).take(length).collect() } - /// Appends an element to the back of a collection. - /// - /// # Panics + /// Resizes the `Vec` in-place so that `len()` is equal to `new_len`. /// - /// Panics if the number of elements in the vector overflows a `uint`. + /// Calls either `extend()` or `truncate()` depending on whether `new_len` + /// is larger than the current value of `len()` or not. /// /// # Examples /// - /// ```rust - /// let mut vec = vec!(1i, 2); - /// vec.push(3); - /// assert_eq!(vec, vec!(1, 2, 3)); /// ``` - #[inline] - #[stable] - pub fn push(&mut self, value: T) { - if mem::size_of::() == 0 { - // zero-size types consume no memory, so we can't rely on the address space running out - self.len = self.len.checked_add(1).expect("length overflow"); - unsafe { mem::forget(value); } - return - } - if self.len == self.cap { - let old_size = self.cap * mem::size_of::(); - let size = max(old_size, 2 * mem::size_of::()) * 2; - if old_size > size { panic!("capacity overflow") } - unsafe { - let ptr = alloc_or_realloc(*self.ptr, old_size, size); - if ptr.is_null() { ::alloc::oom() } - self.ptr = NonZero::new(ptr); - } - self.cap = max(self.cap, 2) * 2; - } - - unsafe { - let end = (*self.ptr).offset(self.len as int); - ptr::write(&mut *end, value); - self.len += 1; - } - } - - /// Removes the last element from a vector and returns it, or `None` if it is empty. - /// - /// # Examples + /// let mut vec = vec!["hello"]; + /// vec.resize(3, "world"); + /// assert_eq!(vec, vec!["hello", "world", "world"]); /// - /// ```rust - /// let mut vec = vec![1i, 2, 3]; - /// assert_eq!(vec.pop(), Some(3)); + /// let mut vec = vec![1i, 2, 3, 4]; + /// vec.resize(2, 0); /// assert_eq!(vec, vec![1, 2]); /// ``` - #[inline] - #[stable] - pub fn pop(&mut self) -> Option { - if self.len == 0 { - None - } else { - unsafe { - self.len -= 1; - Some(ptr::read(self.unsafe_get(self.len()))) - } - } - } + #[unstable = "matches collection reform specification; waiting for dust to settle"] + pub fn resize(&mut self, new_len: uint, value: T) { + let len = self.len(); - /// Creates a draining iterator that clears the `Vec` and iterates over - /// the removed items from start to end. - /// - /// # Examples - /// - /// ``` - /// let mut v = vec!["a".to_string(), "b".to_string()]; - /// for s in v.drain() { - /// // s has type String, not &String - /// println!("{}", s); - /// } - /// assert!(v.is_empty()); - /// ``` - #[inline] - #[unstable = "matches collection reform specification, waiting for dust to settle"] - pub fn drain<'a>(&'a mut self) -> Drain<'a, T> { - unsafe { - let begin = *self.ptr as *const T; - let end = if mem::size_of::() == 0 { - (*self.ptr as uint + self.len()) as *const T - } else { - (*self.ptr).offset(self.len() as int) as *const T - }; - self.set_len(0); - Drain { - ptr: begin, - end: end, - marker: ContravariantLifetime, - } + if new_len > len { + self.extend(repeat(value).take(new_len - len)); + } else { + self.truncate(new_len); } } - /// Clears the vector, removing all values. - /// - /// # Examples + /// Appends all elements in a slice to the `Vec`. /// - /// ``` - /// let mut v = vec![1i, 2, 3]; - /// - /// v.clear(); - /// - /// assert!(v.is_empty()); - /// ``` - #[inline] - #[stable] - pub fn clear(&mut self) { - self.truncate(0) - } - - /// Returns the number of elements in the vector. + /// Iterates over the slice `other`, clones each element, and then appends + /// it to this `Vec`. The `other` vector is traversed in-order. /// /// # Examples /// /// ``` - /// let a = vec![1i, 2, 3]; - /// assert_eq!(a.len(), 3); + /// let mut vec = vec![1i]; + /// vec.push_all(&[2i, 3, 4]); + /// assert_eq!(vec, vec![1, 2, 3, 4]); /// ``` #[inline] - #[stable] - pub fn len(&self) -> uint { self.len } - - /// Returns `true` if the vector contains no elements. - /// - /// # Examples - /// - /// ``` - /// let mut v = Vec::new(); - /// assert!(v.is_empty()); - /// - /// v.push(1i); - /// assert!(!v.is_empty()); - /// ``` - #[unstable = "matches collection reform specification, waiting for dust to settle"] - pub fn is_empty(&self) -> bool { self.len() == 0 } + #[experimental = "likely to be replaced by a more optimized extend"] + pub fn push_all(&mut self, other: &[T]) { + self.reserve(other.len()); - /// Reserves capacity for exactly `capacity` elements in the given vector. - /// - /// If the capacity for `self` is already equal to or greater than the - /// requested capacity, then no action is taken. - fn grow_capacity(&mut self, capacity: uint) { - if mem::size_of::() == 0 { return } + for i in range(0, other.len()) { + let len = self.len(); - if capacity > self.cap { - let size = capacity.checked_mul(mem::size_of::()) - .expect("capacity overflow"); + // Unsafe code so this can be optimised to a memcpy (or something similarly + // fast) when T is Copy. LLVM is easily confused, so any extra operations + // during the loop can prevent this optimisation. unsafe { - let ptr = alloc_or_realloc(*self.ptr, self.cap * mem::size_of::(), size); - if ptr.is_null() { ::alloc::oom() } - self.ptr = NonZero::new(ptr); + ptr::write( + self.get_unchecked_mut(len), + other.get_unchecked(i).clone()); + self.set_len(len + 1); } - self.cap = capacity; } } + + /// Deprecated: use `extend(repeat(value).take(n))` instead + #[deprecated = "use extend(repeat(value).take(n)) instead"] + pub fn grow(&mut self, n: uint, value: T) { + self.extend(repeat(value).take(n)) + } + + /// Deprecated: use `iter().cloned().partition(f)` instead. + #[deprecated = "use iter().cloned().partition(f) instead"] + pub fn partitioned(&self, f: F) -> (Vec, Vec) where F: FnMut(&T) -> bool { + self.iter().cloned().partition(f) + } } impl Vec { @@ -1260,7 +1072,7 @@ impl Vec { /// /// assert_eq!(vec, vec![1i, 2, 3, 2]); /// ``` - #[unstable = "this function may be renamed"] + #[stable] pub fn dedup(&mut self) { unsafe { // Although we have a mutable reference to `self`, we cannot make @@ -1341,8 +1153,276 @@ impl Vec { r += 1; } - self.truncate(w); - } + self.truncate(w); + } + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Public free fns +//////////////////////////////////////////////////////////////////////////////// + +/// Deprecated: use `unzip` directly on the iterator instead. +#[deprecated = "use unzip directly on the iterator instead"] +pub fn unzip>(iter: V) -> (Vec, Vec) { + iter.unzip() +} + +//////////////////////////////////////////////////////////////////////////////// +// Internal methods and functions +//////////////////////////////////////////////////////////////////////////////// + +impl Vec { + /// Reserves capacity for exactly `capacity` elements in the given vector. + /// + /// If the capacity for `self` is already equal to or greater than the + /// requested capacity, then no action is taken. + fn grow_capacity(&mut self, capacity: uint) { + if mem::size_of::() == 0 { return } + + if capacity > self.cap { + let size = capacity.checked_mul(mem::size_of::()) + .expect("capacity overflow"); + unsafe { + let ptr = alloc_or_realloc(*self.ptr, self.cap * mem::size_of::(), size); + if ptr.is_null() { ::alloc::oom() } + self.ptr = NonZero::new(ptr); + } + self.cap = capacity; + } + } +} + +// FIXME: #13996: need a way to mark the return value as `noalias` +#[inline(never)] +unsafe fn alloc_or_realloc(ptr: *mut T, old_size: uint, size: uint) -> *mut T { + if old_size == 0 { + allocate(size, mem::min_align_of::()) as *mut T + } else { + reallocate(ptr as *mut u8, old_size, size, mem::min_align_of::()) as *mut T + } +} + +#[inline] +unsafe fn dealloc(ptr: *mut T, len: uint) { + if mem::size_of::() != 0 { + deallocate(ptr as *mut u8, + len * mem::size_of::(), + mem::min_align_of::()) + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Common trait implementations for Vec +//////////////////////////////////////////////////////////////////////////////// + +#[unstable] +impl Clone for Vec { + fn clone(&self) -> Vec { self.as_slice().to_vec() } + + fn clone_from(&mut self, other: &Vec) { + // drop anything in self that will not be overwritten + if self.len() > other.len() { + self.truncate(other.len()) + } + + // reuse the contained values' allocations/resources. + for (place, thing) in self.iter_mut().zip(other.iter()) { + place.clone_from(thing) + } + + // self.len <= other.len due to the truncate above, so the + // slice here is always in-bounds. + let slice = other[self.len()..]; + self.push_all(slice); + } +} + +impl> Hash for Vec { + #[inline] + fn hash(&self, state: &mut S) { + self.as_slice().hash(state); + } +} + +#[experimental = "waiting on Index stability"] +impl Index for Vec { + #[inline] + fn index<'a>(&'a self, index: &uint) -> &'a T { + &self.as_slice()[*index] + } +} + +impl IndexMut for Vec { + #[inline] + fn index_mut<'a>(&'a mut self, index: &uint) -> &'a mut T { + &mut self.as_mut_slice()[*index] + } +} + +impl ops::Slice for Vec { + #[inline] + fn as_slice_<'a>(&'a self) -> &'a [T] { + self.as_slice() + } + + #[inline] + fn slice_from_or_fail<'a>(&'a self, start: &uint) -> &'a [T] { + self.as_slice().slice_from_or_fail(start) + } + + #[inline] + fn slice_to_or_fail<'a>(&'a self, end: &uint) -> &'a [T] { + self.as_slice().slice_to_or_fail(end) + } + #[inline] + fn slice_or_fail<'a>(&'a self, start: &uint, end: &uint) -> &'a [T] { + self.as_slice().slice_or_fail(start, end) + } +} + +impl ops::SliceMut for Vec { + #[inline] + fn as_mut_slice_<'a>(&'a mut self) -> &'a mut [T] { + self.as_mut_slice() + } + + #[inline] + fn slice_from_or_fail_mut<'a>(&'a mut self, start: &uint) -> &'a mut [T] { + self.as_mut_slice().slice_from_or_fail_mut(start) + } + + #[inline] + fn slice_to_or_fail_mut<'a>(&'a mut self, end: &uint) -> &'a mut [T] { + self.as_mut_slice().slice_to_or_fail_mut(end) + } + #[inline] + fn slice_or_fail_mut<'a>(&'a mut self, start: &uint, end: &uint) -> &'a mut [T] { + self.as_mut_slice().slice_or_fail_mut(start, end) + } +} + +#[experimental = "waiting on Deref stability"] +impl ops::Deref<[T]> for Vec { + fn deref<'a>(&'a self) -> &'a [T] { self.as_slice() } +} + +#[experimental = "waiting on DerefMut stability"] +impl ops::DerefMut<[T]> for Vec { + fn deref_mut<'a>(&'a mut self) -> &'a mut [T] { self.as_mut_slice() } +} + +#[experimental = "waiting on FromIterator stability"] +impl FromIterator for Vec { + #[inline] + fn from_iter>(mut iterator: I) -> Vec { + let (lower, _) = iterator.size_hint(); + let mut vector = Vec::with_capacity(lower); + for element in iterator { + vector.push(element) + } + vector + } +} + +#[experimental = "waiting on Extend stability"] +impl Extend for Vec { + #[inline] + fn extend>(&mut self, mut iterator: I) { + let (lower, _) = iterator.size_hint(); + self.reserve(lower); + for element in iterator { + self.push(element) + } + } +} + +impl PartialEq> for Vec where A: PartialEq { + #[inline] + fn eq(&self, other: &Vec) -> bool { PartialEq::eq(&**self, &**other) } + #[inline] + fn ne(&self, other: &Vec) -> bool { PartialEq::ne(&**self, &**other) } +} + +macro_rules! impl_eq { + ($lhs:ty, $rhs:ty) => { + impl<'b, A, B> PartialEq<$rhs> for $lhs where A: PartialEq { + #[inline] + fn eq(&self, other: &$rhs) -> bool { PartialEq::eq(&**self, &**other) } + #[inline] + fn ne(&self, other: &$rhs) -> bool { PartialEq::ne(&**self, &**other) } + } + + impl<'b, A, B> PartialEq<$lhs> for $rhs where B: PartialEq { + #[inline] + fn eq(&self, other: &$lhs) -> bool { PartialEq::eq(&**self, &**other) } + #[inline] + fn ne(&self, other: &$lhs) -> bool { PartialEq::ne(&**self, &**other) } + } + } +} + +impl_eq! { Vec, &'b [B] } +impl_eq! { Vec, &'b mut [B] } + +impl<'a, A, B> PartialEq> for CowVec<'a, A> where A: PartialEq + Clone { + #[inline] + fn eq(&self, other: &Vec) -> bool { PartialEq::eq(&**self, &**other) } + #[inline] + fn ne(&self, other: &Vec) -> bool { PartialEq::ne(&**self, &**other) } +} + +impl<'a, A, B> PartialEq> for Vec where A: Clone, B: PartialEq { + #[inline] + fn eq(&self, other: &CowVec<'a, A>) -> bool { PartialEq::eq(&**self, &**other) } + #[inline] + fn ne(&self, other: &CowVec<'a, A>) -> bool { PartialEq::ne(&**self, &**other) } +} + +macro_rules! impl_eq_for_cowvec { + ($rhs:ty) => { + impl<'a, 'b, A, B> PartialEq<$rhs> for CowVec<'a, A> where A: PartialEq + Clone { + #[inline] + fn eq(&self, other: &$rhs) -> bool { PartialEq::eq(&**self, &**other) } + #[inline] + fn ne(&self, other: &$rhs) -> bool { PartialEq::ne(&**self, &**other) } + } + + impl<'a, 'b, A, B> PartialEq> for $rhs where A: Clone, B: PartialEq { + #[inline] + fn eq(&self, other: &CowVec<'a, A>) -> bool { PartialEq::eq(&**self, &**other) } + #[inline] + fn ne(&self, other: &CowVec<'a, A>) -> bool { PartialEq::ne(&**self, &**other) } + } + } +} + +impl_eq_for_cowvec! { &'b [B] } +impl_eq_for_cowvec! { &'b mut [B] } + +#[unstable = "waiting on PartialOrd stability"] +impl PartialOrd for Vec { + #[inline] + fn partial_cmp(&self, other: &Vec) -> Option { + self.as_slice().partial_cmp(other.as_slice()) + } +} + +#[unstable = "waiting on Eq stability"] +impl Eq for Vec {} + +#[allow(deprecated)] +#[deprecated = "Use overloaded `core::cmp::PartialEq`"] +impl> Equiv for Vec { + #[inline] + fn equiv(&self, other: &V) -> bool { self.as_slice() == other.as_slice() } +} + +#[unstable = "waiting on Ord stability"] +impl Ord for Vec { + #[inline] + fn cmp(&self, other: &Vec) -> Ordering { + self.as_slice().cmp(other.as_slice()) } } @@ -1408,7 +1488,45 @@ impl fmt::Show for Vec { } } +impl<'a> fmt::FormatWriter for Vec { + fn write(&mut self, buf: &[u8]) -> fmt::Result { + self.push_all(buf); + Ok(()) + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Clone-on-write +//////////////////////////////////////////////////////////////////////////////// + +#[experimental = "unclear how valuable this alias is"] +/// A clone-on-write vector +pub type CowVec<'a, T> = Cow<'a, Vec, [T]>; + +impl<'a, T> FromIterator for CowVec<'a, T> where T: Clone { + fn from_iter>(it: I) -> CowVec<'a, T> { + Cow::Owned(FromIterator::from_iter(it)) + } +} + +impl<'a, T: 'a> IntoCow<'a, Vec, [T]> for Vec where T: Clone { + fn into_cow(self) -> CowVec<'a, T> { + Cow::Owned(self) + } +} + +impl<'a, T> IntoCow<'a, Vec, [T]> for &'a [T] where T: Clone { + fn into_cow(self) -> CowVec<'a, T> { + Cow::Borrowed(self) + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Iterators +//////////////////////////////////////////////////////////////////////////////// + /// An iterator that moves out of a vector. +#[stable] pub struct IntoIter { allocation: *mut T, // the block of memory allocated for the vector cap: uint, // the capacity of the vector @@ -1416,9 +1534,12 @@ pub struct IntoIter { end: *const T } +#[deprecated = "use IntoIter instead"] +pub type MoveItems = IntoIter; + impl IntoIter { - /// Drops all items that have not yet been moved and returns the empty vector. #[inline] + /// Drops all items that have not yet been moved and returns the empty vector. #[unstable] pub fn into_inner(mut self) -> Vec { unsafe { @@ -1508,6 +1629,7 @@ impl Drop for IntoIter { /// An iterator that drains a vector. #[unsafe_no_drop_flag] +#[unstable = "recently added as part of collections reform 2"] pub struct Drain<'a, T> { ptr: *const T, end: *const T, @@ -1584,22 +1706,9 @@ impl<'a, T> Drop for Drain<'a, T> { } } -/// Converts an iterator of pairs into a pair of vectors. -/// -/// Returns a tuple containing two vectors where the i-th element of the first vector contains the -/// first element of the i-th tuple of the input iterator, and the i-th element of the second -/// vector contains the second element of the i-th tuple of the input iterator. -#[unstable = "this functionality may become more generic over time"] -pub fn unzip>(mut iter: V) -> (Vec, Vec) { - let (lo, _) = iter.size_hint(); - let mut ts = Vec::with_capacity(lo); - let mut us = Vec::with_capacity(lo); - for (t, u) in iter { - ts.push(t); - us.push(u); - } - (ts, us) -} +//////////////////////////////////////////////////////////////////////////////// +// Conversion from &[T] to &Vec +//////////////////////////////////////////////////////////////////////////////// /// Wrapper type providing a `&Vec` reference via `Deref`. #[experimental] @@ -1608,6 +1717,7 @@ pub struct DerefVec<'a, T> { l: ContravariantLifetime<'a> } +#[experimental] impl<'a, T> Deref> for DerefVec<'a, T> { fn deref<'b>(&'b self) -> &'b Vec { &self.x @@ -1616,6 +1726,7 @@ impl<'a, T> Deref> for DerefVec<'a, T> { // Prevent the inner `Vec` from attempting to deallocate memory. #[unsafe_destructor] +#[experimental] impl<'a, T> Drop for DerefVec<'a, T> { fn drop(&mut self) { self.x.len = 0; @@ -1634,6 +1745,10 @@ pub fn as_vec<'a, T>(x: &'a [T]) -> DerefVec<'a, T> { } } +//////////////////////////////////////////////////////////////////////////////// +// Raw module (deprecated) +//////////////////////////////////////////////////////////////////////////////// + /// Unsafe vector operations. #[deprecated] pub mod raw { @@ -1650,6 +1765,10 @@ pub mod raw { } } +//////////////////////////////////////////////////////////////////////////////// +// Partial vec, used for map_in_place +//////////////////////////////////////////////////////////////////////////////// + /// An owned, partially type-converted vector of elements with non-zero size. /// /// `T` and `U` must have the same, non-zero size. They must also have the same @@ -1721,211 +1840,6 @@ impl Drop for PartialVecZeroSized { } } -impl Vec { - /// Converts a `Vec` to a `Vec` where `T` and `U` have the same - /// size and in case they are not zero-sized the same minimal alignment. - /// - /// # Panics - /// - /// Panics if `T` and `U` have differing sizes or are not zero-sized and - /// have differing minimal alignments. - /// - /// # Examples - /// - /// ``` - /// let v = vec![0u, 1, 2]; - /// let w = v.map_in_place(|i| i + 3); - /// assert_eq!(w.as_slice(), [3, 4, 5].as_slice()); - /// - /// #[deriving(PartialEq, Show)] - /// struct Newtype(u8); - /// let bytes = vec![0x11, 0x22]; - /// let newtyped_bytes = bytes.map_in_place(|x| Newtype(x)); - /// assert_eq!(newtyped_bytes.as_slice(), [Newtype(0x11), Newtype(0x22)].as_slice()); - /// ``` - pub fn map_in_place(self, mut f: F) -> Vec where F: FnMut(T) -> U { - // FIXME: Assert statically that the types `T` and `U` have the same - // size. - assert!(mem::size_of::() == mem::size_of::()); - - let mut vec = self; - - if mem::size_of::() != 0 { - // FIXME: Assert statically that the types `T` and `U` have the - // same minimal alignment in case they are not zero-sized. - - // These asserts are necessary because the `min_align_of` of the - // types are passed to the allocator by `Vec`. - assert!(mem::min_align_of::() == mem::min_align_of::()); - - // This `as int` cast is safe, because the size of the elements of the - // vector is not 0, and: - // - // 1) If the size of the elements in the vector is 1, the `int` may - // overflow, but it has the correct bit pattern so that the - // `.offset()` function will work. - // - // Example: - // Address space 0x0-0xF. - // `u8` array at: 0x1. - // Size of `u8` array: 0x8. - // Calculated `offset`: -0x8. - // After `array.offset(offset)`: 0x9. - // (0x1 + 0x8 = 0x1 - 0x8) - // - // 2) If the size of the elements in the vector is >1, the `uint` -> - // `int` conversion can't overflow. - let offset = vec.len() as int; - let start = vec.as_mut_ptr(); - - let mut pv = PartialVecNonZeroSized { - vec: vec, - - start_t: start, - // This points inside the vector, as the vector has length - // `offset`. - end_t: unsafe { start.offset(offset) }, - start_u: start as *mut U, - end_u: start as *mut U, - }; - // start_t - // start_u - // | - // +-+-+-+-+-+-+ - // |T|T|T|...|T| - // +-+-+-+-+-+-+ - // | | - // end_u end_t - - while pv.end_u as *mut T != pv.end_t { - unsafe { - // start_u start_t - // | | - // +-+-+-+-+-+-+-+-+-+ - // |U|...|U|T|T|...|T| - // +-+-+-+-+-+-+-+-+-+ - // | | - // end_u end_t - - let t = ptr::read(pv.start_t as *const T); - // start_u start_t - // | | - // +-+-+-+-+-+-+-+-+-+ - // |U|...|U|X|T|...|T| - // +-+-+-+-+-+-+-+-+-+ - // | | - // end_u end_t - // We must not panic here, one cell is marked as `T` - // although it is not `T`. - - pv.start_t = pv.start_t.offset(1); - // start_u start_t - // | | - // +-+-+-+-+-+-+-+-+-+ - // |U|...|U|X|T|...|T| - // +-+-+-+-+-+-+-+-+-+ - // | | - // end_u end_t - // We may panic again. - - // The function given by the user might panic. - let u = f(t); - - ptr::write(pv.end_u, u); - // start_u start_t - // | | - // +-+-+-+-+-+-+-+-+-+ - // |U|...|U|U|T|...|T| - // +-+-+-+-+-+-+-+-+-+ - // | | - // end_u end_t - // We should not panic here, because that would leak the `U` - // pointed to by `end_u`. - - pv.end_u = pv.end_u.offset(1); - // start_u start_t - // | | - // +-+-+-+-+-+-+-+-+-+ - // |U|...|U|U|T|...|T| - // +-+-+-+-+-+-+-+-+-+ - // | | - // end_u end_t - // We may panic again. - } - } - - // start_u start_t - // | | - // +-+-+-+-+-+-+ - // |U|...|U|U|U| - // +-+-+-+-+-+-+ - // | - // end_t - // end_u - // Extract `vec` and prevent the destructor of - // `PartialVecNonZeroSized` from running. Note that none of the - // function calls can panic, thus no resources can be leaked (as the - // `vec` member of `PartialVec` is the only one which holds - // allocations -- and it is returned from this function. None of - // this can panic. - unsafe { - let vec_len = pv.vec.len(); - let vec_cap = pv.vec.capacity(); - let vec_ptr = pv.vec.as_mut_ptr() as *mut U; - mem::forget(pv); - Vec::from_raw_parts(vec_ptr, vec_len, vec_cap) - } - } else { - // Put the `Vec` into the `PartialVecZeroSized` structure and - // prevent the destructor of the `Vec` from running. Since the - // `Vec` contained zero-sized objects, it did not allocate, so we - // are not leaking memory here. - let mut pv = PartialVecZeroSized:: { - num_t: vec.len(), - num_u: 0, - marker_t: InvariantType, - marker_u: InvariantType, - }; - unsafe { mem::forget(vec); } - - while pv.num_t != 0 { - unsafe { - // Create a `T` out of thin air and decrement `num_t`. This - // must not panic between these steps, as otherwise a - // destructor of `T` which doesn't exist runs. - let t = mem::uninitialized(); - pv.num_t -= 1; - - // The function given by the user might panic. - let u = f(t); - - // Forget the `U` and increment `num_u`. This increment - // cannot overflow the `uint` as we only do this for a - // number of times that fits into a `uint` (and start with - // `0`). Again, we should not panic between these steps. - mem::forget(u); - pv.num_u += 1; - } - } - // Create a `Vec` from our `PartialVecZeroSized` and make sure the - // destructor of the latter will not run. None of this can panic. - let mut result = Vec::new(); - unsafe { - result.set_len(pv.num_u); - mem::forget(pv); - } - result - } - } -} - -impl<'a> fmt::FormatWriter for Vec { - fn write(&mut self, buf: &[u8]) -> fmt::Result { - self.push_all(buf); - Ok(()) - } -} - #[cfg(test)] mod tests { use prelude::*; @@ -2293,9 +2207,10 @@ mod tests { } #[test] + #[should_fail] fn test_swap_remove_empty() { let mut vec: Vec = vec!(); - assert_eq!(vec.swap_remove(0), None); + vec.swap_remove(0); } #[test] diff --git a/src/libcollections/vec_map.rs b/src/libcollections/vec_map.rs index 5ebcc736624f6..3a7168094fff4 100644 --- a/src/libcollections/vec_map.rs +++ b/src/libcollections/vec_map.rs @@ -448,7 +448,7 @@ impl VecMap { pub fn insert(&mut self, key: uint, value: V) -> Option { let len = self.v.len(); if len <= key { - self.v.grow_fn(key - len + 1, |_| None); + self.v.extend(range(0, key - len + 1).map(|_| None)); } replace(&mut self.v[key], Some(value)) } @@ -537,14 +537,18 @@ impl VecMap { } } + +#[stable] impl PartialEq for VecMap { fn eq(&self, other: &VecMap) -> bool { iter::order::eq(self.iter(), other.iter()) } } +#[stable] impl Eq for VecMap {} +#[stable] impl PartialOrd for VecMap { #[inline] fn partial_cmp(&self, other: &VecMap) -> Option { @@ -552,6 +556,7 @@ impl PartialOrd for VecMap { } } +#[stable] impl Ord for VecMap { #[inline] fn cmp(&self, other: &VecMap) -> Ordering { @@ -667,6 +672,17 @@ pub struct Iter<'a, V:'a> { iter: slice::Iter<'a, Option> } +// FIXME(#19839) Remove in favor of `#[deriving(Clone)]` +impl<'a, V> Clone for Iter<'a, V> { + fn clone(&self) -> Iter<'a, V> { + Iter { + front: self.front, + back: self.back, + iter: self.iter.clone() + } + } +} + iterator! { impl Iter -> (uint, &'a V), as_ref } double_ended_iterator! { impl Iter -> (uint, &'a V), as_ref } @@ -686,11 +702,29 @@ pub struct Keys<'a, V: 'a> { iter: Map<(uint, &'a V), uint, Iter<'a, V>, fn((uint, &'a V)) -> uint> } +// FIXME(#19839) Remove in favor of `#[deriving(Clone)]` +impl<'a, V> Clone for Keys<'a, V> { + fn clone(&self) -> Keys<'a, V> { + Keys { + iter: self.iter.clone() + } + } +} + /// An iterator over the values of a map. pub struct Values<'a, V: 'a> { iter: Map<(uint, &'a V), &'a V, Iter<'a, V>, fn((uint, &'a V)) -> &'a V> } +// FIXME(#19839) Remove in favor of `#[deriving(Clone)]` +impl<'a, V> Clone for Values<'a, V> { + fn clone(&self) -> Values<'a, V> { + Values { + iter: self.iter.clone() + } + } +} + /// A consuming iterator over the key-value pairs of a map. pub struct IntoIter { iter: FilterMap< diff --git a/src/libcore/array.rs b/src/libcore/array.rs index e85a132ed363f..88e23377046f1 100644 --- a/src/libcore/array.rs +++ b/src/libcore/array.rs @@ -39,7 +39,7 @@ macro_rules! array_impls { } } - #[unstable = "waiting for PartialEq to stabilize"] + #[stable] impl PartialEq<[B, ..$N]> for [A, ..$N] where A: PartialEq { #[inline] fn eq(&self, other: &[B, ..$N]) -> bool { @@ -51,6 +51,7 @@ macro_rules! array_impls { } } + #[stable] impl<'a, A, B, Rhs> PartialEq for [A, ..$N] where A: PartialEq, Rhs: Deref<[B]>, @@ -61,6 +62,7 @@ macro_rules! array_impls { fn ne(&self, other: &Rhs) -> bool { PartialEq::ne(self[], &**other) } } + #[stable] impl<'a, A, B, Lhs> PartialEq<[B, ..$N]> for Lhs where A: PartialEq, Lhs: Deref<[A]> @@ -71,10 +73,10 @@ macro_rules! array_impls { fn ne(&self, other: &[B, ..$N]) -> bool { PartialEq::ne(&**self, other[]) } } - #[unstable = "waiting for Eq to stabilize"] + #[stable] impl Eq for [T, ..$N] { } - #[unstable = "waiting for PartialOrd to stabilize"] + #[stable] impl PartialOrd for [T, ..$N] { #[inline] fn partial_cmp(&self, other: &[T, ..$N]) -> Option { @@ -98,7 +100,7 @@ macro_rules! array_impls { } } - #[unstable = "waiting for Ord to stabilize"] + #[stable] impl Ord for [T, ..$N] { #[inline] fn cmp(&self, other: &[T, ..$N]) -> Ordering { diff --git a/src/libcore/atomic.rs b/src/libcore/atomic.rs index 9452d0a64bf63..6a40915f4dd82 100644 --- a/src/libcore/atomic.rs +++ b/src/libcore/atomic.rs @@ -12,7 +12,7 @@ #![stable] -pub use self::Ordering::*; +use self::Ordering::*; use kinds::Sync; diff --git a/src/libcore/borrow.rs b/src/libcore/borrow.rs index 9bbcf67773ebb..3a2cb8ea7d984 100644 --- a/src/libcore/borrow.rs +++ b/src/libcore/borrow.rs @@ -200,8 +200,10 @@ impl<'a, T, Sized? B> Deref for Cow<'a, T, B> where B: ToOwned { } } +#[stable] impl<'a, T, Sized? B> Eq for Cow<'a, T, B> where B: Eq + ToOwned {} +#[stable] impl<'a, T, Sized? B> Ord for Cow<'a, T, B> where B: Ord + ToOwned { #[inline] fn cmp(&self, other: &Cow<'a, T, B>) -> Ordering { @@ -209,6 +211,7 @@ impl<'a, T, Sized? B> Ord for Cow<'a, T, B> where B: Ord + ToOwned { } } +#[stable] impl<'a, 'b, T, U, Sized? B, Sized? C> PartialEq> for Cow<'a, T, B> where B: PartialEq + ToOwned, C: ToOwned, @@ -219,6 +222,7 @@ impl<'a, 'b, T, U, Sized? B, Sized? C> PartialEq> for Cow<'a, T, B } } +#[stable] impl<'a, T, Sized? B> PartialOrd for Cow<'a, T, B> where B: PartialOrd + ToOwned { #[inline] fn partial_cmp(&self, other: &Cow<'a, T, B>) -> Option { diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index 01a1e7f97110a..6249f7600cd22 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -224,7 +224,7 @@ impl Default for Cell { } } -#[unstable = "waiting for `PartialEq` trait to become stable"] +#[stable] impl PartialEq for Cell { fn eq(&self, other: &Cell) -> bool { self.get() == other.get() @@ -358,7 +358,7 @@ impl Default for RefCell { } } -#[unstable = "waiting for `PartialEq` to become stable"] +#[stable] impl PartialEq for RefCell { fn eq(&self, other: &RefCell) -> bool { *self.borrow() == *other.borrow() diff --git a/src/libcore/char.rs b/src/libcore/char.rs index 9c12b3f68d3de..f0151dda8d71e 100644 --- a/src/libcore/char.rs +++ b/src/libcore/char.rs @@ -430,11 +430,13 @@ impl Char for char { /// An iterator over the characters that represent a `char`, as escaped by /// Rust's unicode escaping rules. +#[deriving(Clone)] pub struct EscapeUnicode { c: char, state: EscapeUnicodeState } +#[deriving(Clone)] enum EscapeUnicodeState { Backslash, Type, @@ -486,10 +488,12 @@ impl Iterator for EscapeUnicode { /// An iterator over the characters that represent a `char`, escaped /// for maximum portability. +#[deriving(Clone)] pub struct EscapeDefault { state: EscapeDefaultState } +#[deriving(Clone)] enum EscapeDefaultState { Backslash(char), Char(char), @@ -513,4 +517,3 @@ impl Iterator for EscapeDefault { } } } - diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index ca523db214b0c..367c794e84bb6 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -46,27 +46,37 @@ use self::Ordering::*; use kinds::Sized; use option::Option::{mod, Some, None}; -/// Trait for values that can be compared for equality and inequality. +/// Trait for equality comparisons which are [partial equivalence relations]( +/// http://en.wikipedia.org/wiki/Partial_equivalence_relation). /// -/// This trait allows for partial equality, for types that do not have an +/// This trait allows for partial equality, for types that do not have a full /// equivalence relation. For example, in floating point numbers `NaN != NaN`, /// so floating point types implement `PartialEq` but not `Eq`. /// +/// Formally, the equality must be (for all `a`, `b` and `c`): +/// +/// - symmetric: `a == b` implies `b == a`; and +/// - transitive: `a == b` and `b == c` implies `a == c`. +/// +/// Note that these requirements mean that the trait itself must be +/// implemented symmetrically and transitively: if `T: PartialEq` +/// and `U: PartialEq` then `U: PartialEq` and `T: +/// PartialEq`. +/// /// PartialEq only requires the `eq` method to be implemented; `ne` is defined /// in terms of it by default. Any manual implementation of `ne` *must* respect /// the rule that `eq` is a strict inverse of `ne`; that is, `!(a == b)` if and /// only if `a != b`. -/// -/// Eventually, this will be implemented by default for types that implement -/// `Eq`. #[lang="eq"] -#[unstable = "Definition may change slightly after trait reform"] +#[stable] pub trait PartialEq for Sized? { /// This method tests for `self` and `other` values to be equal, and is used by `==`. + #[stable] fn eq(&self, other: &Rhs) -> bool; /// This method tests for `!=`. #[inline] + #[stable] fn ne(&self, other: &Rhs) -> bool { !self.eq(other) } } @@ -79,8 +89,8 @@ pub trait PartialEq for Sized? { /// - reflexive: `a == a`; /// - symmetric: `a == b` implies `b == a`; and /// - transitive: `a == b` and `b == c` implies `a == c`. -#[unstable = "Definition may change slightly after trait reform"] -pub trait Eq for Sized?: PartialEq { +#[stable] +pub trait Eq for Sized?: PartialEq { // FIXME #13101: this method is used solely by #[deriving] to // assert that every component of a type implements #[deriving] // itself, the current deriving infrastructure means doing this @@ -97,12 +107,15 @@ pub trait Eq for Sized?: PartialEq { #[deriving(Clone, Copy, PartialEq, Show)] #[stable] pub enum Ordering { - /// An ordering where a compared value is less [than another]. - Less = -1i, - /// An ordering where a compared value is equal [to another]. - Equal = 0i, - /// An ordering where a compared value is greater [than another]. - Greater = 1i, + /// An ordering where a compared value is less [than another]. + #[stable] + Less = -1i, + /// An ordering where a compared value is equal [to another]. + #[stable] + Equal = 0i, + /// An ordering where a compared value is greater [than another]. + #[stable] + Greater = 1i, } impl Ordering { @@ -126,7 +139,7 @@ impl Ordering { /// assert!(data == b); /// ``` #[inline] - #[experimental] + #[stable] pub fn reverse(self) -> Ordering { unsafe { // this compiles really nicely (to a single instruction); @@ -149,8 +162,8 @@ impl Ordering { /// true; and /// - transitive, `a < b` and `b < c` implies `a < c`. The same must hold for /// both `==` and `>`. -#[unstable = "Definition may change slightly after trait reform"] -pub trait Ord for Sized?: Eq + PartialOrd { +#[stable] +pub trait Ord for Sized?: Eq + PartialOrd { /// This method returns an ordering between `self` and `other` values. /// /// By convention, `self.cmp(&other)` returns the ordering matching @@ -161,23 +174,26 @@ pub trait Ord for Sized?: Eq + PartialOrd { /// assert_eq!(10u.cmp(&5), Greater); // because 10 > 5 /// assert_eq!( 5u.cmp(&5), Equal); // because 5 == 5 /// ``` - fn cmp(&self, other: &Rhs) -> Ordering; + #[stable] + fn cmp(&self, other: &Self) -> Ordering; } -#[unstable = "Trait is unstable."] +#[stable] impl Eq for Ordering {} -#[unstable = "Trait is unstable."] +#[stable] impl Ord for Ordering { #[inline] + #[stable] fn cmp(&self, other: &Ordering) -> Ordering { (*self as int).cmp(&(*other as int)) } } -#[unstable = "Trait is unstable."] +#[stable] impl PartialOrd for Ordering { #[inline] + #[stable] fn partial_cmp(&self, other: &Ordering) -> Option { (*self as int).partial_cmp(&(*other as int)) } @@ -185,6 +201,17 @@ impl PartialOrd for Ordering { /// Trait for values that can be compared for a sort-order. /// +/// The comparison must satisfy, for all `a`, `b` and `c`: +/// +/// - antisymmetry: if `a < b` then `!(a > b)` and vice versa; and +/// - transitivity: `a < b` and `b < c` implies `a < c`. The same must hold for +/// both `==` and `>`. +/// +/// Note that these requirements mean that the trait itself must be +/// implemented symmetrically and transitively: if `T: PartialOrd` +/// and `U: PartialOrd` then `U: PartialOrd` and `T: +/// PartialOrd`. +/// /// PartialOrd only requires implementation of the `partial_cmp` method, /// with the others generated from default implementations. /// @@ -193,14 +220,16 @@ impl PartialOrd for Ordering { /// `NaN < 0 == false` and `NaN >= 0 == false` (cf. IEEE 754-2008 section /// 5.11). #[lang="ord"] -#[unstable = "Definition may change slightly after trait reform"] +#[stable] pub trait PartialOrd for Sized?: PartialEq { /// This method returns an ordering between `self` and `other` values /// if one exists. + #[stable] fn partial_cmp(&self, other: &Rhs) -> Option; /// This method tests less than (for `self` and `other`) and is used by the `<` operator. #[inline] + #[stable] fn lt(&self, other: &Rhs) -> bool { match self.partial_cmp(other) { Some(Less) => true, @@ -210,6 +239,7 @@ pub trait PartialOrd for Sized?: PartialEq { /// This method tests less than or equal to (`<=`). #[inline] + #[stable] fn le(&self, other: &Rhs) -> bool { match self.partial_cmp(other) { Some(Less) | Some(Equal) => true, @@ -219,6 +249,7 @@ pub trait PartialOrd for Sized?: PartialEq { /// This method tests greater than (`>`). #[inline] + #[stable] fn gt(&self, other: &Rhs) -> bool { match self.partial_cmp(other) { Some(Greater) => true, @@ -228,6 +259,7 @@ pub trait PartialOrd for Sized?: PartialEq { /// This method tests greater than or equal to (`>=`). #[inline] + #[stable] fn ge(&self, other: &Rhs) -> bool { match self.partial_cmp(other) { Some(Greater) | Some(Equal) => true, @@ -296,7 +328,7 @@ mod impls { macro_rules! partial_eq_impl { ($($t:ty)*) => ($( - #[unstable = "Trait is unstable."] + #[stable] impl PartialEq for $t { #[inline] fn eq(&self, other: &$t) -> bool { (*self) == (*other) } @@ -306,7 +338,7 @@ mod impls { )*) } - #[unstable = "Trait is unstable."] + #[stable] impl PartialEq for () { #[inline] fn eq(&self, _other: &()) -> bool { true } @@ -320,7 +352,7 @@ mod impls { macro_rules! eq_impl { ($($t:ty)*) => ($( - #[unstable = "Trait is unstable."] + #[stable] impl Eq for $t {} )*) } @@ -329,7 +361,7 @@ mod impls { macro_rules! partial_ord_impl { ($($t:ty)*) => ($( - #[unstable = "Trait is unstable."] + #[stable] impl PartialOrd for $t { #[inline] fn partial_cmp(&self, other: &$t) -> Option { @@ -352,7 +384,7 @@ mod impls { )*) } - #[unstable = "Trait is unstable."] + #[stable] impl PartialOrd for () { #[inline] fn partial_cmp(&self, _: &()) -> Option { @@ -360,7 +392,7 @@ mod impls { } } - #[unstable = "Trait is unstable."] + #[stable] impl PartialOrd for bool { #[inline] fn partial_cmp(&self, other: &bool) -> Option { @@ -372,7 +404,7 @@ mod impls { macro_rules! ord_impl { ($($t:ty)*) => ($( - #[unstable = "Trait is unstable."] + #[stable] impl Ord for $t { #[inline] fn cmp(&self, other: &$t) -> Ordering { @@ -384,13 +416,13 @@ mod impls { )*) } - #[unstable = "Trait is unstable."] + #[stable] impl Ord for () { #[inline] fn cmp(&self, _other: &()) -> Ordering { Equal } } - #[unstable = "Trait is unstable."] + #[stable] impl Ord for bool { #[inline] fn cmp(&self, other: &bool) -> Ordering { @@ -402,68 +434,69 @@ mod impls { // & pointers - #[unstable = "Trait is unstable."] + #[stable] impl<'a, 'b, Sized? A, Sized? B> PartialEq<&'b B> for &'a A where A: PartialEq { #[inline] fn eq(&self, other: & &'b B) -> bool { PartialEq::eq(*self, *other) } #[inline] fn ne(&self, other: & &'b B) -> bool { PartialEq::ne(*self, *other) } } - #[unstable = "Trait is unstable."] - impl<'a, Sized? T: PartialOrd> PartialOrd for &'a T { + #[stable] + impl<'a, 'b, Sized? A, Sized? B> PartialOrd<&'b B> for &'a A where A: PartialOrd { #[inline] - fn partial_cmp(&self, other: &&'a T) -> Option { + fn partial_cmp(&self, other: &&'b B) -> Option { PartialOrd::partial_cmp(*self, *other) } #[inline] - fn lt(&self, other: & &'a T) -> bool { PartialOrd::lt(*self, *other) } + fn lt(&self, other: & &'b B) -> bool { PartialOrd::lt(*self, *other) } #[inline] - fn le(&self, other: & &'a T) -> bool { PartialOrd::le(*self, *other) } + fn le(&self, other: & &'b B) -> bool { PartialOrd::le(*self, *other) } #[inline] - fn ge(&self, other: & &'a T) -> bool { PartialOrd::ge(*self, *other) } + fn ge(&self, other: & &'b B) -> bool { PartialOrd::ge(*self, *other) } #[inline] - fn gt(&self, other: & &'a T) -> bool { PartialOrd::gt(*self, *other) } + fn gt(&self, other: & &'b B) -> bool { PartialOrd::gt(*self, *other) } } - #[unstable = "Trait is unstable."] - impl<'a, Sized? T: Ord> Ord for &'a T { + #[stable] + impl<'a, Sized? A> Ord for &'a A where A: Ord { #[inline] - fn cmp(&self, other: & &'a T) -> Ordering { Ord::cmp(*self, *other) } + fn cmp(&self, other: & &'a A) -> Ordering { Ord::cmp(*self, *other) } } - #[unstable = "Trait is unstable."] - impl<'a, Sized? T: Eq> Eq for &'a T {} + #[stable] + impl<'a, Sized? A> Eq for &'a A where A: Eq {} // &mut pointers - #[unstable = "Trait is unstable."] + #[stable] impl<'a, 'b, Sized? A, Sized? B> PartialEq<&'b mut B> for &'a mut A where A: PartialEq { #[inline] fn eq(&self, other: &&'b mut B) -> bool { PartialEq::eq(*self, *other) } #[inline] fn ne(&self, other: &&'b mut B) -> bool { PartialEq::ne(*self, *other) } } - #[unstable = "Trait is unstable."] - impl<'a, Sized? T: PartialOrd> PartialOrd for &'a mut T { + #[stable] + impl<'a, 'b, Sized? A, Sized? B> PartialOrd<&'b mut B> for &'a mut A where A: PartialOrd { #[inline] - fn partial_cmp(&self, other: &&'a mut T) -> Option { + fn partial_cmp(&self, other: &&'b mut B) -> Option { PartialOrd::partial_cmp(*self, *other) } #[inline] - fn lt(&self, other: &&'a mut T) -> bool { PartialOrd::lt(*self, *other) } + fn lt(&self, other: &&'b mut B) -> bool { PartialOrd::lt(*self, *other) } #[inline] - fn le(&self, other: &&'a mut T) -> bool { PartialOrd::le(*self, *other) } + fn le(&self, other: &&'b mut B) -> bool { PartialOrd::le(*self, *other) } #[inline] - fn ge(&self, other: &&'a mut T) -> bool { PartialOrd::ge(*self, *other) } + fn ge(&self, other: &&'b mut B) -> bool { PartialOrd::ge(*self, *other) } #[inline] - fn gt(&self, other: &&'a mut T) -> bool { PartialOrd::gt(*self, *other) } + fn gt(&self, other: &&'b mut B) -> bool { PartialOrd::gt(*self, *other) } } - #[unstable = "Trait is unstable."] - impl<'a, Sized? T: Ord> Ord for &'a mut T { + #[stable] + impl<'a, Sized? A> Ord for &'a mut A where A: Ord { #[inline] - fn cmp(&self, other: &&'a mut T) -> Ordering { Ord::cmp(*self, *other) } + fn cmp(&self, other: &&'a mut A) -> Ordering { Ord::cmp(*self, *other) } } - #[unstable = "Trait is unstable."] - impl<'a, Sized? T: Eq> Eq for &'a mut T {} + #[stable] + impl<'a, Sized? A> Eq for &'a mut A where A: Eq {} + #[stable] impl<'a, 'b, Sized? A, Sized? B> PartialEq<&'b mut B> for &'a A where A: PartialEq { #[inline] fn eq(&self, other: &&'b mut B) -> bool { PartialEq::eq(*self, *other) } @@ -471,6 +504,7 @@ mod impls { fn ne(&self, other: &&'b mut B) -> bool { PartialEq::ne(*self, *other) } } + #[stable] impl<'a, 'b, Sized? A, Sized? B> PartialEq<&'b B> for &'a mut A where A: PartialEq { #[inline] fn eq(&self, other: &&'b B) -> bool { PartialEq::eq(*self, *other) } diff --git a/src/libcore/fmt/float.rs b/src/libcore/fmt/float.rs index 329fe7c7b4913..3787ae33fdaad 100644 --- a/src/libcore/fmt/float.rs +++ b/src/libcore/fmt/float.rs @@ -325,18 +325,9 @@ pub fn float_to_str_bytes_common( let mut filler = Filler { buf: &mut buf, end: &mut end }; match sign { - // NOTE(stage0): Remove cfg after a snapshot - #[cfg(not(stage0))] SignNeg => { let _ = fmt::write(&mut filler, format_args!("{:-}", exp)); } - // NOTE(stage0): Remove match arm after a snapshot - #[cfg(stage0)] - SignNeg => { - let _ = format_args!(|args| { - fmt::write(&mut filler, args) - }, "{:-}", exp); - } } } } diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index b050b98de2f81..9d275c9da9cb3 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -70,21 +70,11 @@ pub trait FormatWriter { /// This function will return an instance of `FormatError` on error. fn write(&mut self, bytes: &[u8]) -> Result; - // NOTE(stage0): Remove cfg after a snapshot - #[cfg(not(stage0))] /// Glue for usage of the `write!` macro with implementers of this trait. /// /// This method should generally not be invoked manually, but rather through /// the `write!` macro itself. fn write_fmt(&mut self, args: Arguments) -> Result { write(self, args) } - - // NOTE(stage0): Remove method after a snapshot - #[cfg(stage0)] - /// Glue for usage of the `write!` macro with implementers of this trait. - /// - /// This method should generally not be invoked manually, but rather through - /// the `write!` macro itself. - fn write_fmt(&mut self, args: &Arguments) -> Result { write(self, args) } } /// A struct to represent both where to emit formatting strings to and how they @@ -204,17 +194,9 @@ pub struct Arguments<'a> { } impl<'a> Show for Arguments<'a> { - // NOTE(stage0): Remove cfg after a snapshot - #[cfg(not(stage0))] fn fmt(&self, fmt: &mut Formatter) -> Result { write(fmt.buf, *self) } - - // NOTE(stage0): Remove method after a snapshot - #[cfg(stage0)] - fn fmt(&self, fmt: &mut Formatter) -> Result { - write(fmt.buf, self) - } } /// When a format is not otherwise specified, types are formatted by ascribing @@ -287,8 +269,6 @@ static DEFAULT_ARGUMENT: rt::Argument<'static> = rt::Argument { } }; -// NOTE(stage0): Remove cfg after a snapshot -#[cfg(not(stage0))] /// The `write` function takes an output stream, a precompiled format string, /// and a list of arguments. The arguments will be formatted according to the /// specified format string into the output stream provided. @@ -342,61 +322,6 @@ pub fn write(output: &mut FormatWriter, args: Arguments) -> Result { Ok(()) } -// NOTE(stage0): Remove function after a snapshot -#[cfg(stage0)] -/// The `write` function takes an output stream, a precompiled format string, -/// and a list of arguments. The arguments will be formatted according to the -/// specified format string into the output stream provided. -/// -/// # Arguments -/// -/// * output - the buffer to write output to -/// * args - the precompiled arguments generated by `format_args!` -#[experimental = "libcore and I/O have yet to be reconciled, and this is an \ - implementation detail which should not otherwise be exported"] -pub fn write(output: &mut FormatWriter, args: &Arguments) -> Result { - let mut formatter = Formatter { - flags: 0, - width: None, - precision: None, - buf: output, - align: rt::AlignUnknown, - fill: ' ', - args: args.args, - curarg: args.args.iter(), - }; - - let mut pieces = args.pieces.iter(); - - match args.fmt { - None => { - // We can use default formatting parameters for all arguments. - for _ in range(0, args.args.len()) { - try!(formatter.buf.write(pieces.next().unwrap().as_bytes())); - try!(formatter.run(&DEFAULT_ARGUMENT)); - } - } - Some(fmt) => { - // Every spec has a corresponding argument that is preceded by - // a string piece. - for (arg, piece) in fmt.iter().zip(pieces.by_ref()) { - try!(formatter.buf.write(piece.as_bytes())); - try!(formatter.run(arg)); - } - } - } - - // There can be only one trailing string piece left. - match pieces.next() { - Some(piece) => { - try!(formatter.buf.write(piece.as_bytes())); - } - None => {} - } - - Ok(()) -} - impl<'a> Formatter<'a> { // First up is the collection of functions used to execute a format string @@ -603,22 +528,12 @@ impl<'a> Formatter<'a> { self.buf.write(data) } - // NOTE(stage0): Remove cfg after a snapshot - #[cfg(not(stage0))] /// Writes some formatted information into this instance #[unstable = "reconciling core and I/O may alter this definition"] pub fn write_fmt(&mut self, fmt: Arguments) -> Result { write(self.buf, fmt) } - // NOTE(stage0): Remove method after a snapshot - #[cfg(stage0)] - /// Writes some formatted information into this instance - #[unstable = "reconciling core and I/O may alter this definition"] - pub fn write_fmt(&mut self, fmt: &Arguments) -> Result { - write(self.buf, fmt) - } - /// Flags for formatting (packed version of rt::Flag) #[experimental = "return type may change and method was just created"] pub fn flags(&self) -> uint { self.flags } diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index 9c3e53a1aceeb..b0fd52896fe57 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -59,6 +59,7 @@ pub use self::MinMaxResult::*; use clone::Clone; use cmp; use cmp::Ord; +use default::Default; use mem; use num::{ToPrimitive, Int}; use ops::{Add, Deref, FnMut}; @@ -68,20 +69,6 @@ use uint; #[deprecated = "renamed to Extend"] pub use self::Extend as Extendable; -/// Conversion from an `Iterator` -#[unstable = "may be replaced by a more general conversion trait"] -pub trait FromIterator { - /// Build a container with elements from an external iterator. - fn from_iter>(iterator: T) -> Self; -} - -/// A type growable from an `Iterator` implementation -#[unstable = "just renamed as part of collections reform"] -pub trait Extend { - /// Extend a container with the elements yielded by an arbitrary iterator - fn extend>(&mut self, iterator: T); -} - /// An interface for dealing with "external iterators". These types of iterators /// can be resumed at any time as all state is stored internally as opposed to /// being located on the call stack. @@ -106,6 +93,20 @@ pub trait Iterator { fn size_hint(&self) -> (uint, Option) { (0, None) } } +/// Conversion from an `Iterator` +#[unstable = "may be replaced by a more general conversion trait"] +pub trait FromIterator { + /// Build a container with elements from an external iterator. + fn from_iter>(iterator: T) -> Self; +} + +/// A type growable from an `Iterator` implementation +#[unstable = "just renamed as part of collections reform"] +pub trait Extend { + /// Extend a container with the elements yielded by an arbitrary iterator + fn extend>(&mut self, iterator: T); +} + #[unstable = "new convention for extension traits"] /// An extension trait providing numerous methods applicable to all iterators. pub trait IteratorExt: Iterator { @@ -223,7 +224,6 @@ pub trait IteratorExt: Iterator { Enumerate{iter: self, count: 0} } - /// Creates an iterator that has a `.peek()` method /// that returns an optional reference to the next element. /// @@ -471,6 +471,35 @@ pub trait IteratorExt: Iterator { FromIterator::from_iter(self) } + /// Loops through the entire iterator, collecting all of the elements into + /// one of two containers, depending on a predicate. The elements of the + /// first container satisfy the predicate, while the elements of the second + /// do not. + /// + /// ``` + /// let vec = vec![1i, 2i, 3i, 4i]; + /// let (even, odd): (Vec, Vec) = vec.into_iter().partition(|&n| n % 2 == 0); + /// assert_eq!(even, vec![2, 4]); + /// assert_eq!(odd, vec![1, 3]); + /// ``` + #[unstable = "recently added as part of collections reform"] + fn partition(mut self, mut f: F) -> (B, B) where + B: Default + Extend, F: FnMut(&A) -> bool + { + let mut left: B = Default::default(); + let mut right: B = Default::default(); + + for x in self { + if f(&x) { + left.extend(Some(x).into_iter()) + } else { + right.extend(Some(x).into_iter()) + } + } + + (left, right) + } + /// Loops through `n` iterations, returning the `n`th element of the /// iterator. /// @@ -661,6 +690,42 @@ pub trait IteratorExt: Iterator { #[unstable = "trait is unstable"] impl IteratorExt for I where I: Iterator {} +/// Extention trait for iterators of pairs. +#[unstable = "newly added trait, likely to be merged with IteratorExt"] +pub trait IteratorPairExt: Iterator<(A, B)> { + /// Converts an iterator of pairs into a pair of containers. + /// + /// Loops through the entire iterator, collecting the first component of + /// each item into one new container, and the second component into another. + fn unzip(mut self) -> (FromA, FromB) where + FromA: Default + Extend, FromB: Default + Extend + { + struct SizeHint(uint, Option); + impl Iterator for SizeHint { + fn next(&mut self) -> Option { None } + fn size_hint(&self) -> (uint, Option) { + (self.0, self.1) + } + } + + let (lo, hi) = self.size_hint(); + let mut ts: FromA = Default::default(); + let mut us: FromB = Default::default(); + + ts.extend(SizeHint(lo, hi)); + us.extend(SizeHint(lo, hi)); + + for (t, u) in self { + ts.extend(Some(t).into_iter()); + us.extend(Some(u).into_iter()); + } + + (ts, us) + } +} + +impl IteratorPairExt for I where I: Iterator<(A, B)> {} + /// A range iterator able to yield elements from both ends /// /// A `DoubleEndedIterator` can be thought of as a deque in that `next()` and `next_back()` exhaust diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index 781dbb0e55a3f..e8fbd9d930f33 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -10,8 +10,6 @@ #![macro_escape] -// NOTE(stage0): Remove cfg after a snapshot -#[cfg(not(stage0))] /// Entry point of task panic, for details, see std::macros #[macro_export] macro_rules! panic { @@ -32,44 +30,6 @@ macro_rules! panic { }); } -// NOTE(stage0): Remove macro after a snapshot -#[cfg(stage0)] -/// Entry point of task panic, for details, see std::macros -#[macro_export] -macro_rules! panic { - () => ( - panic!("{}", "explicit panic") - ); - ($msg:expr) => ({ - static _MSG_FILE_LINE: (&'static str, &'static str, uint) = ($msg, file!(), line!()); - ::core::panicking::panic(&_MSG_FILE_LINE) - }); - ($fmt:expr, $($arg:tt)*) => ({ - // a closure can't have return type !, so we need a full - // function to pass to format_args!, *and* we need the - // file and line numbers right here; so an inner bare fn - // is our only choice. - // - // LLVM doesn't tend to inline this, presumably because begin_unwind_fmt - // is #[cold] and #[inline(never)] and because this is flagged as cold - // as returning !. We really do want this to be inlined, however, - // because it's just a tiny wrapper. Small wins (156K to 149K in size) - // were seen when forcing this to be inlined, and that number just goes - // up with the number of calls to panic!() - // - // The leading _'s are to avoid dead code warnings if this is - // used inside a dead function. Just `#[allow(dead_code)]` is - // insufficient, since the user may have - // `#[forbid(dead_code)]` and which cannot be overridden. - #[inline(always)] - fn _run_fmt(fmt: &::std::fmt::Arguments) -> ! { - static _FILE_LINE: (&'static str, uint) = (file!(), line!()); - ::core::panicking::panic_fmt(fmt, &_FILE_LINE) - } - format_args!(_run_fmt, $fmt, $($arg)*) - }); -} - /// Runtime assertion, for details see std::macros #[macro_export] macro_rules! assert { @@ -119,25 +79,12 @@ macro_rules! try { ($e:expr) => (match $e { Ok(e) => e, Err(e) => return Err(e) }) } -// NOTE(stage0): Remove cfg after a snapshot -#[cfg(not(stage0))] /// Writing a formatted string into a writer #[macro_export] macro_rules! write { ($dst:expr, $($arg:tt)*) => ((&mut *$dst).write_fmt(format_args!($($arg)*))) } -// NOTE(stage0): Remove macro after a snapshot -#[cfg(stage0)] -/// Writing a formatted string into a writer -#[macro_export] -macro_rules! write { - ($dst:expr, $($arg:tt)*) => ({ - let dst = &mut *$dst; - format_args!(|args| { dst.write_fmt(args) }, $($arg)*) - }) -} - /// Writing a formatted string plus a newline into a writer #[macro_export] macro_rules! writeln { diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs index f6b79ccc42b01..af07869e95feb 100644 --- a/src/libcore/ops.rs +++ b/src/libcore/ops.rs @@ -292,58 +292,6 @@ rem_impl! { uint u8 u16 u32 u64 int i8 i16 i32 i64 } rem_float_impl! { f32, fmodf } rem_float_impl! { f64, fmod } -/// The `Neg` trait is used to specify the functionality of unary `-`. -/// -/// # Example -/// -/// A trivial implementation of `Neg`. When `-Foo` happens, it ends up calling -/// `neg`, and therefore, `main` prints `Negating!`. -/// -/// ``` -/// #[deriving(Copy)] -/// struct Foo; -/// -/// impl Neg for Foo { -/// fn neg(&self) -> Foo { -/// println!("Negating!"); -/// *self -/// } -/// } -/// -/// fn main() { -/// -Foo; -/// } -/// ``` -// NOTE(stage0): Remove trait after a snapshot -#[cfg(stage0)] -#[lang="neg"] -pub trait Neg for Sized? { - /// The method for the unary `-` operator - fn neg(&self) -> Result; -} - -// NOTE(stage0): Remove macro after a snapshot -#[cfg(stage0)] -macro_rules! neg_impl { - ($($t:ty)*) => ($( - impl Neg<$t> for $t { - #[inline] - fn neg(&self) -> $t { -*self } - } - )*) -} - -// NOTE(stage0): Remove macro after a snapshot -#[cfg(stage0)] -macro_rules! neg_uint_impl { - ($t:ty, $t_signed:ty) => { - impl Neg<$t> for $t { - #[inline] - fn neg(&self) -> $t { -(*self as $t_signed) as $t } - } - } -} - /// The `Neg` trait is used to specify the functionality of unary `-`. /// /// # Example @@ -367,14 +315,12 @@ macro_rules! neg_uint_impl { /// -Foo; /// } /// ``` -#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot #[lang="neg"] pub trait Neg { /// The method for the unary `-` operator fn neg(self) -> Result; } -#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot macro_rules! neg_impl { ($($t:ty)*) => ($( impl Neg<$t> for $t { @@ -384,7 +330,6 @@ macro_rules! neg_impl { )*) } -#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot macro_rules! neg_uint_impl { ($t:ty, $t_signed:ty) => { impl Neg<$t> for $t { @@ -403,48 +348,6 @@ neg_uint_impl! { u32, i32 } neg_uint_impl! { u64, i64 } -/// The `Not` trait is used to specify the functionality of unary `!`. -/// -/// # Example -/// -/// A trivial implementation of `Not`. When `!Foo` happens, it ends up calling -/// `not`, and therefore, `main` prints `Not-ing!`. -/// -/// ``` -/// #[deriving(Copy)] -/// struct Foo; -/// -/// impl Not for Foo { -/// fn not(&self) -> Foo { -/// println!("Not-ing!"); -/// *self -/// } -/// } -/// -/// fn main() { -/// !Foo; -/// } -/// ``` -// NOTE(stage0): Remove macro after a snapshot -#[cfg(stage0)] -#[lang="not"] -pub trait Not for Sized? { - /// The method for the unary `!` operator - fn not(&self) -> Result; -} - - -// NOTE(stage0): Remove macro after a snapshot -#[cfg(stage0)] -macro_rules! not_impl { - ($($t:ty)*) => ($( - impl Not<$t> for $t { - #[inline] - fn not(&self) -> $t { !*self } - } - )*) -} - /// The `Not` trait is used to specify the functionality of unary `!`. /// /// # Example @@ -468,14 +371,12 @@ macro_rules! not_impl { /// !Foo; /// } /// ``` -#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot #[lang="not"] pub trait Not { /// The method for the unary `!` operator fn not(self) -> Result; } -#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot macro_rules! not_impl { ($($t:ty)*) => ($( impl Not<$t> for $t { diff --git a/src/libcore/panicking.rs b/src/libcore/panicking.rs index 32f09a4c17f3c..61b4284e1dd9c 100644 --- a/src/libcore/panicking.rs +++ b/src/libcore/panicking.rs @@ -31,11 +31,7 @@ #![allow(dead_code, missing_docs)] use fmt; -// NOTE(stage0): Remove import after a snapshot -#[cfg(stage0)] use intrinsics; -// NOTE(stage0): Remove cfg after a snapshot -#[cfg(not(stage0))] #[cold] #[inline(never)] // this is the slow path, always #[lang="panic"] pub fn panic(expr_file_line: &(&'static str, &'static str, uint)) -> ! { @@ -43,22 +39,6 @@ pub fn panic(expr_file_line: &(&'static str, &'static str, uint)) -> ! { panic_fmt(format_args!("{}", expr), &(file, line)) } -// NOTE(stage0): Remove function after a snapshot -#[cfg(stage0)] -#[cold] #[inline(never)] // this is the slow path, always -#[lang="panic"] -pub fn panic(expr_file_line: &(&'static str, &'static str, uint)) -> ! { - let (expr, file, line) = *expr_file_line; - let ref file_line = (file, line); - format_args!(|args| -> () { - panic_fmt(args, file_line); - }, "{}", expr); - - unsafe { intrinsics::abort() } -} - -// NOTE(stage0): Remove cfg after a snapshot -#[cfg(not(stage0))] #[cold] #[inline(never)] #[lang="panic_bounds_check"] fn panic_bounds_check(file_line: &(&'static str, uint), @@ -67,20 +47,6 @@ fn panic_bounds_check(file_line: &(&'static str, uint), len, index), file_line) } -// NOTE(stage0): Remove function after a snapshot -#[cfg(stage0)] -#[cold] #[inline(never)] -#[lang="panic_bounds_check"] -fn panic_bounds_check(file_line: &(&'static str, uint), - index: uint, len: uint) -> ! { - format_args!(|args| -> () { - panic_fmt(args, file_line); - }, "index out of bounds: the len is {} but the index is {}", len, index); - unsafe { intrinsics::abort() } -} - -// NOTE(stage0): Remove cfg after a snapshot -#[cfg(not(stage0))] #[cold] #[inline(never)] pub fn panic_fmt(fmt: fmt::Arguments, file_line: &(&'static str, uint)) -> ! { #[allow(improper_ctypes)] @@ -91,18 +57,3 @@ pub fn panic_fmt(fmt: fmt::Arguments, file_line: &(&'static str, uint)) -> ! { let (file, line) = *file_line; unsafe { panic_impl(fmt, file, line) } } - -// NOTE(stage0): Remove function after a snapshot -#[cfg(stage0)] -#[cold] #[inline(never)] -pub fn panic_fmt(fmt: &fmt::Arguments, file_line: &(&'static str, uint)) -> ! { - #[allow(improper_ctypes)] - extern { - #[lang = "panic_fmt"] - fn panic_impl(fmt: &fmt::Arguments, file: &'static str, - line: uint) -> !; - - } - let (file, line) = *file_line; - unsafe { panic_impl(fmt, file, line) } -} diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs index fd1598db8cdfc..cecb493815380 100644 --- a/src/libcore/prelude.rs +++ b/src/libcore/prelude.rs @@ -52,7 +52,7 @@ pub use cmp::{Ordering, Equiv}; pub use cmp::Ordering::{Less, Equal, Greater}; pub use iter::{FromIterator, Extend, IteratorExt}; pub use iter::{Iterator, DoubleEndedIterator, DoubleEndedIteratorExt, RandomAccessIterator}; -pub use iter::{IteratorCloneExt, CloneIteratorExt}; +pub use iter::{IteratorCloneExt, CloneIteratorExt, IteratorPairExt}; pub use iter::{IteratorOrdExt, MutableDoubleEndedIterator, ExactSizeIterator}; pub use num::{ToPrimitive, FromPrimitive}; pub use option::Option; diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 75bb8d33ea85f..faf1d781465c7 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -379,6 +379,7 @@ impl MutPtrExt for *mut T { } // Equality for pointers +#[stable] impl PartialEq for *const T { #[inline] fn eq(&self, other: &*const T) -> bool { @@ -388,8 +389,10 @@ impl PartialEq for *const T { fn ne(&self, other: &*const T) -> bool { !self.eq(other) } } +#[stable] impl Eq for *const T {} +#[stable] impl PartialEq for *mut T { #[inline] fn eq(&self, other: &*mut T) -> bool { @@ -399,6 +402,7 @@ impl PartialEq for *mut T { fn ne(&self, other: &*mut T) -> bool { !self.eq(other) } } +#[stable] impl Eq for *mut T {} // Equivalence for pointers @@ -439,6 +443,7 @@ mod externfnpointers { use mem; use cmp::PartialEq; + #[stable] impl<_R> PartialEq for extern "C" fn() -> _R { #[inline] fn eq(&self, other: &extern "C" fn() -> _R) -> bool { @@ -449,6 +454,7 @@ mod externfnpointers { } macro_rules! fnptreq { ($($p:ident),*) => { + #[stable] impl<_R,$($p),*> PartialEq for extern "C" fn($($p),*) -> _R { #[inline] fn eq(&self, other: &extern "C" fn($($p),*) -> _R) -> bool { @@ -468,6 +474,7 @@ mod externfnpointers { } // Comparison for pointers +#[stable] impl Ord for *const T { #[inline] fn cmp(&self, other: &*const T) -> Ordering { @@ -481,6 +488,7 @@ impl Ord for *const T { } } +#[stable] impl PartialOrd for *const T { #[inline] fn partial_cmp(&self, other: &*const T) -> Option { @@ -500,6 +508,7 @@ impl PartialOrd for *const T { fn ge(&self, other: &*const T) -> bool { *self >= *other } } +#[stable] impl Ord for *mut T { #[inline] fn cmp(&self, other: &*mut T) -> Ordering { @@ -513,6 +522,7 @@ impl Ord for *mut T { } } +#[stable] impl PartialOrd for *mut T { #[inline] fn partial_cmp(&self, other: &*mut T) -> Option { diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index f356a0867d252..7d894ac697be2 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -46,6 +46,8 @@ use num::Int; use ops::{FnMut, mod}; use option::Option; use option::Option::{None, Some}; +use result::Result; +use result::Result::{Ok, Err}; use ptr; use ptr::PtrExt; use mem; @@ -68,23 +70,23 @@ pub trait SliceExt for Sized? { fn slice_to<'a>(&'a self, end: uint) -> &'a [T]; fn split_at<'a>(&'a self, mid: uint) -> (&'a [T], &'a [T]); fn iter<'a>(&'a self) -> Iter<'a, T>; - fn split<'a, P>(&'a self, pred: P) -> Splits<'a, T, P> + fn split<'a, P>(&'a self, pred: P) -> Split<'a, T, P> where P: FnMut(&T) -> bool; - fn splitn<'a, P>(&'a self, n: uint, pred: P) -> SplitsN> + fn splitn<'a, P>(&'a self, n: uint, pred: P) -> SplitN<'a, T, P> where P: FnMut(&T) -> bool; - fn rsplitn<'a, P>(&'a self, n: uint, pred: P) -> SplitsN> + fn rsplitn<'a, P>(&'a self, n: uint, pred: P) -> RSplitN<'a, T, P> where P: FnMut(&T) -> bool; fn windows<'a>(&'a self, size: uint) -> Windows<'a, T>; fn chunks<'a>(&'a self, size: uint) -> Chunks<'a, T>; fn get<'a>(&'a self, index: uint) -> Option<&'a T>; - fn head<'a>(&'a self) -> Option<&'a T>; + fn first<'a>(&'a self) -> Option<&'a T>; fn tail<'a>(&'a self) -> &'a [T]; fn init<'a>(&'a self) -> &'a [T]; fn last<'a>(&'a self) -> Option<&'a T>; - unsafe fn unsafe_get<'a>(&'a self, index: uint) -> &'a T; + unsafe fn get_unchecked<'a>(&'a self, index: uint) -> &'a T; fn as_ptr(&self) -> *const T; - fn binary_search(&self, f: F) -> BinarySearchResult - where F: FnMut(&T) -> Ordering; + fn binary_search_by(&self, f: F) -> Result where + F: FnMut(&T) -> Ordering; fn len(&self) -> uint; fn is_empty(&self) -> bool { self.len() == 0 } fn get_mut<'a>(&'a mut self, index: uint) -> Option<&'a mut T>; @@ -93,21 +95,21 @@ pub trait SliceExt for Sized? { fn slice_from_mut<'a>(&'a mut self, start: uint) -> &'a mut [T]; fn slice_to_mut<'a>(&'a mut self, end: uint) -> &'a mut [T]; fn iter_mut<'a>(&'a mut self) -> IterMut<'a, T>; - fn head_mut<'a>(&'a mut self) -> Option<&'a mut T>; + fn first_mut<'a>(&'a mut self) -> Option<&'a mut T>; fn tail_mut<'a>(&'a mut self) -> &'a mut [T]; fn init_mut<'a>(&'a mut self) -> &'a mut [T]; fn last_mut<'a>(&'a mut self) -> Option<&'a mut T>; - fn split_mut<'a, P>(&'a mut self, pred: P) -> MutSplits<'a, T, P> + fn split_mut<'a, P>(&'a mut self, pred: P) -> SplitMut<'a, T, P> where P: FnMut(&T) -> bool; - fn splitn_mut

(&mut self, n: uint, pred: P) -> SplitsN> + fn splitn_mut

(&mut self, n: uint, pred: P) -> SplitNMut where P: FnMut(&T) -> bool; - fn rsplitn_mut

(&mut self, n: uint, pred: P) -> SplitsN> + fn rsplitn_mut

(&mut self, n: uint, pred: P) -> RSplitNMut where P: FnMut(&T) -> bool; - fn chunks_mut<'a>(&'a mut self, chunk_size: uint) -> MutChunks<'a, T>; + fn chunks_mut<'a>(&'a mut self, chunk_size: uint) -> ChunksMut<'a, T>; fn swap(&mut self, a: uint, b: uint); fn split_at_mut<'a>(&'a mut self, mid: uint) -> (&'a mut [T], &'a mut [T]); fn reverse(&mut self); - unsafe fn unsafe_mut<'a>(&'a mut self, index: uint) -> &'a mut T; + unsafe fn get_unchecked_mut<'a>(&'a mut self, index: uint) -> &'a mut T; fn as_mut_ptr(&mut self) -> *mut T; } @@ -145,11 +147,11 @@ impl SliceExt for [T] { unsafe { let p = self.as_ptr(); if mem::size_of::() == 0 { - Iter{ptr: p, + Iter {ptr: p, end: (p as uint + self.len()) as *const T, marker: marker::ContravariantLifetime::<'a>} } else { - Iter{ptr: p, + Iter {ptr: p, end: p.offset(self.len() as int), marker: marker::ContravariantLifetime::<'a>} } @@ -157,8 +159,8 @@ impl SliceExt for [T] { } #[inline] - fn split<'a, P>(&'a self, pred: P) -> Splits<'a, T, P> where P: FnMut(&T) -> bool { - Splits { + fn split<'a, P>(&'a self, pred: P) -> Split<'a, T, P> where P: FnMut(&T) -> bool { + Split { v: self, pred: pred, finished: false @@ -166,24 +168,28 @@ impl SliceExt for [T] { } #[inline] - fn splitn<'a, P>(&'a self, n: uint, pred: P) -> SplitsN> where + fn splitn<'a, P>(&'a self, n: uint, pred: P) -> SplitN<'a, T, P> where P: FnMut(&T) -> bool, { - SplitsN { - iter: self.split(pred), - count: n, - invert: false + SplitN { + inner: GenericSplitN { + iter: self.split(pred), + count: n, + invert: false + } } } #[inline] - fn rsplitn<'a, P>(&'a self, n: uint, pred: P) -> SplitsN> where + fn rsplitn<'a, P>(&'a self, n: uint, pred: P) -> RSplitN<'a, T, P> where P: FnMut(&T) -> bool, { - SplitsN { - iter: self.split(pred), - count: n, - invert: true + RSplitN { + inner: GenericSplitN { + iter: self.split(pred), + count: n, + invert: true + } } } @@ -205,7 +211,7 @@ impl SliceExt for [T] { } #[inline] - fn head(&self) -> Option<&T> { + fn first(&self) -> Option<&T> { if self.len() == 0 { None } else { Some(&self[0]) } } @@ -223,7 +229,7 @@ impl SliceExt for [T] { } #[inline] - unsafe fn unsafe_get(&self, index: uint) -> &T { + unsafe fn get_unchecked(&self, index: uint) -> &T { transmute(self.repr().data.offset(index as int)) } @@ -233,14 +239,16 @@ impl SliceExt for [T] { } #[unstable] - fn binary_search(&self, mut f: F) -> BinarySearchResult where F: FnMut(&T) -> Ordering { + fn binary_search_by(&self, mut f: F) -> Result where + F: FnMut(&T) -> Ordering + { let mut base : uint = 0; let mut lim : uint = self.len(); while lim != 0 { let ix = base + (lim >> 1); match f(&self[ix]) { - Equal => return BinarySearchResult::Found(ix), + Equal => return Ok(ix), Less => { base = ix + 1; lim -= 1; @@ -249,7 +257,7 @@ impl SliceExt for [T] { } lim >>= 1; } - return BinarySearchResult::NotFound(base); + Err(base) } #[inline] @@ -292,11 +300,11 @@ impl SliceExt for [T] { unsafe { let p = self.as_mut_ptr(); if mem::size_of::() == 0 { - IterMut{ptr: p, + IterMut {ptr: p, end: (p as uint + self.len()) as *mut T, marker: marker::ContravariantLifetime::<'a>} } else { - IterMut{ptr: p, + IterMut {ptr: p, end: p.offset(self.len() as int), marker: marker::ContravariantLifetime::<'a>} } @@ -311,7 +319,7 @@ impl SliceExt for [T] { } #[inline] - fn head_mut(&mut self) -> Option<&mut T> { + fn first_mut(&mut self) -> Option<&mut T> { if self.len() == 0 { None } else { Some(&mut self[0]) } } @@ -327,36 +335,40 @@ impl SliceExt for [T] { } #[inline] - fn split_mut<'a, P>(&'a mut self, pred: P) -> MutSplits<'a, T, P> where P: FnMut(&T) -> bool { - MutSplits { v: self, pred: pred, finished: false } + fn split_mut<'a, P>(&'a mut self, pred: P) -> SplitMut<'a, T, P> where P: FnMut(&T) -> bool { + SplitMut { v: self, pred: pred, finished: false } } #[inline] - fn splitn_mut<'a, P>(&'a mut self, n: uint, pred: P) -> SplitsN> where + fn splitn_mut<'a, P>(&'a mut self, n: uint, pred: P) -> SplitNMut<'a, T, P> where P: FnMut(&T) -> bool { - SplitsN { - iter: self.split_mut(pred), - count: n, - invert: false + SplitNMut { + inner: GenericSplitN { + iter: self.split_mut(pred), + count: n, + invert: false + } } } #[inline] - fn rsplitn_mut<'a, P>(&'a mut self, n: uint, pred: P) -> SplitsN> where + fn rsplitn_mut<'a, P>(&'a mut self, n: uint, pred: P) -> RSplitNMut<'a, T, P> where P: FnMut(&T) -> bool, { - SplitsN { - iter: self.split_mut(pred), - count: n, - invert: true + RSplitNMut { + inner: GenericSplitN { + iter: self.split_mut(pred), + count: n, + invert: true + } } } #[inline] - fn chunks_mut(&mut self, chunk_size: uint) -> MutChunks { + fn chunks_mut(&mut self, chunk_size: uint) -> ChunksMut { assert!(chunk_size > 0); - MutChunks { v: self, chunk_size: chunk_size } + ChunksMut { v: self, chunk_size: chunk_size } } fn swap(&mut self, a: uint, b: uint) { @@ -375,8 +387,8 @@ impl SliceExt for [T] { while i < ln / 2 { // Unsafe swap to avoid the bounds check in safe swap. unsafe { - let pa: *mut T = self.unsafe_mut(i); - let pb: *mut T = self.unsafe_mut(ln - i - 1); + let pa: *mut T = self.get_unchecked_mut(i); + let pb: *mut T = self.get_unchecked_mut(ln - i - 1); ptr::swap(pa, pb); } i += 1; @@ -384,7 +396,7 @@ impl SliceExt for [T] { } #[inline] - unsafe fn unsafe_mut(&mut self, index: uint) -> &mut T { + unsafe fn get_unchecked_mut(&mut self, index: uint) -> &mut T { transmute((self.repr().data as *mut T).offset(index as int)) } @@ -468,21 +480,26 @@ impl ops::SliceMut for [T] { } /// Extension methods for slices containing `PartialEq` elements. -#[unstable = "may merge with other traits"] +#[unstable = "may merge with SliceExt"] pub trait PartialEqSliceExt for Sized? { /// Find the first index containing a matching value. + #[experimental] fn position_elem(&self, t: &T) -> Option; /// Find the last index containing a matching value. + #[experimental] fn rposition_elem(&self, t: &T) -> Option; /// Return true if the slice contains an element with the given value. + #[stable] fn contains(&self, x: &T) -> bool; /// Returns true if `needle` is a prefix of the slice. + #[stable] fn starts_with(&self, needle: &[T]) -> bool; /// Returns true if `needle` is a suffix of the slice. + #[stable] fn ends_with(&self, needle: &[T]) -> bool; } @@ -520,19 +537,16 @@ impl PartialEqSliceExt for [T] { #[unstable = "may merge with other traits"] #[allow(missing_docs)] // docs in libcollections pub trait OrdSliceExt for Sized? { - #[unstable = "name likely to change"] - fn binary_search_elem(&self, x: &T) -> BinarySearchResult; - #[experimental] + fn binary_search(&self, x: &T) -> Result; fn next_permutation(&mut self) -> bool; - #[experimental] fn prev_permutation(&mut self) -> bool; } #[unstable = "trait is unstable"] impl OrdSliceExt for [T] { #[unstable] - fn binary_search_elem(&self, x: &T) -> BinarySearchResult { - self.binary_search(|p| p.cmp(x)) + fn binary_search(&self, x: &T) -> Result { + self.binary_search_by(|p| p.cmp(x)) } #[experimental] @@ -619,28 +633,30 @@ impl CloneSliceExt for [T] { } } -// +//////////////////////////////////////////////////////////////////////////////// // Common traits -// +//////////////////////////////////////////////////////////////////////////////// /// Data that is viewable as a slice. -#[unstable = "may merge with other traits"] +#[experimental = "will be replaced by slice syntax"] pub trait AsSlice for Sized? { /// Work with `self` as a slice. fn as_slice<'a>(&'a self) -> &'a [T]; } -#[unstable = "trait is unstable"] +#[experimental = "trait is experimental"] impl AsSlice for [T] { #[inline(always)] fn as_slice<'a>(&'a self) -> &'a [T] { self } } +#[experimental = "trait is experimental"] impl<'a, T, Sized? U: AsSlice> AsSlice for &'a U { #[inline(always)] fn as_slice(&self) -> &[T] { AsSlice::as_slice(*self) } } +#[experimental = "trait is experimental"] impl<'a, T, Sized? U: AsSlice> AsSlice for &'a mut U { #[inline(always)] fn as_slice(&self) -> &[T] { AsSlice::as_slice(*self) } @@ -656,7 +672,7 @@ impl<'a, T> Default for &'a [T] { // Iterators // -// The shared definition of the `Item` and `IterMut` iterators +// The shared definition of the `Iter` and `IterMut` iterators macro_rules! iterator { (struct $name:ident -> $ptr:ty, $elem:ty) => { #[experimental = "needs review"] @@ -736,9 +752,8 @@ macro_rules! make_slice { }} } - /// Immutable slice iterator -#[experimental = "needs review"] +#[stable] pub struct Iter<'a, T: 'a> { ptr: *const T, end: *const T, @@ -813,7 +828,7 @@ impl<'a, T> RandomAccessIterator<&'a T> for Iter<'a, T> { } /// Mutable slice iterator. -#[experimental = "needs review"] +#[stable] pub struct IterMut<'a, T: 'a> { ptr: *mut T, end: *mut T, @@ -876,9 +891,9 @@ iterator!{struct IterMut -> *mut T, &'a mut T} #[experimental = "needs review"] impl<'a, T> ExactSizeIterator<&'a mut T> for IterMut<'a, T> {} -/// An abstraction over the splitting iterators, so that splitn, splitn_mut etc -/// can be implemented once. -trait SplitsIter: DoubleEndedIterator { +/// An internal abstraction over the splitting iterators, so that +/// splitn, splitn_mut etc can be implemented once. +trait SplitIter: DoubleEndedIterator { /// Mark the underlying iterator as complete, extracting the remaining /// portion of the slice. fn finish(&mut self) -> Option; @@ -886,8 +901,8 @@ trait SplitsIter: DoubleEndedIterator { /// An iterator over subslices separated by elements that match a predicate /// function. -#[experimental = "needs review"] -pub struct Splits<'a, T:'a, P> where P: FnMut(&T) -> bool { +#[stable] +pub struct Split<'a, T:'a, P> where P: FnMut(&T) -> bool { v: &'a [T], pred: P, finished: bool @@ -895,9 +910,9 @@ pub struct Splits<'a, T:'a, P> where P: FnMut(&T) -> bool { // FIXME(#19839) Remove in favor of `#[deriving(Clone)]` #[stable] -impl<'a, T, P> Clone for Splits<'a, T, P> where P: Clone + FnMut(&T) -> bool { - fn clone(&self) -> Splits<'a, T, P> { - Splits { +impl<'a, T, P> Clone for Split<'a, T, P> where P: Clone + FnMut(&T) -> bool { + fn clone(&self) -> Split<'a, T, P> { + Split { v: self.v, pred: self.pred.clone(), finished: self.finished, @@ -906,7 +921,7 @@ impl<'a, T, P> Clone for Splits<'a, T, P> where P: Clone + FnMut(&T) -> bool { } #[experimental = "needs review"] -impl<'a, T, P> Iterator<&'a [T]> for Splits<'a, T, P> where P: FnMut(&T) -> bool { +impl<'a, T, P> Iterator<&'a [T]> for Split<'a, T, P> where P: FnMut(&T) -> bool { #[inline] fn next(&mut self) -> Option<&'a [T]> { if self.finished { return None; } @@ -932,7 +947,7 @@ impl<'a, T, P> Iterator<&'a [T]> for Splits<'a, T, P> where P: FnMut(&T) -> bool } #[experimental = "needs review"] -impl<'a, T, P> DoubleEndedIterator<&'a [T]> for Splits<'a, T, P> where P: FnMut(&T) -> bool { +impl<'a, T, P> DoubleEndedIterator<&'a [T]> for Split<'a, T, P> where P: FnMut(&T) -> bool { #[inline] fn next_back(&mut self) -> Option<&'a [T]> { if self.finished { return None; } @@ -948,7 +963,7 @@ impl<'a, T, P> DoubleEndedIterator<&'a [T]> for Splits<'a, T, P> where P: FnMut( } } -impl<'a, T, P> SplitsIter<&'a [T]> for Splits<'a, T, P> where P: FnMut(&T) -> bool { +impl<'a, T, P> SplitIter<&'a [T]> for Split<'a, T, P> where P: FnMut(&T) -> bool { #[inline] fn finish(&mut self) -> Option<&'a [T]> { if self.finished { None } else { self.finished = true; Some(self.v) } @@ -957,14 +972,14 @@ impl<'a, T, P> SplitsIter<&'a [T]> for Splits<'a, T, P> where P: FnMut(&T) -> bo /// An iterator over the subslices of the vector which are separated /// by elements that match `pred`. -#[experimental = "needs review"] -pub struct MutSplits<'a, T:'a, P> where P: FnMut(&T) -> bool { +#[stable] +pub struct SplitMut<'a, T:'a, P> where P: FnMut(&T) -> bool { v: &'a mut [T], pred: P, finished: bool } -impl<'a, T, P> SplitsIter<&'a mut [T]> for MutSplits<'a, T, P> where P: FnMut(&T) -> bool { +impl<'a, T, P> SplitIter<&'a mut [T]> for SplitMut<'a, T, P> where P: FnMut(&T) -> bool { #[inline] fn finish(&mut self) -> Option<&'a mut [T]> { if self.finished { @@ -977,7 +992,7 @@ impl<'a, T, P> SplitsIter<&'a mut [T]> for MutSplits<'a, T, P> where P: FnMut(&T } #[experimental = "needs review"] -impl<'a, T, P> Iterator<&'a mut [T]> for MutSplits<'a, T, P> where P: FnMut(&T) -> bool { +impl<'a, T, P> Iterator<&'a mut [T]> for SplitMut<'a, T, P> where P: FnMut(&T) -> bool { #[inline] fn next(&mut self) -> Option<&'a mut [T]> { if self.finished { return None; } @@ -1010,7 +1025,7 @@ impl<'a, T, P> Iterator<&'a mut [T]> for MutSplits<'a, T, P> where P: FnMut(&T) } #[experimental = "needs review"] -impl<'a, T, P> DoubleEndedIterator<&'a mut [T]> for MutSplits<'a, T, P> where +impl<'a, T, P> DoubleEndedIterator<&'a mut [T]> for SplitMut<'a, T, P> where P: FnMut(&T) -> bool, { #[inline] @@ -1033,17 +1048,17 @@ impl<'a, T, P> DoubleEndedIterator<&'a mut [T]> for MutSplits<'a, T, P> where } } -/// An iterator over subslices separated by elements that match a predicate -/// function, splitting at most a fixed number of times. -#[experimental = "needs review"] -pub struct SplitsN { +/// An private iterator over subslices separated by elements that +/// match a predicate function, splitting at most a fixed number of +/// times. +struct GenericSplitN { iter: I, count: uint, invert: bool } #[experimental = "needs review"] -impl> Iterator for SplitsN { +impl> Iterator for GenericSplitN { #[inline] fn next(&mut self) -> Option { if self.count == 0 { @@ -1061,6 +1076,55 @@ impl> Iterator for SplitsN { } } +/// An iterator over subslices separated by elements that match a predicate +/// function, limited to a given number of splits. +pub struct SplitN<'a, T: 'a, P> where P: FnMut(&T) -> bool { + inner: GenericSplitN> +} + +/// An iterator over subslices separated by elements that match a +/// predicate function, limited to a given number of splits, starting +/// from the end of the slice. +pub struct RSplitN<'a, T: 'a, P> where P: FnMut(&T) -> bool { + inner: GenericSplitN> +} + +/// An iterator over subslices separated by elements that match a predicate +/// function, limited to a given number of splits. +pub struct SplitNMut<'a, T: 'a, P> where P: FnMut(&T) -> bool { + inner: GenericSplitN> +} + +/// An iterator over subslices separated by elements that match a +/// predicate function, limited to a given number of splits, starting +/// from the end of the slice. +pub struct RSplitNMut<'a, T: 'a, P> where P: FnMut(&T) -> bool { + inner: GenericSplitN> +} + +macro_rules! forward_iterator { + ($name:ident: $elem:ident, $iter_of:ty) => { + impl<'a, $elem, P> Iterator<$iter_of> for $name<'a, $elem, P> where + P: FnMut(&T) -> bool + { + #[inline] + fn next(&mut self) -> Option<$iter_of> { + self.inner.next() + } + + #[inline] + fn size_hint(&self) -> (uint, Option) { + self.inner.size_hint() + } + } + } +} + +forward_iterator! { SplitN: T, &'a [T] } +forward_iterator! { RSplitN: T, &'a [T] } +forward_iterator! { SplitNMut: T, &'a mut [T] } +forward_iterator! { RSplitNMut: T, &'a mut [T] } + /// An iterator over overlapping subslices of length `size`. #[deriving(Clone)] #[experimental = "needs review"] @@ -1172,13 +1236,13 @@ impl<'a, T> RandomAccessIterator<&'a [T]> for Chunks<'a, T> { /// elements at a time). When the slice len is not evenly divided by the chunk /// size, the last slice of the iteration will be the remainder. #[experimental = "needs review"] -pub struct MutChunks<'a, T:'a> { +pub struct ChunksMut<'a, T:'a> { v: &'a mut [T], chunk_size: uint } #[experimental = "needs review"] -impl<'a, T> Iterator<&'a mut [T]> for MutChunks<'a, T> { +impl<'a, T> Iterator<&'a mut [T]> for ChunksMut<'a, T> { #[inline] fn next(&mut self) -> Option<&'a mut [T]> { if self.v.len() == 0 { @@ -1206,7 +1270,7 @@ impl<'a, T> Iterator<&'a mut [T]> for MutChunks<'a, T> { } #[experimental = "needs review"] -impl<'a, T> DoubleEndedIterator<&'a mut [T]> for MutChunks<'a, T> { +impl<'a, T> DoubleEndedIterator<&'a mut [T]> for ChunksMut<'a, T> { #[inline] fn next_back(&mut self) -> Option<&'a mut [T]> { if self.v.len() == 0 { @@ -1224,51 +1288,12 @@ impl<'a, T> DoubleEndedIterator<&'a mut [T]> for MutChunks<'a, T> { } - -/// The result of calling `binary_search`. -/// -/// `Found` means the search succeeded, and the contained value is the -/// index of the matching element. `NotFound` means the search -/// succeeded, and the contained value is an index where a matching -/// value could be inserted while maintaining sort order. -#[deriving(Copy, PartialEq, Show)] -#[experimental = "needs review"] -pub enum BinarySearchResult { - /// The index of the found value. - Found(uint), - /// The index where the value should have been found. - NotFound(uint) -} - -#[experimental = "needs review"] -impl BinarySearchResult { - /// Converts a `Found` to `Some`, `NotFound` to `None`. - /// Similar to `Result::ok`. - pub fn found(&self) -> Option { - match *self { - BinarySearchResult::Found(i) => Some(i), - BinarySearchResult::NotFound(_) => None - } - } - - /// Convert a `Found` to `None`, `NotFound` to `Some`. - /// Similar to `Result::err`. - pub fn not_found(&self) -> Option { - match *self { - BinarySearchResult::Found(_) => None, - BinarySearchResult::NotFound(i) => Some(i) - } - } -} - - - // // Free functions // /// Converts a pointer to A into a slice of length 1 (without copying). -#[unstable = "waiting for DST"] +#[unstable] pub fn ref_slice<'a, A>(s: &'a A) -> &'a [A] { unsafe { transmute(RawSlice { data: s, len: 1 }) @@ -1276,7 +1301,7 @@ pub fn ref_slice<'a, A>(s: &'a A) -> &'a [A] { } /// Converts a pointer to A into a slice of length 1 (without copying). -#[unstable = "waiting for DST"] +#[unstable] pub fn mut_ref_slice<'a, A>(s: &'a mut A) -> &'a mut [A] { unsafe { let ptr: *const A = transmute(s); @@ -1310,7 +1335,7 @@ pub fn mut_ref_slice<'a, A>(s: &'a mut A) -> &'a mut [A] { /// } /// ``` #[inline] -#[unstable = "just renamed from `mod raw`"] +#[unstable = "should be renamed to from_raw_parts"] pub unsafe fn from_raw_buf<'a, T>(p: &'a *const T, len: uint) -> &'a [T] { transmute(RawSlice { data: *p, len: len }) } @@ -1322,7 +1347,7 @@ pub unsafe fn from_raw_buf<'a, T>(p: &'a *const T, len: uint) -> &'a [T] { /// not being able to provide a non-aliasing guarantee of the returned mutable /// slice. #[inline] -#[unstable = "just renamed from `mod raw`"] +#[unstable = "jshould be renamed to from_raw_parts_mut"] pub unsafe fn from_raw_mut_buf<'a, T>(p: &'a *mut T, len: uint) -> &'a mut [T] { transmute(RawSlice { data: *p as *const T, len: len }) } @@ -1437,7 +1462,7 @@ pub mod bytes { // Boilerplate traits // -#[unstable = "waiting for DST"] +#[stable] impl PartialEq<[B]> for [A] where A: PartialEq { fn eq(&self, other: &[B]) -> bool { self.len() == other.len() && @@ -1449,7 +1474,7 @@ impl PartialEq<[B]> for [A] where A: PartialEq { } } -#[unstable = "waiting for DST"] +#[stable] impl Eq for [T] {} #[allow(deprecated)] @@ -1466,14 +1491,14 @@ impl<'a,T:PartialEq, Sized? V: AsSlice> Equiv for &'a mut [T] { fn equiv(&self, other: &V) -> bool { self.as_slice() == other.as_slice() } } -#[unstable = "waiting for DST"] +#[stable] impl Ord for [T] { fn cmp(&self, other: &[T]) -> Ordering { order::cmp(self.iter(), other.iter()) } } -#[unstable = "waiting for DST"] +#[stable] impl PartialOrd for [T] { #[inline] fn partial_cmp(&self, other: &[T]) -> Option { @@ -1497,39 +1522,28 @@ impl PartialOrd for [T] { } } -/// Extension methods for immutable slices containing integers. +/// Extension methods for slices containing integers. #[experimental] -pub trait ImmutableIntSlice for Sized? { +pub trait IntSliceExt for Sized? { /// Converts the slice to an immutable slice of unsigned integers with the same width. fn as_unsigned<'a>(&'a self) -> &'a [U]; /// Converts the slice to an immutable slice of signed integers with the same width. fn as_signed<'a>(&'a self) -> &'a [S]; -} -/// Extension methods for mutable slices containing integers. -#[experimental] -pub trait MutableIntSlice for Sized?: ImmutableIntSlice { /// Converts the slice to a mutable slice of unsigned integers with the same width. fn as_unsigned_mut<'a>(&'a mut self) -> &'a mut [U]; /// Converts the slice to a mutable slice of signed integers with the same width. fn as_signed_mut<'a>(&'a mut self) -> &'a mut [S]; } -macro_rules! impl_immut_int_slice { +macro_rules! impl_int_slice { ($u:ty, $s:ty, $t:ty) => { #[experimental] - impl ImmutableIntSlice<$u, $s> for [$t] { + impl IntSliceExt<$u, $s> for [$t] { #[inline] fn as_unsigned(&self) -> &[$u] { unsafe { transmute(self) } } #[inline] fn as_signed(&self) -> &[$s] { unsafe { transmute(self) } } - } - } -} -macro_rules! impl_mut_int_slice { - ($u:ty, $s:ty, $t:ty) => { - #[experimental] - impl MutableIntSlice<$u, $s> for [$t] { #[inline] fn as_unsigned_mut(&mut self) -> &mut [$u] { unsafe { transmute(self) } } #[inline] @@ -1538,17 +1552,15 @@ macro_rules! impl_mut_int_slice { } } -macro_rules! impl_int_slice { +macro_rules! impl_int_slices { ($u:ty, $s:ty) => { - impl_immut_int_slice! { $u, $s, $u } - impl_immut_int_slice! { $u, $s, $s } - impl_mut_int_slice! { $u, $s, $u } - impl_mut_int_slice! { $u, $s, $s } + impl_int_slice! { $u, $s, $u } + impl_int_slice! { $u, $s, $s } } } -impl_int_slice! { u8, i8 } -impl_int_slice! { u16, i16 } -impl_int_slice! { u32, i32 } -impl_int_slice! { u64, i64 } -impl_int_slice! { uint, int } +impl_int_slices! { u8, i8 } +impl_int_slices! { u16, i16 } +impl_int_slices! { u32, i32 } +impl_int_slices! { u64, i64 } +impl_int_slices! { uint, int } diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 8db672b265375..59cf79408b100 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -1143,6 +1143,7 @@ pub mod traits { use ops; use str::{Str, StrExt, eq_slice}; + #[stable] impl Ord for str { #[inline] fn cmp(&self, other: &str) -> Ordering { @@ -1158,6 +1159,7 @@ pub mod traits { } } + #[stable] impl PartialEq for str { #[inline] fn eq(&self, other: &str) -> bool { @@ -1167,8 +1169,10 @@ pub mod traits { fn ne(&self, other: &str) -> bool { !(*self).eq(other) } } + #[stable] impl Eq for str {} + #[stable] impl PartialOrd for str { #[inline] fn partial_cmp(&self, other: &str) -> Option { diff --git a/src/libcore/tuple.rs b/src/libcore/tuple.rs index a92914c99e35b..576989fabe77c 100644 --- a/src/libcore/tuple.rs +++ b/src/libcore/tuple.rs @@ -132,7 +132,7 @@ macro_rules! tuple_impls { } } - #[unstable = "waiting for PartialEq to stabilize"] + #[stable] impl<$($T:PartialEq),+> PartialEq for ($($T,)+) { #[inline] fn eq(&self, other: &($($T,)+)) -> bool { @@ -144,10 +144,10 @@ macro_rules! tuple_impls { } } - #[unstable = "waiting for Eq to stabilize"] + #[stable] impl<$($T:Eq),+> Eq for ($($T,)+) {} - #[unstable = "waiting for PartialOrd to stabilize"] + #[stable] impl<$($T:PartialOrd + PartialEq),+> PartialOrd for ($($T,)+) { #[inline] fn partial_cmp(&self, other: &($($T,)+)) -> Option { @@ -171,7 +171,7 @@ macro_rules! tuple_impls { } } - #[unstable = "waiting for Ord to stabilize"] + #[stable] impl<$($T:Ord),+> Ord for ($($T,)+) { #[inline] fn cmp(&self, other: &($($T,)+)) -> Ordering { diff --git a/src/libcoretest/atomic.rs b/src/libcoretest/atomic.rs index ab9c7ab9f11da..1fee304a97648 100644 --- a/src/libcoretest/atomic.rs +++ b/src/libcoretest/atomic.rs @@ -9,6 +9,7 @@ // except according to those terms. use core::atomic::*; +use core::atomic::Ordering::SeqCst; #[test] fn bool_() { diff --git a/src/libcoretest/slice.rs b/src/libcoretest/slice.rs index 987da90321117..9ef7d6030593a 100644 --- a/src/libcoretest/slice.rs +++ b/src/libcoretest/slice.rs @@ -8,30 +8,30 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::slice::BinarySearchResult::{Found, NotFound}; +use core::result::Result::{Ok, Err}; #[test] fn binary_search_not_found() { let b = [1i, 2, 4, 6, 8, 9]; - assert!(b.binary_search(|v| v.cmp(&6)) == Found(3)); + assert!(b.binary_search_by(|v| v.cmp(&6)) == Ok(3)); let b = [1i, 2, 4, 6, 8, 9]; - assert!(b.binary_search(|v| v.cmp(&5)) == NotFound(3)); + assert!(b.binary_search_by(|v| v.cmp(&5)) == Err(3)); let b = [1i, 2, 4, 6, 7, 8, 9]; - assert!(b.binary_search(|v| v.cmp(&6)) == Found(3)); + assert!(b.binary_search_by(|v| v.cmp(&6)) == Ok(3)); let b = [1i, 2, 4, 6, 7, 8, 9]; - assert!(b.binary_search(|v| v.cmp(&5)) == NotFound(3)); + assert!(b.binary_search_by(|v| v.cmp(&5)) == Err(3)); let b = [1i, 2, 4, 6, 8, 9]; - assert!(b.binary_search(|v| v.cmp(&8)) == Found(4)); + assert!(b.binary_search_by(|v| v.cmp(&8)) == Ok(4)); let b = [1i, 2, 4, 6, 8, 9]; - assert!(b.binary_search(|v| v.cmp(&7)) == NotFound(4)); + assert!(b.binary_search_by(|v| v.cmp(&7)) == Err(4)); let b = [1i, 2, 4, 6, 7, 8, 9]; - assert!(b.binary_search(|v| v.cmp(&8)) == Found(5)); + assert!(b.binary_search_by(|v| v.cmp(&8)) == Ok(5)); let b = [1i, 2, 4, 5, 6, 8, 9]; - assert!(b.binary_search(|v| v.cmp(&7)) == NotFound(5)); + assert!(b.binary_search_by(|v| v.cmp(&7)) == Err(5)); let b = [1i, 2, 4, 5, 6, 8, 9]; - assert!(b.binary_search(|v| v.cmp(&0)) == NotFound(0)); + assert!(b.binary_search_by(|v| v.cmp(&0)) == Err(0)); let b = [1i, 2, 4, 5, 6, 8]; - assert!(b.binary_search(|v| v.cmp(&9)) == NotFound(6)); + assert!(b.binary_search_by(|v| v.cmp(&9)) == Err(6)); } #[test] diff --git a/src/libgetopts/lib.rs b/src/libgetopts/lib.rs index 0426f26937621..0184222b9e0b6 100644 --- a/src/libgetopts/lib.rs +++ b/src/libgetopts/lib.rs @@ -578,7 +578,7 @@ pub fn getopts(args: &[String], optgrps: &[OptGroup]) -> Result { fn f(_x: uint) -> Vec { return Vec::new(); } - let mut vals = Vec::from_fn(n_opts, f); + let mut vals: Vec<_> = range(0, n_opts).map(f).collect(); let mut free: Vec = Vec::new(); let l = args.len(); let mut i = 0; diff --git a/src/liblog/lib.rs b/src/liblog/lib.rs index 1d865868f1883..b30938ae7f577 100644 --- a/src/liblog/lib.rs +++ b/src/liblog/lib.rs @@ -268,8 +268,6 @@ impl Drop for DefaultLogger { } } -// NOTE(stage0): Remove cfg after a snapshot -#[cfg(not(stage0))] /// This function is called directly by the compiler when using the logging /// macros. This function does not take into account whether the log level /// specified is active or not, it will always log something if this method is @@ -304,42 +302,6 @@ pub fn log(level: u32, loc: &'static LogLocation, args: fmt::Arguments) { set_logger(logger); } -// NOTE(stage0): Remove function after a snapshot -#[cfg(stage0)] -/// This function is called directly by the compiler when using the logging -/// macros. This function does not take into account whether the log level -/// specified is active or not, it will always log something if this method is -/// called. -/// -/// It is not recommended to call this function directly, rather it should be -/// 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.as_ref() } { - 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. - let mut logger = LOCAL_LOGGER.with(|s| { - s.borrow_mut().take() - }).unwrap_or_else(|| { - box DefaultLogger { handle: io::stderr() } as Box - }); - logger.log(&LogRecord { - level: LogLevel(level), - args: *args, - file: loc.file, - module_path: loc.module_path, - line: loc.line, - }); - set_logger(logger); -} - /// Getter for the global log level. This is a function so that it can be called /// safely #[doc(hidden)] diff --git a/src/liblog/macros.rs b/src/liblog/macros.rs index 2e8302cc10f9a..233d1c049f4e5 100644 --- a/src/liblog/macros.rs +++ b/src/liblog/macros.rs @@ -12,8 +12,6 @@ #![macro_escape] -// NOTE(stage0): Remove cfg after a snapshot -#[cfg(not(stage0))] /// The standard logging macro /// /// This macro will generically log over a provided level (of type u32) with a @@ -67,61 +65,6 @@ macro_rules! log { }) } -// NOTE(stage0): Remove macro after a snapshot -#[cfg(stage0)] -/// The standard logging macro -/// -/// This macro will generically log over a provided level (of type u32) with a -/// format!-based argument list. See documentation in `std::fmt` for details on -/// how to use the syntax. -/// -/// # Example -/// -/// ``` -/// #![feature(phase)] -/// #[phase(plugin, link)] extern crate log; -/// -/// fn main() { -/// log!(log::WARN, "this is a warning {}", "message"); -/// log!(log::DEBUG, "this is a debug message"); -/// log!(6, "this is a custom logging level: {level}", level=6u); -/// } -/// ``` -/// -/// Assumes the binary is `main`: -/// -/// ```{.bash} -/// $ RUST_LOG=warn ./main -/// WARN:main: this is a warning message -/// ``` -/// -/// ```{.bash} -/// $ RUST_LOG=debug ./main -/// DEBUG:main: this is a debug message -/// WARN:main: this is a warning message -/// ``` -/// -/// ```{.bash} -/// $ RUST_LOG=6 ./main -/// DEBUG:main: this is a debug message -/// WARN:main: this is a warning message -/// 6:main: this is a custom logging level: 6 -/// ``` -#[macro_export] -macro_rules! log { - ($lvl:expr, $($arg:tt)+) => ({ - static LOC: ::log::LogLocation = ::log::LogLocation { - line: line!(), - file: file!(), - module_path: module_path!(), - }; - let lvl = $lvl; - if log_enabled!(lvl) { - format_args!(|args| { ::log::log(lvl, &LOC, args) }, $($arg)+) - } - }) -} - /// A convenience macro for logging at the error log level. /// /// # Example diff --git a/src/librand/isaac.rs b/src/librand/isaac.rs index 3cb1f51a6a801..a76e5ebd08a84 100644 --- a/src/librand/isaac.rs +++ b/src/librand/isaac.rs @@ -361,7 +361,7 @@ impl Isaac64Rng { const MP_VEC: [(uint, uint), .. 2] = [(0,MIDPOINT), (MIDPOINT, 0)]; macro_rules! ind ( ($x:expr) => { - *self.mem.unsafe_get(($x as uint >> 3) & (RAND_SIZE_64 - 1)) + *self.mem.get_unchecked(($x as uint >> 3) & (RAND_SIZE_64 - 1)) } ); @@ -375,13 +375,13 @@ impl Isaac64Rng { let mix = if $j == 0 {!mix} else {mix}; unsafe { - let x = *self.mem.unsafe_get(base + mr_offset); - a = mix + *self.mem.unsafe_get(base + m2_offset); + let x = *self.mem.get_unchecked(base + mr_offset); + a = mix + *self.mem.get_unchecked(base + m2_offset); let y = ind!(x) + a + b; - *self.mem.unsafe_mut(base + mr_offset) = y; + *self.mem.get_unchecked_mut(base + mr_offset) = y; b = ind!(y >> RAND_SIZE_64_LEN) + x; - *self.rsl.unsafe_mut(base + mr_offset) = b; + *self.rsl.get_unchecked_mut(base + mr_offset) = b; } }} ); @@ -392,13 +392,13 @@ impl Isaac64Rng { let mix = if $j == 0 {!mix} else {mix}; unsafe { - let x = *self.mem.unsafe_get(base + mr_offset); - a = mix + *self.mem.unsafe_get(base + m2_offset); + let x = *self.mem.get_unchecked(base + mr_offset); + a = mix + *self.mem.get_unchecked(base + m2_offset); let y = ind!(x) + a + b; - *self.mem.unsafe_mut(base + mr_offset) = y; + *self.mem.get_unchecked_mut(base + mr_offset) = y; b = ind!(y >> RAND_SIZE_64_LEN) + x; - *self.rsl.unsafe_mut(base + mr_offset) = b; + *self.rsl.get_unchecked_mut(base + mr_offset) = b; } }} ); diff --git a/src/librbml/io.rs b/src/librbml/io.rs index cbe69295050ec..fd0c54e8ed3a8 100644 --- a/src/librbml/io.rs +++ b/src/librbml/io.rs @@ -11,6 +11,7 @@ use std::io::{IoError, IoResult, SeekStyle}; use std::io; use std::slice; +use std::iter::repeat; static BUF_CAPACITY: uint = 128; @@ -87,7 +88,7 @@ impl Writer for SeekableMemWriter { // currently are let difference = self.pos as i64 - self.buf.len() as i64; if difference > 0 { - self.buf.grow(difference as uint, 0); + self.buf.extend(repeat(0).take(difference as uint)); } // Figure out what bytes will be used to overwrite what's currently diff --git a/src/libregex/compile.rs b/src/libregex/compile.rs index c361a25bf52eb..1476e6ab8a706 100644 --- a/src/libregex/compile.rs +++ b/src/libregex/compile.rs @@ -14,6 +14,7 @@ pub use self::Inst::*; use std::cmp; +use std::iter::repeat; use parse; use parse::{ Flags, FLAG_EMPTY, @@ -157,7 +158,7 @@ impl<'r> Compiler<'r> { Capture(cap, name, x) => { let len = self.names.len(); if cap >= len { - self.names.grow(10 + cap - len, None) + self.names.extend(repeat(None).take(10 + cap - len)) } self.names[cap] = name; diff --git a/src/libregex/parse.rs b/src/libregex/parse.rs index 86c02de76dcc6..692a065299ca2 100644 --- a/src/libregex/parse.rs +++ b/src/libregex/parse.rs @@ -18,7 +18,6 @@ use std::cmp; use std::fmt; use std::iter; use std::num; -use std::slice::BinarySearchResult; /// Static data containing Unicode ranges for general categories and scripts. use unicode::regex::{UNICODE_CLASSES, PERLD, PERLS, PERLW}; @@ -1028,9 +1027,9 @@ fn is_valid_cap(c: char) -> bool { } fn find_class(classes: NamedClasses, name: &str) -> Option> { - match classes.binary_search(|&(s, _)| s.cmp(name)) { - BinarySearchResult::Found(i) => Some(classes[i].1.to_vec()), - BinarySearchResult::NotFound(_) => None, + match classes.binary_search_by(|&(s, _)| s.cmp(name)) { + Ok(i) => Some(classes[i].1.to_vec()), + Err(_) => None, } } diff --git a/src/libregex/re.rs b/src/libregex/re.rs index 4383192edafb0..51c234631550c 100644 --- a/src/libregex/re.rs +++ b/src/libregex/re.rs @@ -539,6 +539,7 @@ impl Regex { } +#[deriving(Clone)] pub enum NamesIter<'a> { NamesIterNative(::std::slice::Iter<'a, Option<&'static str>>), NamesIterDynamic(::std::slice::Iter<'a, Option>) @@ -595,6 +596,7 @@ impl Replacer for F where F: FnMut(&Captures) -> String { /// /// `'r` is the lifetime of the compiled expression and `'t` is the lifetime /// of the string being split. +#[deriving(Clone)] pub struct RegexSplits<'r, 't> { finder: FindMatches<'r, 't>, last: uint, @@ -628,6 +630,7 @@ impl<'r, 't> Iterator<&'t str> for RegexSplits<'r, 't> { /// /// `'r` is the lifetime of the compiled expression and `'t` is the lifetime /// of the string being split. +#[deriving(Clone)] pub struct RegexSplitsN<'r, 't> { splits: RegexSplits<'r, 't>, cur: uint, @@ -791,6 +794,7 @@ impl<'t> Captures<'t> { /// expression. /// /// `'t` is the lifetime of the matched text. +#[deriving(Clone)] pub struct SubCaptures<'t> { idx: uint, caps: &'t Captures<'t>, @@ -813,6 +817,7 @@ impl<'t> Iterator<&'t str> for SubCaptures<'t> { /// Positions are byte indices in terms of the original string matched. /// /// `'t` is the lifetime of the matched text. +#[deriving(Clone)] pub struct SubCapturesPos<'t> { idx: uint, caps: &'t Captures<'t>, @@ -836,6 +841,7 @@ impl<'t> Iterator> for SubCapturesPos<'t> { /// /// `'r` is the lifetime of the compiled expression and `'t` is the lifetime /// of the matched string. +#[deriving(Clone)] pub struct FindCaptures<'r, 't> { re: &'r Regex, search: &'t str, @@ -878,6 +884,7 @@ impl<'r, 't> Iterator> for FindCaptures<'r, 't> { /// /// `'r` is the lifetime of the compiled expression and `'t` is the lifetime /// of the matched string. +#[deriving(Clone)] pub struct FindMatches<'r, 't> { re: &'r Regex, search: &'t str, diff --git a/src/libregex/vm.rs b/src/libregex/vm.rs index 990d5a159f60d..72e0e559c805b 100644 --- a/src/libregex/vm.rs +++ b/src/libregex/vm.rs @@ -38,6 +38,7 @@ pub use self::StepState::*; use std::cmp; use std::mem; +use std::iter::repeat; use std::slice::SliceExt; use compile::{ Program, @@ -121,7 +122,7 @@ impl<'r, 't> Nfa<'r, 't> { let mut clist = &mut Threads::new(self.which, ninsts, ncaps); let mut nlist = &mut Threads::new(self.which, ninsts, ncaps); - let mut groups = Vec::from_elem(ncaps * 2, None); + let mut groups: Vec<_> = repeat(None).take(ncaps * 2).collect(); // Determine if the expression starts with a '^' so we can avoid // simulating .*? @@ -227,8 +228,7 @@ impl<'r, 't> Nfa<'r, 't> { let negate = flags & FLAG_NEGATED > 0; let casei = flags & FLAG_NOCASE > 0; let found = ranges.as_slice(); - let found = found.binary_search(|&rc| class_cmp(casei, c, rc)) - .found().is_some(); + let found = found.binary_search_by(|&rc| class_cmp(casei, c, rc)).is_ok(); if found ^ negate { self.add(nlist, pc+1, caps); } @@ -457,10 +457,10 @@ impl Threads { fn new(which: MatchKind, num_insts: uint, ncaps: uint) -> Threads { Threads { which: which, - queue: Vec::from_fn(num_insts, |_| { - Thread { pc: 0, groups: Vec::from_elem(ncaps * 2, None) } - }), - sparse: Vec::from_elem(num_insts, 0u), + queue: range(0, num_insts).map(|_| { + Thread { pc: 0, groups: repeat(None).take(ncaps * 2).collect() } + }).collect(), + sparse: repeat(0u).take(num_insts).collect(), size: 0, } } @@ -518,7 +518,7 @@ pub fn is_word(c: Option) -> bool { // Try the common ASCII case before invoking binary search. match c { '_' | '0' ... '9' | 'a' ... 'z' | 'A' ... 'Z' => true, - _ => PERLW.binary_search(|&(start, end)| { + _ => PERLW.binary_search_by(|&(start, end)| { if c >= start && c <= end { Equal } else if start > c { @@ -526,7 +526,7 @@ pub fn is_word(c: Option) -> bool { } else { Less } - }).found().is_some() + }).is_ok() } } diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 35c29f646e4a0..7c496623d62d2 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -654,6 +654,7 @@ impl LintPass for UnusedAttributes { "static_assert", "thread_local", "no_debug", + "omit_gdb_pretty_printer_section", "unsafe_no_drop_flag", // used in resolve diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index db29d0111f446..5d0532a621022 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -1599,7 +1599,7 @@ fn encode_index(rbml_w: &mut Encoder, index: Vec>, mut write_fn: F: FnMut(&mut SeekableMemWriter, &T), T: Hash, { - let mut buckets: Vec>> = Vec::from_fn(256, |_| Vec::new()); + let mut buckets: Vec>> = range(0, 256u16).map(|_| Vec::new()).collect(); for elt in index.into_iter() { let h = hash::hash(&elt.val) as uint; buckets[h % 256].push(elt); diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index b7e67ea469059..522e1d4d3b284 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -611,9 +611,9 @@ fn is_useful(cx: &MatchCheckCtxt, let arity = constructor_arity(cx, &c, left_ty); let mut result = { let pat_slice = pats[]; - let subpats = Vec::from_fn(arity, |i| { + let subpats: Vec<_> = range(0, arity).map(|i| { pat_slice.get(i).map_or(DUMMY_WILD_PAT, |p| &**p) - }); + }).collect(); vec![construct_witness(cx, &c, subpats, left_ty)] }; result.extend(pats.into_iter().skip(arity)); @@ -635,7 +635,7 @@ fn is_useful(cx: &MatchCheckCtxt, match is_useful(cx, &matrix, v.tail(), witness) { UsefulWithWitness(pats) => { let arity = constructor_arity(cx, &constructor, left_ty); - let wild_pats = Vec::from_elem(arity, DUMMY_WILD_PAT); + let wild_pats: Vec<_> = repeat(DUMMY_WILD_PAT).take(arity).collect(); let enum_pat = construct_witness(cx, &constructor, wild_pats, left_ty); let mut new_pats = vec![enum_pat]; new_pats.extend(pats.into_iter()); @@ -788,7 +788,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat], } = raw_pat(r[col]); let head: Option> = match *node { ast::PatWild(_) => - Some(Vec::from_elem(arity, DUMMY_WILD_PAT)), + Some(repeat(DUMMY_WILD_PAT).take(arity).collect()), ast::PatIdent(_, _, _) => { let opt_def = cx.tcx.def_map.borrow().get(&pat_id).cloned(); @@ -801,7 +801,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat], } else { None }, - _ => Some(Vec::from_elem(arity, DUMMY_WILD_PAT)) + _ => Some(repeat(DUMMY_WILD_PAT).take(arity).collect()) } } @@ -815,7 +815,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat], DefVariant(..) | DefStruct(..) => { Some(match args { &Some(ref args) => args.iter().map(|p| &**p).collect(), - &None => Vec::from_elem(arity, DUMMY_WILD_PAT) + &None => repeat(DUMMY_WILD_PAT).take(arity).collect(), }) } _ => None @@ -894,13 +894,13 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat], // Fixed-length vectors. Single => { let mut pats: Vec<&Pat> = before.iter().map(|p| &**p).collect(); - pats.grow_fn(arity - before.len() - after.len(), |_| DUMMY_WILD_PAT); + pats.extend(repeat(DUMMY_WILD_PAT).take(arity - before.len() - after.len())); pats.extend(after.iter().map(|p| &**p)); Some(pats) }, Slice(length) if before.len() + after.len() <= length && slice.is_some() => { let mut pats: Vec<&Pat> = before.iter().map(|p| &**p).collect(); - pats.grow_fn(arity - before.len() - after.len(), |_| DUMMY_WILD_PAT); + pats.extend(repeat(DUMMY_WILD_PAT).take(arity - before.len() - after.len())); pats.extend(after.iter().map(|p| &**p)); Some(pats) }, diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs index a2d417ca345d8..6cf6065de19f0 100644 --- a/src/librustc/middle/dataflow.rs +++ b/src/librustc/middle/dataflow.rs @@ -21,6 +21,7 @@ use middle::cfg::CFGIndex; use middle::ty; use std::io; use std::uint; +use std::iter::repeat; use syntax::ast; use syntax::ast_util::IdRange; use syntax::visit; @@ -203,9 +204,9 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { let entry = if oper.initial_value() { uint::MAX } else {0}; - let gens = Vec::from_elem(num_nodes * words_per_id, 0); - let kills = Vec::from_elem(num_nodes * words_per_id, 0); - let on_entry = Vec::from_elem(num_nodes * words_per_id, entry); + let gens: Vec<_> = repeat(0).take(num_nodes * words_per_id).collect(); + let kills: Vec<_> = repeat(0).take(num_nodes * words_per_id).collect(); + let on_entry: Vec<_> = repeat(entry).take(num_nodes * words_per_id).collect(); let nodeid_to_index = build_nodeid_to_index(decl, cfg); @@ -446,7 +447,7 @@ impl<'a, 'tcx, O:DataFlowOperator+Clone+'static> DataFlowContext<'a, 'tcx, O> { changed: true }; - let mut temp = Vec::from_elem(words_per_id, 0u); + let mut temp: Vec<_> = repeat(0u).take(words_per_id).collect(); while propcx.changed { propcx.changed = false; propcx.reset(temp.as_mut_slice()); diff --git a/src/librustc/middle/infer/error_reporting.rs b/src/librustc/middle/infer/error_reporting.rs index e38b721ce2d0d..6f1c7af5b8628 100644 --- a/src/librustc/middle/infer/error_reporting.rs +++ b/src/librustc/middle/infer/error_reporting.rs @@ -1187,7 +1187,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> { let mut new_ty = P(ty.clone()); let mut ty_queue = vec!(ty); while !ty_queue.is_empty() { - let cur_ty = ty_queue.remove(0).unwrap(); + let cur_ty = ty_queue.remove(0); match cur_ty.node { ast::TyRptr(lt_opt, ref mut_ty) => { let rebuild = match lt_opt { diff --git a/src/librustc/middle/infer/mod.rs b/src/librustc/middle/infer/mod.rs index 386768bd9d6f7..91fbaca26d113 100644 --- a/src/librustc/middle/infer/mod.rs +++ b/src/librustc/middle/infer/mod.rs @@ -799,7 +799,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } pub fn next_ty_vars(&self, n: uint) -> Vec> { - Vec::from_fn(n, |_i| self.next_ty_var()) + range(0, n).map(|_i| self.next_ty_var()).collect() } pub fn next_int_var_id(&self) -> IntVid { diff --git a/src/librustc/middle/infer/region_inference/mod.rs b/src/librustc/middle/infer/region_inference/mod.rs index 97fab3bc9395a..7372bb267b06c 100644 --- a/src/librustc/middle/infer/region_inference/mod.rs +++ b/src/librustc/middle/infer/region_inference/mod.rs @@ -34,6 +34,7 @@ use util::ppaux::Repr; use std::cell::{Cell, RefCell}; use std::u32; +use std::iter::repeat; use syntax::ast; mod doc; @@ -975,7 +976,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { } fn construct_var_data(&self) -> Vec { - Vec::from_fn(self.num_vars() as uint, |_| { + range(0, self.num_vars() as uint).map(|_| { VarData { // All nodes are initially classified as contracting; during // the expansion phase, we will shift the classification for @@ -984,7 +985,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { classification: Contracting, value: NoValue, } - }) + }).collect() } fn dump_constraints(&self) { @@ -1247,7 +1248,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { // idea is to report errors that derive from independent // regions of the graph, but not those that derive from // overlapping locations. - let mut dup_vec = Vec::from_elem(self.num_vars() as uint, u32::MAX); + let mut dup_vec: Vec<_> = repeat(u32::MAX).take(self.num_vars() as uint).collect(); let mut opt_graph = None; @@ -1308,7 +1309,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { } } - Vec::from_fn(self.num_vars() as uint, |idx| var_data[idx].value) + range(0, self.num_vars() as uint).map(|idx| var_data[idx].value).collect() } fn construct_graph(&self) -> RegionGraph { diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index d3859ca12a971..5be8d03e74359 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -117,6 +117,7 @@ use util::nodemap::NodeMap; use std::{fmt, io, uint}; use std::rc::Rc; +use std::iter::repeat; use syntax::ast::{mod, NodeId, Expr}; use syntax::codemap::{BytePos, original_sp, Span}; use syntax::parse::token::{mod, special_idents}; @@ -575,8 +576,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { Liveness { ir: ir, s: specials, - successors: Vec::from_elem(num_live_nodes, invalid_node()), - users: Vec::from_elem(num_live_nodes * num_vars, invalid_users()), + successors: repeat(invalid_node()).take(num_live_nodes).collect(), + users: repeat(invalid_users()).take(num_live_nodes * num_vars).collect(), loop_scope: Vec::new(), break_ln: NodeMap::new(), cont_ln: NodeMap::new(), @@ -1068,7 +1069,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { // the same bindings, and we also consider the first pattern to be // the "authoritative" set of ids let arm_succ = - self.define_bindings_in_arm_pats(arm.pats.head().map(|p| &**p), + self.define_bindings_in_arm_pats(arm.pats.first().map(|p| &**p), guard_succ); self.merge_from_succ(ln, arm_succ, first_merge); first_merge = false; @@ -1436,7 +1437,7 @@ fn check_arm(this: &mut Liveness, arm: &ast::Arm) { // only consider the first pattern; any later patterns must have // the same bindings, and we also consider the first pattern to be // the "authoritative" set of ids - this.arm_pats_bindings(arm.pats.head().map(|p| &**p), |this, ln, var, sp, id| { + this.arm_pats_bindings(arm.pats.first().map(|p| &**p), |this, ln, var, sp, id| { this.warn_about_unused(sp, id, ln, var); }); visit::walk_arm(this, arm); @@ -1542,7 +1543,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } else { let ends_with_stmt = match body.expr { None if body.stmts.len() > 0 => - match body.stmts.last().unwrap().node { + match body.stmts.first().unwrap().node { ast::StmtSemi(ref e, _) => { ty::expr_ty(self.ir.tcx, &**e) == t_ret }, @@ -1553,7 +1554,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { self.ir.tcx.sess.span_err( sp, "not all control paths return a value"); if ends_with_stmt { - let last_stmt = body.stmts.last().unwrap(); + let last_stmt = body.stmts.first().unwrap(); let original_span = original_sp(self.ir.tcx.sess.codemap(), last_stmt.span, sp); let span_semicolon = Span { diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs index 730da26eda3dc..edba2839f37ea 100644 --- a/src/librustc/middle/privacy.rs +++ b/src/librustc/middle/privacy.rs @@ -751,10 +751,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> { let orig_def = self.tcx.def_map.borrow()[path_id].clone(); let ck = |tyname: &str| { let ck_public = |def: ast::DefId| { - let name = token::get_ident(path.segments - .last() - .unwrap() - .identifier); + let name = token::get_ident(path.segments.last().unwrap().identifier); let origdid = orig_def.def_id(); self.ensure_public(span, def, diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 4feafff3b9211..e9504a92f7b46 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -296,7 +296,7 @@ impl<'a> LifetimeContext<'a> { debug!("visit_early_late: referenced_idents={}", referenced_idents); - let (early, late) = generics.lifetimes.clone().partition( + let (early, late): (Vec<_>, _) = generics.lifetimes.iter().cloned().partition( |l| referenced_idents.iter().any(|&i| i == l.lifetime.name)); self.with(EarlyScope(early_space, &early, self.scope), move |old_scope, this| { diff --git a/src/librustc/middle/subst.rs b/src/librustc/middle/subst.rs index 3066ae5b479ef..07da9853e5585 100644 --- a/src/librustc/middle/subst.rs +++ b/src/librustc/middle/subst.rs @@ -323,7 +323,11 @@ impl VecPerParamSpace { SelfSpace => { self.self_limit -= 1; } FnSpace => {} } - self.content.remove(limit - 1) + if self.content.is_empty() { + None + } else { + Some(self.content.remove(limit - 1)) + } } } diff --git a/src/librustc/util/lev_distance.rs b/src/librustc/util/lev_distance.rs index 24e9883744407..e7c77b1249927 100644 --- a/src/librustc/util/lev_distance.rs +++ b/src/librustc/util/lev_distance.rs @@ -14,7 +14,7 @@ pub fn lev_distance(me: &str, t: &str) -> uint { if me.is_empty() { return t.chars().count(); } if t.is_empty() { return me.chars().count(); } - let mut dcol = Vec::from_fn(t.len() + 1, |x| x); + let mut dcol: Vec<_> = range(0, t.len() + 1).collect(); let mut t_last = 0; for (i, sc) in me.chars().enumerate() { diff --git a/src/librustc_back/sha2.rs b/src/librustc_back/sha2.rs index e1f0168d86be4..366e33d6384ba 100644 --- a/src/librustc_back/sha2.rs +++ b/src/librustc_back/sha2.rs @@ -14,7 +14,7 @@ #![allow(deprecated)] // to_be32 -use std::iter::range_step; +use std::iter::{range_step, repeat}; use std::num::Int; use std::slice::bytes::{MutableByteVector, copy_memory}; use serialize::hex::ToHex; @@ -258,7 +258,7 @@ pub trait Digest { /// Convenience function that retrieves the result of a digest as a /// newly allocated vec of bytes. fn result_bytes(&mut self) -> Vec { - let mut buf = Vec::from_elem((self.output_bits()+7)/8, 0u8); + let mut buf: Vec = repeat(0u8).take((self.output_bits()+7)/8).collect(); self.result(buf.as_mut_slice()); buf } @@ -530,11 +530,12 @@ static H256: [u32, ..8] = [ mod tests { extern crate rand; - use super::{Digest, Sha256, FixedBuffer}; - use self::rand::isaac::IsaacRng; use self::rand::Rng; + use self::rand::isaac::IsaacRng; use serialize::hex::FromHex; + use std::iter::repeat; use std::num::Int; + use super::{Digest, Sha256, FixedBuffer}; // A normal addition - no overflow occurs #[test] @@ -612,7 +613,7 @@ mod tests { /// correct. fn test_digest_1million_random(digest: &mut D, blocksize: uint, expected: &str) { let total_size = 1000000; - let buffer = Vec::from_elem(blocksize * 2, 'a' as u8); + let buffer: Vec = repeat('a' as u8).take(blocksize * 2).collect(); let mut rng = IsaacRng::new_unseeded(); let mut count = 0; diff --git a/src/librustc_borrowck/borrowck/fragments.rs b/src/librustc_borrowck/borrowck/fragments.rs index 7609554033cef..070ae1151aa6d 100644 --- a/src/librustc_borrowck/borrowck/fragments.rs +++ b/src/librustc_borrowck/borrowck/fragments.rs @@ -25,7 +25,6 @@ use rustc::middle::mem_categorization as mc; use rustc::util::ppaux::{Repr, UserString}; use std::mem; use std::rc::Rc; -use std::slice; use syntax::ast; use syntax::ast_map; use syntax::attr::AttrMetaMethods; @@ -268,9 +267,9 @@ pub fn fixup_fragment_sets<'tcx>(this: &MoveData<'tcx>, tcx: &ty::ctxt<'tcx>) { return; fn non_member(elem: MovePathIndex, set: &[MovePathIndex]) -> bool { - match set.binary_search_elem(&elem) { - slice::BinarySearchResult::Found(_) => false, - slice::BinarySearchResult::NotFound(_) => true, + match set.binary_search(&elem) { + Ok(_) => false, + Err(_) => true, } } } diff --git a/src/librustc_borrowck/lib.rs b/src/librustc_borrowck/lib.rs index e71e9e5dfea1b..664d470b11bd1 100644 --- a/src/librustc_borrowck/lib.rs +++ b/src/librustc_borrowck/lib.rs @@ -37,4 +37,3 @@ pub use borrowck::FnPartsWithCFG; mod borrowck; pub mod graphviz; - diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index e20404bf63891..0d98434d042ba 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -265,11 +265,13 @@ Available lint options: lints } - let (plugin, builtin) = lint_store.get_lints().partitioned(|&(_, p)| p); + let (plugin, builtin): (Vec<_>, _) = lint_store.get_lints() + .iter().cloned().partition(|&(_, p)| p); let plugin = sort_lints(plugin); let builtin = sort_lints(builtin); - let (plugin_groups, builtin_groups) = lint_store.get_lint_groups().partitioned(|&(_, _, p)| p); + let (plugin_groups, builtin_groups): (Vec<_>, _) = lint_store.get_lint_groups() + .iter().cloned().partition(|&(_, _, p)| p); let plugin_groups = sort_lint_groups(plugin_groups); let builtin_groups = sort_lint_groups(builtin_groups); @@ -377,7 +379,7 @@ fn describe_codegen_flags() { /// returns None. pub fn handle_options(mut args: Vec) -> Option { // Throw away the first argument, the name of the binary - let _binary = args.remove(0).unwrap(); + let _binary = args.remove(0); if args.is_empty() { // user did not write `-v` nor `-Z unstable-options`, so do not diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index 3528b510ea1bb..296ebcf9cfd8f 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -1743,7 +1743,8 @@ extern { isOptimized: bool, Flags: *const c_char, RuntimeVer: c_uint, - SplitName: *const c_char); + SplitName: *const c_char) + -> DIDescriptor; pub fn LLVMDIBuilderCreateFile(Builder: DIBuilderRef, Filename: *const c_char, diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs new file mode 100644 index 0000000000000..7dbcc810b571b --- /dev/null +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -0,0 +1,1282 @@ +// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Reduced graph building +//! +//! Here we build the "reduced graph": the graph of the module tree without +//! any imports resolved. + +use {DefModifiers, PUBLIC, IMPORTABLE}; +use ImportDirective; +use ImportDirectiveSubclass::{mod, SingleImport, GlobImport}; +use ImportResolution; +use Module; +use ModuleKind::*; +use Namespace::{TypeNS, ValueNS}; +use NameBindings; +use ParentLink::{mod, ModuleParentLink, BlockParentLink}; +use Resolver; +use RibKind::*; +use Shadowable; +use TypeNsDef; +use TypeParameters::HasTypeParameters; + +use self::DuplicateCheckingMode::*; +use self::NamespaceError::*; + +use rustc::metadata::csearch; +use rustc::metadata::decoder::{DefLike, DlDef, DlField, DlImpl}; +use rustc::middle::def::*; +use rustc::middle::subst::FnSpace; + +use syntax::ast::{Block, Crate}; +use syntax::ast::{DeclItem, DefId}; +use syntax::ast::{ForeignItem, ForeignItemFn, ForeignItemStatic}; +use syntax::ast::{Item, ItemConst, ItemEnum, ItemFn}; +use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic}; +use syntax::ast::{ItemStruct, ItemTrait, ItemTy}; +use syntax::ast::{MethodImplItem, Name, NamedField, NodeId}; +use syntax::ast::{PathListIdent, PathListMod}; +use syntax::ast::{Public, SelfStatic}; +use syntax::ast::StmtDecl; +use syntax::ast::StructVariantKind; +use syntax::ast::TupleVariantKind; +use syntax::ast::TyObjectSum; +use syntax::ast::{TypeImplItem, UnnamedField}; +use syntax::ast::{Variant, ViewItem, ViewItemExternCrate}; +use syntax::ast::{ViewItemUse, ViewPathGlob, ViewPathList, ViewPathSimple}; +use syntax::ast::{Visibility}; +use syntax::ast::TyPath; +use syntax::ast; +use syntax::ast_util::{mod, PostExpansionMethod, local_def}; +use syntax::attr::AttrMetaMethods; +use syntax::parse::token::{mod, special_idents}; +use syntax::codemap::{Span, DUMMY_SP}; +use syntax::visit::{mod, Visitor}; + +use std::rc::Rc; +use std::mem::replace; + +// Specifies how duplicates should be handled when adding a child item if +// another item exists with the same name in some namespace. +#[deriving(Copy, PartialEq)] +enum DuplicateCheckingMode { + ForbidDuplicateModules, + ForbidDuplicateTypesAndModules, + ForbidDuplicateValues, + ForbidDuplicateTypesAndValues, + OverwriteDuplicates +} + +#[deriving(Copy, PartialEq)] +enum NamespaceError { + NoError, + ModuleError, + TypeError, + ValueError +} + +fn namespace_error_to_string(ns: NamespaceError) -> &'static str { + match ns { + NoError => "", + ModuleError | TypeError => "type or module", + ValueError => "value", + } +} + +struct GraphBuilder<'a, 'b:'a, 'tcx:'b> { + resolver: &'a mut Resolver<'b, 'tcx> +} + +impl<'a, 'b:'a, 'tcx:'b> Deref> for GraphBuilder<'a, 'b, 'tcx> { + fn deref(&self) -> &Resolver<'b, 'tcx> { + &*self.resolver + } +} + +impl<'a, 'b:'a, 'tcx:'b> DerefMut> for GraphBuilder<'a, 'b, 'tcx> { + fn deref_mut(&mut self) -> &mut Resolver<'b, 'tcx> { + &mut *self.resolver + } +} + +impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { + /// Constructs the reduced graph for the entire crate. + fn build_reduced_graph(self, krate: &ast::Crate) { + let parent = self.graph_root.get_module(); + let mut visitor = BuildReducedGraphVisitor { + builder: self, + parent: parent + }; + visit::walk_crate(&mut visitor, krate); + } + + /// Adds a new child item to the module definition of the parent node and + /// returns its corresponding name bindings as well as the current parent. + /// Or, if we're inside a block, creates (or reuses) an anonymous module + /// corresponding to the innermost block ID and returns the name bindings + /// as well as the newly-created parent. + /// + /// # Panics + /// + /// Panics if this node does not have a module definition and we are not inside + /// a block. + fn add_child(&self, + name: Name, + parent: &Rc, + duplicate_checking_mode: DuplicateCheckingMode, + // For printing errors + sp: Span) + -> Rc { + // If this is the immediate descendant of a module, then we add the + // child name directly. Otherwise, we create or reuse an anonymous + // module and add the child to that. + + self.check_for_conflicts_between_external_crates_and_items(&**parent, + name, + sp); + + // Add or reuse the child. + let child = parent.children.borrow().get(&name).cloned(); + match child { + None => { + let child = Rc::new(NameBindings::new()); + parent.children.borrow_mut().insert(name, child.clone()); + child + } + Some(child) => { + // Enforce the duplicate checking mode: + // + // * If we're requesting duplicate module checking, check that + // there isn't a module in the module with the same name. + // + // * If we're requesting duplicate type checking, check that + // there isn't a type in the module with the same name. + // + // * If we're requesting duplicate value checking, check that + // there isn't a value in the module with the same name. + // + // * If we're requesting duplicate type checking and duplicate + // value checking, check that there isn't a duplicate type + // and a duplicate value with the same name. + // + // * If no duplicate checking was requested at all, do + // nothing. + + let mut duplicate_type = NoError; + let ns = match duplicate_checking_mode { + ForbidDuplicateModules => { + if child.get_module_if_available().is_some() { + duplicate_type = ModuleError; + } + Some(TypeNS) + } + ForbidDuplicateTypesAndModules => { + match child.def_for_namespace(TypeNS) { + None => {} + Some(_) if child.get_module_if_available() + .map(|m| m.kind.get()) == + Some(ImplModuleKind) => {} + Some(_) => duplicate_type = TypeError + } + Some(TypeNS) + } + ForbidDuplicateValues => { + if child.defined_in_namespace(ValueNS) { + duplicate_type = ValueError; + } + Some(ValueNS) + } + ForbidDuplicateTypesAndValues => { + let mut n = None; + match child.def_for_namespace(TypeNS) { + Some(DefMod(_)) | None => {} + Some(_) => { + n = Some(TypeNS); + duplicate_type = TypeError; + } + }; + if child.defined_in_namespace(ValueNS) { + duplicate_type = ValueError; + n = Some(ValueNS); + } + n + } + OverwriteDuplicates => None + }; + if duplicate_type != NoError { + // Return an error here by looking up the namespace that + // had the duplicate. + let ns = ns.unwrap(); + self.resolve_error(sp, + format!("duplicate definition of {} `{}`", + namespace_error_to_string(duplicate_type), + token::get_name(name))[]); + { + let r = child.span_for_namespace(ns); + for sp in r.iter() { + self.session.span_note(*sp, + format!("first definition of {} `{}` here", + namespace_error_to_string(duplicate_type), + token::get_name(name))[]); + } + } + } + child + } + } + } + + fn block_needs_anonymous_module(&mut self, block: &Block) -> bool { + // If the block has view items, we need an anonymous module. + if block.view_items.len() > 0 { + return true; + } + + // Check each statement. + for statement in block.stmts.iter() { + match statement.node { + StmtDecl(ref declaration, _) => { + match declaration.node { + DeclItem(_) => { + return true; + } + _ => { + // Keep searching. + } + } + } + _ => { + // Keep searching. + } + } + } + + // If we found neither view items nor items, we don't need to create + // an anonymous module. + + return false; + } + + fn get_parent_link(&mut self, parent: &Rc, name: Name) -> ParentLink { + ModuleParentLink(parent.downgrade(), name) + } + + /// Constructs the reduced graph for one item. + fn build_reduced_graph_for_item(&mut self, item: &Item, parent: &Rc) -> Rc { + let name = item.ident.name; + let sp = item.span; + let is_public = item.vis == ast::Public; + let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE; + + match item.node { + ItemMod(..) => { + let name_bindings = self.add_child(name, parent, ForbidDuplicateModules, sp); + + let parent_link = self.get_parent_link(parent, name); + let def_id = DefId { krate: 0, node: item.id }; + name_bindings.define_module(parent_link, + Some(def_id), + NormalModuleKind, + false, + item.vis == ast::Public, + sp); + + name_bindings.get_module() + } + + ItemForeignMod(..) => parent.clone(), + + // These items live in the value namespace. + ItemStatic(_, m, _) => { + let name_bindings = self.add_child(name, parent, ForbidDuplicateValues, sp); + let mutbl = m == ast::MutMutable; + + name_bindings.define_value(DefStatic(local_def(item.id), mutbl), sp, modifiers); + parent.clone() + } + ItemConst(_, _) => { + self.add_child(name, parent, ForbidDuplicateValues, sp) + .define_value(DefConst(local_def(item.id)), sp, modifiers); + parent.clone() + } + ItemFn(_, _, _, _, _) => { + let name_bindings = self.add_child(name, parent, ForbidDuplicateValues, sp); + + let def = DefFn(local_def(item.id), false); + name_bindings.define_value(def, sp, modifiers); + parent.clone() + } + + // These items live in the type namespace. + ItemTy(..) => { + let name_bindings = + self.add_child(name, parent, ForbidDuplicateTypesAndModules, sp); + + name_bindings.define_type(DefTy(local_def(item.id), false), sp, modifiers); + parent.clone() + } + + ItemEnum(ref enum_definition, _) => { + let name_bindings = + self.add_child(name, parent, ForbidDuplicateTypesAndModules, sp); + + name_bindings.define_type(DefTy(local_def(item.id), true), sp, modifiers); + + let parent_link = self.get_parent_link(parent, name); + // We want to make sure the module type is EnumModuleKind + // even if there's already an ImplModuleKind module defined, + // since that's how we prevent duplicate enum definitions + name_bindings.set_module_kind(parent_link, + Some(local_def(item.id)), + EnumModuleKind, + false, + is_public, + sp); + + let module = name_bindings.get_module(); + + for variant in (*enum_definition).variants.iter() { + self.build_reduced_graph_for_variant( + &**variant, + local_def(item.id), + &module); + } + parent.clone() + } + + // These items live in both the type and value namespaces. + ItemStruct(ref struct_def, _) => { + // Adding to both Type and Value namespaces or just Type? + let (forbid, ctor_id) = match struct_def.ctor_id { + Some(ctor_id) => (ForbidDuplicateTypesAndValues, Some(ctor_id)), + None => (ForbidDuplicateTypesAndModules, None) + }; + + let name_bindings = self.add_child(name, parent, forbid, sp); + + // Define a name in the type namespace. + name_bindings.define_type(DefTy(local_def(item.id), false), sp, modifiers); + + // If this is a newtype or unit-like struct, define a name + // in the value namespace as well + if let Some(cid) = ctor_id { + name_bindings.define_value(DefStruct(local_def(cid)), sp, modifiers); + } + + // Record the def ID and fields of this struct. + let named_fields = struct_def.fields.iter().filter_map(|f| { + match f.node.kind { + NamedField(ident, _) => Some(ident.name), + UnnamedField(_) => None + } + }).collect(); + self.structs.insert(local_def(item.id), named_fields); + + parent.clone() + } + + ItemImpl(_, _, None, ref ty, ref impl_items) => { + // If this implements an anonymous trait, then add all the + // methods within to a new module, if the type was defined + // within this module. + + let mod_name = match ty.node { + TyPath(ref path, _) if path.segments.len() == 1 => { + // FIXME(18446) we should distinguish between the name of + // a trait and the name of an impl of that trait. + Some(path.segments.last().unwrap().identifier.name) + } + TyObjectSum(ref lhs_ty, _) => { + match lhs_ty.node { + TyPath(ref path, _) if path.segments.len() == 1 => { + Some(path.segments.last().unwrap().identifier.name) + } + _ => { + None + } + } + } + _ => { + None + } + }; + + match mod_name { + None => { + self.resolve_error(ty.span, + "inherent implementations may \ + only be implemented in the same \ + module as the type they are \ + implemented for") + } + Some(mod_name) => { + // Create the module and add all methods. + let parent_opt = parent.children.borrow().get(&mod_name).cloned(); + let new_parent = match parent_opt { + // It already exists + Some(ref child) if child.get_module_if_available() + .is_some() && + (child.get_module().kind.get() == ImplModuleKind || + child.get_module().kind.get() == TraitModuleKind) => { + child.get_module() + } + Some(ref child) if child.get_module_if_available() + .is_some() && + child.get_module().kind.get() == + EnumModuleKind => child.get_module(), + // Create the module + _ => { + let name_bindings = + self.add_child(mod_name, parent, ForbidDuplicateModules, sp); + + let parent_link = self.get_parent_link(parent, name); + let def_id = local_def(item.id); + let ns = TypeNS; + let is_public = + !name_bindings.defined_in_namespace(ns) || + name_bindings.defined_in_public_namespace(ns); + + name_bindings.define_module(parent_link, + Some(def_id), + ImplModuleKind, + false, + is_public, + sp); + + name_bindings.get_module() + } + }; + + // For each implementation item... + for impl_item in impl_items.iter() { + match *impl_item { + MethodImplItem(ref method) => { + // Add the method to the module. + let name = method.pe_ident().name; + let method_name_bindings = + self.add_child(name, + &new_parent, + ForbidDuplicateValues, + method.span); + let def = match method.pe_explicit_self() + .node { + SelfStatic => { + // Static methods become + // `DefStaticMethod`s. + DefStaticMethod(local_def(method.id), + FromImpl(local_def(item.id))) + } + _ => { + // Non-static methods become + // `DefMethod`s. + DefMethod(local_def(method.id), + None, + FromImpl(local_def(item.id))) + } + }; + + // NB: not IMPORTABLE + let modifiers = if method.pe_vis() == ast::Public { + PUBLIC + } else { + DefModifiers::empty() + }; + method_name_bindings.define_value( + def, + method.span, + modifiers); + } + TypeImplItem(ref typedef) => { + // Add the typedef to the module. + let name = typedef.ident.name; + let typedef_name_bindings = + self.add_child( + name, + &new_parent, + ForbidDuplicateTypesAndModules, + typedef.span); + let def = DefAssociatedTy(local_def( + typedef.id)); + // NB: not IMPORTABLE + let modifiers = if typedef.vis == ast::Public { + PUBLIC + } else { + DefModifiers::empty() + }; + typedef_name_bindings.define_type( + def, + typedef.span, + modifiers); + } + } + } + } + } + + parent.clone() + } + + ItemImpl(_, _, Some(_), _, _) => parent.clone(), + + ItemTrait(_, _, _, ref items) => { + let name_bindings = + self.add_child(name, parent, ForbidDuplicateTypesAndModules, sp); + + // Add all the items within to a new module. + let parent_link = self.get_parent_link(parent, name); + name_bindings.define_module(parent_link, + Some(local_def(item.id)), + TraitModuleKind, + false, + item.vis == ast::Public, + sp); + let module_parent = name_bindings.get_module(); + + let def_id = local_def(item.id); + + // Add the names of all the items to the trait info. + for trait_item in items.iter() { + let (name, kind) = match *trait_item { + ast::RequiredMethod(_) | + ast::ProvidedMethod(_) => { + let ty_m = ast_util::trait_item_to_ty_method(trait_item); + + let name = ty_m.ident.name; + + // Add it as a name in the trait module. + let (def, static_flag) = match ty_m.explicit_self + .node { + SelfStatic => { + // Static methods become `DefStaticMethod`s. + (DefStaticMethod( + local_def(ty_m.id), + FromTrait(local_def(item.id))), + StaticMethodTraitItemKind) + } + _ => { + // Non-static methods become `DefMethod`s. + (DefMethod(local_def(ty_m.id), + Some(local_def(item.id)), + FromTrait(local_def(item.id))), + NonstaticMethodTraitItemKind) + } + }; + + let method_name_bindings = + self.add_child(name, + &module_parent, + ForbidDuplicateTypesAndValues, + ty_m.span); + // NB: not IMPORTABLE + method_name_bindings.define_value(def, + ty_m.span, + PUBLIC); + + (name, static_flag) + } + ast::TypeTraitItem(ref associated_type) => { + let def = DefAssociatedTy(local_def( + associated_type.ty_param.id)); + + let name_bindings = + self.add_child(associated_type.ty_param.ident.name, + &module_parent, + ForbidDuplicateTypesAndValues, + associated_type.ty_param.span); + // NB: not IMPORTABLE + name_bindings.define_type(def, + associated_type.ty_param.span, + PUBLIC); + + (associated_type.ty_param.ident.name, TypeTraitItemKind) + } + }; + + self.trait_item_map.insert((name, def_id), kind); + } + + name_bindings.define_type(DefTrait(def_id), sp, modifiers); + parent.clone() + } + ItemMac(..) => parent.clone() + } + } + + // Constructs the reduced graph for one variant. Variants exist in the + // type and value namespaces. + fn build_reduced_graph_for_variant(&mut self, + variant: &Variant, + item_id: DefId, + parent: &Rc) { + let name = variant.node.name.name; + let is_exported = match variant.node.kind { + TupleVariantKind(_) => false, + StructVariantKind(_) => { + // Not adding fields for variants as they are not accessed with a self receiver + self.structs.insert(local_def(variant.node.id), Vec::new()); + true + } + }; + + let child = self.add_child(name, parent, + ForbidDuplicateTypesAndValues, + variant.span); + // variants are always treated as importable to allow them to be glob + // used + child.define_value(DefVariant(item_id, + local_def(variant.node.id), is_exported), + variant.span, PUBLIC | IMPORTABLE); + child.define_type(DefVariant(item_id, + local_def(variant.node.id), is_exported), + variant.span, PUBLIC | IMPORTABLE); + } + + /// Constructs the reduced graph for one 'view item'. View items consist + /// of imports and use directives. + fn build_reduced_graph_for_view_item(&mut self, view_item: &ViewItem, parent: &Rc) { + match view_item.node { + ViewItemUse(ref view_path) => { + // Extract and intern the module part of the path. For + // globs and lists, the path is found directly in the AST; + // for simple paths we have to munge the path a little. + let module_path = match view_path.node { + ViewPathSimple(_, ref full_path, _) => { + full_path.segments + .init() + .iter().map(|ident| ident.identifier.name) + .collect() + } + + ViewPathGlob(ref module_ident_path, _) | + ViewPathList(ref module_ident_path, _, _) => { + module_ident_path.segments + .iter().map(|ident| ident.identifier.name).collect() + } + }; + + // Build up the import directives. + let is_public = view_item.vis == ast::Public; + let shadowable = + view_item.attrs + .iter() + .any(|attr| { + attr.name() == token::get_name( + special_idents::prelude_import.name) + }); + let shadowable = if shadowable { + Shadowable::Always + } else { + Shadowable::Never + }; + + match view_path.node { + ViewPathSimple(binding, ref full_path, id) => { + let source_name = + full_path.segments.last().unwrap().identifier.name; + if token::get_name(source_name).get() == "mod" { + self.resolve_error(view_path.span, + "`mod` imports are only allowed within a { } list"); + } + + let subclass = SingleImport(binding.name, + source_name); + self.build_import_directive(&**parent, + module_path, + subclass, + view_path.span, + id, + is_public, + shadowable); + } + ViewPathList(_, ref source_items, _) => { + // Make sure there's at most one `mod` import in the list. + let mod_spans = source_items.iter().filter_map(|item| match item.node { + PathListMod { .. } => Some(item.span), + _ => None + }).collect::>(); + if mod_spans.len() > 1 { + self.resolve_error(mod_spans[0], + "`mod` import can only appear once in the list"); + for other_span in mod_spans.iter().skip(1) { + self.session.span_note(*other_span, + "another `mod` import appears here"); + } + } + + for source_item in source_items.iter() { + let (module_path, name) = match source_item.node { + PathListIdent { name, .. } => + (module_path.clone(), name.name), + PathListMod { .. } => { + let name = match module_path.last() { + Some(name) => *name, + None => { + self.resolve_error(source_item.span, + "`mod` import can only appear in an import list \ + with a non-empty prefix"); + continue; + } + }; + let module_path = module_path.init(); + (module_path.to_vec(), name) + } + }; + self.build_import_directive( + &**parent, + module_path, + SingleImport(name, name), + source_item.span, + source_item.node.id(), + is_public, + shadowable); + } + } + ViewPathGlob(_, id) => { + self.build_import_directive(&**parent, + module_path, + GlobImport, + view_path.span, + id, + is_public, + shadowable); + } + } + } + + ViewItemExternCrate(name, _, node_id) => { + // n.b. we don't need to look at the path option here, because cstore already did + for &crate_id in self.session.cstore + .find_extern_mod_stmt_cnum(node_id).iter() { + let def_id = DefId { krate: crate_id, node: 0 }; + self.external_exports.insert(def_id); + let parent_link = ModuleParentLink(parent.downgrade(), name.name); + let external_module = Rc::new(Module::new(parent_link, + Some(def_id), + NormalModuleKind, + false, + true)); + debug!("(build reduced graph for item) found extern `{}`", + self.module_to_string(&*external_module)); + self.check_for_conflicts_between_external_crates( + &**parent, + name.name, + view_item.span); + parent.external_module_children.borrow_mut() + .insert(name.name, external_module.clone()); + self.build_reduced_graph_for_external_crate(&external_module); + } + } + } + } + + /// Constructs the reduced graph for one foreign item. + fn build_reduced_graph_for_foreign_item(&mut self, + foreign_item: &ForeignItem, + parent: &Rc, + f: F) where + F: FnOnce(&mut Resolver), + { + let name = foreign_item.ident.name; + let is_public = foreign_item.vis == ast::Public; + let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE; + let name_bindings = + self.add_child(name, parent, ForbidDuplicateValues, + foreign_item.span); + + match foreign_item.node { + ForeignItemFn(_, ref generics) => { + let def = DefFn(local_def(foreign_item.id), false); + name_bindings.define_value(def, foreign_item.span, modifiers); + + self.with_type_parameter_rib( + HasTypeParameters(generics, + FnSpace, + foreign_item.id, + NormalRibKind), + f); + } + ForeignItemStatic(_, m) => { + let def = DefStatic(local_def(foreign_item.id), m); + name_bindings.define_value(def, foreign_item.span, modifiers); + + f(self.resolver) + } + } + } + + fn build_reduced_graph_for_block(&mut self, block: &Block, parent: &Rc) -> Rc { + if self.block_needs_anonymous_module(block) { + let block_id = block.id; + + debug!("(building reduced graph for block) creating a new \ + anonymous module for block {}", + block_id); + + let new_module = Rc::new(Module::new( + BlockParentLink(parent.downgrade(), block_id), + None, + AnonymousModuleKind, + false, + false)); + parent.anonymous_children.borrow_mut().insert(block_id, new_module.clone()); + new_module + } else { + parent.clone() + } + } + + fn handle_external_def(&mut self, + def: Def, + vis: Visibility, + child_name_bindings: &NameBindings, + final_ident: &str, + name: Name, + new_parent: &Rc) { + debug!("(building reduced graph for \ + external crate) building external def, priv {}", + vis); + let is_public = vis == ast::Public; + let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE; + let is_exported = is_public && match new_parent.def_id.get() { + None => true, + Some(did) => self.external_exports.contains(&did) + }; + if is_exported { + self.external_exports.insert(def.def_id()); + } + + let kind = match def { + DefTy(_, true) => EnumModuleKind, + DefStruct(..) | DefTy(..) => ImplModuleKind, + _ => NormalModuleKind + }; + + match def { + DefMod(def_id) | DefForeignMod(def_id) | DefStruct(def_id) | + DefTy(def_id, _) => { + let type_def = child_name_bindings.type_def.borrow().clone(); + match type_def { + Some(TypeNsDef { module_def: Some(module_def), .. }) => { + debug!("(building reduced graph for external crate) \ + already created module"); + module_def.def_id.set(Some(def_id)); + } + Some(_) | None => { + debug!("(building reduced graph for \ + external crate) building module \ + {}", final_ident); + let parent_link = self.get_parent_link(new_parent, name); + + child_name_bindings.define_module(parent_link, + Some(def_id), + kind, + true, + is_public, + DUMMY_SP); + } + } + } + _ => {} + } + + match def { + DefMod(_) | DefForeignMod(_) => {} + DefVariant(_, variant_id, is_struct) => { + debug!("(building reduced graph for external crate) building \ + variant {}", + final_ident); + // variants are always treated as importable to allow them to be + // glob used + let modifiers = PUBLIC | IMPORTABLE; + if is_struct { + child_name_bindings.define_type(def, DUMMY_SP, modifiers); + // Not adding fields for variants as they are not accessed with a self receiver + self.structs.insert(variant_id, Vec::new()); + } else { + child_name_bindings.define_value(def, DUMMY_SP, modifiers); + } + } + DefFn(ctor_id, true) => { + child_name_bindings.define_value( + csearch::get_tuple_struct_definition_if_ctor(&self.session.cstore, ctor_id) + .map_or(def, |_| DefStruct(ctor_id)), DUMMY_SP, modifiers); + } + DefFn(..) | DefStaticMethod(..) | DefStatic(..) | DefConst(..) | DefMethod(..) => { + debug!("(building reduced graph for external \ + crate) building value (fn/static) {}", final_ident); + // impl methods have already been defined with the correct importability modifier + let mut modifiers = match *child_name_bindings.value_def.borrow() { + Some(ref def) => (modifiers & !IMPORTABLE) | (def.modifiers & IMPORTABLE), + None => modifiers + }; + if new_parent.kind.get() != NormalModuleKind { + modifiers = modifiers & !IMPORTABLE; + } + child_name_bindings.define_value(def, DUMMY_SP, modifiers); + } + DefTrait(def_id) => { + debug!("(building reduced graph for external \ + crate) building type {}", final_ident); + + // If this is a trait, add all the trait item names to the trait + // info. + + let trait_item_def_ids = + csearch::get_trait_item_def_ids(&self.session.cstore, def_id); + for trait_item_def_id in trait_item_def_ids.iter() { + let (trait_item_name, trait_item_kind) = + csearch::get_trait_item_name_and_kind( + &self.session.cstore, + trait_item_def_id.def_id()); + + debug!("(building reduced graph for external crate) ... \ + adding trait item '{}'", + token::get_name(trait_item_name)); + + self.trait_item_map.insert((trait_item_name, def_id), trait_item_kind); + + if is_exported { + self.external_exports + .insert(trait_item_def_id.def_id()); + } + } + + child_name_bindings.define_type(def, DUMMY_SP, modifiers); + + // Define a module if necessary. + let parent_link = self.get_parent_link(new_parent, name); + child_name_bindings.set_module_kind(parent_link, + Some(def_id), + TraitModuleKind, + true, + is_public, + DUMMY_SP) + } + DefTy(..) | DefAssociatedTy(..) | DefAssociatedPath(..) => { + debug!("(building reduced graph for external \ + crate) building type {}", final_ident); + + child_name_bindings.define_type(def, DUMMY_SP, modifiers); + } + DefStruct(def_id) => { + debug!("(building reduced graph for external \ + crate) building type and value for {}", + final_ident); + child_name_bindings.define_type(def, DUMMY_SP, modifiers); + let fields = csearch::get_struct_fields(&self.session.cstore, def_id).iter().map(|f| { + f.name + }).collect::>(); + + if fields.len() == 0 { + child_name_bindings.define_value(def, DUMMY_SP, modifiers); + } + + // Record the def ID and fields of this struct. + self.structs.insert(def_id, fields); + } + DefLocal(..) | DefPrimTy(..) | DefTyParam(..) | + DefUse(..) | DefUpvar(..) | DefRegion(..) | + DefTyParamBinder(..) | DefLabel(..) | DefSelfTy(..) => { + panic!("didn't expect `{}`", def); + } + } + } + + /// Builds the reduced graph for a single item in an external crate. + fn build_reduced_graph_for_external_crate_def(&mut self, + root: &Rc, + def_like: DefLike, + name: Name, + visibility: Visibility) { + match def_like { + DlDef(def) => { + // Add the new child item, if necessary. + match def { + DefForeignMod(def_id) => { + // Foreign modules have no names. Recur and populate + // eagerly. + csearch::each_child_of_item(&self.session.cstore, + def_id, + |def_like, + child_name, + vis| { + self.build_reduced_graph_for_external_crate_def( + root, + def_like, + child_name, + vis) + }); + } + _ => { + let child_name_bindings = + self.add_child(name, + root, + OverwriteDuplicates, + DUMMY_SP); + + self.handle_external_def(def, + visibility, + &*child_name_bindings, + token::get_name(name).get(), + name, + root); + } + } + } + DlImpl(def) => { + match csearch::get_type_name_if_impl(&self.session.cstore, def) { + None => {} + Some(final_name) => { + let methods_opt = + csearch::get_methods_if_impl(&self.session.cstore, def); + match methods_opt { + Some(ref methods) if + methods.len() >= 1 => { + debug!("(building reduced graph for \ + external crate) processing \ + static methods for type name {}", + token::get_name(final_name)); + + let child_name_bindings = + self.add_child( + final_name, + root, + OverwriteDuplicates, + DUMMY_SP); + + // Process the static methods. First, + // create the module. + let type_module; + let type_def = child_name_bindings.type_def.borrow().clone(); + match type_def { + Some(TypeNsDef { + module_def: Some(module_def), + .. + }) => { + // We already have a module. This + // is OK. + type_module = module_def; + + // Mark it as an impl module if + // necessary. + type_module.kind.set(ImplModuleKind); + } + Some(_) | None => { + let parent_link = + self.get_parent_link(root, final_name); + child_name_bindings.define_module( + parent_link, + Some(def), + ImplModuleKind, + true, + true, + DUMMY_SP); + type_module = + child_name_bindings. + get_module(); + } + } + + // Add each static method to the module. + let new_parent = type_module; + for method_info in methods.iter() { + let name = method_info.name; + debug!("(building reduced graph for \ + external crate) creating \ + static method '{}'", + token::get_name(name)); + + let method_name_bindings = + self.add_child(name, + &new_parent, + OverwriteDuplicates, + DUMMY_SP); + let def = DefFn(method_info.def_id, false); + + // NB: not IMPORTABLE + let modifiers = if visibility == ast::Public { + PUBLIC + } else { + DefModifiers::empty() + }; + method_name_bindings.define_value( + def, DUMMY_SP, modifiers); + } + } + + // Otherwise, do nothing. + Some(_) | None => {} + } + } + } + } + DlField => { + debug!("(building reduced graph for external crate) \ + ignoring field"); + } + } + } + + /// Builds the reduced graph rooted at the given external module. + fn populate_external_module(&mut self, module: &Rc) { + debug!("(populating external module) attempting to populate {}", + self.module_to_string(&**module)); + + let def_id = match module.def_id.get() { + None => { + debug!("(populating external module) ... no def ID!"); + return + } + Some(def_id) => def_id, + }; + + csearch::each_child_of_item(&self.session.cstore, + def_id, + |def_like, child_name, visibility| { + debug!("(populating external module) ... found ident: {}", + token::get_name(child_name)); + self.build_reduced_graph_for_external_crate_def(module, + def_like, + child_name, + visibility) + }); + module.populated.set(true) + } + + /// Ensures that the reduced graph rooted at the given external module + /// is built, building it if it is not. + fn populate_module_if_necessary(&mut self, module: &Rc) { + if !module.populated.get() { + self.populate_external_module(module) + } + assert!(module.populated.get()) + } + + /// Builds the reduced graph rooted at the 'use' directive for an external + /// crate. + fn build_reduced_graph_for_external_crate(&mut self, root: &Rc) { + csearch::each_top_level_item_of_crate(&self.session.cstore, + root.def_id + .get() + .unwrap() + .krate, + |def_like, name, visibility| { + self.build_reduced_graph_for_external_crate_def(root, def_like, name, visibility) + }); + } + + /// Creates and adds an import directive to the given module. + fn build_import_directive(&mut self, + module_: &Module, + module_path: Vec, + subclass: ImportDirectiveSubclass, + span: Span, + id: NodeId, + is_public: bool, + shadowable: Shadowable) { + module_.imports.borrow_mut().push(ImportDirective::new(module_path, + subclass, + span, + id, + is_public, + shadowable)); + self.unresolved_imports += 1; + // Bump the reference count on the name. Or, if this is a glob, set + // the appropriate flag. + + match subclass { + SingleImport(target, _) => { + debug!("(building import directive) building import \ + directive: {}::{}", + self.names_to_string(module_.imports.borrow().last().unwrap() + .module_path[]), + token::get_name(target)); + + let mut import_resolutions = module_.import_resolutions + .borrow_mut(); + match import_resolutions.get_mut(&target) { + Some(resolution) => { + debug!("(building import directive) bumping \ + reference"); + resolution.outstanding_references += 1; + + // the source of this name is different now + resolution.type_id = id; + resolution.value_id = id; + resolution.is_public = is_public; + return; + } + None => {} + } + debug!("(building import directive) creating new"); + let mut resolution = ImportResolution::new(id, is_public); + resolution.outstanding_references = 1; + import_resolutions.insert(target, resolution); + } + GlobImport => { + // Set the glob flag. This tells us that we don't know the + // module's exports ahead of time. + + module_.glob_count.set(module_.glob_count.get() + 1); + } + } + } +} + +struct BuildReducedGraphVisitor<'a, 'b:'a, 'tcx:'b> { + builder: GraphBuilder<'a, 'b, 'tcx>, + parent: Rc +} + +impl<'a, 'b, 'v, 'tcx> Visitor<'v> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { + fn visit_item(&mut self, item: &Item) { + let p = self.builder.build_reduced_graph_for_item(item, &self.parent); + let old_parent = replace(&mut self.parent, p); + visit::walk_item(self, item); + self.parent = old_parent; + } + + fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) { + let parent = &self.parent; + self.builder.build_reduced_graph_for_foreign_item(foreign_item, + parent, + |r| { + let mut v = BuildReducedGraphVisitor { + builder: GraphBuilder { resolver: r }, + parent: parent.clone() + }; + visit::walk_foreign_item(&mut v, foreign_item); + }) + } + + fn visit_view_item(&mut self, view_item: &ViewItem) { + self.builder.build_reduced_graph_for_view_item(view_item, &self.parent); + } + + fn visit_block(&mut self, block: &Block) { + let np = self.builder.build_reduced_graph_for_block(block, &self.parent); + let old_parent = replace(&mut self.parent, np); + visit::walk_block(self, block); + self.parent = old_parent; + } +} + +pub fn build_reduced_graph(resolver: &mut Resolver, krate: &ast::Crate) { + GraphBuilder { + resolver: resolver + }.build_reduced_graph(krate); +} + +pub fn populate_module_if_necessary(resolver: &mut Resolver, module: &Rc) { + GraphBuilder { + resolver: resolver + }.populate_module_if_necessary(module); +} diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 52bd096eb83de..e371046a9b21d 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -26,11 +26,9 @@ extern crate rustc; use self::PatternBindingMode::*; use self::Namespace::*; -use self::NamespaceError::*; use self::NamespaceResult::*; use self::NameDefinition::*; use self::ImportDirectiveSubclass::*; -use self::ReducedGraphParent::*; use self::ResolveResult::*; use self::FallbackSuggestion::*; use self::TypeParameters::*; @@ -40,7 +38,6 @@ use self::UseLexicalScopeFlag::*; use self::ModulePrefixResult::*; use self::NameSearchType::*; use self::BareIdentifierPatternResolution::*; -use self::DuplicateCheckingMode::*; use self::ParentLink::*; use self::ModuleKind::*; use self::TraitReferenceType::*; @@ -60,34 +57,31 @@ use rustc::util::nodemap::{NodeMap, NodeSet, DefIdSet, FnvHashMap}; use rustc::util::lev_distance::lev_distance; use syntax::ast::{Arm, BindByRef, BindByValue, BindingMode, Block, Crate, CrateNum}; -use syntax::ast::{DeclItem, DefId, Expr, ExprAgain, ExprBreak, ExprField}; +use syntax::ast::{DefId, Expr, ExprAgain, ExprBreak, ExprField}; use syntax::ast::{ExprClosure, ExprForLoop, ExprLoop, ExprWhile, ExprMethodCall}; use syntax::ast::{ExprPath, ExprStruct, FnDecl}; -use syntax::ast::{ForeignItem, ForeignItemFn, ForeignItemStatic, Generics}; +use syntax::ast::{ForeignItemFn, ForeignItemStatic, Generics}; use syntax::ast::{Ident, ImplItem, Item, ItemConst, ItemEnum, ItemFn}; use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic}; use syntax::ast::{ItemStruct, ItemTrait, ItemTy, Local, LOCAL_CRATE}; -use syntax::ast::{MethodImplItem, Mod, Name, NamedField, NodeId}; +use syntax::ast::{MethodImplItem, Mod, Name, NodeId}; use syntax::ast::{Pat, PatEnum, PatIdent, PatLit}; -use syntax::ast::{PatRange, PatStruct, Path, PathListIdent, PathListMod}; -use syntax::ast::{PolyTraitRef, PrimTy, Public, SelfExplicit, SelfStatic}; -use syntax::ast::{RegionTyParamBound, StmtDecl, StructField}; -use syntax::ast::{StructVariantKind, TraitRef, TraitTyParamBound}; -use syntax::ast::{TupleVariantKind, Ty, TyBool, TyChar, TyClosure, TyF32}; +use syntax::ast::{PatRange, PatStruct, Path}; +use syntax::ast::{PolyTraitRef, PrimTy, SelfExplicit}; +use syntax::ast::{RegionTyParamBound, StructField}; +use syntax::ast::{TraitRef, TraitTyParamBound}; +use syntax::ast::{Ty, TyBool, TyChar, TyClosure, TyF32}; use syntax::ast::{TyF64, TyFloat, TyI, TyI8, TyI16, TyI32, TyI64, TyInt, TyObjectSum}; use syntax::ast::{TyParam, TyParamBound, TyPath, TyPtr, TyPolyTraitRef, TyQPath}; use syntax::ast::{TyRptr, TyStr, TyU, TyU8, TyU16, TyU32, TyU64, TyUint}; -use syntax::ast::{TypeImplItem, UnnamedField}; -use syntax::ast::{Variant, ViewItem, ViewItemExternCrate}; -use syntax::ast::{ViewItemUse, ViewPathGlob, ViewPathList, ViewPathSimple}; -use syntax::ast::{Visibility}; +use syntax::ast::{TypeImplItem}; use syntax::ast; use syntax::ast_map; -use syntax::ast_util::{mod, PostExpansionMethod, local_def, walk_pat}; +use syntax::ast_util::{PostExpansionMethod, local_def, walk_pat}; use syntax::attr::AttrMetaMethods; use syntax::ext::mtwt; use syntax::parse::token::{mod, special_names, special_idents}; -use syntax::codemap::{Span, DUMMY_SP, Pos}; +use syntax::codemap::{Span, Pos}; use syntax::owned_slice::OwnedSlice; use syntax::visit::{mod, Visitor}; @@ -100,6 +94,7 @@ use std::uint; mod check_unused; mod record_exports; +mod build_reduced_graph; #[deriving(Copy)] struct BindingInfo { @@ -123,14 +118,6 @@ enum Namespace { ValueNS } -#[deriving(Copy, PartialEq)] -enum NamespaceError { - NoError, - ModuleError, - TypeError, - ValueError -} - /// A NamespaceResult represents the result of resolving an import in /// a particular namespace. The result is either definitely-resolved, /// definitely- unresolved, or unknown. @@ -197,22 +184,6 @@ enum ImportDirectiveSubclass { GlobImport } -/// The context that we thread through while building the reduced graph. -#[deriving(Clone)] -enum ReducedGraphParent { - ModuleReducedGraphParent(Rc) -} - -impl ReducedGraphParent { - fn module(&self) -> Rc { - match *self { - ModuleReducedGraphParent(ref m) => { - m.clone() - } - } - } -} - type ErrorMessage = Option<(Span, String)>; enum ResolveResult { @@ -314,17 +285,6 @@ enum BareIdentifierPatternResolution { BareIdentifierPatternUnresolved } -// Specifies how duplicates should be handled when adding a child item if -// another item exists with the same name in some namespace. -#[deriving(Copy, PartialEq)] -enum DuplicateCheckingMode { - ForbidDuplicateModules, - ForbidDuplicateTypesAndModules, - ForbidDuplicateValues, - ForbidDuplicateTypesAndValues, - OverwriteDuplicates -} - /// One local scope. #[deriving(Show)] struct Rib { @@ -865,15 +825,6 @@ impl PrimitiveTypeTable { } } - -fn namespace_error_to_string(ns: NamespaceError) -> &'static str { - match ns { - NoError => "", - ModuleError | TypeError => "type or module", - ValueError => "value", - } -} - /// The main resolver class. struct Resolver<'a, 'tcx:'a> { session: &'a Session, @@ -939,46 +890,6 @@ struct Resolver<'a, 'tcx:'a> { used_crates: HashSet, } -struct BuildReducedGraphVisitor<'a, 'b:'a, 'tcx:'b> { - resolver: &'a mut Resolver<'b, 'tcx>, - parent: ReducedGraphParent -} - -impl<'a, 'b, 'v, 'tcx> Visitor<'v> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { - - fn visit_item(&mut self, item: &Item) { - let p = self.resolver.build_reduced_graph_for_item(item, self.parent.clone()); - let old_parent = replace(&mut self.parent, p); - visit::walk_item(self, item); - self.parent = old_parent; - } - - fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) { - let parent = self.parent.clone(); - self.resolver.build_reduced_graph_for_foreign_item(foreign_item, - parent.clone(), - |r| { - let mut v = BuildReducedGraphVisitor { - resolver: r, - parent: parent.clone() - }; - visit::walk_foreign_item(&mut v, foreign_item); - }) - } - - fn visit_view_item(&mut self, view_item: &ViewItem) { - self.resolver.build_reduced_graph_for_view_item(view_item, self.parent.clone()); - } - - fn visit_block(&mut self, block: &Block) { - let np = self.resolver.build_reduced_graph_for_block(block, self.parent.clone()); - let old_parent = replace(&mut self.parent, np); - visit::walk_block(self, block); - self.parent = old_parent; - } - -} - #[deriving(PartialEq)] enum FallbackChecks { Everything, @@ -1047,1191 +958,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - // - // Reduced graph building - // - // Here we build the "reduced graph": the graph of the module tree without - // any imports resolved. - // - - /// Constructs the reduced graph for the entire crate. - fn build_reduced_graph(&mut self, krate: &ast::Crate) { - let parent = ModuleReducedGraphParent(self.graph_root.get_module()); - let mut visitor = BuildReducedGraphVisitor { - resolver: self, - parent: parent - }; - visit::walk_crate(&mut visitor, krate); - } - - /// Adds a new child item to the module definition of the parent node and - /// returns its corresponding name bindings as well as the current parent. - /// Or, if we're inside a block, creates (or reuses) an anonymous module - /// corresponding to the innermost block ID and returns the name bindings - /// as well as the newly-created parent. - /// - /// # Panics - /// - /// Panics if this node does not have a module definition and we are not inside - /// a block. - fn add_child(&self, - name: Name, - reduced_graph_parent: ReducedGraphParent, - duplicate_checking_mode: DuplicateCheckingMode, - // For printing errors - sp: Span) - -> Rc { - // If this is the immediate descendant of a module, then we add the - // child name directly. Otherwise, we create or reuse an anonymous - // module and add the child to that. - - let module_ = reduced_graph_parent.module(); - - self.check_for_conflicts_between_external_crates_and_items(&*module_, - name, - sp); - - // Add or reuse the child. - let child = module_.children.borrow().get(&name).cloned(); - match child { - None => { - let child = Rc::new(NameBindings::new()); - module_.children.borrow_mut().insert(name, child.clone()); - child - } - Some(child) => { - // Enforce the duplicate checking mode: - // - // * If we're requesting duplicate module checking, check that - // there isn't a module in the module with the same name. - // - // * If we're requesting duplicate type checking, check that - // there isn't a type in the module with the same name. - // - // * If we're requesting duplicate value checking, check that - // there isn't a value in the module with the same name. - // - // * If we're requesting duplicate type checking and duplicate - // value checking, check that there isn't a duplicate type - // and a duplicate value with the same name. - // - // * If no duplicate checking was requested at all, do - // nothing. - - let mut duplicate_type = NoError; - let ns = match duplicate_checking_mode { - ForbidDuplicateModules => { - if child.get_module_if_available().is_some() { - duplicate_type = ModuleError; - } - Some(TypeNS) - } - ForbidDuplicateTypesAndModules => { - match child.def_for_namespace(TypeNS) { - None => {} - Some(_) if child.get_module_if_available() - .map(|m| m.kind.get()) == - Some(ImplModuleKind) => {} - Some(_) => duplicate_type = TypeError - } - Some(TypeNS) - } - ForbidDuplicateValues => { - if child.defined_in_namespace(ValueNS) { - duplicate_type = ValueError; - } - Some(ValueNS) - } - ForbidDuplicateTypesAndValues => { - let mut n = None; - match child.def_for_namespace(TypeNS) { - Some(DefMod(_)) | None => {} - Some(_) => { - n = Some(TypeNS); - duplicate_type = TypeError; - } - }; - if child.defined_in_namespace(ValueNS) { - duplicate_type = ValueError; - n = Some(ValueNS); - } - n - } - OverwriteDuplicates => None - }; - if duplicate_type != NoError { - // Return an error here by looking up the namespace that - // had the duplicate. - let ns = ns.unwrap(); - self.resolve_error(sp, - format!("duplicate definition of {} `{}`", - namespace_error_to_string(duplicate_type), - token::get_name(name))[]); - { - let r = child.span_for_namespace(ns); - for sp in r.iter() { - self.session.span_note(*sp, - format!("first definition of {} `{}` here", - namespace_error_to_string(duplicate_type), - token::get_name(name))[]); - } - } - } - child - } - } - } - - fn block_needs_anonymous_module(&mut self, block: &Block) -> bool { - // If the block has view items, we need an anonymous module. - if block.view_items.len() > 0 { - return true; - } - - // Check each statement. - for statement in block.stmts.iter() { - match statement.node { - StmtDecl(ref declaration, _) => { - match declaration.node { - DeclItem(_) => { - return true; - } - _ => { - // Keep searching. - } - } - } - _ => { - // Keep searching. - } - } - } - - // If we found neither view items nor items, we don't need to create - // an anonymous module. - - return false; - } - - fn get_parent_link(&mut self, parent: ReducedGraphParent, name: Name) - -> ParentLink { - match parent { - ModuleReducedGraphParent(module_) => { - return ModuleParentLink(module_.downgrade(), name); - } - } - } - - /// Constructs the reduced graph for one item. - fn build_reduced_graph_for_item(&mut self, - item: &Item, - parent: ReducedGraphParent) - -> ReducedGraphParent - { - let name = item.ident.name; - let sp = item.span; - let is_public = item.vis == ast::Public; - let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE; - - match item.node { - ItemMod(..) => { - let name_bindings = - self.add_child(name, parent.clone(), ForbidDuplicateModules, sp); - - let parent_link = self.get_parent_link(parent, name); - let def_id = DefId { krate: 0, node: item.id }; - name_bindings.define_module(parent_link, - Some(def_id), - NormalModuleKind, - false, - item.vis == ast::Public, - sp); - - ModuleReducedGraphParent(name_bindings.get_module()) - } - - ItemForeignMod(..) => parent, - - // These items live in the value namespace. - ItemStatic(_, m, _) => { - let name_bindings = - self.add_child(name, parent.clone(), ForbidDuplicateValues, sp); - let mutbl = m == ast::MutMutable; - - name_bindings.define_value - (DefStatic(local_def(item.id), mutbl), sp, modifiers); - parent - } - ItemConst(_, _) => { - self.add_child(name, parent.clone(), ForbidDuplicateValues, sp) - .define_value(DefConst(local_def(item.id)), - sp, modifiers); - parent - } - ItemFn(_, _, _, _, _) => { - let name_bindings = - self.add_child(name, parent.clone(), ForbidDuplicateValues, sp); - - let def = DefFn(local_def(item.id), false); - name_bindings.define_value(def, sp, modifiers); - parent - } - - // These items live in the type namespace. - ItemTy(..) => { - let name_bindings = - self.add_child(name, - parent.clone(), - ForbidDuplicateTypesAndModules, - sp); - - name_bindings.define_type - (DefTy(local_def(item.id), false), sp, modifiers); - parent - } - - ItemEnum(ref enum_definition, _) => { - let name_bindings = - self.add_child(name, - parent.clone(), - ForbidDuplicateTypesAndModules, - sp); - - name_bindings.define_type - (DefTy(local_def(item.id), true), sp, modifiers); - - let parent_link = self.get_parent_link(parent.clone(), name); - // We want to make sure the module type is EnumModuleKind - // even if there's already an ImplModuleKind module defined, - // since that's how we prevent duplicate enum definitions - name_bindings.set_module_kind(parent_link, - Some(local_def(item.id)), - EnumModuleKind, - false, - is_public, - sp); - - for variant in (*enum_definition).variants.iter() { - self.build_reduced_graph_for_variant( - &**variant, - local_def(item.id), - ModuleReducedGraphParent(name_bindings.get_module())); - } - parent - } - - // These items live in both the type and value namespaces. - ItemStruct(ref struct_def, _) => { - // Adding to both Type and Value namespaces or just Type? - let (forbid, ctor_id) = match struct_def.ctor_id { - Some(ctor_id) => (ForbidDuplicateTypesAndValues, Some(ctor_id)), - None => (ForbidDuplicateTypesAndModules, None) - }; - - let name_bindings = self.add_child(name, parent.clone(), forbid, sp); - - // Define a name in the type namespace. - name_bindings.define_type(DefTy(local_def(item.id), false), sp, modifiers); - - // If this is a newtype or unit-like struct, define a name - // in the value namespace as well - match ctor_id { - Some(cid) => { - name_bindings.define_value(DefStruct(local_def(cid)), - sp, modifiers); - } - None => {} - } - - // Record the def ID and fields of this struct. - let named_fields = struct_def.fields.iter().filter_map(|f| { - match f.node.kind { - NamedField(ident, _) => Some(ident.name), - UnnamedField(_) => None - } - }).collect(); - self.structs.insert(local_def(item.id), named_fields); - - parent - } - - ItemImpl(_, _, None, ref ty, ref impl_items) => { - // If this implements an anonymous trait, then add all the - // methods within to a new module, if the type was defined - // within this module. - - let mod_name = match ty.node { - TyPath(ref path, _) if path.segments.len() == 1 => { - // FIXME(18446) we should distinguish between the name of - // a trait and the name of an impl of that trait. - Some(path.segments.last().unwrap().identifier.name) - } - TyObjectSum(ref lhs_ty, _) => { - match lhs_ty.node { - TyPath(ref path, _) if path.segments.len() == 1 => { - Some(path.segments.last().unwrap().identifier.name) - } - _ => { - None - } - } - } - _ => { - None - } - }; - - match mod_name { - None => { - self.resolve_error(ty.span, - "inherent implementations may \ - only be implemented in the same \ - module as the type they are \ - implemented for") - } - Some(mod_name) => { - // Create the module and add all methods. - let parent_opt = parent.module().children.borrow() - .get(&mod_name).cloned(); - let new_parent = match parent_opt { - // It already exists - Some(ref child) if child.get_module_if_available() - .is_some() && - (child.get_module().kind.get() == ImplModuleKind || - child.get_module().kind.get() == TraitModuleKind) => { - ModuleReducedGraphParent(child.get_module()) - } - Some(ref child) if child.get_module_if_available() - .is_some() && - child.get_module().kind.get() == - EnumModuleKind => { - ModuleReducedGraphParent(child.get_module()) - } - // Create the module - _ => { - let name_bindings = - self.add_child(mod_name, - parent.clone(), - ForbidDuplicateModules, - sp); - - let parent_link = - self.get_parent_link(parent.clone(), name); - let def_id = local_def(item.id); - let ns = TypeNS; - let is_public = - !name_bindings.defined_in_namespace(ns) || - name_bindings.defined_in_public_namespace(ns); - - name_bindings.define_module(parent_link, - Some(def_id), - ImplModuleKind, - false, - is_public, - sp); - - ModuleReducedGraphParent( - name_bindings.get_module()) - } - }; - - // For each implementation item... - for impl_item in impl_items.iter() { - match *impl_item { - MethodImplItem(ref method) => { - // Add the method to the module. - let name = method.pe_ident().name; - let method_name_bindings = - self.add_child(name, - new_parent.clone(), - ForbidDuplicateValues, - method.span); - let def = match method.pe_explicit_self() - .node { - SelfStatic => { - // Static methods become - // `DefStaticMethod`s. - DefStaticMethod(local_def(method.id), - FromImpl(local_def(item.id))) - } - _ => { - // Non-static methods become - // `DefMethod`s. - DefMethod(local_def(method.id), - None, - FromImpl(local_def(item.id))) - } - }; - - // NB: not IMPORTABLE - let modifiers = if method.pe_vis() == ast::Public { - PUBLIC - } else { - DefModifiers::empty() - }; - method_name_bindings.define_value( - def, - method.span, - modifiers); - } - TypeImplItem(ref typedef) => { - // Add the typedef to the module. - let name = typedef.ident.name; - let typedef_name_bindings = - self.add_child( - name, - new_parent.clone(), - ForbidDuplicateTypesAndModules, - typedef.span); - let def = DefAssociatedTy(local_def( - typedef.id)); - // NB: not IMPORTABLE - let modifiers = if typedef.vis == ast::Public { - PUBLIC - } else { - DefModifiers::empty() - }; - typedef_name_bindings.define_type( - def, - typedef.span, - modifiers); - } - } - } - } - } - - parent - } - - ItemImpl(_, _, Some(_), _, _) => parent, - - ItemTrait(_, _, _, ref items) => { - let name_bindings = - self.add_child(name, - parent.clone(), - ForbidDuplicateTypesAndModules, - sp); - - // Add all the items within to a new module. - let parent_link = self.get_parent_link(parent.clone(), name); - name_bindings.define_module(parent_link, - Some(local_def(item.id)), - TraitModuleKind, - false, - item.vis == ast::Public, - sp); - let module_parent = ModuleReducedGraphParent(name_bindings. - get_module()); - - let def_id = local_def(item.id); - - // Add the names of all the items to the trait info. - for trait_item in items.iter() { - let (name, kind) = match *trait_item { - ast::RequiredMethod(_) | - ast::ProvidedMethod(_) => { - let ty_m = ast_util::trait_item_to_ty_method(trait_item); - - let name = ty_m.ident.name; - - // Add it as a name in the trait module. - let (def, static_flag) = match ty_m.explicit_self - .node { - SelfStatic => { - // Static methods become `DefStaticMethod`s. - (DefStaticMethod( - local_def(ty_m.id), - FromTrait(local_def(item.id))), - StaticMethodTraitItemKind) - } - _ => { - // Non-static methods become `DefMethod`s. - (DefMethod(local_def(ty_m.id), - Some(local_def(item.id)), - FromTrait(local_def(item.id))), - NonstaticMethodTraitItemKind) - } - }; - - let method_name_bindings = - self.add_child(name, - module_parent.clone(), - ForbidDuplicateTypesAndValues, - ty_m.span); - // NB: not IMPORTABLE - method_name_bindings.define_value(def, - ty_m.span, - PUBLIC); - - (name, static_flag) - } - ast::TypeTraitItem(ref associated_type) => { - let def = DefAssociatedTy(local_def( - associated_type.ty_param.id)); - - let name_bindings = - self.add_child(associated_type.ty_param.ident.name, - module_parent.clone(), - ForbidDuplicateTypesAndValues, - associated_type.ty_param.span); - // NB: not IMPORTABLE - name_bindings.define_type(def, - associated_type.ty_param.span, - PUBLIC); - - (associated_type.ty_param.ident.name, TypeTraitItemKind) - } - }; - - self.trait_item_map.insert((name, def_id), kind); - } - - name_bindings.define_type(DefTrait(def_id), sp, modifiers); - parent - } - ItemMac(..) => parent - } - } - - // Constructs the reduced graph for one variant. Variants exist in the - // type and value namespaces. - fn build_reduced_graph_for_variant(&mut self, - variant: &Variant, - item_id: DefId, - parent: ReducedGraphParent) { - let name = variant.node.name.name; - let is_exported = match variant.node.kind { - TupleVariantKind(_) => false, - StructVariantKind(_) => { - // Not adding fields for variants as they are not accessed with a self receiver - self.structs.insert(local_def(variant.node.id), Vec::new()); - true - } - }; - - let child = self.add_child(name, parent, - ForbidDuplicateTypesAndValues, - variant.span); - // variants are always treated as importable to allow them to be glob - // used - child.define_value(DefVariant(item_id, - local_def(variant.node.id), is_exported), - variant.span, PUBLIC | IMPORTABLE); - child.define_type(DefVariant(item_id, - local_def(variant.node.id), is_exported), - variant.span, PUBLIC | IMPORTABLE); - } - - /// Constructs the reduced graph for one 'view item'. View items consist - /// of imports and use directives. - fn build_reduced_graph_for_view_item(&mut self, view_item: &ViewItem, - parent: ReducedGraphParent) { - match view_item.node { - ViewItemUse(ref view_path) => { - // Extract and intern the module part of the path. For - // globs and lists, the path is found directly in the AST; - // for simple paths we have to munge the path a little. - let module_path = match view_path.node { - ViewPathSimple(_, ref full_path, _) => { - full_path.segments - .init() - .iter().map(|ident| ident.identifier.name) - .collect() - } - - ViewPathGlob(ref module_ident_path, _) | - ViewPathList(ref module_ident_path, _, _) => { - module_ident_path.segments - .iter().map(|ident| ident.identifier.name).collect() - } - }; - - // Build up the import directives. - let module_ = parent.module(); - let is_public = view_item.vis == ast::Public; - let shadowable = - view_item.attrs - .iter() - .any(|attr| { - attr.name() == token::get_name( - special_idents::prelude_import.name) - }); - let shadowable = if shadowable { - Shadowable::Always - } else { - Shadowable::Never - }; - - match view_path.node { - ViewPathSimple(binding, ref full_path, id) => { - let source_name = - full_path.segments.last().unwrap().identifier.name; - if token::get_name(source_name).get() == "mod" { - self.resolve_error(view_path.span, - "`mod` imports are only allowed within a { } list"); - } - - let subclass = SingleImport(binding.name, - source_name); - self.build_import_directive(&*module_, - module_path, - subclass, - view_path.span, - id, - is_public, - shadowable); - } - ViewPathList(_, ref source_items, _) => { - // Make sure there's at most one `mod` import in the list. - let mod_spans = source_items.iter().filter_map(|item| match item.node { - PathListMod { .. } => Some(item.span), - _ => None - }).collect::>(); - if mod_spans.len() > 1 { - self.resolve_error(mod_spans[0], - "`mod` import can only appear once in the list"); - for other_span in mod_spans.iter().skip(1) { - self.session.span_note(*other_span, - "another `mod` import appears here"); - } - } - - for source_item in source_items.iter() { - let (module_path, name) = match source_item.node { - PathListIdent { name, .. } => - (module_path.clone(), name.name), - PathListMod { .. } => { - let name = match module_path.last() { - Some(name) => *name, - None => { - self.resolve_error(source_item.span, - "`mod` import can only appear in an import list \ - with a non-empty prefix"); - continue; - } - }; - let module_path = module_path.init(); - (module_path.to_vec(), name) - } - }; - self.build_import_directive( - &*module_, - module_path, - SingleImport(name, name), - source_item.span, - source_item.node.id(), - is_public, - shadowable); - } - } - ViewPathGlob(_, id) => { - self.build_import_directive(&*module_, - module_path, - GlobImport, - view_path.span, - id, - is_public, - shadowable); - } - } - } - - ViewItemExternCrate(name, _, node_id) => { - // n.b. we don't need to look at the path option here, because cstore already did - for &crate_id in self.session.cstore - .find_extern_mod_stmt_cnum(node_id).iter() { - let def_id = DefId { krate: crate_id, node: 0 }; - self.external_exports.insert(def_id); - let parent_link = - ModuleParentLink(parent.module().downgrade(), name.name); - let external_module = Rc::new(Module::new(parent_link, - Some(def_id), - NormalModuleKind, - false, - true)); - debug!("(build reduced graph for item) found extern `{}`", - self.module_to_string(&*external_module)); - self.check_for_conflicts_between_external_crates( - &*parent.module(), - name.name, - view_item.span); - parent.module().external_module_children.borrow_mut() - .insert(name.name, external_module.clone()); - self.build_reduced_graph_for_external_crate(external_module); - } - } - } - } - - /// Constructs the reduced graph for one foreign item. - fn build_reduced_graph_for_foreign_item(&mut self, - foreign_item: &ForeignItem, - parent: ReducedGraphParent, - f: F) where - F: FnOnce(&mut Resolver), - { - let name = foreign_item.ident.name; - let is_public = foreign_item.vis == ast::Public; - let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE; - let name_bindings = - self.add_child(name, parent, ForbidDuplicateValues, - foreign_item.span); - - match foreign_item.node { - ForeignItemFn(_, ref generics) => { - let def = DefFn(local_def(foreign_item.id), false); - name_bindings.define_value(def, foreign_item.span, modifiers); - - self.with_type_parameter_rib( - HasTypeParameters(generics, - FnSpace, - foreign_item.id, - NormalRibKind), - f); - } - ForeignItemStatic(_, m) => { - let def = DefStatic(local_def(foreign_item.id), m); - name_bindings.define_value(def, foreign_item.span, modifiers); - - f(self) - } - } - } - - fn build_reduced_graph_for_block(&mut self, - block: &Block, - parent: ReducedGraphParent) - -> ReducedGraphParent - { - if self.block_needs_anonymous_module(block) { - let block_id = block.id; - - debug!("(building reduced graph for block) creating a new \ - anonymous module for block {}", - block_id); - - let parent_module = parent.module(); - let new_module = Rc::new(Module::new( - BlockParentLink(parent_module.downgrade(), block_id), - None, - AnonymousModuleKind, - false, - false)); - parent_module.anonymous_children.borrow_mut() - .insert(block_id, new_module.clone()); - ModuleReducedGraphParent(new_module) - } else { - parent - } - } - - fn handle_external_def(&mut self, - def: Def, - vis: Visibility, - child_name_bindings: &NameBindings, - final_ident: &str, - name: Name, - new_parent: ReducedGraphParent) { - debug!("(building reduced graph for \ - external crate) building external def, priv {}", - vis); - let is_public = vis == ast::Public; - let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE; - let is_exported = is_public && match new_parent { - ModuleReducedGraphParent(ref module) => { - match module.def_id.get() { - None => true, - Some(did) => self.external_exports.contains(&did) - } - } - }; - if is_exported { - self.external_exports.insert(def.def_id()); - } - - let kind = match def { - DefTy(_, true) => EnumModuleKind, - DefStruct(..) | DefTy(..) => ImplModuleKind, - _ => NormalModuleKind - }; - - match def { - DefMod(def_id) | DefForeignMod(def_id) | DefStruct(def_id) | - DefTy(def_id, _) => { - let type_def = child_name_bindings.type_def.borrow().clone(); - match type_def { - Some(TypeNsDef { module_def: Some(module_def), .. }) => { - debug!("(building reduced graph for external crate) \ - already created module"); - module_def.def_id.set(Some(def_id)); - } - Some(_) | None => { - debug!("(building reduced graph for \ - external crate) building module \ - {}", final_ident); - let parent_link = self.get_parent_link(new_parent.clone(), name); - - child_name_bindings.define_module(parent_link, - Some(def_id), - kind, - true, - is_public, - DUMMY_SP); - } - } - } - _ => {} - } - - match def { - DefMod(_) | DefForeignMod(_) => {} - DefVariant(_, variant_id, is_struct) => { - debug!("(building reduced graph for external crate) building \ - variant {}", - final_ident); - // variants are always treated as importable to allow them to be - // glob used - let modifiers = PUBLIC | IMPORTABLE; - if is_struct { - child_name_bindings.define_type(def, DUMMY_SP, modifiers); - // Not adding fields for variants as they are not accessed with a self receiver - self.structs.insert(variant_id, Vec::new()); - } else { - child_name_bindings.define_value(def, DUMMY_SP, modifiers); - } - } - DefFn(ctor_id, true) => { - child_name_bindings.define_value( - csearch::get_tuple_struct_definition_if_ctor(&self.session.cstore, ctor_id) - .map_or(def, |_| DefStruct(ctor_id)), DUMMY_SP, modifiers); - } - DefFn(..) | DefStaticMethod(..) | DefStatic(..) | DefConst(..) | DefMethod(..) => { - debug!("(building reduced graph for external \ - crate) building value (fn/static) {}", final_ident); - // impl methods have already been defined with the correct importability modifier - let mut modifiers = match *child_name_bindings.value_def.borrow() { - Some(ref def) => (modifiers & !IMPORTABLE) | (def.modifiers & IMPORTABLE), - None => modifiers - }; - if new_parent.module().kind.get() != NormalModuleKind { - modifiers = modifiers & !IMPORTABLE; - } - child_name_bindings.define_value(def, DUMMY_SP, modifiers); - } - DefTrait(def_id) => { - debug!("(building reduced graph for external \ - crate) building type {}", final_ident); - - // If this is a trait, add all the trait item names to the trait - // info. - - let trait_item_def_ids = - csearch::get_trait_item_def_ids(&self.session.cstore, def_id); - for trait_item_def_id in trait_item_def_ids.iter() { - let (trait_item_name, trait_item_kind) = - csearch::get_trait_item_name_and_kind( - &self.session.cstore, - trait_item_def_id.def_id()); - - debug!("(building reduced graph for external crate) ... \ - adding trait item '{}'", - token::get_name(trait_item_name)); - - self.trait_item_map.insert((trait_item_name, def_id), trait_item_kind); - - if is_exported { - self.external_exports - .insert(trait_item_def_id.def_id()); - } - } - - child_name_bindings.define_type(def, DUMMY_SP, modifiers); - - // Define a module if necessary. - let parent_link = self.get_parent_link(new_parent, name); - child_name_bindings.set_module_kind(parent_link, - Some(def_id), - TraitModuleKind, - true, - is_public, - DUMMY_SP) - } - DefTy(..) | DefAssociatedTy(..) | DefAssociatedPath(..) => { - debug!("(building reduced graph for external \ - crate) building type {}", final_ident); - - child_name_bindings.define_type(def, DUMMY_SP, modifiers); - } - DefStruct(def_id) => { - debug!("(building reduced graph for external \ - crate) building type and value for {}", - final_ident); - child_name_bindings.define_type(def, DUMMY_SP, modifiers); - let fields = csearch::get_struct_fields(&self.session.cstore, def_id).iter().map(|f| { - f.name - }).collect::>(); - - if fields.len() == 0 { - child_name_bindings.define_value(def, DUMMY_SP, modifiers); - } - - // Record the def ID and fields of this struct. - self.structs.insert(def_id, fields); - } - DefLocal(..) | DefPrimTy(..) | DefTyParam(..) | - DefUse(..) | DefUpvar(..) | DefRegion(..) | - DefTyParamBinder(..) | DefLabel(..) | DefSelfTy(..) => { - panic!("didn't expect `{}`", def); - } - } - } - - /// Builds the reduced graph for a single item in an external crate. - fn build_reduced_graph_for_external_crate_def(&mut self, - root: Rc, - def_like: DefLike, - name: Name, - visibility: Visibility) { - match def_like { - DlDef(def) => { - // Add the new child item, if necessary. - match def { - DefForeignMod(def_id) => { - // Foreign modules have no names. Recur and populate - // eagerly. - csearch::each_child_of_item(&self.session.cstore, - def_id, - |def_like, - child_name, - vis| { - self.build_reduced_graph_for_external_crate_def( - root.clone(), - def_like, - child_name, - vis) - }); - } - _ => { - let child_name_bindings = - self.add_child(name, - ModuleReducedGraphParent(root.clone()), - OverwriteDuplicates, - DUMMY_SP); - - self.handle_external_def(def, - visibility, - &*child_name_bindings, - token::get_name(name).get(), - name, - ModuleReducedGraphParent(root)); - } - } - } - DlImpl(def) => { - match csearch::get_type_name_if_impl(&self.session.cstore, def) { - None => {} - Some(final_name) => { - let methods_opt = - csearch::get_methods_if_impl(&self.session.cstore, def); - match methods_opt { - Some(ref methods) if - methods.len() >= 1 => { - debug!("(building reduced graph for \ - external crate) processing \ - static methods for type name {}", - token::get_name(final_name)); - - let child_name_bindings = - self.add_child( - final_name, - ModuleReducedGraphParent(root.clone()), - OverwriteDuplicates, - DUMMY_SP); - - // Process the static methods. First, - // create the module. - let type_module; - let type_def = child_name_bindings.type_def.borrow().clone(); - match type_def { - Some(TypeNsDef { - module_def: Some(module_def), - .. - }) => { - // We already have a module. This - // is OK. - type_module = module_def; - - // Mark it as an impl module if - // necessary. - type_module.kind.set(ImplModuleKind); - } - Some(_) | None => { - let parent_link = - self.get_parent_link(ModuleReducedGraphParent(root), - final_name); - child_name_bindings.define_module( - parent_link, - Some(def), - ImplModuleKind, - true, - true, - DUMMY_SP); - type_module = - child_name_bindings. - get_module(); - } - } - - // Add each static method to the module. - let new_parent = - ModuleReducedGraphParent(type_module); - for method_info in methods.iter() { - let name = method_info.name; - debug!("(building reduced graph for \ - external crate) creating \ - static method '{}'", - token::get_name(name)); - - let method_name_bindings = - self.add_child(name, - new_parent.clone(), - OverwriteDuplicates, - DUMMY_SP); - let def = DefFn(method_info.def_id, false); - - // NB: not IMPORTABLE - let modifiers = if visibility == ast::Public { - PUBLIC - } else { - DefModifiers::empty() - }; - method_name_bindings.define_value( - def, DUMMY_SP, modifiers); - } - } - - // Otherwise, do nothing. - Some(_) | None => {} - } - } - } - } - DlField => { - debug!("(building reduced graph for external crate) \ - ignoring field"); - } - } - } - - /// Builds the reduced graph rooted at the given external module. - fn populate_external_module(&mut self, module: Rc) { - debug!("(populating external module) attempting to populate {}", - self.module_to_string(&*module)); - - let def_id = match module.def_id.get() { - None => { - debug!("(populating external module) ... no def ID!"); - return - } - Some(def_id) => def_id, - }; - - csearch::each_child_of_item(&self.session.cstore, - def_id, - |def_like, child_name, visibility| { - debug!("(populating external module) ... found ident: {}", - token::get_name(child_name)); - self.build_reduced_graph_for_external_crate_def(module.clone(), - def_like, - child_name, - visibility) - }); - module.populated.set(true) - } - - /// Ensures that the reduced graph rooted at the given external module - /// is built, building it if it is not. - fn populate_module_if_necessary(&mut self, module: &Rc) { - if !module.populated.get() { - self.populate_external_module(module.clone()) - } - assert!(module.populated.get()) - } - - /// Builds the reduced graph rooted at the 'use' directive for an external - /// crate. - fn build_reduced_graph_for_external_crate(&mut self, root: Rc) { - csearch::each_top_level_item_of_crate(&self.session.cstore, - root.def_id - .get() - .unwrap() - .krate, - |def_like, name, visibility| { - self.build_reduced_graph_for_external_crate_def(root.clone(), - def_like, - name, - visibility) - }); - } - - /// Creates and adds an import directive to the given module. - fn build_import_directive(&mut self, - module_: &Module, - module_path: Vec, - subclass: ImportDirectiveSubclass, - span: Span, - id: NodeId, - is_public: bool, - shadowable: Shadowable) { - module_.imports.borrow_mut().push(ImportDirective::new(module_path, - subclass, - span, - id, - is_public, - shadowable)); - self.unresolved_imports += 1; - // Bump the reference count on the name. Or, if this is a glob, set - // the appropriate flag. - - match subclass { - SingleImport(target, _) => { - debug!("(building import directive) building import \ - directive: {}::{}", - self.names_to_string(module_.imports.borrow().last().unwrap() - .module_path[]), - token::get_name(target)); - - let mut import_resolutions = module_.import_resolutions - .borrow_mut(); - match import_resolutions.get_mut(&target) { - Some(resolution) => { - debug!("(building import directive) bumping \ - reference"); - resolution.outstanding_references += 1; - - // the source of this name is different now - resolution.type_id = id; - resolution.value_id = id; - resolution.is_public = is_public; - return; - } - None => {} - } - debug!("(building import directive) creating new"); - let mut resolution = ImportResolution::new(id, is_public); - resolution.outstanding_references = 1; - import_resolutions.insert(target, resolution); - } - GlobImport => { - // Set the glob flag. This tells us that we don't know the - // module's exports ahead of time. - - module_.glob_count.set(module_.glob_count.get() + 1); - } - } - } - // Import resolution // // This is a fixed-point algorithm. We resolve imports until our efforts @@ -2276,7 +1002,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.resolve_imports_for_module(module_.clone()); self.current_module = orig_module; - self.populate_module_if_necessary(&module_); + build_reduced_graph::populate_module_if_necessary(self, &module_); for (_, child_node) in module_.children.borrow().iter() { match child_node.get_module_if_available() { None => { @@ -2542,7 +1268,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let mut type_result = UnknownResult; // Search for direct children of the containing module. - self.populate_module_if_necessary(&containing_module); + build_reduced_graph::populate_module_if_necessary(self, &containing_module); match containing_module.children.borrow().get(&source) { None => { @@ -2902,7 +1628,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } // Add all children from the containing module. - self.populate_module_if_necessary(&containing_module); + build_reduced_graph::populate_module_if_necessary(self, &containing_module); for (&name, name_bindings) in containing_module.children.borrow().iter() { self.merge_import_resolution(module_, @@ -3422,7 +2148,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // The current module node is handled specially. First, check for // its immediate children. - self.populate_module_if_necessary(&module_); + build_reduced_graph::populate_module_if_necessary(self, &module_); match module_.children.borrow().get(&name) { Some(name_bindings) @@ -3687,7 +2413,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.module_to_string(&*module_)); // First, check the direct children of the module. - self.populate_module_if_necessary(&module_); + build_reduced_graph::populate_module_if_necessary(self, &module_); match module_.children.borrow().get(&name) { Some(name_bindings) @@ -3783,7 +2509,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } // Descend into children and anonymous children. - self.populate_module_if_necessary(&module_); + build_reduced_graph::populate_module_if_necessary(self, &module_); for (_, child_node) in module_.children.borrow().iter() { match child_node.get_module_if_available() { @@ -3830,7 +2556,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Nothing to do. } Some(name) => { - self.populate_module_if_necessary(&orig_module); + build_reduced_graph::populate_module_if_necessary(self, &orig_module); match orig_module.children.borrow().get(&name) { None => { @@ -4828,9 +3554,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Some(def) => { debug!("(resolving type) resolved `{}` to \ type {}", - token::get_ident(path.segments - .last().unwrap() - .identifier), + token::get_ident(path.segments.last().unwrap() .identifier), def); result_def = Some(def); } @@ -5021,19 +3745,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.resolve_error(path.span, format!("`{}` is not an enum variant, struct or const", token::get_ident( - path.segments - .last() - .unwrap() - .identifier))[]); + path.segments.last().unwrap().identifier))[]); } None => { self.resolve_error(path.span, format!("unresolved enum variant, struct or const `{}`", token::get_ident( - path.segments - .last() - .unwrap() - .identifier))[]); + path.segments.last().unwrap().identifier))[]); } } @@ -5187,9 +3905,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Try to find a path to an item in a module. let unqualified_def = - self.resolve_identifier(path.segments - .last().unwrap() - .identifier, + self.resolve_identifier(path.segments.last().unwrap().identifier, namespace, check_ribs, path.span); @@ -5243,7 +3959,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { namespace: Namespace) -> NameDefinition { // First, search children. - self.populate_module_if_necessary(&containing_module); + build_reduced_graph::populate_module_if_necessary(self, &containing_module); match containing_module.children.borrow().get(&name) { Some(child_name_bindings) => { @@ -5931,7 +4647,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } // Look for trait children. - self.populate_module_if_necessary(&search_module); + build_reduced_graph::populate_module_if_necessary(self, &search_module); { for (_, child_names) in search_module.children.borrow().iter() { @@ -6059,7 +4775,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { debug!("Dump of module `{}`:", self.module_to_string(&*module_)); debug!("Children:"); - self.populate_module_if_necessary(&module_); + build_reduced_graph::populate_module_if_necessary(self, &module_); for (&name, _) in module_.children.borrow().iter() { debug!("* {}", token::get_name(name)); } @@ -6116,7 +4832,7 @@ pub fn resolve_crate<'a, 'tcx>(session: &'a Session, -> CrateMap { let mut resolver = Resolver::new(session, ast_map, krate.span, make_glob_map); - resolver.build_reduced_graph(krate); + build_reduced_graph::build_reduced_graph(&mut resolver, krate); session.abort_if_errors(); resolver.resolve_imports(); diff --git a/src/librustc_resolve/record_exports.rs b/src/librustc_resolve/record_exports.rs index 80659152f9fc7..9c2437c376ddd 100644 --- a/src/librustc_resolve/record_exports.rs +++ b/src/librustc_resolve/record_exports.rs @@ -21,6 +21,8 @@ use {Module, NameBindings, Resolver}; use Namespace::{mod, TypeNS, ValueNS}; +use build_reduced_graph; + use rustc::middle::def::Export; use syntax::ast; use syntax::parse::token; @@ -73,7 +75,7 @@ impl<'a, 'b, 'tcx> ExportRecorder<'a, 'b, 'tcx> { } self.record_exports_for_module(&*module_); - self.populate_module_if_necessary(&module_); + build_reduced_graph::populate_module_if_necessary(self.resolver, &module_); for (_, child_name_bindings) in module_.children.borrow().iter() { match child_name_bindings.get_module_if_available() { diff --git a/src/librustc_trans/trans/_match.rs b/src/librustc_trans/trans/_match.rs index 0e37cd0f3b8d6..c6e4ce9457b53 100644 --- a/src/librustc_trans/trans/_match.rs +++ b/src/librustc_trans/trans/_match.rs @@ -606,9 +606,9 @@ fn extract_variant_args<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, val: ValueRef) -> ExtractedBlock<'blk, 'tcx> { let _icx = push_ctxt("match::extract_variant_args"); - let args = Vec::from_fn(adt::num_args(repr, disr_val), |i| { + let args = range(0, adt::num_args(repr, disr_val)).map(|i| { adt::trans_field_ptr(bcx, repr, val, disr_val, i) - }); + }).collect(); ExtractedBlock { vals: args, bcx: bcx } } diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index c5d3ad805d934..fb4ae21478bc2 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -55,7 +55,7 @@ use trans::cleanup::CleanupMethods; use trans::cleanup; use trans::closure; use trans::common::{Block, C_bool, C_bytes_in_context, C_i32, C_integral}; -use trans::common::{C_null, C_struct_in_context, C_u64, C_u8, C_uint, C_undef}; +use trans::common::{C_null, C_struct_in_context, C_u64, C_u8, C_undef}; use trans::common::{CrateContext, ExternMap, FunctionContext}; use trans::common::{NodeInfo, Result}; use trans::common::{node_id_type, return_type_is_void}; @@ -73,7 +73,7 @@ use trans::glue; use trans::inline; use trans::intrinsic; use trans::machine; -use trans::machine::{llsize_of, llsize_of_real, llalign_of_min}; +use trans::machine::{llsize_of, llsize_of_real}; use trans::meth; use trans::monomorphize; use trans::tvec; @@ -396,30 +396,6 @@ pub fn malloc_raw_dyn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, Result::new(r.bcx, PointerCast(r.bcx, r.val, llty_ptr)) } -pub fn malloc_raw_dyn_proc<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t: Ty<'tcx>) - -> Result<'blk, 'tcx> { - let _icx = push_ctxt("malloc_raw_dyn_proc"); - let ccx = bcx.ccx(); - - // Grab the TypeRef type of ptr_ty. - let ptr_ty = ty::mk_uniq(bcx.tcx(), t); - let ptr_llty = type_of(ccx, ptr_ty); - - let llty = type_of(bcx.ccx(), t); - let size = llsize_of(bcx.ccx(), llty); - let llalign = C_uint(ccx, llalign_of_min(bcx.ccx(), llty)); - - // Allocate space and store the destructor pointer: - let Result {bcx, val: llbox} = malloc_raw_dyn(bcx, ptr_llty, t, size, llalign); - let dtor_ptr = GEPi(bcx, llbox, &[0u, abi::BOX_FIELD_DROP_GLUE]); - let drop_glue_field_ty = type_of(ccx, ty::mk_nil_ptr(bcx.tcx())); - let drop_glue = PointerCast(bcx, glue::get_drop_glue(ccx, ty::mk_uniq(bcx.tcx(), t)), - drop_glue_field_ty); - Store(bcx, drop_glue, dtor_ptr); - - Result::new(bcx, llbox) -} - // Type descriptor and type glue stuff pub fn get_tydesc<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, @@ -2676,6 +2652,8 @@ pub fn create_entry_wrapper(ccx: &CrateContext, unsafe { llvm::LLVMPositionBuilderAtEnd(bld, llbb); + debuginfo::insert_reference_to_gdb_debug_scripts_section_global(ccx); + let (start_fn, args) = if use_start_lang_item { let start_def_id = match ccx.tcx().lang_items.require(StartFnLangItem) { Ok(id) => id, diff --git a/src/librustc_trans/trans/cabi_x86_64.rs b/src/librustc_trans/trans/cabi_x86_64.rs index 9b678a4f3ae9b..fffdc9c97ab97 100644 --- a/src/librustc_trans/trans/cabi_x86_64.rs +++ b/src/librustc_trans/trans/cabi_x86_64.rs @@ -23,6 +23,7 @@ use trans::context::CrateContext; use trans::type_::Type; use std::cmp; +use std::iter::repeat; #[deriving(Clone, Copy, PartialEq)] enum RegClass { @@ -286,7 +287,7 @@ fn classify_ty(ty: Type) -> Vec { } let words = (ty_size(ty) + 7) / 8; - let mut cls = Vec::from_elem(words, NoClass); + let mut cls: Vec<_> = repeat(NoClass).take(words).collect(); if words > 4 { all_mem(cls.as_mut_slice()); return cls; diff --git a/src/librustc_trans/trans/closure.rs b/src/librustc_trans/trans/closure.rs index ed3c820f2faf4..3723ad07a36ec 100644 --- a/src/librustc_trans/trans/closure.rs +++ b/src/librustc_trans/trans/closure.rs @@ -137,26 +137,6 @@ fn tuplify_box_ty<'tcx>(tcx: &ty::ctxt<'tcx>, t: Ty<'tcx>) -> Ty<'tcx> { ty::mk_tup(tcx, vec!(tcx.types.uint, ty::mk_nil_ptr(tcx), ptr, ptr, t)) } -fn allocate_cbox<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, - store: ty::TraitStore, - cdata_ty: Ty<'tcx>) - -> Result<'blk, 'tcx> { - let _icx = push_ctxt("closure::allocate_cbox"); - let tcx = bcx.tcx(); - - // Allocate and initialize the box: - let cbox_ty = tuplify_box_ty(tcx, cdata_ty); - match store { - ty::UniqTraitStore => { - malloc_raw_dyn_proc(bcx, cbox_ty) - } - ty::RegionTraitStore(..) => { - let llbox = alloc_ty(bcx, cbox_ty, "__closure"); - Result::new(bcx, llbox) - } - } -} - pub struct ClosureResult<'blk, 'tcx: 'blk> { llbox: ValueRef, // llvalue of ptr to closure cdata_ty: Ty<'tcx>, // type of the closure data @@ -168,8 +148,7 @@ pub struct ClosureResult<'blk, 'tcx: 'blk> { // heap allocated closure that copies the upvars into environment. // Otherwise, it is stack allocated and copies pointers to the upvars. pub fn store_environment<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, - bound_values: Vec> , - store: ty::TraitStore) + bound_values: Vec>) -> ClosureResult<'blk, 'tcx> { let _icx = push_ctxt("closure::store_environment"); let ccx = bcx.ccx(); @@ -193,7 +172,7 @@ pub fn store_environment<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } // allocate closure in the heap - let Result {bcx, val: llbox} = allocate_cbox(bcx, store, cdata_ty); + let llbox = alloc_ty(bcx, cbox_ty, "__closure"); let llbox = PointerCast(bcx, llbox, llboxptr_ty); debug!("tuplify_box_ty = {}", ty_to_string(tcx, cbox_ty)); @@ -227,8 +206,7 @@ pub fn store_environment<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, // collects the upvars and packages them up for store_environment. fn build_closure<'blk, 'tcx>(bcx0: Block<'blk, 'tcx>, freevar_mode: ast::CaptureClause, - freevars: &Vec, - store: ty::TraitStore) + freevars: &Vec) -> ClosureResult<'blk, 'tcx> { let _icx = push_ctxt("closure::build_closure"); @@ -242,7 +220,7 @@ fn build_closure<'blk, 'tcx>(bcx0: Block<'blk, 'tcx>, env_vals.push(EnvValue {action: freevar_mode, datum: datum}); } - store_environment(bcx, env_vals, store) + store_environment(bcx, env_vals) } // Given an enclosing block context, a new function context, a closure type, @@ -456,7 +434,7 @@ pub fn trans_expr_fn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, llbox, cdata_ty, bcx - } = build_closure(bcx, freevar_mode, &freevars, store); + } = build_closure(bcx, freevar_mode, &freevars); trans_closure(ccx, decl, diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs index 0fd6d286e8b2d..1f01da8a124b3 100644 --- a/src/librustc_trans/trans/consts.rs +++ b/src/librustc_trans/trans/consts.rs @@ -25,6 +25,7 @@ use middle::ty::{mod, Ty}; use util::ppaux::{Repr, ty_to_string}; use std::c_str::ToCStr; +use std::iter::repeat; use libc::c_uint; use syntax::{ast, ast_util}; use syntax::ptr::P; @@ -608,7 +609,7 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr) -> ValueRef { const_eval::const_uint(i) => i as uint, _ => cx.sess().span_bug(count.span, "count must be integral const expression.") }; - let vs = Vec::from_elem(n, const_expr(cx, &**elem).0); + let vs: Vec<_> = repeat(const_expr(cx, &**elem).0).take(n).collect(); if vs.iter().any(|vi| val_ty(*vi) != llunitty) { C_struct(cx, vs[], false) } else { diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs index b5b1c6ff86479..589250430cd71 100644 --- a/src/librustc_trans/trans/debuginfo.rs +++ b/src/librustc_trans/trans/debuginfo.rs @@ -213,7 +213,7 @@ use std::ptr; use std::rc::{Rc, Weak}; use syntax::util::interner::Interner; use syntax::codemap::{Span, Pos}; -use syntax::{ast, codemap, ast_util, ast_map}; +use syntax::{ast, codemap, ast_util, ast_map, attr}; use syntax::ast_util::PostExpansionMethod; use syntax::parse::token::{mod, special_idents}; @@ -741,7 +741,16 @@ pub fn finalize(cx: &CrateContext) { } debug!("finalize"); - compile_unit_metadata(cx); + let _ = compile_unit_metadata(cx); + + if needs_gdb_debug_scripts_section(cx) { + // Add a .debug_gdb_scripts section to this compile-unit. This will + // cause GDB to try and load the gdb_load_rust_pretty_printers.py file, + // which activates the Rust pretty printers for binary this section is + // contained in. + get_or_insert_gdb_debug_scripts_section_global(cx); + } + unsafe { llvm::LLVMDIBuilderFinalize(DIB(cx)); llvm::LLVMDIBuilderDispose(DIB(cx)); @@ -1586,7 +1595,7 @@ fn create_DIArray(builder: DIBuilderRef, arr: &[DIDescriptor]) -> DIArray { }; } -fn compile_unit_metadata(cx: &CrateContext) { +fn compile_unit_metadata(cx: &CrateContext) -> DIDescriptor { let work_dir = &cx.sess().working_dir; let compile_unit_name = match cx.sess().local_crate_source_file { None => fallback_path(cx), @@ -1621,7 +1630,7 @@ fn compile_unit_metadata(cx: &CrateContext) { (option_env!("CFG_VERSION")).expect("CFG_VERSION")); let compile_unit_name = compile_unit_name.as_ptr(); - work_dir.as_vec().with_c_str(|work_dir| { + return work_dir.as_vec().with_c_str(|work_dir| { producer.with_c_str(|producer| { "".with_c_str(|flags| { "".with_c_str(|split_name| { @@ -1635,7 +1644,7 @@ fn compile_unit_metadata(cx: &CrateContext) { cx.sess().opts.optimize != config::No, flags, 0, - split_name); + split_name) } }) }) @@ -3396,10 +3405,7 @@ fn create_scope_map(cx: &CrateContext, if need_new_scope { // Create a new lexical scope and push it onto the stack let loc = cx.sess().codemap().lookup_char_pos(pat.span.lo); - let file_metadata = file_metadata(cx, - loc.file - .name - []); + let file_metadata = file_metadata(cx, loc.file.name[]); let parent_scope = scope_stack.last().unwrap().scope_metadata; let scope_metadata = unsafe { @@ -4112,3 +4118,76 @@ fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> Rc llvm::ValueRef { + let section_var_name = b"__rustc_debug_gdb_scripts_section__".to_c_str(); + + let section_var = unsafe { + llvm::LLVMGetNamedGlobal(ccx.llmod(), section_var_name.as_ptr()) + }; + + if section_var == ptr::null_mut() { + let section_name = b".debug_gdb_scripts".to_c_str(); + let section_contents = b"\x01gdb_load_rust_pretty_printers.py\0"; + + unsafe { + let llvm_type = Type::array(&Type::i8(ccx), + section_contents.len() as u64); + let section_var = llvm::LLVMAddGlobal(ccx.llmod(), + llvm_type.to_ref(), + section_var_name.as_ptr()); + llvm::LLVMSetSection(section_var, section_name.as_ptr()); + llvm::LLVMSetInitializer(section_var, C_bytes(ccx, section_contents)); + llvm::LLVMSetGlobalConstant(section_var, llvm::True); + llvm::LLVMSetUnnamedAddr(section_var, llvm::True); + llvm::SetLinkage(section_var, llvm::Linkage::LinkOnceODRLinkage); + // This should make sure that the whole section is not larger than + // the string it contains. Otherwise we get a warning from GDB. + llvm::LLVMSetAlignment(section_var, 1); + section_var + } + } else { + section_var + } +} + +fn needs_gdb_debug_scripts_section(ccx: &CrateContext) -> bool { + let omit_gdb_pretty_printer_section = + attr::contains_name(ccx.tcx() + .map + .krate() + .attrs + .as_slice(), + "omit_gdb_pretty_printer_section"); + + !omit_gdb_pretty_printer_section && + !ccx.sess().target.target.options.is_like_osx && + !ccx.sess().target.target.options.is_like_windows && + ccx.sess().opts.debuginfo != NoDebugInfo +} + diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs index 5a20a297fdb09..7587adae5b7ef 100644 --- a/src/librustc_trans/trans/expr.rs +++ b/src/librustc_trans/trans/expr.rs @@ -68,6 +68,7 @@ use syntax::print::pprust::{expr_to_string}; use syntax::ptr::P; use syntax::parse::token; use std::rc::Rc; +use std::iter::repeat; // Destinations @@ -1413,7 +1414,7 @@ fn trans_struct<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let tcx = bcx.tcx(); with_field_tys(tcx, ty, Some(expr_id), |discr, field_tys| { - let mut need_base = Vec::from_elem(field_tys.len(), true); + let mut need_base: Vec<_> = repeat(true).take(field_tys.len()).collect(); let numbered_fields = fields.iter().map(|field| { let opt_pos = diff --git a/src/librustc_trans/trans/type_.rs b/src/librustc_trans/trans/type_.rs index 45a2a343066c4..2cc40a6179508 100644 --- a/src/librustc_trans/trans/type_.rs +++ b/src/librustc_trans/trans/type_.rs @@ -22,6 +22,7 @@ use syntax::ast; use std::c_str::ToCStr; use std::mem; use std::cell::RefCell; +use std::iter::repeat; use libc::c_uint; @@ -282,7 +283,7 @@ impl Type { if n_elts == 0 { return Vec::new(); } - let mut elts = Vec::from_elem(n_elts, Type { rf: 0 as TypeRef }); + let mut elts: Vec<_> = repeat(Type { rf: 0 as TypeRef }).take(n_elts).collect(); llvm::LLVMGetStructElementTypes(self.to_ref(), elts.as_mut_ptr() as *mut TypeRef); elts @@ -296,7 +297,7 @@ impl Type { pub fn func_params(&self) -> Vec { unsafe { let n_args = llvm::LLVMCountParamTypes(self.to_ref()) as uint; - let mut args = Vec::from_elem(n_args, Type { rf: 0 as TypeRef }); + let mut args: Vec<_> = repeat(Type { rf: 0 as TypeRef }).take(n_args).collect(); llvm::LLVMGetParamTypes(self.to_ref(), args.as_mut_ptr() as *mut TypeRef); args diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 587a85cfcbac4..dee9aafd06d7b 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -62,7 +62,7 @@ use util::nodemap::DefIdMap; use util::ppaux::{mod, Repr, UserString}; use std::rc::Rc; -use std::iter::AdditiveIterator; +use std::iter::{repeat, AdditiveIterator}; use syntax::{abi, ast, ast_util}; use syntax::codemap::Span; use syntax::parse::token; @@ -317,8 +317,8 @@ fn create_substs_for_ast_path<'tcx,AC,RS>( match anon_regions { Ok(v) => v.into_iter().collect(), - Err(_) => Vec::from_fn(expected_num_region_params, - |_| ty::ReStatic) // hokey + Err(_) => range(0, expected_num_region_params) + .map(|_| ty::ReStatic).collect() // hokey } }; @@ -500,7 +500,7 @@ fn convert_parenthesized_parameters<'tcx,AC>(this: &AC, .map(|a_t| ast_ty_to_ty(this, &binding_rscope, &**a_t)) .collect::>>(); - let input_params = Vec::from_elem(inputs.len(), String::new()); + let input_params: Vec<_> = repeat(String::new()).take(inputs.len()).collect(); let (implied_output_region, params_lifetimes) = find_implied_output_region(&*inputs, input_params); @@ -734,8 +734,8 @@ pub fn ast_path_to_ty_relaxed<'tcx,AC,RS>( path.segments.iter().all(|s| s.parameters.is_empty()); let substs = if needs_defaults { - let type_params = Vec::from_fn(generics.types.len(TypeSpace), - |_| this.ty_infer(path.span)); + let type_params: Vec<_> = range(0, generics.types.len(TypeSpace)) + .map(|_| this.ty_infer(path.span)).collect(); let region_params = rscope.anon_regions(path.span, generics.regions.len(TypeSpace)) .unwrap(); @@ -1528,21 +1528,18 @@ fn conv_ty_poly_trait_ref<'tcx, AC, RS>( let mut partitioned_bounds = partition_bounds(this.tcx(), span, ast_bounds[]); let mut projection_bounds = Vec::new(); - let main_trait_bound = match partitioned_bounds.trait_bounds.remove(0) { - Some(trait_bound) => { - let ptr = instantiate_poly_trait_ref(this, - rscope, - trait_bound, - None, - &mut projection_bounds); - Some(ptr) - } - None => { - this.tcx().sess.span_err( - span, - "at least one non-builtin trait is required for an object type"); - None - } + let main_trait_bound = if !partitioned_bounds.trait_bounds.is_empty() { + let trait_bound = partitioned_bounds.trait_bounds.remove(0); + Some(instantiate_poly_trait_ref(this, + rscope, + trait_bound, + None, + &mut projection_bounds)) + } else { + this.tcx().sess.span_err( + span, + "at least one non-builtin trait is required for an object type"); + None }; let bounds = diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 0e8b5b373f144..7c431b4fc0bd0 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -124,7 +124,8 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, check_pat_struct(pcx, pat, path, fields.as_slice(), etc, expected); } ast::PatTup(ref elements) => { - let element_tys = Vec::from_fn(elements.len(), |_| fcx.infcx().next_ty_var()); + let element_tys: Vec<_> = range(0, elements.len()).map(|_| fcx.infcx() + .next_ty_var()).collect(); let pat_ty = ty::mk_tup(tcx, element_tys.clone()); fcx.write_ty(pat.id, pat_ty); demand::eqtype(fcx, pat.span, expected, pat_ty); diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index a189f780b0c27..a751b65a0f8c5 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -24,6 +24,7 @@ use syntax::ast; use syntax::codemap::Span; use std::rc::Rc; use std::mem; +use std::iter::repeat; use util::ppaux::Repr; struct ConfirmContext<'a, 'tcx:'a> { @@ -339,7 +340,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { } else if num_supplied_types != num_method_types { span_err!(self.tcx().sess, self.span, E0036, "incorrect number of type parameters given for this method"); - Vec::from_elem(num_method_types, self.tcx().types.err) + repeat(self.tcx().types.err).take(num_method_types).collect() } else { supplied_method_types } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 8069d00dda826..f3a4a8d177e23 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -110,6 +110,7 @@ use util::nodemap::{DefIdMap, FnvHashMap, NodeMap}; use std::cell::{Cell, Ref, RefCell}; use std::mem::replace; use std::rc::Rc; +use std::iter::repeat; use syntax::{mod, abi, attr}; use syntax::ast::{mod, ProvidedMethod, RequiredMethod, TypeTraitItem, DefId}; use syntax::ast_util::{mod, local_def, PostExpansionMethod}; @@ -2130,9 +2131,9 @@ impl<'a, 'tcx> RegionScope for FnCtxt<'a, 'tcx> { fn anon_regions(&self, span: Span, count: uint) -> Result, Option>> { - Ok(Vec::from_fn(count, |_| { + Ok(range(0, count).map(|_| { self.infcx().next_region_var(infer::MiscVariable(span)) - })) + }).collect()) } } @@ -2810,7 +2811,7 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // FIXME(#17596) Ty<'tcx> is incorrectly invariant w.r.t 'tcx. fn err_args<'tcx>(tcx: &ty::ctxt<'tcx>, len: uint) -> Vec> { - Vec::from_fn(len, |_| tcx.types.err) + range(0, len).map(|_| tcx.types.err).collect() } fn write_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, @@ -5166,7 +5167,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // The first step then is to categorize the segments appropriately. assert!(path.segments.len() >= 1); - let mut segment_spaces; + let mut segment_spaces: Vec<_>; match def { // Case 1 and 1b. Reference to a *type* or *enum variant*. def::DefSelfTy(..) | @@ -5181,7 +5182,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, def::DefTyParam(..) => { // Everything but the final segment should have no // parameters at all. - segment_spaces = Vec::from_elem(path.segments.len() - 1, None); + segment_spaces = repeat(None).take(path.segments.len() - 1).collect(); segment_spaces.push(Some(subst::TypeSpace)); } @@ -5189,7 +5190,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, def::DefFn(..) | def::DefConst(..) | def::DefStatic(..) => { - segment_spaces = Vec::from_elem(path.segments.len() - 1, None); + segment_spaces = repeat(None).take(path.segments.len() - 1).collect(); segment_spaces.push(Some(subst::FnSpace)); } @@ -5205,7 +5206,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, def::FromImpl(_) => {} } - segment_spaces = Vec::from_elem(path.segments.len() - 2, None); + segment_spaces = repeat(None).take(path.segments.len() - 2).collect(); segment_spaces.push(Some(subst::TypeSpace)); segment_spaces.push(Some(subst::FnSpace)); } @@ -5220,7 +5221,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, def::DefRegion(..) | def::DefLabel(..) | def::DefUpvar(..) => { - segment_spaces = Vec::from_elem(path.segments.len(), None); + segment_spaces = repeat(None).take(path.segments.len()).collect(); } } assert_eq!(segment_spaces.len(), path.segments.len()); @@ -5489,8 +5490,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, "too few type parameters provided: expected {}{} parameter(s) \ , found {} parameter(s)", qualifier, required_len, provided_len); - substs.types.replace(space, - Vec::from_elem(desired.len(), fcx.tcx().types.err)); + substs.types.replace(space, repeat(fcx.tcx().types.err).take(desired.len()).collect()); return; } @@ -5614,7 +5614,7 @@ pub fn check_bounds_are_used<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, // make a vector of booleans initially false, set to true when used if tps.len() == 0u { return; } - let mut tps_used = Vec::from_elem(tps.len(), false); + let mut tps_used: Vec<_> = repeat(false).take(tps.len()).collect(); ty::walk_ty(ty, |t| { match t.sty { diff --git a/src/librustc_typeck/check/regionmanip.rs b/src/librustc_typeck/check/regionmanip.rs index bb051ab15250c..42ffe2d5327bc 100644 --- a/src/librustc_typeck/check/regionmanip.rs +++ b/src/librustc_typeck/check/regionmanip.rs @@ -409,4 +409,3 @@ impl<'tcx> Repr<'tcx> for WfConstraint<'tcx> { } } } - diff --git a/src/librustc_typeck/check/vtable.rs b/src/librustc_typeck/check/vtable.rs index 23a8643aadcf5..f153b51c5df77 100644 --- a/src/librustc_typeck/check/vtable.rs +++ b/src/librustc_typeck/check/vtable.rs @@ -190,11 +190,13 @@ fn check_object_safety_inner<'tcx>(tcx: &ty::ctxt<'tcx>, } } - /// Returns a vec of error messages. If hte vec is empty - no errors! + /// Returns a vec of error messages. If the vec is empty - no errors! /// /// There are some limitations to calling functions through an object, because (a) the self /// type is not known (that's the whole point of a trait instance, after all, to obscure the - /// self type) and (b) the call must go through a vtable and hence cannot be monomorphized. + /// self type), (b) the call must go through a vtable and hence cannot be monomorphized and + /// (c) the trait contains static methods which can't be called because we don't know the + /// concrete type. fn check_object_safety_of_method<'tcx>(tcx: &ty::ctxt<'tcx>, object_trait: &ty::PolyTraitRef<'tcx>, method: &ty::Method<'tcx>) @@ -210,9 +212,11 @@ fn check_object_safety_inner<'tcx>(tcx: &ty::ctxt<'tcx>, } ty::StaticExplicitSelfCategory => { - // Static methods are always object-safe since they - // can't be called through a trait object - return msgs + // Static methods are never object safe (reason (c)). + msgs.push(format!("cannot call a static method (`{}`) \ + through a trait object", + method_name)); + return msgs; } ty::ByReferenceExplicitSelfCategory(..) | ty::ByBoxExplicitSelfCategory => {} diff --git a/src/librustc_typeck/rscope.rs b/src/librustc_typeck/rscope.rs index a97dce88a5762..c62218313f4e8 100644 --- a/src/librustc_typeck/rscope.rs +++ b/src/librustc_typeck/rscope.rs @@ -13,6 +13,7 @@ use middle::ty; use middle::ty_fold; use std::cell::Cell; +use std::iter::repeat; use syntax::codemap::Span; /// Defines strategies for handling regions that are omitted. For @@ -99,7 +100,7 @@ impl RegionScope for SpecificRscope { count: uint) -> Result, Option>> { - Ok(Vec::from_elem(count, self.default)) + Ok(repeat(self.default).take(count).collect()) } } @@ -134,7 +135,7 @@ impl RegionScope for BindingRscope { count: uint) -> Result, Option>> { - Ok(Vec::from_fn(count, |_| self.next_region())) + Ok(range(0, count).map(|_| self.next_region()).collect()) } } diff --git a/src/librustc_typeck/variance.rs b/src/librustc_typeck/variance.rs index c4c33f24f87e2..de0b0a7ad3548 100644 --- a/src/librustc_typeck/variance.rs +++ b/src/librustc_typeck/variance.rs @@ -199,6 +199,7 @@ use middle::subst::{ParamSpace, FnSpace, TypeSpace, SelfSpace, VecPerParamSpace} use middle::ty::{mod, Ty}; use std::fmt; use std::rc::Rc; +use std::iter::repeat; use syntax::ast; use syntax::ast_map; use syntax::ast_util; @@ -971,7 +972,7 @@ struct SolveContext<'a, 'tcx: 'a> { fn solve_constraints(constraints_cx: ConstraintContext) { let ConstraintContext { terms_cx, constraints, .. } = constraints_cx; - let solutions = Vec::from_elem(terms_cx.num_inferred(), ty::Bivariant); + let solutions: Vec<_> = repeat(ty::Bivariant).take(terms_cx.num_inferred()).collect(); let mut solutions_cx = SolveContext { terms_cx: terms_cx, constraints: constraints, diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index dc264a5b5aa05..3c09a10f3d98e 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -398,7 +398,7 @@ fn primitive_link(f: &mut fmt::Formatter, Some(root) => { try!(write!(f, "", root, - path.0.head().unwrap(), + path.0.first().unwrap(), prim.to_url_str())); needs_termination = true; } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index bfb03cb2589c2..f8a0b88b4088d 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1799,7 +1799,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, try!(write!(w, r#""#, - root_path = Vec::from_elem(cx.current.len(), "..").connect("/"), + root_path = repeat("..").take(cx.current.len()).collect::>().connect("/"), path = if ast_util::is_local(it.def_id) { cx.current.connect("/") } else { @@ -2055,7 +2055,8 @@ fn render_struct(w: &mut fmt::Formatter, it: &clean::Item, fn render_methods(w: &mut fmt::Formatter, it: &clean::Item) -> fmt::Result { match cache().impls.get(&it.def_id) { Some(v) => { - let (non_trait, traits) = v.partitioned(|i| i.impl_.trait_.is_none()); + let (non_trait, traits): (Vec<_>, _) = v.iter().cloned() + .partition(|i| i.impl_.trait_.is_none()); if non_trait.len() > 0 { try!(write!(w, "

Methods

")); for i in non_trait.iter() { @@ -2065,7 +2066,8 @@ fn render_methods(w: &mut fmt::Formatter, it: &clean::Item) -> fmt::Result { if traits.len() > 0 { try!(write!(w, "

Trait \ Implementations

")); - let (derived, manual) = traits.partition(|i| i.impl_.derived); + let (derived, manual): (Vec<_>, _) = traits.into_iter() + .partition(|i| i.impl_.derived); for i in manual.iter() { try!(render_impl(w, i)); } diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 8b66d5751e4cc..ccdc816425503 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -116,7 +116,8 @@ pub fn opts() -> Vec { use getopts::*; vec!( optflag("h", "help", "show this help message"), - optflagopt("", "version", "print rustdoc's version", "verbose"), + optflag("V", "version", "print rustdoc's version"), + optflag("v", "verbose", "use verbose output"), optopt("r", "input-format", "the input type of the specified file", "[rust|json]"), optopt("w", "output-format", "the output type to write", diff --git a/src/libstd/bitflags.rs b/src/libstd/bitflags.rs index a46b8a9ad9024..aeb4df402a2cf 100644 --- a/src/libstd/bitflags.rs +++ b/src/libstd/bitflags.rs @@ -241,17 +241,6 @@ macro_rules! bitflags { } } - // NOTE(stage0): Remove impl after a snapshot - #[cfg(stage0)] - impl Not<$BitFlags> for $BitFlags { - /// Returns the complement of this set of flags. - #[inline] - fn not(&self) -> $BitFlags { - $BitFlags { bits: !self.bits } & $BitFlags::all() - } - } - - #[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot impl Not<$BitFlags> for $BitFlags { /// Returns the complement of this set of flags. #[inline] diff --git a/src/libstd/c_str.rs b/src/libstd/c_str.rs index f28abcc10cfd8..4e22fc6008037 100644 --- a/src/libstd/c_str.rs +++ b/src/libstd/c_str.rs @@ -74,7 +74,7 @@ use fmt; use hash; use mem; use ptr; -use slice::{mod, ImmutableIntSlice}; +use slice::{mod, IntSliceExt}; use str; use string::String; use core::kinds::marker; @@ -486,6 +486,8 @@ fn check_for_null(v: &[u8], buf: *mut libc::c_char) { /// External iterator for a CString's bytes. /// /// Use with the `std::iter` module. +#[allow(raw_pointer_deriving)] +#[deriving(Clone)] pub struct CChars<'a> { ptr: *const libc::c_char, marker: marker::ContravariantLifetime<'a>, diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 7b7473b2c993c..3bfe2009f8b4b 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -1261,6 +1261,7 @@ impl, V: Clone, S, H: Hasher> HashMap { } } +#[stable] impl, V: PartialEq, S, H: Hasher> PartialEq for HashMap { fn eq(&self, other: &HashMap) -> bool { if self.len() != other.len() { return false; } @@ -1271,6 +1272,7 @@ impl, V: PartialEq, S, H: Hasher> PartialEq for HashMap, V: Eq, S, H: Hasher> Eq for HashMap {} impl + Show, V: Show, S, H: Hasher> Show for HashMap { @@ -1317,6 +1319,15 @@ pub struct Iter<'a, K: 'a, V: 'a> { inner: table::Iter<'a, K, V> } +// FIXME(#19839) Remove in favor of `#[deriving(Clone)]` +impl<'a, K, V> Clone for Iter<'a, K, V> { + fn clone(&self) -> Iter<'a, K, V> { + Iter { + inner: self.inner.clone() + } + } +} + /// HashMap mutable values iterator pub struct IterMut<'a, K: 'a, V: 'a> { inner: table::IterMut<'a, K, V> @@ -1337,11 +1348,29 @@ pub struct Keys<'a, K: 'a, V: 'a> { inner: Map<(&'a K, &'a V), &'a K, Iter<'a, K, V>, fn((&'a K, &'a V)) -> &'a K> } +// FIXME(#19839) Remove in favor of `#[deriving(Clone)]` +impl<'a, K, V> Clone for Keys<'a, K, V> { + fn clone(&self) -> Keys<'a, K, V> { + Keys { + inner: self.inner.clone() + } + } +} + /// HashMap values iterator pub struct Values<'a, K: 'a, V: 'a> { inner: Map<(&'a K, &'a V), &'a V, Iter<'a, K, V>, fn((&'a K, &'a V)) -> &'a V> } +// FIXME(#19839) Remove in favor of `#[deriving(Clone)]` +impl<'a, K, V> Clone for Values<'a, K, V> { + fn clone(&self) -> Values<'a, K, V> { + Values { + inner: self.inner.clone() + } + } +} + /// HashMap drain iterator pub struct Drain<'a, K: 'a, V: 'a> { inner: iter::Map< diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index 6d83d5510b357..93f6895f6885b 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -572,6 +572,7 @@ impl, S, H: Hasher> HashSet { } } +#[stable] impl, S, H: Hasher> PartialEq for HashSet { fn eq(&self, other: &HashSet) -> bool { if self.len() != other.len() { return false; } @@ -580,6 +581,7 @@ impl, S, H: Hasher> PartialEq for HashSet { } } +#[stable] impl, S, H: Hasher> Eq for HashSet {} impl + fmt::Show, S, H: Hasher> fmt::Show for HashSet { diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs index f76b8ac3326f5..6938ab9b0b6d7 100644 --- a/src/libstd/collections/hash/table.rs +++ b/src/libstd/collections/hash/table.rs @@ -718,6 +718,18 @@ struct RawBuckets<'a, K, V> { marker: marker::ContravariantLifetime<'a>, } +// FIXME(#19839) Remove in favor of `#[deriving(Clone)]` +impl<'a, K, V> Clone for RawBuckets<'a, K, V> { + fn clone(&self) -> RawBuckets<'a, K, V> { + RawBuckets { + raw: self.raw, + hashes_end: self.hashes_end, + marker: marker::ContravariantLifetime, + } + } +} + + impl<'a, K, V> Iterator> for RawBuckets<'a, K, V> { fn next(&mut self) -> Option> { while self.raw.hash != self.hashes_end { @@ -775,6 +787,17 @@ pub struct Iter<'a, K: 'a, V: 'a> { elems_left: uint, } +// FIXME(#19839) Remove in favor of `#[deriving(Clone)]` +impl<'a, K, V> Clone for Iter<'a, K, V> { + fn clone(&self) -> Iter<'a, K, V> { + Iter { + iter: self.iter.clone(), + elems_left: self.elems_left + } + } +} + + /// Iterator over mutable references to entries in a table. pub struct IterMut<'a, K: 'a, V: 'a> { iter: RawBuckets<'a, K, V>, diff --git a/src/libstd/comm/sync.rs b/src/libstd/comm/sync.rs index 82ec1814ebde7..a8004155af06d 100644 --- a/src/libstd/comm/sync.rs +++ b/src/libstd/comm/sync.rs @@ -148,7 +148,7 @@ impl Packet { tail: 0 as *mut Node, }, buf: Buffer { - buf: Vec::from_fn(cap + if cap == 0 {1} else {0}, |_| None), + buf: range(0, cap + if cap == 0 {1} else {0}).map(|_| None).collect(), start: 0, size: 0, }, diff --git a/src/libstd/fmt.rs b/src/libstd/fmt.rs index b75cf9a196b50..957dd54a037cf 100644 --- a/src/libstd/fmt.rs +++ b/src/libstd/fmt.rs @@ -406,8 +406,6 @@ pub use core::fmt::{Argument, Arguments, write, radix, Radix, RadixFmt}; #[doc(hidden)] pub use core::fmt::{argument, argumentuint}; -// NOTE(stage0): Remove cfg after a snapshot -#[cfg(not(stage0))] /// The format function takes a precompiled format string and a list of /// arguments, to return the resulting formatted string. /// @@ -431,31 +429,6 @@ pub fn format(args: Arguments) -> string::String { string::String::from_utf8(output).unwrap() } -// NOTE(stage0): Remove function after a snapshot -#[cfg(stage0)] -/// The format function takes a precompiled format string and a list of -/// arguments, to return the resulting formatted string. -/// -/// # Arguments -/// -/// * args - a structure of arguments generated via the `format_args!` macro. -/// -/// # Example -/// -/// ```rust -/// use std::fmt; -/// -/// let s = format_args!(fmt::format, "Hello, {}!", "world"); -/// assert_eq!(s, "Hello, world!".to_string()); -/// ``` -#[experimental = "this is an implementation detail of format! and should not \ - be called directly"] -pub fn format(args: &Arguments) -> string::String { - let mut output = Vec::new(); - let _ = write!(&mut output as &mut Writer, "{}", args); - string::String::from_utf8(output).unwrap() -} - impl<'a> Writer for Formatter<'a> { fn write(&mut self, b: &[u8]) -> io::IoResult<()> { match (*self).write(b) { diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index fdbce101c1d6c..0fba0f6704be4 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -439,9 +439,10 @@ mod test { impl Reader for ShortReader { fn read(&mut self, _: &mut [u8]) -> io::IoResult { - match self.lengths.remove(0) { - Some(i) => Ok(i), - None => Err(io::standard_error(io::EndOfFile)) + if self.lengths.is_empty() { + Err(io::standard_error(io::EndOfFile)) + } else { + Ok(self.lengths.remove(0)) } } } diff --git a/src/libstd/io/fs.rs b/src/libstd/io/fs.rs index caa6590bb2821..e4c31ff8dd321 100644 --- a/src/libstd/io/fs.rs +++ b/src/libstd/io/fs.rs @@ -558,6 +558,7 @@ pub fn walk_dir(path: &Path) -> IoResult { } /// An iterator that walks over a directory +#[deriving(Clone)] pub struct Directories { stack: Vec, } diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 7a25360e695e4..8d5b125bb081f 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -1017,8 +1017,6 @@ pub trait Writer { /// decide whether their stream needs to be buffered or not. fn flush(&mut self) -> IoResult<()> { Ok(()) } - // NOTE(stage0): Remove cfg after a snapshot - #[cfg(not(stage0))] /// Writes a formatted string into this writer, returning any error /// encountered. /// @@ -1057,45 +1055,6 @@ pub trait Writer { } - // NOTE(stage0): Remove method after a snapshot - #[cfg(stage0)] - /// Writes a formatted string into this writer, returning any error - /// encountered. - /// - /// This method is primarily used to interface with the `format_args!` - /// macro, but it is rare that this should explicitly be called. The - /// `write!` macro should be favored to invoke this method instead. - /// - /// # Errors - /// - /// This function will return any I/O error reported while formatting. - fn write_fmt(&mut self, fmt: &fmt::Arguments) -> IoResult<()> { - // Create a shim which translates a Writer to a FormatWriter and saves - // off I/O errors. instead of discarding them - struct Adaptor<'a, T:'a> { - inner: &'a mut T, - error: IoResult<()>, - } - - impl<'a, T: Writer> fmt::FormatWriter for Adaptor<'a, T> { - fn write(&mut self, bytes: &[u8]) -> fmt::Result { - match self.inner.write(bytes) { - Ok(()) => Ok(()), - Err(e) => { - self.error = Err(e); - Err(fmt::Error) - } - } - } - } - - let mut output = Adaptor { inner: self, error: Ok(()) }; - match fmt::write(&mut output, fmt) { - Ok(()) => Ok(()), - Err(..) => output.error - } - } - /// Write a rust string into this sink. /// /// The bytes written will be the UTF-8 encoded version of the input string. diff --git a/src/libstd/io/net/addrinfo.rs b/src/libstd/io/net/addrinfo.rs index 69ba64d856e7f..e8fbb12118199 100644 --- a/src/libstd/io/net/addrinfo.rs +++ b/src/libstd/io/net/addrinfo.rs @@ -10,8 +10,8 @@ //! Synchronous DNS Resolution //! -//! Contains the functionality to perform DNS resolution in a style related to -//! `getaddrinfo()` +//! Contains the functionality to perform DNS resolution or reverse lookup, +//! in a style related to `getaddrinfo()` and `getnameinfo()`, respectively. #![allow(missing_docs)] @@ -24,6 +24,7 @@ use io::{IoResult}; use io::net::ip::{SocketAddr, IpAddr}; use option::Option; use option::Option::{Some, None}; +use string::String; use sys; use vec::Vec; @@ -83,6 +84,12 @@ pub fn get_host_addresses(host: &str) -> IoResult> { lookup(Some(host), None, None).map(|a| a.into_iter().map(|i| i.address.ip).collect()) } +/// Reverse name resolution. Given an address, returns the corresponding +/// hostname. +pub fn get_address_name(addr: IpAddr) -> IoResult { + sys::addrinfo::get_address_name(addr) +} + /// Full-fledged resolution. This function will perform a synchronous call to /// getaddrinfo, controlled by the parameters /// diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index 6c8e4eea40fdc..43d2e078035a6 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -378,38 +378,18 @@ pub fn println(s: &str) { }) } -// NOTE(stage0): Remove cfg after a snapshot -#[cfg(not(stage0))] /// Similar to `print`, but takes a `fmt::Arguments` structure to be compatible /// with the `format_args!` macro. pub fn print_args(fmt: fmt::Arguments) { with_task_stdout(|io| write!(io, "{}", fmt)) } -// NOTE(stage0): Remove function after a snapshot -#[cfg(stage0)] -/// Similar to `print`, but takes a `fmt::Arguments` structure to be compatible -/// with the `format_args!` macro. -pub fn print_args(fmt: &fmt::Arguments) { - with_task_stdout(|io| write!(io, "{}", fmt)) -} - -// NOTE(stage0): Remove cfg after a snapshot -#[cfg(not(stage0))] /// Similar to `println`, but takes a `fmt::Arguments` structure to be /// compatible with the `format_args!` macro. pub fn println_args(fmt: fmt::Arguments) { with_task_stdout(|io| writeln!(io, "{}", fmt)) } -// NOTE(stage0): Remove function after a snapshot -#[cfg(stage0)] -/// Similar to `println`, but takes a `fmt::Arguments` structure to be -/// compatible with the `format_args!` macro. -pub fn println_args(fmt: &fmt::Arguments) { - with_task_stdout(|io| writeln!(io, "{}", fmt)) -} - /// Representation of a reader of a standard input stream pub struct StdReader { inner: StdSource diff --git a/src/libstd/io/util.rs b/src/libstd/io/util.rs index 90d7c1388a196..2a98067c97080 100644 --- a/src/libstd/io/util.rs +++ b/src/libstd/io/util.rs @@ -163,6 +163,7 @@ impl Writer for MultiWriter { /// A `Reader` which chains input from multiple `Reader`s, reading each to /// completion before moving onto the next. +#[deriving(Clone)] pub struct ChainedReader { readers: I, cur_reader: Option, @@ -246,6 +247,7 @@ pub fn copy(r: &mut R, w: &mut W) -> io::IoResult<()> { } /// An adaptor converting an `Iterator` to a `Reader`. +#[deriving(Clone)] pub struct IterReader { iter: T, } diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 8274baeacfad8..74c387c5eeaf1 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -158,6 +158,7 @@ pub use alloc::rc; pub use core_collections::slice; pub use core_collections::str; pub use core_collections::string; +#[stable] pub use core_collections::vec; pub use unicode::char; diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index edb6218c5cc0b..ebb64bc2f2d51 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -17,8 +17,6 @@ #![experimental] #![macro_escape] -// NOTE(stage0): Remove cfg after a snapshot -#[cfg(not(stage0))] /// The entry point for panic of Rust tasks. /// /// This macro is used to inject panic into a Rust task, causing the task to @@ -59,63 +57,6 @@ macro_rules! panic { }); } -// NOTE(stage0): Remove macro after a snapshot -#[cfg(stage0)] -/// The entry point for panic of Rust tasks. -/// -/// This macro is used to inject panic into a Rust task, causing the task to -/// unwind and panic entirely. Each task's panic can be reaped as the -/// `Box` type, and the single-argument form of the `panic!` macro will be -/// the value which is transmitted. -/// -/// The multi-argument form of this macro panics with a string and has the -/// `format!` syntax for building a string. -/// -/// # Example -/// -/// ```should_fail -/// # #![allow(unreachable_code)] -/// panic!(); -/// panic!("this is a terrible mistake!"); -/// panic!(4i); // panic with the value of 4 to be collected elsewhere -/// panic!("this is a {} {message}", "fancy", message = "message"); -/// ``` -#[macro_export] -macro_rules! panic { - () => ({ - panic!("explicit panic") - }); - ($msg:expr) => ({ - // static requires less code at runtime, more constant data - static _FILE_LINE: (&'static str, uint) = (file!(), line!()); - ::std::rt::begin_unwind($msg, &_FILE_LINE) - }); - ($fmt:expr, $($arg:tt)*) => ({ - // a closure can't have return type !, so we need a full - // function to pass to format_args!, *and* we need the - // file and line numbers right here; so an inner bare fn - // is our only choice. - // - // LLVM doesn't tend to inline this, presumably because begin_unwind_fmt - // is #[cold] and #[inline(never)] and because this is flagged as cold - // as returning !. We really do want this to be inlined, however, - // because it's just a tiny wrapper. Small wins (156K to 149K in size) - // were seen when forcing this to be inlined, and that number just goes - // up with the number of calls to panic!() - // - // The leading _'s are to avoid dead code warnings if this is - // used inside a dead function. Just `#[allow(dead_code)]` is - // insufficient, since the user may have - // `#[forbid(dead_code)]` and which cannot be overridden. - #[inline(always)] - fn _run_fmt(fmt: &::std::fmt::Arguments) -> ! { - static _FILE_LINE: (&'static str, uint) = (file!(), line!()); - ::std::rt::begin_unwind_fmt(fmt, &_FILE_LINE) - } - format_args!(_run_fmt, $fmt, $($arg)*) - }); -} - /// Ensure that a boolean expression is `true` at runtime. /// /// This will invoke the `panic!` macro if the provided expression cannot be @@ -289,8 +230,6 @@ macro_rules! unimplemented { () => (panic!("not yet implemented")) } -// NOTE(stage0): Remove cfg after a snapshot -#[cfg(not(stage0))] /// Use the syntax described in `std::fmt` to create a value of type `String`. /// See `std::fmt` for more information. /// @@ -307,28 +246,6 @@ macro_rules! format { ($($arg:tt)*) => (::std::fmt::format(format_args!($($arg)*))) } -// NOTE(stage0): Remove macro after a snapshot -#[cfg(stage0)] -/// Use the syntax described in `std::fmt` to create a value of type `String`. -/// See `std::fmt` for more information. -/// -/// # Example -/// -/// ``` -/// format!("test"); -/// format!("hello {}", "world!"); -/// format!("x = {}, y = {y}", 10i, y = 30i); -/// ``` -#[macro_export] -#[stable] -macro_rules! format { - ($($arg:tt)*) => ( - format_args!(::std::fmt::format, $($arg)*) - ) -} - -// NOTE(stage0): Remove cfg after a snapshot -#[cfg(not(stage0))] /// Use the `format!` syntax to write data into a buffer of type `&mut Writer`. /// See `std::fmt` for more information. /// @@ -347,29 +264,6 @@ macro_rules! write { ($dst:expr, $($arg:tt)*) => ((&mut *$dst).write_fmt(format_args!($($arg)*))) } -// NOTE(stage0): Remove macro after a snapshot -#[cfg(stage0)] -/// Use the `format!` syntax to write data into a buffer of type `&mut Writer`. -/// See `std::fmt` for more information. -/// -/// # Example -/// -/// ``` -/// # #![allow(unused_must_use)] -/// -/// let mut w = Vec::new(); -/// write!(&mut w, "test"); -/// write!(&mut w, "formatted {}", "arguments"); -/// ``` -#[macro_export] -#[stable] -macro_rules! write { - ($dst:expr, $($arg:tt)*) => ({ - let dst = &mut *$dst; - format_args!(|args| { dst.write_fmt(args) }, $($arg)*) - }) -} - /// Equivalent to the `write!` macro, except that a newline is appended after /// the message is written. #[macro_export] @@ -380,8 +274,6 @@ macro_rules! writeln { ) } -// NOTE(stage0): Remove cfg after a snapshot -#[cfg(not(stage0))] /// Equivalent to the `println!` macro except that a newline is not printed at /// the end of the message. #[macro_export] @@ -390,18 +282,6 @@ macro_rules! print { ($($arg:tt)*) => (::std::io::stdio::print_args(format_args!($($arg)*))) } -// NOTE(stage0): Remove macro after a snapshot -#[cfg(stage0)] -/// Equivalent to the `println!` macro except that a newline is not printed at -/// the end of the message. -#[macro_export] -#[stable] -macro_rules! print { - ($($arg:tt)*) => (format_args!(::std::io::stdio::print_args, $($arg)*)) -} - -// NOTE(stage0): Remove cfg after a snapshot -#[cfg(not(stage0))] /// Macro for printing to a task's stdout handle. /// /// Each task can override its stdout handle via `std::io::stdio::set_stdout`. @@ -420,26 +300,6 @@ macro_rules! println { ($($arg:tt)*) => (::std::io::stdio::println_args(format_args!($($arg)*))) } -// NOTE(stage0): Remove macro after a snapshot -#[cfg(stage0)] -/// Macro for printing to a task's stdout handle. -/// -/// Each task can override its stdout handle via `std::io::stdio::set_stdout`. -/// The syntax of this macro is the same as that used for `format!`. For more -/// information, see `std::fmt` and `std::io::stdio`. -/// -/// # Example -/// -/// ``` -/// println!("hello there!"); -/// println!("format {} arguments", "some"); -/// ``` -#[macro_export] -#[stable] -macro_rules! println { - ($($arg:tt)*) => (format_args!(::std::io::stdio::println_args, $($arg)*)) -} - /// Helper macro for unwrapping `Result` values while returning early with an /// error if the value of the expression is `Err`. For more information, see /// `std::io`. diff --git a/src/libstd/os.rs b/src/libstd/os.rs index 989f44f7b8e42..df50b7f81afcf 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -620,10 +620,11 @@ pub fn get_exit_status() -> int { unsafe fn load_argc_and_argv(argc: int, argv: *const *const c_char) -> Vec> { use c_str::CString; + use iter::range; - Vec::from_fn(argc as uint, |i| { + range(0, argc as uint).map(|i| { CString::new(*argv.offset(i as int), false).as_bytes_no_nul().to_vec() - }) + }).collect() } /// Returns the command line arguments @@ -715,13 +716,14 @@ fn real_args() -> Vec { #[cfg(windows)] fn real_args() -> Vec { use slice; + use iter::range; let mut nArgs: c_int = 0; let lpArgCount: *mut c_int = &mut nArgs; let lpCmdLine = unsafe { GetCommandLineW() }; let szArgList = unsafe { CommandLineToArgvW(lpCmdLine, lpArgCount) }; - let args = Vec::from_fn(nArgs as uint, |i| unsafe { + let args: Vec<_> = range(0, nArgs as uint).map(|i| unsafe { // Determine the length of this argument. let ptr = *szArgList.offset(i as int); let mut len = 0; @@ -732,7 +734,7 @@ fn real_args() -> Vec { let buf = slice::from_raw_buf(&ptr, len); let opt_s = String::from_utf16(sys::os::truncate_utf16_at_nul(buf)); opt_s.ok().expect("CommandLineToArgvW returned invalid UTF-16") - }); + }).collect(); unsafe { LocalFree(szArgList as *mut c_void); diff --git a/src/libstd/path/posix.rs b/src/libstd/path/posix.rs index 60f147eac9b2b..bd4031e623085 100644 --- a/src/libstd/path/posix.rs +++ b/src/libstd/path/posix.rs @@ -22,14 +22,14 @@ use option::Option::{None, Some}; use kinds::Sized; use str::{FromStr, Str}; use str; -use slice::{CloneSliceExt, Splits, AsSlice, VectorVector, +use slice::{CloneSliceExt, Split, AsSlice, SliceConcatExt, PartialEqSliceExt, SliceExt}; use vec::Vec; use super::{BytesContainer, GenericPath, GenericPathUnsafe}; /// Iterator that yields successive components of a Path as &[u8] -pub type Components<'a> = Splits<'a, u8, fn(&u8) -> bool>; +pub type Components<'a> = Split<'a, u8, fn(&u8) -> bool>; /// Iterator that yields successive components of a Path as Option<&str> pub type StrComponents<'a> = @@ -306,7 +306,7 @@ impl GenericPath for Path { } } } - Some(Path::new(comps.connect_vec(&SEP_BYTE))) + Some(Path::new(comps.as_slice().connect(&SEP_BYTE))) } } diff --git a/src/libstd/path/windows.rs b/src/libstd/path/windows.rs index 879a96e802643..751ed4b70fb38 100644 --- a/src/libstd/path/windows.rs +++ b/src/libstd/path/windows.rs @@ -25,8 +25,8 @@ use iter::{Iterator, IteratorExt, Map, repeat}; use mem; use option::Option; use option::Option::{Some, None}; -use slice::SliceExt; -use str::{SplitTerminator, FromStr, StrVector, StrExt}; +use slice::{SliceExt, SliceConcatExt}; +use str::{SplitTerminator, FromStr, StrExt}; use string::{String, ToString}; use unicode::char::UnicodeChar; use vec::Vec; diff --git a/src/libstd/prelude.rs b/src/libstd/prelude.rs index fc59f06ae6cf3..f016683e3d0a9 100644 --- a/src/libstd/prelude.rs +++ b/src/libstd/prelude.rs @@ -66,7 +66,7 @@ #[doc(no_inline)] pub use iter::{FromIterator, Extend, ExactSizeIterator}; #[doc(no_inline)] pub use iter::{Iterator, IteratorExt, DoubleEndedIterator}; #[doc(no_inline)] pub use iter::{DoubleEndedIteratorExt, CloneIteratorExt}; -#[doc(no_inline)] pub use iter::{RandomAccessIterator, IteratorCloneExt}; +#[doc(no_inline)] pub use iter::{RandomAccessIterator, IteratorCloneExt, IteratorPairExt}; #[doc(no_inline)] pub use iter::{IteratorOrdExt, MutableDoubleEndedIterator}; #[doc(no_inline)] pub use num::{ToPrimitive, FromPrimitive}; #[doc(no_inline)] pub use boxed::Box; @@ -80,10 +80,9 @@ #[doc(no_inline)] pub use core::prelude::{Tuple1, Tuple2, Tuple3, Tuple4}; #[doc(no_inline)] pub use core::prelude::{Tuple5, Tuple6, Tuple7, Tuple8}; #[doc(no_inline)] pub use core::prelude::{Tuple9, Tuple10, Tuple11, Tuple12}; -#[doc(no_inline)] pub use str::{Str, StrVector}; -#[doc(no_inline)] pub use str::StrExt; +#[doc(no_inline)] pub use str::{Str, StrExt}; #[doc(no_inline)] pub use slice::AsSlice; -#[doc(no_inline)] pub use slice::{VectorVector, PartialEqSliceExt}; +#[doc(no_inline)] pub use slice::{SliceConcatExt, PartialEqSliceExt}; #[doc(no_inline)] pub use slice::{CloneSliceExt, OrdSliceExt, SliceExt}; #[doc(no_inline)] pub use slice::{BoxedSliceExt}; #[doc(no_inline)] pub use string::{IntoString, String, ToString}; diff --git a/src/libstd/rand/os.rs b/src/libstd/rand/os.rs index 46c3a4f622a54..91b6a1f0ce0ce 100644 --- a/src/libstd/rand/os.rs +++ b/src/libstd/rand/os.rs @@ -170,6 +170,7 @@ mod imp { extern crate libc; use io::{IoResult}; + use kinds::Sync; use mem; use os; use rand::Rng; @@ -196,6 +197,8 @@ mod imp { #[repr(C)] struct SecRandom; + unsafe impl Sync for *const SecRandom {} + #[allow(non_upper_case_globals)] static kSecRandomDefault: *const SecRandom = 0 as *const SecRandom; diff --git a/src/libstd/rt/args.rs b/src/libstd/rt/args.rs index b1f268597c7ad..98eff621ce0f3 100644 --- a/src/libstd/rt/args.rs +++ b/src/libstd/rt/args.rs @@ -95,14 +95,14 @@ mod imp { } unsafe fn load_argc_and_argv(argc: int, argv: *const *const u8) -> Vec> { - Vec::from_fn(argc as uint, |i| { + range(0, argc as uint).map(|i| { let arg = *argv.offset(i as int); let mut len = 0u; while *arg.offset(len as int) != 0 { len += 1u; } slice::from_raw_buf(&arg, len).to_vec() - }) + }).collect() } #[cfg(test)] diff --git a/src/libstd/rt/macros.rs b/src/libstd/rt/macros.rs index 095a27203f981..0f35500a04a73 100644 --- a/src/libstd/rt/macros.rs +++ b/src/libstd/rt/macros.rs @@ -15,22 +15,12 @@ #![macro_escape] -// NOTE(stage0): Remove cfg after a snapshot -#[cfg(not(stage0))] macro_rules! rterrln { ($fmt:expr $($arg:tt)*) => ( { ::rt::util::dumb_print(format_args!(concat!($fmt, "\n") $($arg)*)) } ) } -// NOTE(stage0): Remove macro after a snapshot -#[cfg(stage0)] -macro_rules! rterrln { - ($fmt:expr $($arg:tt)*) => ( { - format_args!(::rt::util::dumb_print, concat!($fmt, "\n") $($arg)*) - } ) -} - // Some basic logging. Enabled by passing `--cfg rtdebug` to the libstd build. macro_rules! rtdebug { ($($arg:tt)*) => ( { @@ -50,14 +40,6 @@ macro_rules! rtassert { } ) } -// NOTE(stage0): Remove cfg after a snapshot -#[cfg(not(stage0))] macro_rules! rtabort { ($($arg:tt)*) => (::rt::util::abort(format_args!($($arg)*))) } - -// NOTE(stage0): Remove macro after a snapshot -#[cfg(stage0)] -macro_rules! rtabort { - ($($arg:tt)*) => (format_args!(::rt::util::abort, $($arg)*)) -} diff --git a/src/libstd/rt/unwind.rs b/src/libstd/rt/unwind.rs index 9b57dcc9e18bf..c273c52daccad 100644 --- a/src/libstd/rt/unwind.rs +++ b/src/libstd/rt/unwind.rs @@ -477,8 +477,6 @@ pub mod eabi { } } -// NOTE(stage0): Remove cfg after a snapshot -#[cfg(not(stage0))] #[cfg(not(test))] /// Entry point of panic from the libcore crate. #[lang = "panic_fmt"] @@ -487,18 +485,6 @@ pub extern fn rust_begin_unwind(msg: fmt::Arguments, begin_unwind_fmt(msg, &(file, line)) } -// NOTE(stage0): Remove function after a snapshot -#[cfg(stage0)] -#[cfg(not(test))] -/// Entry point of panic from the libcore crate. -#[lang = "panic_fmt"] -pub extern fn rust_begin_unwind(msg: &fmt::Arguments, - file: &'static str, line: uint) -> ! { - begin_unwind_fmt(msg, &(file, line)) -} - -// NOTE(stage0): Remove cfg after a snapshot -#[cfg(not(stage0))] /// The entry point for unwinding with a formatted message. /// /// This is designed to reduce the amount of code required at the call @@ -530,39 +516,6 @@ pub fn begin_unwind_fmt(msg: fmt::Arguments, file_line: &(&'static str, uint)) - begin_unwind_inner(msg, file_line) } -// NOTE(stage0): Remove function after a snapshot -#[cfg(stage0)] -/// The entry point for unwinding with a formatted message. -/// -/// This is designed to reduce the amount of code required at the call -/// site as much as possible (so that `panic!()` has as low an impact -/// on (e.g.) the inlining of other functions as possible), by moving -/// the actual formatting into this shared place. -#[inline(never)] #[cold] -pub fn begin_unwind_fmt(msg: &fmt::Arguments, file_line: &(&'static str, uint)) -> ! { - use fmt::FormatWriter; - - // We do two allocations here, unfortunately. But (a) they're - // required with the current scheme, and (b) we don't handle - // panic + OOM properly anyway (see comment in begin_unwind - // below). - - struct VecWriter<'a> { v: &'a mut Vec } - - impl<'a> fmt::FormatWriter for VecWriter<'a> { - fn write(&mut self, buf: &[u8]) -> fmt::Result { - self.v.push_all(buf); - Ok(()) - } - } - - let mut v = Vec::new(); - let _ = write!(&mut VecWriter { v: &mut v }, "{}", msg); - - let msg = box String::from_utf8_lossy(v.as_slice()).into_owned(); - begin_unwind_inner(msg, file_line) -} - /// This is the entry point of unwinding for panic!() and assert!(). #[inline(never)] #[cold] // avoid code bloat at the call sites as much as possible pub fn begin_unwind(msg: M, file_line: &(&'static str, uint)) -> ! { diff --git a/src/libstd/rt/util.rs b/src/libstd/rt/util.rs index 6b007056a5114..5448af3f753b3 100644 --- a/src/libstd/rt/util.rs +++ b/src/libstd/rt/util.rs @@ -112,25 +112,11 @@ impl fmt::FormatWriter for Stdio { } } -// NOTE(stage0): Remove cfg after a snapshot -#[cfg(not(stage0))] pub fn dumb_print(args: fmt::Arguments) { let _ = Stderr.write_fmt(args); } -// NOTE(stage0): Remove function after a snapshot -#[cfg(stage0)] -pub fn dumb_print(args: &fmt::Arguments) { - let mut w = Stderr; - let _ = write!(&mut w, "{}", args); -} - -// NOTE(stage0): Remove wrappers after a snapshot -#[cfg(not(stage0))] pub fn abort(args: fmt::Arguments) -> ! { abort_(&args) } -#[cfg(stage0)] pub fn abort(args: &fmt::Arguments) -> ! { abort_(args) } - -// NOTE(stage0): Change to `pub fn abort(args: fmt::Arguments) -> !` after a snapshot -fn abort_(args: &fmt::Arguments) -> ! { +pub fn abort(args: fmt::Arguments) -> ! { use fmt::FormatWriter; struct BufWriter<'a> { diff --git a/src/libstd/sync/atomic.rs b/src/libstd/sync/atomic.rs index bdf947438f36b..18c917aca8a4a 100644 --- a/src/libstd/sync/atomic.rs +++ b/src/libstd/sync/atomic.rs @@ -101,9 +101,9 @@ use core::mem; use core::prelude::{Send, Drop, None, Option, Some}; pub use core::atomic::{AtomicBool, AtomicInt, AtomicUint, AtomicPtr}; -pub use core::atomic::{Ordering, Relaxed, Release, Acquire, AcqRel, SeqCst}; pub use core::atomic::{INIT_ATOMIC_BOOL, INIT_ATOMIC_INT, INIT_ATOMIC_UINT}; pub use core::atomic::fence; +pub use core::atomic::Ordering::{mod, Relaxed, Release, Acquire, AcqRel, SeqCst}; /// An atomic, nullable unique pointer /// diff --git a/src/libstd/sys/common/net.rs b/src/libstd/sys/common/net.rs index 7a09137a225dc..87ec20fbef872 100644 --- a/src/libstd/sys/common/net.rs +++ b/src/libstd/sys/common/net.rs @@ -13,6 +13,7 @@ use self::InAddr::*; use alloc::arc::Arc; use libc::{mod, c_char, c_int}; +use c_str::CString; use mem; use num::Int; use ptr::{mod, null, null_mut}; @@ -290,6 +291,43 @@ pub fn get_host_addresses(host: Option<&str>, servname: Option<&str>, Ok(addrs) } +//////////////////////////////////////////////////////////////////////////////// +// get_address_name +//////////////////////////////////////////////////////////////////////////////// + +extern "system" { + fn getnameinfo(sa: *const libc::sockaddr, salen: libc::socklen_t, + host: *mut c_char, hostlen: libc::size_t, + serv: *mut c_char, servlen: libc::size_t, + flags: c_int) -> c_int; +} + +const NI_MAXHOST: uint = 1025; + +pub fn get_address_name(addr: IpAddr) -> Result { + let addr = SocketAddr{ip: addr, port: 0}; + + let mut storage: libc::sockaddr_storage = unsafe { mem::zeroed() }; + let len = addr_to_sockaddr(addr, &mut storage); + + let mut hostbuf = [0 as c_char, ..NI_MAXHOST]; + + let res = unsafe { + getnameinfo(&storage as *const _ as *const libc::sockaddr, len, + hostbuf.as_mut_ptr(), NI_MAXHOST as libc::size_t, + ptr::null_mut(), 0, + 0) + }; + + if res != 0 { + return Err(last_gai_error(res)); + } + + unsafe { + Ok(CString::new(hostbuf.as_ptr(), false).as_str().unwrap().to_string()) + } +} + //////////////////////////////////////////////////////////////////////////////// // Timeout helpers // diff --git a/src/libstd/sys/unix/c.rs b/src/libstd/sys/unix/c.rs index a4ebcbd25d00e..208dc60e405dc 100644 --- a/src/libstd/sys/unix/c.rs +++ b/src/libstd/sys/unix/c.rs @@ -214,8 +214,8 @@ mod signal { sa_resv: [libc::c_int, ..1], } - impl ::kinds::Send for sigaction { } - impl ::kinds::Sync for sigaction { } + unsafe impl ::kinds::Send for sigaction { } + unsafe impl ::kinds::Sync for sigaction { } #[repr(C)] pub struct sigset_t { diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs index 4b7ac8ff4d3a9..c82dacf1e44e9 100644 --- a/src/libstd/sys/unix/mod.rs +++ b/src/libstd/sys/unix/mod.rs @@ -56,6 +56,7 @@ pub mod udp; pub mod addrinfo { pub use sys_common::net::get_host_addresses; + pub use sys_common::net::get_address_name; } // FIXME: move these to c module diff --git a/src/libstd/sys/unix/timer.rs b/src/libstd/sys/unix/timer.rs index fe393b81e3d9a..c0ef89666c0f5 100644 --- a/src/libstd/sys/unix/timer.rs +++ b/src/libstd/sys/unix/timer.rs @@ -120,9 +120,9 @@ fn helper(input: libc::c_int, messages: Receiver, _: ()) { // signals the first requests in the queue, possible re-enqueueing it. fn signal(active: &mut Vec>, dead: &mut Vec<(uint, Box)>) { - let mut timer = match active.remove(0) { - Some(timer) => timer, None => return - }; + if active.is_empty() { return } + + let mut timer = active.remove(0); let mut cb = timer.cb.take().unwrap(); cb.call(); if timer.repeat { @@ -178,7 +178,7 @@ fn helper(input: libc::c_int, messages: Receiver, _: ()) { Ok(RemoveTimer(id, ack)) => { match dead.iter().position(|&(i, _)| id == i) { Some(i) => { - let (_, i) = dead.remove(i).unwrap(); + let (_, i) = dead.remove(i); ack.send(i); continue } @@ -186,7 +186,7 @@ fn helper(input: libc::c_int, messages: Receiver, _: ()) { } let i = active.iter().position(|i| i.id == id); let i = i.expect("no timer found"); - let t = active.remove(i).unwrap(); + let t = active.remove(i); ack.send(t); } Err(..) => break diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs index aee98e22836be..57c284ed6a326 100644 --- a/src/libstd/sys/windows/mod.rs +++ b/src/libstd/sys/windows/mod.rs @@ -57,6 +57,7 @@ pub mod udp; pub mod addrinfo { pub use sys_common::net::get_host_addresses; + pub use sys_common::net::get_address_name; } // FIXME: move these to c module diff --git a/src/libstd/sys/windows/os.rs b/src/libstd/sys/windows/os.rs index fa08290a888e9..e7194df7ac3cb 100644 --- a/src/libstd/sys/windows/os.rs +++ b/src/libstd/sys/windows/os.rs @@ -17,14 +17,14 @@ use prelude::*; use fmt; use io::{IoResult, IoError}; -use libc::{c_int, c_char, c_void}; +use iter::repeat; +use libc::{c_int, c_void}; use libc; use os; use path::BytesContainer; use ptr; -use sync::atomic::{AtomicInt, INIT_ATOMIC_INT, SeqCst}; -use sys::fs::FileDesc; use slice; +use sys::fs::FileDesc; use os::TMPBUF_SZ; use libc::types::os::arch::extra::DWORD; @@ -130,7 +130,7 @@ pub fn fill_utf16_buf_and_decode(f: |*mut u16, DWORD| -> DWORD) -> Option = repeat(0u16).take(n as uint).collect(); let k = f(buf.as_mut_ptr(), n); if k == (0 as DWORD) { done = true; diff --git a/src/libstd/sys/windows/tty.rs b/src/libstd/sys/windows/tty.rs index 99292b3b44bd1..a88d11eed22bd 100644 --- a/src/libstd/sys/windows/tty.rs +++ b/src/libstd/sys/windows/tty.rs @@ -34,6 +34,7 @@ use libc::{c_int, HANDLE, LPDWORD, DWORD, LPVOID}; use libc::{get_osfhandle, CloseHandle}; use libc::types::os::arch::extra::LPCVOID; use io::{mod, IoError, IoResult, MemReader}; +use iter::repeat; use prelude::*; use ptr; use str::from_utf8; @@ -89,7 +90,7 @@ impl TTY { pub fn read(&mut self, buf: &mut [u8]) -> IoResult { // Read more if the buffer is empty if self.utf8.eof() { - let mut utf16 = Vec::from_elem(0x1000, 0u16); + let mut utf16: Vec = repeat(0u16).take(0x1000).collect(); let mut num: DWORD = 0; match unsafe { ReadConsoleW(self.handle, utf16.as_mut_ptr() as LPVOID, diff --git a/src/libstd/thread_local/mod.rs b/src/libstd/thread_local/mod.rs index 4cfa27093527a..14dd2a1ac9b58 100644 --- a/src/libstd/thread_local/mod.rs +++ b/src/libstd/thread_local/mod.rs @@ -189,22 +189,7 @@ macro_rules! __thread_local_inner { } }; - #[cfg(all(stage0, not(any(target_os = "macos", target_os = "linux"))))] - const INIT: ::std::thread_local::KeyInner<$t> = { - unsafe extern fn __destroy(ptr: *mut u8) { - ::std::thread_local::destroy_value::<$t>(ptr); - } - - ::std::thread_local::KeyInner { - inner: ::std::cell::UnsafeCell { value: $init }, - os: ::std::thread_local::OsStaticKey { - inner: ::std::thread_local::OS_INIT_INNER, - dtor: ::std::option::Option::Some(__destroy), - }, - } - }; - - #[cfg(all(not(stage0), not(any(target_os = "macos", target_os = "linux"))))] + #[cfg(all(not(any(target_os = "macos", target_os = "linux"))))] const INIT: ::std::thread_local::KeyInner<$t> = { unsafe extern fn __destroy(ptr: *mut u8) { ::std::thread_local::destroy_value::<$t>(ptr); @@ -346,16 +331,10 @@ mod imp { // *should* be the case that this loop always terminates because we // provide the guarantee that a TLS key cannot be set after it is // flagged for destruction. - #[cfg(not(stage0))] static DTORS: os::StaticKey = os::StaticKey { inner: os::INIT_INNER, dtor: Some(run_dtors as unsafe extern "C" fn(*mut u8)), }; - #[cfg(stage0)] - static DTORS: os::StaticKey = os::StaticKey { - inner: os::INIT_INNER, - dtor: Some(run_dtors), - }; type List = Vec<(*mut u8, unsafe extern fn(*mut u8))>; if DTORS.get().is_null() { let v: Box = box Vec::new(); diff --git a/src/libstd/time/duration.rs b/src/libstd/time/duration.rs index f7351c9580f2f..51564b539768d 100644 --- a/src/libstd/time/duration.rs +++ b/src/libstd/time/duration.rs @@ -262,20 +262,6 @@ impl Duration { } } -// NOTE(stage0): Remove impl after a snapshot -#[cfg(stage0)] -impl Neg for Duration { - #[inline] - fn neg(&self) -> Duration { - if self.nanos == 0 { - Duration { secs: -self.secs, nanos: 0 } - } else { - Duration { secs: -self.secs - 1, nanos: NANOS_PER_SEC - self.nanos } - } - } -} - -#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot impl Neg for Duration { #[inline] fn neg(self) -> Duration { diff --git a/src/libsyntax/ast_map/mod.rs b/src/libsyntax/ast_map/mod.rs index 5a4f5731be50d..b5395d09ca7d4 100644 --- a/src/libsyntax/ast_map/mod.rs +++ b/src/libsyntax/ast_map/mod.rs @@ -26,7 +26,7 @@ use arena::TypedArena; use std::cell::RefCell; use std::fmt; use std::io::IoResult; -use std::iter; +use std::iter::{mod, repeat}; use std::mem; use std::slice; @@ -726,7 +726,7 @@ impl<'ast> NodeCollector<'ast> { debug!("ast_map: {} => {}", id, entry); let len = self.map.len(); if id as uint >= len { - self.map.grow(id as uint - len + 1, NotPresent); + self.map.extend(repeat(NotPresent).take(id as uint - len + 1)); } self.map[id as uint] = entry; } diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index d2d624fa05e77..9fcaf2210c194 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -470,7 +470,7 @@ pub fn expand_item(it: P, fld: &mut MacroExpander) fn expand_item_modifiers(mut it: P, fld: &mut MacroExpander) -> P { // partition the attributes into ItemModifiers and others - let (modifiers, other_attrs) = it.attrs.partitioned(|attr| { + let (modifiers, other_attrs): (Vec<_>, _) = it.attrs.iter().cloned().partition(|attr| { match fld.cx.syntax_env.find(&intern(attr.name().get())) { Some(rc) => match *rc { Modifier(_) => true, _ => false }, _ => false diff --git a/src/libsyntax/ext/format.rs b/src/libsyntax/ext/format.rs index 6474d92953fd1..500070a14d2d9 100644 --- a/src/libsyntax/ext/format.rs +++ b/src/libsyntax/ext/format.rs @@ -22,6 +22,7 @@ use parse::token; use ptr::P; use std::collections::HashMap; +use std::iter::repeat; #[deriving(PartialEq)] enum ArgumentType { @@ -477,7 +478,7 @@ impl<'a, 'b> Context<'a, 'b> { /// to fn into_expr(mut self) -> P { let mut locals = Vec::new(); - let mut names = Vec::from_fn(self.name_positions.len(), |_| None); + let mut names: Vec<_> = repeat(None).take(self.name_positions.len()).collect(); let mut pats = Vec::new(); let mut heads = Vec::new(); @@ -664,7 +665,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span, name_ordering: Vec, names: HashMap>) -> P { - let arg_types = Vec::from_fn(args.len(), |_| None); + let arg_types: Vec<_> = range(0, args.len()).map(|_| None).collect(); let mut cx = Context { ecx: ecx, args: args, @@ -707,13 +708,10 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span, None => break } } - match parser.errors.remove(0) { - Some(error) => { - cx.ecx.span_err(cx.fmtsp, - format!("invalid format string: {}", error)[]); - return DummyResult::raw_expr(sp); - } - None => {} + if !parser.errors.is_empty() { + cx.ecx.span_err(cx.fmtsp, format!("invalid format string: {}", + parser.errors.remove(0))[]); + return DummyResult::raw_expr(sp); } if !cx.literal.is_empty() { let s = cx.trans_literal_string(); diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index 73ef18b8449e0..65ecf701e8dfc 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -166,7 +166,7 @@ pub fn count_names(ms: &[TokenTree]) -> uint { pub fn initial_matcher_pos(ms: Rc>, sep: Option, lo: BytePos) -> Box { let match_idx_hi = count_names(ms[]); - let matches = Vec::from_fn(match_idx_hi, |_i| Vec::new()); + let matches: Vec<_> = range(0, match_idx_hi).map(|_| Vec::new()).collect(); box MatcherPos { stack: vec![], top_elts: TtSeq(ms), @@ -392,7 +392,8 @@ pub fn parse(sess: &ParseSess, cur_eis.push(new_ei); } - let matches = Vec::from_elem(ei.matches.len(), Vec::new()); + let matches: Vec<_> = range(0, ei.matches.len()) + .map(|_| Vec::new()).collect(); let ei_t = ei; cur_eis.push(box MatcherPos { stack: vec![], diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs index ab0e0f9585c4e..a15f1ca354bff 100644 --- a/src/libsyntax/print/pp.rs +++ b/src/libsyntax/print/pp.rs @@ -65,6 +65,7 @@ pub use self::Token::*; use std::io; use std::string; +use std::iter::repeat; #[deriving(Clone, Copy, PartialEq)] pub enum Breaks { @@ -166,9 +167,9 @@ pub fn mk_printer(out: Box, linewidth: uint) -> Printer { // fall behind. let n: uint = 3 * linewidth; debug!("mk_printer {}", linewidth); - let token: Vec = Vec::from_elem(n, Eof); - let size: Vec = Vec::from_elem(n, 0i); - let scan_stack: Vec = Vec::from_elem(n, 0u); + let token: Vec = repeat(Eof).take(n).collect(); + let size: Vec = repeat(0i).take(n).collect(); + let scan_stack: Vec = repeat(0u).take(n).collect(); Printer { out: out, buf_len: n, diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs index e1c8ff5011b26..c1823231e24f7 100644 --- a/src/libsyntax/std_inject.rs +++ b/src/libsyntax/std_inject.rs @@ -163,7 +163,7 @@ impl<'a> fold::Folder for PreludeInjector<'a> { }), }; - let (crates, uses) = view_items.partitioned(|x| { + let (crates, uses): (Vec<_>, _) = view_items.iter().cloned().partition(|x| { match x.node { ast::ViewItemExternCrate(..) => true, _ => false, diff --git a/src/libterm/terminfo/parm.rs b/src/libterm/terminfo/parm.rs index bac2452524e3e..680ed55cd9843 100644 --- a/src/libterm/terminfo/parm.rs +++ b/src/libterm/terminfo/parm.rs @@ -16,6 +16,7 @@ use self::FormatState::*; use self::FormatOp::*; use std::ascii::OwnedAsciiExt; use std::mem::replace; +use std::iter::repeat; #[deriving(Copy, PartialEq)] enum States { @@ -508,7 +509,7 @@ fn format(val: Param, op: FormatOp, flags: Flags) -> Result ,String> { if flags.precision > s.len() { let mut s_ = Vec::with_capacity(flags.precision); let n = flags.precision - s.len(); - s_.grow(n, b'0'); + s_.extend(repeat(b'0').take(n)); s_.extend(s.into_iter()); s = s_; } @@ -560,10 +561,10 @@ fn format(val: Param, op: FormatOp, flags: Flags) -> Result ,String> { if flags.width > s.len() { let n = flags.width - s.len(); if flags.left { - s.grow(n, b' '); + s.extend(repeat(b' ').take(n)); } else { let mut s_ = Vec::with_capacity(flags.width); - s_.grow(n, b' '); + s_.extend(repeat(b' ').take(n)); s_.extend(s.into_iter()); s = s_; } diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 88dd6fce88f04..c097e93379050 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -990,8 +990,8 @@ fn run_tests(opts: &TestOpts, try!(callback(TeFiltered(filtered_descs))); - let (filtered_tests, filtered_benchs_and_metrics) = - filtered_tests.partition(|e| { + let (filtered_tests, filtered_benchs_and_metrics): (Vec<_>, _) = + filtered_tests.into_iter().partition(|e| { match e.testfn { StaticTestFn(_) | DynTestFn(_) => true, _ => false diff --git a/src/libtime/lib.rs b/src/libtime/lib.rs index e58a0229d6962..930aa0270647c 100644 --- a/src/libtime/lib.rs +++ b/src/libtime/lib.rs @@ -24,8 +24,6 @@ #[cfg(test)] #[phase(plugin, link)] extern crate log; -#[cfg(stage0)] -extern crate serialize; extern crate "serialize" as rustc_serialize; extern crate libc; diff --git a/src/libunicode/normalize.rs b/src/libunicode/normalize.rs index d239cb8289682..9e4aa0712470b 100644 --- a/src/libunicode/normalize.rs +++ b/src/libunicode/normalize.rs @@ -13,21 +13,21 @@ use core::cmp::Ordering::{Equal, Less, Greater}; use core::option::Option; use core::option::Option::{Some, None}; -use core::slice; use core::slice::SliceExt; +use core::result::Result::{Ok, Err}; use tables::normalization::{canonical_table, compatibility_table, composition_table}; fn bsearch_table(c: char, r: &'static [(char, &'static [T])]) -> Option<&'static [T]> { - match r.binary_search(|&(val, _)| { + match r.binary_search_by(|&(val, _)| { if c == val { Equal } else if val < c { Less } else { Greater } }) { - slice::BinarySearchResult::Found(idx) => { + Ok(idx) => { let (_, result) = r[idx]; Some(result) } - slice::BinarySearchResult::NotFound(_) => None + Err(_) => None } } @@ -81,16 +81,16 @@ pub fn compose(a: char, b: char) -> Option { match bsearch_table(a, composition_table) { None => None, Some(candidates) => { - match candidates.binary_search(|&(val, _)| { + match candidates.binary_search_by(|&(val, _)| { if b == val { Equal } else if val < b { Less } else { Greater } }) { - slice::BinarySearchResult::Found(idx) => { + Ok(idx) => { let (_, result) = candidates[idx]; Some(result) } - slice::BinarySearchResult::NotFound(_) => None + Err(_) => None } } } diff --git a/src/libunicode/tables.rs b/src/libunicode/tables.rs index a219aefad192c..5a8f63f207e27 100644 --- a/src/libunicode/tables.rs +++ b/src/libunicode/tables.rs @@ -19,11 +19,11 @@ pub const UNICODE_VERSION: (uint, uint, uint) = (7, 0, 0); fn bsearch_range_table(c: char, r: &'static [(char,char)]) -> bool { use core::cmp::Ordering::{Equal, Less, Greater}; use core::slice::SliceExt; - r.binary_search(|&(lo,hi)| { + r.binary_search_by(|&(lo,hi)| { if lo <= c && c <= hi { Equal } else if hi < c { Less } else { Greater } - }).found().is_some() + }).is_ok() } pub mod general_category { @@ -6826,17 +6826,17 @@ pub mod normalization { fn bsearch_range_value_table(c: char, r: &'static [(char, char, u8)]) -> u8 { use core::cmp::Ordering::{Equal, Less, Greater}; use core::slice::SliceExt; - use core::slice; - match r.binary_search(|&(lo, hi, _)| { + use core::result::Result::{Ok, Err}; + match r.binary_search_by(|&(lo, hi, _)| { if lo <= c && c <= hi { Equal } else if hi < c { Less } else { Greater } }) { - slice::BinarySearchResult::Found(idx) => { + Ok(idx) => { let (_, _, result) = r[idx]; result } - slice::BinarySearchResult::NotFound(_) => 0 + Err(_) => 0 } } @@ -6961,7 +6961,7 @@ pub mod conversions { use core::slice::SliceExt; use core::option::Option; use core::option::Option::{Some, None}; - use core::slice; + use core::result::Result::{Ok, Err}; pub fn to_lower(c: char) -> char { match bsearch_case_table(c, LuLl_table) { @@ -6978,13 +6978,13 @@ pub mod conversions { } fn bsearch_case_table(c: char, table: &'static [(char, char)]) -> Option { - match table.binary_search(|&(key, _)| { + match table.binary_search_by(|&(key, _)| { if c == key { Equal } else if key < c { Less } else { Greater } }) { - slice::BinarySearchResult::Found(i) => Some(i), - slice::BinarySearchResult::NotFound(_) => None, + Ok(i) => Some(i), + Err(_) => None, } } @@ -7596,20 +7596,20 @@ pub mod charwidth { use core::option::Option; use core::option::Option::{Some, None}; use core::slice::SliceExt; - use core::slice; + use core::result::Result::{Ok, Err}; fn bsearch_range_value_table(c: char, is_cjk: bool, r: &'static [(char, char, u8, u8)]) -> u8 { use core::cmp::Ordering::{Equal, Less, Greater}; - match r.binary_search(|&(lo, hi, _, _)| { + match r.binary_search_by(|&(lo, hi, _, _)| { if lo <= c && c <= hi { Equal } else if hi < c { Less } else { Greater } }) { - slice::BinarySearchResult::Found(idx) => { + Ok(idx) => { let (_, _, r_ncjk, r_cjk) = r[idx]; if is_cjk { r_cjk } else { r_ncjk } } - slice::BinarySearchResult::NotFound(_) => 1 + Err(_) => 1 } } @@ -7804,7 +7804,7 @@ pub mod grapheme { use core::kinds::Copy; use core::slice::SliceExt; pub use self::GraphemeCat::*; - use core::slice; + use core::result::Result::{Ok, Err}; #[allow(non_camel_case_types)] #[deriving(Clone)] @@ -7825,16 +7825,16 @@ pub mod grapheme { fn bsearch_range_value_table(c: char, r: &'static [(char, char, GraphemeCat)]) -> GraphemeCat { use core::cmp::Ordering::{Equal, Less, Greater}; - match r.binary_search(|&(lo, hi, _)| { + match r.binary_search_by(|&(lo, hi, _)| { if lo <= c && c <= hi { Equal } else if hi < c { Less } else { Greater } }) { - slice::BinarySearchResult::Found(idx) => { + Ok(idx) => { let (_, _, cat) = r[idx]; cat } - slice::BinarySearchResult::NotFound(_) => GC_Any + Err(_) => GC_Any } } diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index 9fda05431db49..bce73a2769936 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -257,7 +257,7 @@ extern "C" void LLVMDIBuilderFinalize(DIBuilderRef Builder) { Builder->finalize(); } -extern "C" void LLVMDIBuilderCreateCompileUnit( +extern "C" LLVMValueRef LLVMDIBuilderCreateCompileUnit( DIBuilderRef Builder, unsigned Lang, const char* File, @@ -267,8 +267,14 @@ extern "C" void LLVMDIBuilderCreateCompileUnit( const char* Flags, unsigned RuntimeVer, const char* SplitName) { - Builder->createCompileUnit(Lang, File, Dir, Producer, isOptimized, - Flags, RuntimeVer, SplitName); + return wrap(Builder->createCompileUnit(Lang, + File, + Dir, + Producer, + isOptimized, + Flags, + RuntimeVer, + SplitName)); } extern "C" LLVMValueRef LLVMDIBuilderCreateFile( diff --git a/src/snapshots.txt b/src/snapshots.txt index c3cdf4acba150..6a9bfa07cf771 100644 --- a/src/snapshots.txt +++ b/src/snapshots.txt @@ -1,3 +1,12 @@ +S 2014-12-30 023dfb0 + freebsd-x86_64 41ecd0ac557c823831c46696c7d78dc250398f25 + linux-i386 fe6b59bf70a397e18629cb82264f7c6a70df34d4 + linux-x86_64 8ab3a223f65fbf6b0aa80fcf0564a6d0fb9122e8 + macos-i386 d23edb1be58b8683782a473cdc249c58a959c165 + macos-x86_64 ab87616fa5d427978db3acd2d705042133ca3c09 + winnt-i386 f2c26ac1ccb9d9a00886da9b504190681de89a5f + winnt-x86_64 fa2c7636bb15583ae387554b561ab09babee281a + S 2014-12-20 8443b09 freebsd-x86_64 004f54dce86faeebc15abf92c8742634b53987e6 linux-i386 3daf531aed03f5769402f2fef852377e2838db98 diff --git a/src/test/bench/core-std.rs b/src/test/bench/core-std.rs index d9a4aede7d7d9..26d4ec25c6439 100644 --- a/src/test/bench/core-std.rs +++ b/src/test/bench/core-std.rs @@ -65,7 +65,7 @@ fn shift_push() { let mut v2 = Vec::new(); while v1.len() > 0 { - v2.push(v1.remove(0).unwrap()); + v2.push(v1.remove(0)); } } diff --git a/src/test/bench/shootout-reverse-complement.rs b/src/test/bench/shootout-reverse-complement.rs index 6ee2233f16862..909f8afc34a9f 100644 --- a/src/test/bench/shootout-reverse-complement.rs +++ b/src/test/bench/shootout-reverse-complement.rs @@ -181,7 +181,7 @@ fn reverse_complement(seq: &mut [u8], tables: &Tables) { unsafe { copy_memory(seq.as_mut_ptr().offset((i - off + 1) as int), seq.as_ptr().offset((i - off) as int), off); - *seq.unsafe_mut(i - off) = b'\n'; + *seq.get_unchecked_mut(i - off) = b'\n'; } i += LINE_LEN + 1; } diff --git a/src/test/compile-fail/issue-15756.rs b/src/test/compile-fail/issue-15756.rs index df19de7731a9e..5be3b960ec635 100644 --- a/src/test/compile-fail/issue-15756.rs +++ b/src/test/compile-fail/issue-15756.rs @@ -9,9 +9,9 @@ // except according to those terms. use std::slice::Chunks; -use std::slice::MutChunks; +use std::slice::ChunksMut; -fn dft_iter<'a, T>(arg1: Chunks<'a,T>, arg2: MutChunks<'a,T>) +fn dft_iter<'a, T>(arg1: Chunks<'a,T>, arg2: ChunksMut<'a,T>) { for &something diff --git a/src/test/compile-fail/resolve-conflict-type-vs-import.rs b/src/test/compile-fail/resolve-conflict-type-vs-import.rs index de934286a7cba..45b0314d2c01d 100644 --- a/src/test/compile-fail/resolve-conflict-type-vs-import.rs +++ b/src/test/compile-fail/resolve-conflict-type-vs-import.rs @@ -15,4 +15,3 @@ struct Iter; fn main() { } - diff --git a/src/test/compile-fail/trait-object-safety.rs b/src/test/compile-fail/trait-object-safety.rs new file mode 100644 index 0000000000000..761bcd4968abf --- /dev/null +++ b/src/test/compile-fail/trait-object-safety.rs @@ -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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Check that static methods are not object-safe. + +trait Tr { + fn foo(); +} + +struct St; + +impl Tr for St { + fn foo() {} +} + +fn main() { + let _: &Tr = &St; //~ ERROR cannot convert to a trait object because trait `Tr` is not +} diff --git a/src/test/debuginfo/basic-types-globals-metadata.rs b/src/test/debuginfo/basic-types-globals-metadata.rs index 54d34d1840ca0..4251f22b29147 100644 --- a/src/test/debuginfo/basic-types-globals-metadata.rs +++ b/src/test/debuginfo/basic-types-globals-metadata.rs @@ -45,6 +45,7 @@ #![allow(unused_variables)] #![allow(dead_code)] +#![omit_gdb_pretty_printer_section] static B: bool = false; diff --git a/src/test/debuginfo/basic-types-globals.rs b/src/test/debuginfo/basic-types-globals.rs index bbb8c2423c375..a4d4ddfea531d 100644 --- a/src/test/debuginfo/basic-types-globals.rs +++ b/src/test/debuginfo/basic-types-globals.rs @@ -50,6 +50,7 @@ // gdb-command:continue #![allow(unused_variables)] +#![omit_gdb_pretty_printer_section] static B: bool = false; static I: int = -1; diff --git a/src/test/debuginfo/basic-types-metadata.rs b/src/test/debuginfo/basic-types-metadata.rs index b998f096a0738..6aa228ec51bfc 100644 --- a/src/test/debuginfo/basic-types-metadata.rs +++ b/src/test/debuginfo/basic-types-metadata.rs @@ -48,6 +48,7 @@ // gdb-command:continue #![allow(unused_variables)] +#![omit_gdb_pretty_printer_section] fn main() { let unit: () = (); diff --git a/src/test/debuginfo/basic-types-mut-globals.rs b/src/test/debuginfo/basic-types-mut-globals.rs index 435bfd98989b3..bc8cdaf8eacc9 100644 --- a/src/test/debuginfo/basic-types-mut-globals.rs +++ b/src/test/debuginfo/basic-types-mut-globals.rs @@ -83,6 +83,7 @@ // gdb-check:$28 = 9.25 #![allow(unused_variables)] +#![omit_gdb_pretty_printer_section] static mut B: bool = false; static mut I: int = -1; diff --git a/src/test/debuginfo/basic-types.rs b/src/test/debuginfo/basic-types.rs index 8be91e3ee76b3..f61f49228cdeb 100644 --- a/src/test/debuginfo/basic-types.rs +++ b/src/test/debuginfo/basic-types.rs @@ -88,6 +88,7 @@ // lldb-check:[...]$12 = 3.5 #![allow(unused_variables)] +#![omit_gdb_pretty_printer_section] fn main() { let b: bool = false; diff --git a/src/test/debuginfo/borrowed-basic.rs b/src/test/debuginfo/borrowed-basic.rs index 00bee44d264cf..f4c31278cf63b 100644 --- a/src/test/debuginfo/borrowed-basic.rs +++ b/src/test/debuginfo/borrowed-basic.rs @@ -109,6 +109,7 @@ // lldb-check:[...]$12 = 3.5 #![allow(unused_variables)] +#![omit_gdb_pretty_printer_section] fn main() { let bool_val: bool = true; diff --git a/src/test/debuginfo/borrowed-c-style-enum.rs b/src/test/debuginfo/borrowed-c-style-enum.rs index bbda6c93ebaf9..c2da58f1583c0 100644 --- a/src/test/debuginfo/borrowed-c-style-enum.rs +++ b/src/test/debuginfo/borrowed-c-style-enum.rs @@ -41,6 +41,7 @@ // lldb-check:[...]$2 = TheC #![allow(unused_variables)] +#![omit_gdb_pretty_printer_section] enum ABC { TheA, TheB, TheC } diff --git a/src/test/debuginfo/borrowed-enum.rs b/src/test/debuginfo/borrowed-enum.rs index 9cda56a774380..d54869888f182 100644 --- a/src/test/debuginfo/borrowed-enum.rs +++ b/src/test/debuginfo/borrowed-enum.rs @@ -40,6 +40,7 @@ // lldb-check:[...]$2 = TheOnlyCase(4820353753753434) #![allow(unused_variables)] +#![omit_gdb_pretty_printer_section] // The first element is to ensure proper alignment, irrespective of the machines word size. Since // the size of the discriminant value is machine dependent, this has be taken into account when diff --git a/src/test/debuginfo/borrowed-struct.rs b/src/test/debuginfo/borrowed-struct.rs index 7e6cf41162c38..e3cf438be439c 100644 --- a/src/test/debuginfo/borrowed-struct.rs +++ b/src/test/debuginfo/borrowed-struct.rs @@ -64,6 +64,7 @@ // lldb-check:[...]$6 = 26.5 #![allow(unused_variables)] +#![omit_gdb_pretty_printer_section] struct SomeStruct { x: int, diff --git a/src/test/debuginfo/borrowed-tuple.rs b/src/test/debuginfo/borrowed-tuple.rs index 57c1445046749..ce0930f2fbf38 100644 --- a/src/test/debuginfo/borrowed-tuple.rs +++ b/src/test/debuginfo/borrowed-tuple.rs @@ -42,6 +42,7 @@ #![allow(unused_variables)] +#![omit_gdb_pretty_printer_section] fn main() { let stack_val: (i16, f32) = (-14, -19f32); diff --git a/src/test/debuginfo/borrowed-unique-basic.rs b/src/test/debuginfo/borrowed-unique-basic.rs index 30787716c72a8..d152775a8ed6a 100644 --- a/src/test/debuginfo/borrowed-unique-basic.rs +++ b/src/test/debuginfo/borrowed-unique-basic.rs @@ -112,7 +112,7 @@ // lldb-check:[...]$12 = 3.5 #![allow(unused_variables)] - +#![omit_gdb_pretty_printer_section] fn main() { let bool_box: Box = box true; diff --git a/src/test/debuginfo/box.rs b/src/test/debuginfo/box.rs index 59f0c8f2d657c..5a70eb1904128 100644 --- a/src/test/debuginfo/box.rs +++ b/src/test/debuginfo/box.rs @@ -32,6 +32,7 @@ // lldb-check:[...]$1 = (2, 3.5) #![allow(unused_variables)] +#![omit_gdb_pretty_printer_section] fn main() { let a = box 1i; diff --git a/src/test/debuginfo/boxed-struct.rs b/src/test/debuginfo/boxed-struct.rs index 8f77de7e6d3ce..f9d762bf99d28 100644 --- a/src/test/debuginfo/boxed-struct.rs +++ b/src/test/debuginfo/boxed-struct.rs @@ -35,6 +35,7 @@ // lldb-check:[...]$1 = StructWithDestructor { x: 77, y: 777, z: 7777, w: 77777 } #![allow(unused_variables)] +#![omit_gdb_pretty_printer_section] struct StructWithSomePadding { x: i16, diff --git a/src/test/debuginfo/by-value-non-immediate-argument.rs b/src/test/debuginfo/by-value-non-immediate-argument.rs index 258c49afcc42c..b0c5b2f21b95c 100644 --- a/src/test/debuginfo/by-value-non-immediate-argument.rs +++ b/src/test/debuginfo/by-value-non-immediate-argument.rs @@ -71,6 +71,8 @@ // lldb-check:[...]$6 = Case1 { x: 0, y: 8970181431921507452 } // lldb-command:continue +#![omit_gdb_pretty_printer_section] + #[deriving(Clone)] struct Struct { a: int, diff --git a/src/test/debuginfo/by-value-self-argument-in-trait-impl.rs b/src/test/debuginfo/by-value-self-argument-in-trait-impl.rs index 57a3e503d0aa9..6907313370e1a 100644 --- a/src/test/debuginfo/by-value-self-argument-in-trait-impl.rs +++ b/src/test/debuginfo/by-value-self-argument-in-trait-impl.rs @@ -46,6 +46,8 @@ // lldb-check:[...]$2 = (4444.5, 5555, 6666, 7777.5) // lldb-command:continue +#![omit_gdb_pretty_printer_section] + trait Trait { fn method(self) -> Self; } diff --git a/src/test/debuginfo/c-style-enum-in-composite.rs b/src/test/debuginfo/c-style-enum-in-composite.rs index 17e4110c2f1d3..f2dfc63d52253 100644 --- a/src/test/debuginfo/c-style-enum-in-composite.rs +++ b/src/test/debuginfo/c-style-enum-in-composite.rs @@ -65,6 +65,7 @@ // lldb-check:[...]$6 = (StructWithDrop { a: OneHundred, b: Vienna }, 9) #![allow(unused_variables)] +#![omit_gdb_pretty_printer_section] use self::AnEnum::{OneHundred, OneThousand, OneMillion}; use self::AnotherEnum::{MountainView, Toronto, Vienna}; diff --git a/src/test/debuginfo/c-style-enum.rs b/src/test/debuginfo/c-style-enum.rs index b0a0142f6dd55..b62a8167eaf07 100644 --- a/src/test/debuginfo/c-style-enum.rs +++ b/src/test/debuginfo/c-style-enum.rs @@ -99,6 +99,7 @@ #![allow(unused_variables)] #![allow(dead_code)] +#![omit_gdb_pretty_printer_section] use self::AutoDiscriminant::{One, Two, Three}; use self::ManualDiscriminant::{OneHundred, OneThousand, OneMillion}; diff --git a/src/test/debuginfo/closure-in-generic-function.rs b/src/test/debuginfo/closure-in-generic-function.rs index 673b4676a9552..84366ae711465 100644 --- a/src/test/debuginfo/closure-in-generic-function.rs +++ b/src/test/debuginfo/closure-in-generic-function.rs @@ -46,6 +46,8 @@ // lldb-check:[...]$3 = 110 // lldb-command:continue +#![omit_gdb_pretty_printer_section] + fn some_generic_fun(a: T1, b: T2) -> (T2, T1) { let closure = |x, y| { diff --git a/src/test/debuginfo/destructured-fn-argument.rs b/src/test/debuginfo/destructured-fn-argument.rs index 17e1651f9f6ed..b4688e4928a6b 100644 --- a/src/test/debuginfo/destructured-fn-argument.rs +++ b/src/test/debuginfo/destructured-fn-argument.rs @@ -311,6 +311,7 @@ // lldb-command:continue #![allow(unused_variables)] +#![omit_gdb_pretty_printer_section] use self::Univariant::Unit; diff --git a/src/test/debuginfo/destructured-for-loop-variable.rs b/src/test/debuginfo/destructured-for-loop-variable.rs index 9935bb6036486..364720d0e4fb3 100644 --- a/src/test/debuginfo/destructured-for-loop-variable.rs +++ b/src/test/debuginfo/destructured-for-loop-variable.rs @@ -152,6 +152,9 @@ // lldb-check:[...]$23 = (34903493, 232323) // lldb-command:continue +#![allow(unused_variables)] +#![omit_gdb_pretty_printer_section] + struct Struct { x: i16, y: f32, diff --git a/src/test/debuginfo/destructured-local.rs b/src/test/debuginfo/destructured-local.rs index 58db37888e6d7..d5a6b36f1fcf9 100644 --- a/src/test/debuginfo/destructured-local.rs +++ b/src/test/debuginfo/destructured-local.rs @@ -244,6 +244,7 @@ #![allow(unused_variables)] +#![omit_gdb_pretty_printer_section] use self::Univariant::Unit; diff --git a/src/test/debuginfo/evec-in-struct.rs b/src/test/debuginfo/evec-in-struct.rs index 786868f6b89dd..f623a321922b8 100644 --- a/src/test/debuginfo/evec-in-struct.rs +++ b/src/test/debuginfo/evec-in-struct.rs @@ -51,6 +51,7 @@ // lldb-check:[...]$4 = StructPaddedAtEnd { x: [22, 23], y: [24, 25] } #![allow(unused_variables)] +#![omit_gdb_pretty_printer_section] struct NoPadding1 { x: [u32; 3], diff --git a/src/test/debuginfo/function-arg-initialization.rs b/src/test/debuginfo/function-arg-initialization.rs index 53b3044b0f7f7..55c5c50406416 100644 --- a/src/test/debuginfo/function-arg-initialization.rs +++ b/src/test/debuginfo/function-arg-initialization.rs @@ -222,10 +222,8 @@ // lldb-command:continue - #![allow(unused_variables)] - - +#![omit_gdb_pretty_printer_section] fn immediate_args(a: int, b: bool, c: f64) { ::std::io::print("") // #break diff --git a/src/test/debuginfo/function-arguments.rs b/src/test/debuginfo/function-arguments.rs index 304745e39453d..01136c11014a3 100644 --- a/src/test/debuginfo/function-arguments.rs +++ b/src/test/debuginfo/function-arguments.rs @@ -45,6 +45,9 @@ // lldb-check:[...]$3 = 3000 // lldb-command:continue + +#![omit_gdb_pretty_printer_section] + fn main() { fun(111102, true); diff --git a/src/test/debuginfo/function-prologue-stepping-no-stack-check.rs b/src/test/debuginfo/function-prologue-stepping-no-stack-check.rs index 3288fa4c0cbd1..e437e35db3a99 100644 --- a/src/test/debuginfo/function-prologue-stepping-no-stack-check.rs +++ b/src/test/debuginfo/function-prologue-stepping-no-stack-check.rs @@ -245,6 +245,7 @@ // lldb-command:continue #![allow(unused_variables)] +#![omit_gdb_pretty_printer_section] #[no_stack_check] fn immediate_args(a: int, b: bool, c: f64) { diff --git a/src/test/debuginfo/function-prologue-stepping-regular.rs b/src/test/debuginfo/function-prologue-stepping-regular.rs index dbeb87fd44afe..05ea357389bc6 100644 --- a/src/test/debuginfo/function-prologue-stepping-regular.rs +++ b/src/test/debuginfo/function-prologue-stepping-regular.rs @@ -126,6 +126,7 @@ // lldb-command:continue #![allow(unused_variables)] +#![omit_gdb_pretty_printer_section] fn immediate_args(a: int, b: bool, c: f64) { () 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 index 8abb2cd5c26f9..092cd9edc7065 100644 --- 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 @@ -17,7 +17,6 @@ // ignore-lldb // ignore-android: FIXME(#10381) // compile-flags:-g -// gdb-use-pretty-printer // gdb-command: run diff --git a/src/test/debuginfo/gdb-pretty-struct-and-enums.rs b/src/test/debuginfo/gdb-pretty-struct-and-enums.rs index 76cf3c1149dd5..64c120e1ab3a9 100644 --- a/src/test/debuginfo/gdb-pretty-struct-and-enums.rs +++ b/src/test/debuginfo/gdb-pretty-struct-and-enums.rs @@ -13,7 +13,6 @@ // 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 diff --git a/src/test/debuginfo/generic-function.rs b/src/test/debuginfo/generic-function.rs index abfe95db51ba2..cefe67970e959 100644 --- a/src/test/debuginfo/generic-function.rs +++ b/src/test/debuginfo/generic-function.rs @@ -70,6 +70,7 @@ // lldb-check:[...]$8 = ((5, Struct { a: 6, b: 7.5 }), (Struct { a: 6, b: 7.5 }, 5)) // lldb-command:continue +#![omit_gdb_pretty_printer_section] #[deriving(Clone)] struct Struct { diff --git a/src/test/debuginfo/generic-functions-nested.rs b/src/test/debuginfo/generic-functions-nested.rs index 069906b14fd08..0f3fd556f189a 100644 --- a/src/test/debuginfo/generic-functions-nested.rs +++ b/src/test/debuginfo/generic-functions-nested.rs @@ -70,6 +70,9 @@ // lldb-check:[...]$7 = 2.5 // lldb-command:continue + +#![omit_gdb_pretty_printer_section] + fn outer(a: TA) { inner(a.clone(), 1i); inner(a.clone(), 2.5f64); diff --git a/src/test/debuginfo/generic-method-on-generic-struct.rs b/src/test/debuginfo/generic-method-on-generic-struct.rs index 4c0c82efea35d..0e358499a3d02 100644 --- a/src/test/debuginfo/generic-method-on-generic-struct.rs +++ b/src/test/debuginfo/generic-method-on-generic-struct.rs @@ -112,6 +112,7 @@ // lldb-check:[...]$14 = -10.5 // lldb-command:continue +#![omit_gdb_pretty_printer_section] struct Struct { x: T diff --git a/src/test/debuginfo/generic-static-method-on-struct-and-enum.rs b/src/test/debuginfo/generic-static-method-on-struct-and-enum.rs index d69d432fcb30f..bf755d379a623 100644 --- a/src/test/debuginfo/generic-static-method-on-struct-and-enum.rs +++ b/src/test/debuginfo/generic-static-method-on-struct-and-enum.rs @@ -31,6 +31,9 @@ // gdb-check:$5 = 5 // gdb-command:continue + +#![omit_gdb_pretty_printer_section] + struct Struct { x: int } diff --git a/src/test/debuginfo/generic-struct-style-enum.rs b/src/test/debuginfo/generic-struct-style-enum.rs index 5e96726642172..992e74179137b 100644 --- a/src/test/debuginfo/generic-struct-style-enum.rs +++ b/src/test/debuginfo/generic-struct-style-enum.rs @@ -29,6 +29,9 @@ // gdb-command:print univariant // gdb-check:$4 = {{a = -1}} + +#![omit_gdb_pretty_printer_section] + use self::Regular::{Case1, Case2, Case3}; use self::Univariant::TheOnlyCase; diff --git a/src/test/debuginfo/generic-struct.rs b/src/test/debuginfo/generic-struct.rs index 7d485a6f5d5a0..908968fd6b32a 100644 --- a/src/test/debuginfo/generic-struct.rs +++ b/src/test/debuginfo/generic-struct.rs @@ -41,6 +41,9 @@ // lldb-command:print float_int_float // lldb-check:[...]$3 = AGenericStruct> { key: 6.5, value: AGenericStruct { key: 7, value: 8.5 } } + +#![omit_gdb_pretty_printer_section] + struct AGenericStruct { key: TKey, value: TValue diff --git a/src/test/debuginfo/generic-trait-generic-static-default-method.rs b/src/test/debuginfo/generic-trait-generic-static-default-method.rs index 0984f8c9fa2cf..4382861fd2099 100644 --- a/src/test/debuginfo/generic-trait-generic-static-default-method.rs +++ b/src/test/debuginfo/generic-trait-generic-static-default-method.rs @@ -25,6 +25,7 @@ // gdb-check:$4 = {3.5, {4, 5, 6}} // gdb-command:continue +#![omit_gdb_pretty_printer_section] struct Struct { x: int diff --git a/src/test/debuginfo/generic-tuple-style-enum.rs b/src/test/debuginfo/generic-tuple-style-enum.rs index 74d5dd2adc800..f9dc9d1f055c8 100644 --- a/src/test/debuginfo/generic-tuple-style-enum.rs +++ b/src/test/debuginfo/generic-tuple-style-enum.rs @@ -48,6 +48,8 @@ // lldb-command:print univariant // lldb-check:[...]$3 = TheOnlyCase(-1) +#![omit_gdb_pretty_printer_section] + use self::Regular::{Case1, Case2, Case3}; use self::Univariant::TheOnlyCase; diff --git a/src/test/debuginfo/include_string.rs b/src/test/debuginfo/include_string.rs index f196938437a39..25719a802863d 100644 --- a/src/test/debuginfo/include_string.rs +++ b/src/test/debuginfo/include_string.rs @@ -36,6 +36,7 @@ // lldb-command:continue #![allow(unused_variables)] +#![omit_gdb_pretty_printer_section] // This test case makes sure that debug info does not ICE when include_str is // used multiple times (see issue #11322). diff --git a/src/test/debuginfo/issue12886.rs b/src/test/debuginfo/issue12886.rs index e2dae2dc3f059..c6acc9a31fe3c 100644 --- a/src/test/debuginfo/issue12886.rs +++ b/src/test/debuginfo/issue12886.rs @@ -16,9 +16,11 @@ // gdb-command:run // gdb-command:next -// gdb-check:[...]32[...]s +// gdb-check:[...]34[...]s // gdb-command:continue +#![omit_gdb_pretty_printer_section] + // IF YOU MODIFY THIS FILE, BE CAREFUL TO ADAPT THE LINE NUMBERS IN THE DEBUGGER COMMANDS // This test makes sure that gdb does not set unwanted breakpoints in inlined functions. If a diff --git a/src/test/debuginfo/lexical-scope-in-for-loop.rs b/src/test/debuginfo/lexical-scope-in-for-loop.rs index 7636ffdb07dcd..3309ae13c9dcb 100644 --- a/src/test/debuginfo/lexical-scope-in-for-loop.rs +++ b/src/test/debuginfo/lexical-scope-in-for-loop.rs @@ -86,6 +86,8 @@ // lldb-check:[...]$6 = 1000000 // lldb-command:continue +#![omit_gdb_pretty_printer_section] + fn main() { let range = [1i, 2, 3]; diff --git a/src/test/debuginfo/lexical-scope-in-if.rs b/src/test/debuginfo/lexical-scope-in-if.rs index 5bfe8371209c4..bc3a694524325 100644 --- a/src/test/debuginfo/lexical-scope-in-if.rs +++ b/src/test/debuginfo/lexical-scope-in-if.rs @@ -134,6 +134,7 @@ // lldb-check:[...]$15 = -1 // lldb-command:continue +#![omit_gdb_pretty_printer_section] fn main() { diff --git a/src/test/debuginfo/lexical-scope-in-match.rs b/src/test/debuginfo/lexical-scope-in-match.rs index 6a956e06f245b..37976ab3996ae 100644 --- a/src/test/debuginfo/lexical-scope-in-match.rs +++ b/src/test/debuginfo/lexical-scope-in-match.rs @@ -126,6 +126,7 @@ // lldb-check:[...]$17 = 232 // lldb-command:continue +#![omit_gdb_pretty_printer_section] struct Struct { x: int, diff --git a/src/test/debuginfo/lexical-scope-in-stack-closure.rs b/src/test/debuginfo/lexical-scope-in-stack-closure.rs index 6666ddfbc829c..d6e3a43eea0a6 100644 --- a/src/test/debuginfo/lexical-scope-in-stack-closure.rs +++ b/src/test/debuginfo/lexical-scope-in-stack-closure.rs @@ -70,6 +70,8 @@ // lldb-check:[...]$5 = false // lldb-command:continue +#![omit_gdb_pretty_printer_section] + fn main() { let x = false; diff --git a/src/test/debuginfo/lexical-scope-in-unconditional-loop.rs b/src/test/debuginfo/lexical-scope-in-unconditional-loop.rs index 51ddc83a8d863..b295c6f37a7a1 100644 --- a/src/test/debuginfo/lexical-scope-in-unconditional-loop.rs +++ b/src/test/debuginfo/lexical-scope-in-unconditional-loop.rs @@ -132,6 +132,8 @@ // lldb-check:[...]$12 = 2 // lldb-command:continue +#![omit_gdb_pretty_printer_section] + fn main() { let mut x = 0i; diff --git a/src/test/debuginfo/lexical-scope-in-unique-closure.rs b/src/test/debuginfo/lexical-scope-in-unique-closure.rs index fa7822495d5f1..be4085b63abe5 100644 --- a/src/test/debuginfo/lexical-scope-in-unique-closure.rs +++ b/src/test/debuginfo/lexical-scope-in-unique-closure.rs @@ -70,6 +70,9 @@ // lldb-check:[...]$5 = false // lldb-command:continue + +#![omit_gdb_pretty_printer_section] + fn main() { let x = false; diff --git a/src/test/debuginfo/lexical-scope-in-while.rs b/src/test/debuginfo/lexical-scope-in-while.rs index bafff552cd394..c7a36ef9b82bd 100644 --- a/src/test/debuginfo/lexical-scope-in-while.rs +++ b/src/test/debuginfo/lexical-scope-in-while.rs @@ -132,6 +132,7 @@ // lldb-check:[...]$12 = 2 // lldb-command:continue +#![omit_gdb_pretty_printer_section] fn main() { diff --git a/src/test/debuginfo/lexical-scope-with-macro.rs b/src/test/debuginfo/lexical-scope-with-macro.rs index 2c76f2ca7dfa8..be52ffff1b45e 100644 --- a/src/test/debuginfo/lexical-scope-with-macro.rs +++ b/src/test/debuginfo/lexical-scope-with-macro.rs @@ -112,6 +112,7 @@ #![feature(macro_rules)] +#![omit_gdb_pretty_printer_section] macro_rules! trivial { ($e1:expr) => ($e1) diff --git a/src/test/debuginfo/lexical-scopes-in-block-expression.rs b/src/test/debuginfo/lexical-scopes-in-block-expression.rs index 41dee642feacd..2f8b11ac283b6 100644 --- a/src/test/debuginfo/lexical-scopes-in-block-expression.rs +++ b/src/test/debuginfo/lexical-scopes-in-block-expression.rs @@ -349,6 +349,7 @@ #![allow(unused_variables)] #![allow(unused_assignments)] +#![omit_gdb_pretty_printer_section] static mut MUT_INT: int = 0; diff --git a/src/test/debuginfo/limited-debuginfo.rs b/src/test/debuginfo/limited-debuginfo.rs index 3a633fc5eeccf..35889ff81335c 100644 --- a/src/test/debuginfo/limited-debuginfo.rs +++ b/src/test/debuginfo/limited-debuginfo.rs @@ -30,6 +30,7 @@ #![allow(unused_variables)] +#![omit_gdb_pretty_printer_section] struct Struct { a: i64, diff --git a/src/test/debuginfo/method-on-enum.rs b/src/test/debuginfo/method-on-enum.rs index 8cb8fae75cf06..b1ebb124d4e76 100644 --- a/src/test/debuginfo/method-on-enum.rs +++ b/src/test/debuginfo/method-on-enum.rs @@ -113,6 +113,8 @@ // lldb-check:[...]$14 = -10 // lldb-command:continue +#![omit_gdb_pretty_printer_section] + enum Enum { Variant1 { x: u16, y: u16 }, Variant2 (u32) diff --git a/src/test/debuginfo/method-on-generic-struct.rs b/src/test/debuginfo/method-on-generic-struct.rs index d4244ee27d4c2..68a6ac8c1f31e 100644 --- a/src/test/debuginfo/method-on-generic-struct.rs +++ b/src/test/debuginfo/method-on-generic-struct.rs @@ -113,6 +113,8 @@ // lldb-command:continue +#![omit_gdb_pretty_printer_section] + struct Struct { x: T } diff --git a/src/test/debuginfo/method-on-struct.rs b/src/test/debuginfo/method-on-struct.rs index ca00587ba445d..84e74d4364cfa 100644 --- a/src/test/debuginfo/method-on-struct.rs +++ b/src/test/debuginfo/method-on-struct.rs @@ -112,6 +112,9 @@ // lldb-check:[...]$14 = -10 // lldb-command:continue + +#![omit_gdb_pretty_printer_section] + struct Struct { x: int } diff --git a/src/test/debuginfo/method-on-trait.rs b/src/test/debuginfo/method-on-trait.rs index e70f86a53679e..f53bb11eac442 100644 --- a/src/test/debuginfo/method-on-trait.rs +++ b/src/test/debuginfo/method-on-trait.rs @@ -112,6 +112,9 @@ // lldb-check:[...]$14 = -10 // lldb-command:continue + +#![omit_gdb_pretty_printer_section] + struct Struct { x: int } diff --git a/src/test/debuginfo/method-on-tuple-struct.rs b/src/test/debuginfo/method-on-tuple-struct.rs index 31bdd20e409db..6994c38818c1b 100644 --- a/src/test/debuginfo/method-on-tuple-struct.rs +++ b/src/test/debuginfo/method-on-tuple-struct.rs @@ -112,6 +112,9 @@ // lldb-check:[...]$14 = -10 // lldb-command:continue + +#![omit_gdb_pretty_printer_section] + struct TupleStruct(int, f64); impl TupleStruct { diff --git a/src/test/debuginfo/multiple-functions-equal-var-names.rs b/src/test/debuginfo/multiple-functions-equal-var-names.rs index d5d085bfe50a6..cb21c13426a7b 100644 --- a/src/test/debuginfo/multiple-functions-equal-var-names.rs +++ b/src/test/debuginfo/multiple-functions-equal-var-names.rs @@ -45,6 +45,7 @@ // lldb-check:[...]$2 = 30303 #![allow(unused_variables)] +#![omit_gdb_pretty_printer_section] fn function_one() { let abc = 10101i; diff --git a/src/test/debuginfo/multiple-functions.rs b/src/test/debuginfo/multiple-functions.rs index a94785b892dc0..ef7c4ce2045c7 100644 --- a/src/test/debuginfo/multiple-functions.rs +++ b/src/test/debuginfo/multiple-functions.rs @@ -45,6 +45,7 @@ // lldb-check:[...]$2 = 30303 #![allow(unused_variables)] +#![omit_gdb_pretty_printer_section] fn function_one() { let a = 10101i; diff --git a/src/test/debuginfo/name-shadowing-and-scope-nesting.rs b/src/test/debuginfo/name-shadowing-and-scope-nesting.rs index 5d6dfb90794fd..d248c7e98198c 100644 --- a/src/test/debuginfo/name-shadowing-and-scope-nesting.rs +++ b/src/test/debuginfo/name-shadowing-and-scope-nesting.rs @@ -94,6 +94,8 @@ // lldb-check:[...]$11 = 20 // lldb-command:continue +#![omit_gdb_pretty_printer_section] + fn main() { let x = false; let y = true; diff --git a/src/test/debuginfo/nil-enum.rs b/src/test/debuginfo/nil-enum.rs index 306dfed9895e8..f0eaf6acb6138 100644 --- a/src/test/debuginfo/nil-enum.rs +++ b/src/test/debuginfo/nil-enum.rs @@ -23,6 +23,7 @@ // gdb-check:$2 = {} #![allow(unused_variables)] +#![omit_gdb_pretty_printer_section] enum ANilEnum {} enum AnotherNilEnum {} diff --git a/src/test/debuginfo/no-debug-attribute.rs b/src/test/debuginfo/no-debug-attribute.rs index 826ac381c8209..dcc1928ae50c9 100644 --- a/src/test/debuginfo/no-debug-attribute.rs +++ b/src/test/debuginfo/no-debug-attribute.rs @@ -24,6 +24,7 @@ // gdb-command:continue #![allow(unused_variables)] +#![omit_gdb_pretty_printer_section] fn function_with_debuginfo() { let abc = 10u; diff --git a/src/test/debuginfo/option-like-enum.rs b/src/test/debuginfo/option-like-enum.rs index 333a430e35111..333ad602cf130 100644 --- a/src/test/debuginfo/option-like-enum.rs +++ b/src/test/debuginfo/option-like-enum.rs @@ -68,6 +68,8 @@ // lldb-check:[...]$7 = None +#![omit_gdb_pretty_printer_section] + // If a struct has exactly two variants, one of them is empty, and the other one // contains a non-nullable pointer, then this value is used as the discriminator. // The test cases in this file make sure that something readable is generated for diff --git a/src/test/debuginfo/packed-struct-with-destructor.rs b/src/test/debuginfo/packed-struct-with-destructor.rs index 1140c2cdb44d1..84c0b8da02c06 100644 --- a/src/test/debuginfo/packed-struct-with-destructor.rs +++ b/src/test/debuginfo/packed-struct-with-destructor.rs @@ -74,6 +74,7 @@ #![allow(unused_variables)] +#![omit_gdb_pretty_printer_section] #[repr(packed)] struct Packed { diff --git a/src/test/debuginfo/packed-struct.rs b/src/test/debuginfo/packed-struct.rs index 93941823fbc3a..97e6ee79952e8 100644 --- a/src/test/debuginfo/packed-struct.rs +++ b/src/test/debuginfo/packed-struct.rs @@ -60,6 +60,7 @@ // lldb-check:[...]$5 = 40 #![allow(unused_variables)] +#![omit_gdb_pretty_printer_section] #[repr(packed)] struct Packed { diff --git a/src/test/debuginfo/recursive-enum.rs b/src/test/debuginfo/recursive-enum.rs index f43caed081014..93348e7b53e55 100644 --- a/src/test/debuginfo/recursive-enum.rs +++ b/src/test/debuginfo/recursive-enum.rs @@ -18,6 +18,7 @@ // is taken from issue #11083. #![allow(unused_variables)] +#![omit_gdb_pretty_printer_section] pub struct Window<'a> { callbacks: WindowCallbacks<'a> diff --git a/src/test/debuginfo/recursive-struct.rs b/src/test/debuginfo/recursive-struct.rs index 8cc0fdabfc2e7..90c32ad8da11f 100644 --- a/src/test/debuginfo/recursive-struct.rs +++ b/src/test/debuginfo/recursive-struct.rs @@ -69,6 +69,7 @@ // gdb-command:continue #![allow(unused_variables)] +#![omit_gdb_pretty_printer_section] use self::Opt::{Empty, Val}; diff --git a/src/test/debuginfo/self-in-default-method.rs b/src/test/debuginfo/self-in-default-method.rs index 87fdb2c42c8f8..f8ef5b3d2fcf9 100644 --- a/src/test/debuginfo/self-in-default-method.rs +++ b/src/test/debuginfo/self-in-default-method.rs @@ -112,6 +112,7 @@ // lldb-check:[...]$14 = -10 // lldb-command:continue +#![omit_gdb_pretty_printer_section] struct Struct { x: int diff --git a/src/test/debuginfo/self-in-generic-default-method.rs b/src/test/debuginfo/self-in-generic-default-method.rs index 6f488230521eb..c2594df7d351c 100644 --- a/src/test/debuginfo/self-in-generic-default-method.rs +++ b/src/test/debuginfo/self-in-generic-default-method.rs @@ -112,6 +112,7 @@ // lldb-check:[...]$14 = -10.5 // lldb-command:continue +#![omit_gdb_pretty_printer_section] struct Struct { x: int diff --git a/src/test/debuginfo/shadowed-argument.rs b/src/test/debuginfo/shadowed-argument.rs index ead960c36df99..c5c3664b07a7c 100644 --- a/src/test/debuginfo/shadowed-argument.rs +++ b/src/test/debuginfo/shadowed-argument.rs @@ -58,6 +58,9 @@ // lldb-check:[...]$5 = 20 // lldb-command:continue + +#![omit_gdb_pretty_printer_section] + fn a_function(x: bool, y: bool) { zzz(); // #break sentinel(); diff --git a/src/test/debuginfo/shadowed-variable.rs b/src/test/debuginfo/shadowed-variable.rs index fa56c1d1fb756..f384b756da678 100644 --- a/src/test/debuginfo/shadowed-variable.rs +++ b/src/test/debuginfo/shadowed-variable.rs @@ -58,6 +58,8 @@ // lldb-check:[...]$5 = 20 // lldb-command:continue +#![omit_gdb_pretty_printer_section] + fn main() { let x = false; let y = true; diff --git a/src/test/debuginfo/simd.rs b/src/test/debuginfo/simd.rs index 2c2eedf416775..288e7461dd5a0 100644 --- a/src/test/debuginfo/simd.rs +++ b/src/test/debuginfo/simd.rs @@ -43,6 +43,7 @@ #![allow(experimental)] #![allow(unused_variables)] +#![omit_gdb_pretty_printer_section] use std::simd::{i8x16, i16x8,i32x4,i64x2,u8x16,u16x8,u32x4,u64x2,f32x4,f64x2}; diff --git a/src/test/debuginfo/simple-lexical-scope.rs b/src/test/debuginfo/simple-lexical-scope.rs index 4330a27325837..5981c18494d40 100644 --- a/src/test/debuginfo/simple-lexical-scope.rs +++ b/src/test/debuginfo/simple-lexical-scope.rs @@ -78,6 +78,9 @@ // lldb-check:[...]$6 = false // lldb-command:continue + +#![omit_gdb_pretty_printer_section] + fn main() { let x = false; diff --git a/src/test/debuginfo/simple-struct.rs b/src/test/debuginfo/simple-struct.rs index 51241be921ca2..3015b16a0aa99 100644 --- a/src/test/debuginfo/simple-struct.rs +++ b/src/test/debuginfo/simple-struct.rs @@ -95,8 +95,9 @@ // lldb-command:print padding_at_end // lldb-check:[...]$5 = PaddingAtEnd { x: -10014, y: 10015 } -#![allow(unused_variables)]; -#![allow(dead_code)]; +#![allow(unused_variables)] +#![allow(dead_code)] +#![omit_gdb_pretty_printer_section] struct NoPadding16 { x: u16, diff --git a/src/test/debuginfo/simple-tuple.rs b/src/test/debuginfo/simple-tuple.rs index bbc9941e013c1..78184fab7d390 100644 --- a/src/test/debuginfo/simple-tuple.rs +++ b/src/test/debuginfo/simple-tuple.rs @@ -92,6 +92,7 @@ #![allow(unused_variables)] #![allow(dead_code)] +#![omit_gdb_pretty_printer_section] static mut NO_PADDING_8: (i8, u8) = (-50, 50); static mut NO_PADDING_16: (i16, i16, u16) = (-1, 2, 3); diff --git a/src/test/debuginfo/static-method-on-struct-and-enum.rs b/src/test/debuginfo/static-method-on-struct-and-enum.rs index f808e7f8a90ff..59ee300b3e3b5 100644 --- a/src/test/debuginfo/static-method-on-struct-and-enum.rs +++ b/src/test/debuginfo/static-method-on-struct-and-enum.rs @@ -54,6 +54,8 @@ // lldb-check:[...]$4 = 5 // lldb-command:continue +#![omit_gdb_pretty_printer_section] + struct Struct { x: int } diff --git a/src/test/debuginfo/struct-in-enum.rs b/src/test/debuginfo/struct-in-enum.rs index 68281cb223028..6f801a7d587d3 100644 --- a/src/test/debuginfo/struct-in-enum.rs +++ b/src/test/debuginfo/struct-in-enum.rs @@ -42,6 +42,7 @@ // lldb-check:[...]$2 = TheOnlyCase(Struct { x: 123, y: 456, z: 789 }) #![allow(unused_variables)] +#![omit_gdb_pretty_printer_section] use self::Regular::{Case1, Case2}; use self::Univariant::TheOnlyCase; diff --git a/src/test/debuginfo/struct-in-struct.rs b/src/test/debuginfo/struct-in-struct.rs index 4a7588b0bec59..3f819c92e1017 100644 --- a/src/test/debuginfo/struct-in-struct.rs +++ b/src/test/debuginfo/struct-in-struct.rs @@ -57,6 +57,7 @@ // lldb-check:[...]$7 = Tree { x: Simple { x: 25 }, y: InternalPaddingParent { x: InternalPadding { x: 26, y: 27 }, y: InternalPadding { x: 28, y: 29 }, z: InternalPadding { x: 30, y: 31 } }, z: BagInBag { x: Bag { x: Simple { x: 32 } } } } #![allow(unused_variables)] +#![omit_gdb_pretty_printer_section] struct Simple { x: i32 diff --git a/src/test/debuginfo/struct-style-enum.rs b/src/test/debuginfo/struct-style-enum.rs index 48c6c2d79fb43..f6d4627082f0e 100644 --- a/src/test/debuginfo/struct-style-enum.rs +++ b/src/test/debuginfo/struct-style-enum.rs @@ -49,6 +49,7 @@ // lldb-check:[...]$3 = TheOnlyCase { a: -1 } #![allow(unused_variables)] +#![omit_gdb_pretty_printer_section] use self::Regular::{Case1, Case2, Case3}; use self::Univariant::TheOnlyCase; diff --git a/src/test/debuginfo/struct-with-destructor.rs b/src/test/debuginfo/struct-with-destructor.rs index 854ba2171eb42..743f5ac5ff452 100644 --- a/src/test/debuginfo/struct-with-destructor.rs +++ b/src/test/debuginfo/struct-with-destructor.rs @@ -45,6 +45,7 @@ // lldb-check:[...]$3 = NestedOuter { a: NestedInner { a: WithDestructor { x: 7890, y: 9870 } } } #![allow(unused_variables)] +#![omit_gdb_pretty_printer_section] struct NoDestructor { x: i32, diff --git a/src/test/debuginfo/trait-generic-static-default-method.rs b/src/test/debuginfo/trait-generic-static-default-method.rs index 8d565a323acd3..2ecafb02ae52d 100644 --- a/src/test/debuginfo/trait-generic-static-default-method.rs +++ b/src/test/debuginfo/trait-generic-static-default-method.rs @@ -45,6 +45,8 @@ // lldb-check:[...]$3 = (1, 2, 3) // lldb-command:continue +#![omit_gdb_pretty_printer_section] + struct Struct { x: int } diff --git a/src/test/debuginfo/trait-pointers.rs b/src/test/debuginfo/trait-pointers.rs index d73c3cf0f7789..9f8c0aa06e676 100644 --- a/src/test/debuginfo/trait-pointers.rs +++ b/src/test/debuginfo/trait-pointers.rs @@ -16,6 +16,7 @@ // lldb-command:run #![allow(unused_variables)] +#![omit_gdb_pretty_printer_section] trait Trait { fn method(&self) -> int { 0 } diff --git a/src/test/debuginfo/tuple-in-struct.rs b/src/test/debuginfo/tuple-in-struct.rs index 02492bf1aa2cf..3d28490c0cfd7 100644 --- a/src/test/debuginfo/tuple-in-struct.rs +++ b/src/test/debuginfo/tuple-in-struct.rs @@ -41,6 +41,7 @@ // gdb-check:$10 = {x = {{40, 41, 42}, {43, 44}}, y = {45, 46, 47, 48}} #![allow(unused_variables)] +#![omit_gdb_pretty_printer_section] struct NoPadding1 { x: (i32, i32), diff --git a/src/test/debuginfo/tuple-in-tuple.rs b/src/test/debuginfo/tuple-in-tuple.rs index 30fdd8c5530ad..b1228f7a8846a 100644 --- a/src/test/debuginfo/tuple-in-tuple.rs +++ b/src/test/debuginfo/tuple-in-tuple.rs @@ -57,6 +57,7 @@ // lldb-check:[...]$6 = ((21, 22), 23) #![allow(unused_variables)] +#![omit_gdb_pretty_printer_section] fn main() { let no_padding1: ((u32, u32), u32, u32) = ((0, 1), 2, 3); diff --git a/src/test/debuginfo/tuple-struct.rs b/src/test/debuginfo/tuple-struct.rs index 62c150878cfb9..0960ab5834dd6 100644 --- a/src/test/debuginfo/tuple-struct.rs +++ b/src/test/debuginfo/tuple-struct.rs @@ -62,6 +62,9 @@ // to all fields having the name ""). Otherwise they are handled the same a normal // structs. + +#![omit_gdb_pretty_printer_section] + struct NoPadding16(u16, i16); struct NoPadding32(i32, f32, u32); struct NoPadding64(f64, i64, u64); diff --git a/src/test/debuginfo/tuple-style-enum.rs b/src/test/debuginfo/tuple-style-enum.rs index 07a0f16960611..f205f484f25fb 100644 --- a/src/test/debuginfo/tuple-style-enum.rs +++ b/src/test/debuginfo/tuple-style-enum.rs @@ -49,6 +49,7 @@ // lldb-check:[...]$3 = TheOnlyCase(-1) #![allow(unused_variables)] +#![omit_gdb_pretty_printer_section] use self::Regular::{Case1, Case2, Case3}; use self::Univariant::TheOnlyCase; diff --git a/src/test/debuginfo/type-names.rs b/src/test/debuginfo/type-names.rs index 286c44667c5b4..ddcbfdcceee01 100644 --- a/src/test/debuginfo/type-names.rs +++ b/src/test/debuginfo/type-names.rs @@ -173,6 +173,8 @@ // gdb-command:whatis stack_closure2 // gdb-check:type = struct (&mut|i8, f32| -> f32, uint) +#![omit_gdb_pretty_printer_section] + use self::Enum1::{Variant1_1, Variant1_2}; use std::ptr; diff --git a/src/test/debuginfo/unique-enum.rs b/src/test/debuginfo/unique-enum.rs index 3c0a4a21b4fce..3d028eb1077bc 100644 --- a/src/test/debuginfo/unique-enum.rs +++ b/src/test/debuginfo/unique-enum.rs @@ -42,6 +42,7 @@ // lldb-check:[...]$2 = TheOnlyCase(123234) #![allow(unused_variables)] +#![omit_gdb_pretty_printer_section] // The first element is to ensure proper alignment, irrespective of the machines word size. Since // the size of the discriminant value is machine dependent, this has be taken into account when diff --git a/src/test/debuginfo/var-captured-in-nested-closure.rs b/src/test/debuginfo/var-captured-in-nested-closure.rs index f3ee711e8fdc7..99d67c60516b5 100644 --- a/src/test/debuginfo/var-captured-in-nested-closure.rs +++ b/src/test/debuginfo/var-captured-in-nested-closure.rs @@ -79,6 +79,7 @@ // lldb-command:continue #![allow(unused_variables)] +#![omit_gdb_pretty_printer_section] struct Struct { a: int, diff --git a/src/test/debuginfo/var-captured-in-sendable-closure.rs b/src/test/debuginfo/var-captured-in-sendable-closure.rs index fca47ed47bd7a..b34749260f30c 100644 --- a/src/test/debuginfo/var-captured-in-sendable-closure.rs +++ b/src/test/debuginfo/var-captured-in-sendable-closure.rs @@ -42,6 +42,7 @@ #![allow(unused_variables)] #![feature(unboxed_closures)] +#![omit_gdb_pretty_printer_section] struct Struct { a: int, diff --git a/src/test/debuginfo/var-captured-in-stack-closure.rs b/src/test/debuginfo/var-captured-in-stack-closure.rs index 761d0f0be8f58..f474e8d131799 100644 --- a/src/test/debuginfo/var-captured-in-stack-closure.rs +++ b/src/test/debuginfo/var-captured-in-stack-closure.rs @@ -72,6 +72,7 @@ #![feature(unboxed_closures)] #![allow(unused_variables)] +#![omit_gdb_pretty_printer_section] struct Struct { a: int, diff --git a/src/test/debuginfo/vec-slices.rs b/src/test/debuginfo/vec-slices.rs index dfe16452d8589..70211d74d885d 100644 --- a/src/test/debuginfo/vec-slices.rs +++ b/src/test/debuginfo/vec-slices.rs @@ -78,6 +78,7 @@ #![allow(unused_variables)] #![feature(slicing_syntax)] +#![omit_gdb_pretty_printer_section] struct AStruct { x: i16, diff --git a/src/test/debuginfo/vec.rs b/src/test/debuginfo/vec.rs index 00c93653cf411..92a490206b624 100644 --- a/src/test/debuginfo/vec.rs +++ b/src/test/debuginfo/vec.rs @@ -29,6 +29,7 @@ // lldb-check:[...]$0 = [1, 2, 3] #![allow(unused_variables)] +#![omit_gdb_pretty_printer_section] static mut VECT: [i32; 3] = [1, 2, 3]; diff --git a/src/test/run-pass/issue-12684.rs b/src/test/run-pass/issue-12684.rs index e24cf5a0f2670..856fbbd00b20b 100644 --- a/src/test/run-pass/issue-12684.rs +++ b/src/test/run-pass/issue-12684.rs @@ -9,9 +9,10 @@ // except according to those terms. use std::time::Duration; +use std::thread::Thread; fn main() { - std::task::spawn(move|| customtask()); + Thread::spawn(move|| customtask()).join().ok().unwrap(); } fn customtask() { diff --git a/src/test/run-pass/trait-object-safety.rs b/src/test/run-pass/trait-object-safety.rs index 929cb9e7f1759..ed7284a835365 100644 --- a/src/test/run-pass/trait-object-safety.rs +++ b/src/test/run-pass/trait-object-safety.rs @@ -8,20 +8,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Check that object-safe methods are identified as such. Also -// acts as a regression test for #18490 +// Check that object-safe methods are identified as such. trait Tr { - // Static methods are always safe regardless of other rules - fn new() -> Self; + fn foo(&self); } struct St; impl Tr for St { - fn new() -> St { St } + fn foo(&self) {} } fn main() { - &St as &Tr; + let s: &Tr = &St; + s.foo(); }