diff --git a/COPYRIGHT b/COPYRIGHT index 52039ea7e5734..da8ac7b3adde7 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -6,7 +6,7 @@ terms. Longer version: -The Rust Project is copyright 2014, The Rust Project +The Rust Project is copyright 2015, The Rust Project Developers (given in the file AUTHORS.txt). Licensed under the Apache License, Version 2.0 diff --git a/LICENSE-MIT b/LICENSE-MIT index 39d4bdb5acd31..e69282e381bc0 100644 --- a/LICENSE-MIT +++ b/LICENSE-MIT @@ -1,4 +1,4 @@ -Copyright (c) 2014 The Rust Project Developers +Copyright (c) 2015 The Rust Project Developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated diff --git a/README.md b/README.md index 147d2e9d2f44a..eef27236b1aa3 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,6 @@ documentation. 1. Make sure you have installed the dependencies: * `g++` 4.7 or `clang++` 3.x * `python` 2.6 or later (but not 3.x) - * `perl` 5.0 or later * GNU `make` 3.81 or later * `curl` * `git` diff --git a/configure b/configure index 86ed88c8d0631..b2f8c33380ce7 100755 --- a/configure +++ b/configure @@ -509,7 +509,6 @@ opt optimize-tests 1 "build tests with optimizations" opt libcpp 1 "build with llvm with libc++ instead of libstdc++ when using clang" opt llvm-assertions 1 "build LLVM with assertions" opt debug 1 "build with extra debug fun" -opt ratchet-bench 0 "ratchet benchmarks" opt fast-make 0 "use .gitmodules as timestamp for submodule deps" opt ccache 0 "invoke gcc/clang via ccache to reuse object files between builds" opt local-rust 0 "use an installed rustc rather than downloading a snapshot" @@ -612,12 +611,11 @@ putvar CFG_RELEASE_CHANNEL # channel. # Basing CFG_BOOTSTRAP_KEY on CFG_BOOTSTRAP_KEY lets it get picked up # during a Makefile reconfig. -CFG_BOOTSTRAP_KEY="${CFG_BOOTSTRAP_KEY-`date +%N`}" +CFG_BOOTSTRAP_KEY="${CFG_BOOTSTRAP_KEY-`date +%H:%M:%S`}" putvar CFG_BOOTSTRAP_KEY step_msg "looking for build programs" -probe_need CFG_PERL perl probe_need CFG_CURLORWGET curl wget probe_need CFG_PYTHON python2.7 python2.6 python2 python @@ -1375,7 +1373,7 @@ do done # Munge any paths that appear in config.mk back to posix-y -perl -i.bak -p -e 's@ ([a-zA-Z]):[/\\]@ /\1/@go;' config.tmp +sed -i.bak -e 's@ \([a-zA-Z]\):[/\\]@ /\1/@g;' config.tmp rm -f config.tmp.bak msg diff --git a/man/rustdoc.1 b/man/rustdoc.1 index 4c6557f0f6580..830884b19bde2 100644 --- a/man/rustdoc.1 +++ b/man/rustdoc.1 @@ -35,9 +35,27 @@ space-separated list of plugins to run (default: '') --plugin-path directory to load plugins from (default: /tmp/rustdoc_ng/plugins) .TP +--target +target triple to document +.TP +--crate-name +specify the name of this crate +.TP -L --library-path directory to add to crate search path .TP +--cfg +pass a --cfg to rustc +.TP +--extern +pass an --extern to rustc +.TP +--test +run code examples as tests +.TP +--test-args +pass arguments to the test runner +.TP --html-in-header file to add to .TP @@ -47,8 +65,20 @@ file to add in , before content --html-after-content file to add in , after content .TP +--markdown-css +CSS files to include via in a rendered Markdown file +.TP +--markdown-playground-url +URL to send code snippets to +.TP +--markdown-no-toc +don't include table of contents +.TP -h, --help Print help +.TP +-V, --version +Print rustdoc's version .SH "OUTPUT FORMATS" diff --git a/mk/cfg/aarch64-linux-android.mk b/mk/cfg/aarch64-linux-android.mk new file mode 100644 index 0000000000000..a6f7f2ba1d66e --- /dev/null +++ b/mk/cfg/aarch64-linux-android.mk @@ -0,0 +1,30 @@ +# aarch64-linux-android configuration +# CROSS_PREFIX_aarch64-linux-android- +CC_aarch64-linux-android=$(CFG_ANDROID_CROSS_PATH)/bin/aarch64-linux-android-gcc +CXX_aarch64-linux-android=$(CFG_ANDROID_CROSS_PATH)/bin/aarch64-linux-android-g++ +CPP_aarch64-linux-android=$(CFG_ANDROID_CROSS_PATH)/bin/aarch64-linux-android-gcc -E +AR_aarch64-linux-android=$(CFG_ANDROID_CROSS_PATH)/bin/aarch64-linux-android-ar +CFG_LIB_NAME_aarch64-linux-android=lib$(1).so +CFG_STATIC_LIB_NAME_aarch64-linux-android=lib$(1).a +CFG_LIB_GLOB_aarch64-linux-android=lib$(1)-*.so +CFG_LIB_DSYM_GLOB_aarch64-linux-android=lib$(1)-*.dylib.dSYM +CFG_JEMALLOC_CFLAGS_aarch64-linux-android := -D__aarch64__ -DANDROID -D__ANDROID__ $(CFLAGS) +CFG_GCCISH_CFLAGS_aarch64-linux-android := -Wall -g -fPIC -D__aarch64__ -DANDROID -D__ANDROID__ $(CFLAGS) +CFG_GCCISH_CXXFLAGS_aarch64-linux-android := -fno-rtti $(CXXFLAGS) +CFG_GCCISH_LINK_FLAGS_aarch64-linux-android := -shared -fPIC -ldl -g -lm -lsupc++ +CFG_GCCISH_DEF_FLAG_aarch64-linux-android := -Wl,--export-dynamic,--dynamic-list= +CFG_GCCISH_PRE_LIB_FLAGS_aarch64-linux-android := -Wl,-whole-archive +CFG_GCCISH_POST_LIB_FLAGS_aarch64-linux-android := -Wl,-no-whole-archive +CFG_DEF_SUFFIX_aarch64-linux-android := .android.def +CFG_LLC_FLAGS_aarch64-linux-android := +CFG_INSTALL_NAME_aarch64-linux-android = +CFG_EXE_SUFFIX_aarch64-linux-android := +CFG_WINDOWSY_aarch64-linux-android := +CFG_UNIXY_aarch64-linux-android := 1 +CFG_PATH_MUNGE_aarch64-linux-android := true +CFG_LDPATH_aarch64-linux-android := +CFG_RUN_aarch64-linux-android= +CFG_RUN_TARG_aarch64-linux-android= +RUSTC_FLAGS_aarch64-linux-android := +RUSTC_CROSS_FLAGS_aarch64-linux-android := +CFG_GNU_TRIPLE_aarch64-linux-android := aarch64-linux-android diff --git a/mk/cfg/i686-pc-windows-gnu.mk b/mk/cfg/i686-pc-windows-gnu.mk index ecb405b76f010..357a321688bca 100644 --- a/mk/cfg/i686-pc-windows-gnu.mk +++ b/mk/cfg/i686-pc-windows-gnu.mk @@ -8,8 +8,8 @@ CFG_LIB_NAME_i686-pc-windows-gnu=$(1).dll CFG_STATIC_LIB_NAME_i686-pc-windows-gnu=$(1).lib CFG_LIB_GLOB_i686-pc-windows-gnu=$(1)-*.dll CFG_LIB_DSYM_GLOB_i686-pc-windows-gnu=$(1)-*.dylib.dSYM -CFG_JEMALLOC_CFLAGS_i686-pc-windows-gnu := -march=i686 -m32 -D_WIN32_WINNT=0x0600 $(CFLAGS) -CFG_GCCISH_CFLAGS_i686-pc-windows-gnu := -Wall -Werror -g -m32 -D_WIN32_WINNT=0x0600 $(CFLAGS) +CFG_JEMALLOC_CFLAGS_i686-pc-windows-gnu := -march=i686 -m32 -D_WIN32_WINNT=0x0600 -D__USE_MINGW_ANSI_STDIO=1 $(CFLAGS) +CFG_GCCISH_CFLAGS_i686-pc-windows-gnu := -Wall -Werror -g -m32 -D_WIN32_WINNT=0x0600 -D__USE_MINGW_ANSI_STDIO=1 $(CFLAGS) CFG_GCCISH_CXXFLAGS_i686-pc-windows-gnu := -fno-rtti $(CXXFLAGS) CFG_GCCISH_LINK_FLAGS_i686-pc-windows-gnu := -shared -g -m32 CFG_GCCISH_DEF_FLAG_i686-pc-windows-gnu := @@ -22,7 +22,7 @@ CFG_EXE_SUFFIX_i686-pc-windows-gnu := .exe CFG_WINDOWSY_i686-pc-windows-gnu := 1 CFG_UNIXY_i686-pc-windows-gnu := CFG_PATH_MUNGE_i686-pc-windows-gnu := -CFG_LDPATH_i686-pc-windows-gnu :=$(CFG_LDPATH_i686-pc-windows-gnu):$(PATH) -CFG_RUN_i686-pc-windows-gnu=PATH="$(CFG_LDPATH_i686-pc-windows-gnu):$(1)" $(2) -CFG_RUN_TARG_i686-pc-windows-gnu=$(call CFG_RUN_i686-pc-windows-gnu,$(HLIB$(1)_H_$(CFG_BUILD)),$(2)) +CFG_LDPATH_i686-pc-windows-gnu := +CFG_RUN_i686-pc-windows-gnu=$(2) +CFG_RUN_TARG_i686-pc-windows-gnu=$(call CFG_RUN_i686-pc-windows-gnu,,$(2)) CFG_GNU_TRIPLE_i686-pc-windows-gnu := i686-w64-mingw32 diff --git a/mk/cfg/x86_64-pc-windows-gnu.mk b/mk/cfg/x86_64-pc-windows-gnu.mk index a23e292c7bd5d..e9e5f04ea5433 100644 --- a/mk/cfg/x86_64-pc-windows-gnu.mk +++ b/mk/cfg/x86_64-pc-windows-gnu.mk @@ -8,8 +8,8 @@ CFG_LIB_NAME_x86_64-pc-windows-gnu=$(1).dll CFG_STATIC_LIB_NAME_x86_64-pc-windows-gnu=$(1).lib CFG_LIB_GLOB_x86_64-pc-windows-gnu=$(1)-*.dll CFG_LIB_DSYM_GLOB_x86_64-pc-windows-gnu=$(1)-*.dylib.dSYM -CFG_JEMALLOC_CFLAGS_x86_64-pc-windows-gnu := -m64 -D_WIN32_WINNT=0x0600 $(CFLAGS) -CFG_GCCISH_CFLAGS_x86_64-pc-windows-gnu := -Wall -Werror -g -m64 -D_WIN32_WINNT=0x0600 $(CFLAGS) +CFG_JEMALLOC_CFLAGS_x86_64-pc-windows-gnu := -m64 -D_WIN32_WINNT=0x0600 -D__USE_MINGW_ANSI_STDIO=1 $(CFLAGS) +CFG_GCCISH_CFLAGS_x86_64-pc-windows-gnu := -Wall -Werror -g -m64 -D_WIN32_WINNT=0x0600 -D__USE_MINGW_ANSI_STDIO=1 $(CFLAGS) CFG_GCCISH_CXXFLAGS_x86_64-pc-windows-gnu := -fno-rtti $(CXXFLAGS) CFG_GCCISH_LINK_FLAGS_x86_64-pc-windows-gnu := -shared -g -m64 CFG_GCCISH_DEF_FLAG_x86_64-pc-windows-gnu := @@ -22,7 +22,7 @@ CFG_EXE_SUFFIX_x86_64-pc-windows-gnu := .exe CFG_WINDOWSY_x86_64-pc-windows-gnu := 1 CFG_UNIXY_x86_64-pc-windows-gnu := CFG_PATH_MUNGE_x86_64-pc-windows-gnu := -CFG_LDPATH_x86_64-pc-windows-gnu :=$(CFG_LDPATH_x86_64-pc-windows-gnu):$(PATH) -CFG_RUN_x86_64-pc-windows-gnu=PATH="$(CFG_LDPATH_x86_64-pc-windows-gnu):$(1)" $(2) -CFG_RUN_TARG_x86_64-pc-windows-gnu=$(call CFG_RUN_x86_64-pc-windows-gnu,$(HLIB$(1)_H_$(CFG_BUILD)),$(2)) +CFG_LDPATH_x86_64-pc-windows-gnu := +CFG_RUN_x86_64-pc-windows-gnu=$(2) +CFG_RUN_TARG_x86_64-pc-windows-gnu=$(call CFG_RUN_x86_64-pc-windows-gnu,,$(2)) CFG_GNU_TRIPLE_x86_64-pc-windows-gnu := x86_64-w64-mingw32 diff --git a/mk/crates.mk b/mk/crates.mk index 5b8772c4e0af5..5957405f0f9ec 100644 --- a/mk/crates.mk +++ b/mk/crates.mk @@ -52,9 +52,9 @@ TARGET_CRATES := libc std flate arena term \ serialize getopts collections test rand \ log regex graphviz core rbml alloc \ - unicode + unicode rustc_bitflags RUSTC_CRATES := rustc rustc_typeck rustc_borrowck rustc_resolve rustc_driver \ - rustc_trans rustc_back rustc_llvm + rustc_trans rustc_back rustc_llvm rustc_privacy HOST_CRATES := syntax $(RUSTC_CRATES) rustdoc fmt_macros CRATES := $(TARGET_CRATES) $(HOST_CRATES) TOOLS := compiletest rustdoc rustc rustbook @@ -64,22 +64,27 @@ DEPS_libc := core DEPS_unicode := core DEPS_alloc := core libc native:jemalloc DEPS_std := core libc rand alloc collections unicode \ - native:rust_builtin native:backtrace native:rustrt_native + native:rust_builtin native:backtrace native:rustrt_native \ + rustc_bitflags DEPS_graphviz := std DEPS_syntax := std term serialize log fmt_macros arena libc DEPS_rustc_driver := arena flate getopts graphviz libc rustc rustc_back rustc_borrowck \ - rustc_typeck rustc_resolve log syntax serialize rustc_llvm rustc_trans + rustc_typeck rustc_resolve log syntax serialize rustc_llvm \ + rustc_trans rustc_privacy + DEPS_rustc_trans := arena flate getopts graphviz libc rustc rustc_back \ log syntax serialize rustc_llvm DEPS_rustc_typeck := rustc syntax DEPS_rustc_borrowck := rustc log graphviz syntax DEPS_rustc_resolve := rustc log syntax +DEPS_rustc_privacy := rustc log syntax DEPS_rustc := syntax flate arena serialize getopts rbml \ log graphviz rustc_llvm rustc_back DEPS_rustc_llvm := native:rustllvm libc std DEPS_rustc_back := std syntax rustc_llvm flate log libc DEPS_rustdoc := rustc rustc_driver native:hoedown serialize getopts \ test +DEPS_rustc_bitflags := core DEPS_flate := std native:miniz DEPS_arena := std DEPS_graphviz := std @@ -111,6 +116,7 @@ ONLY_RLIB_alloc := 1 ONLY_RLIB_rand := 1 ONLY_RLIB_collections := 1 ONLY_RLIB_unicode := 1 +ONLY_RLIB_rustc_bitflags := 1 ################################################################################ # You should not need to edit below this line @@ -122,12 +128,13 @@ DOC_CRATES := $(filter-out rustc, \ $(filter-out rustc_borrowck, \ $(filter-out rustc_resolve, \ $(filter-out rustc_driver, \ + $(filter-out rustc_privacy, \ $(filter-out log, \ $(filter-out regex, \ $(filter-out getopts, \ - $(filter-out syntax, $(CRATES))))))))))) + $(filter-out syntax, $(CRATES)))))))))))) COMPILER_DOC_CRATES := rustc rustc_trans rustc_borrowck rustc_resolve \ - rustc_typeck rustc_driver syntax + rustc_typeck rustc_driver syntax rustc_privacy # This macro creates some simple definitions for each crate being built, just # some munging of all of the parameters above. diff --git a/mk/main.mk b/mk/main.mk index 46cbe34904dbc..8c910f4759610 100644 --- a/mk/main.mk +++ b/mk/main.mk @@ -330,10 +330,10 @@ ifdef CFG_DISABLE_UNSTABLE_FEATURES CFG_INFO := $(info cfg: disabling unstable features (CFG_DISABLE_UNSTABLE_FEATURES)) # Turn on feature-staging export CFG_DISABLE_UNSTABLE_FEATURES -endif # Subvert unstable feature lints to do the self-build -export CFG_BOOTSTRAP_KEY export RUSTC_BOOTSTRAP_KEY:=$(CFG_BOOTSTRAP_KEY) +endif +export CFG_BOOTSTRAP_KEY ###################################################################### # Per-stage targets and runner diff --git a/mk/rt.mk b/mk/rt.mk index 6a7be26c7a686..a8bbeb4151701 100644 --- a/mk/rt.mk +++ b/mk/rt.mk @@ -141,6 +141,8 @@ else ifeq ($(OSTYPE_$(1)), apple-ios) JEMALLOC_ARGS_$(1) := --disable-tls else ifeq ($(OSTYPE_$(1)), linux-androideabi) JEMALLOC_ARGS_$(1) := --disable-tls +else ifeq ($(OSTYPE_$(1)), linux-android) + JEMALLOC_ARGS_$(1) := --disable-tls endif ################################################################################ diff --git a/mk/tests.mk b/mk/tests.mk index c8c4beb11531b..32d4d178e6b8c 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -38,16 +38,14 @@ ifdef CHECK_IGNORED TESTARGS += --ignored endif -TEST_BENCH = # Arguments to the cfail/rfail/rpass/bench tests ifdef CFG_VALGRIND CTEST_RUNTOOL = --runtool "$(CFG_VALGRIND)" - TEST_BENCH = endif ifdef PLEASE_BENCH - TEST_BENCH = --bench + TESTARGS += --bench endif # Arguments to the perf tests @@ -302,6 +300,7 @@ tidy: | grep '^$(S)src/libbacktrace' -v \ | grep '^$(S)src/rust-installer' -v \ | xargs $(CFG_PYTHON) $(S)src/etc/check-binaries.py + $(Q) $(CFG_PYTHON) $(S)src/etc/errorck.py $(S)src/ endif @@ -1011,7 +1010,8 @@ $(3)/test/run-make/%-$(1)-T-$(2)-H-$(3).ok: \ $$(LD_LIBRARY_PATH_ENV_NAME$(1)_T_$(2)_H_$(3)) \ "$$(LD_LIBRARY_PATH_ENV_HOSTDIR$(1)_T_$(2)_H_$(3))" \ "$$(LD_LIBRARY_PATH_ENV_TARGETDIR$(1)_T_$(2)_H_$(3))" \ - $(1) + $(1) \ + $$(S) @touch $$@ else # FIXME #11094 - The above rule doesn't work right for multiple targets diff --git a/src/compiletest/common.rs b/src/compiletest/common.rs index c29f74d741810..c21785c45a3ac 100644 --- a/src/compiletest/common.rs +++ b/src/compiletest/common.rs @@ -13,7 +13,7 @@ use std::fmt; use std::str::FromStr; use regex::Regex; -#[derive(Clone, PartialEq)] +#[derive(Clone, PartialEq, Debug)] pub enum Mode { CompileFail, RunFail, @@ -43,9 +43,9 @@ impl FromStr for Mode { } } -impl fmt::String for Mode { +impl fmt::Display for Mode { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::String::fmt(match *self { + fmt::Display::fmt(match *self { CompileFail => "compile-fail", RunFail => "run-fail", RunPass => "run-pass", @@ -58,12 +58,6 @@ impl fmt::String for Mode { } } -impl fmt::Show for Mode { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::String::fmt(self, f) - } -} - #[derive(Clone)] pub struct Config { // The library paths required for running the compiler @@ -115,20 +109,6 @@ pub struct Config { // Write out a parseable log of tests that were run pub logfile: Option, - // Write out a json file containing any metrics of the run - pub save_metrics: Option, - - // Write and ratchet a metrics file - pub ratchet_metrics: Option, - - // Percent change in metrics to consider noise - pub ratchet_noise_percent: Option, - - // "Shard" of the testsuite to pub run: this has the form of - // two numbers (a,b), and causes only those tests with - // positional order equal to a mod b to run. - pub test_shard: Option<(uint,uint)>, - // A command line to prefix program execution with, // for running under valgrind pub runtool: Option, diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs index 802fb05796d66..1a9a1c08b0781 100644 --- a/src/compiletest/compiletest.rs +++ b/src/compiletest/compiletest.rs @@ -13,6 +13,7 @@ #![feature(slicing_syntax, unboxed_closures)] #![feature(box_syntax)] #![feature(int_uint)] +#![allow(unstable)] #![deny(warnings)] @@ -76,10 +77,6 @@ pub fn parse_config(args: Vec ) -> Config { optopt("", "target-rustcflags", "flags to pass to rustc for target", "FLAGS"), optflag("", "verbose", "run tests verbosely, showing all output"), optopt("", "logfile", "file to log test execution to", "FILE"), - optopt("", "save-metrics", "file to save metrics to", "FILE"), - optopt("", "ratchet-metrics", "file to ratchet metrics against", "FILE"), - optopt("", "ratchet-noise-percent", - "percent change in metrics to consider noise", "N"), optflag("", "jit", "run tests under the JIT"), optopt("", "target", "the target to build for", "TARGET"), optopt("", "host", "the host to build for", "HOST"), @@ -89,7 +86,6 @@ pub fn parse_config(args: Vec ) -> Config { optopt("", "adb-path", "path to the android debugger", "PATH"), optopt("", "adb-test-dir", "path to tests for the android debugger", "PATH"), optopt("", "lldb-python-dir", "directory containing LLDB's python module", "PATH"), - optopt("", "test-shard", "run shard A, of B shards, worth of the testsuite", "A.B"), optflag("h", "help", "show this message")); assert!(!args.is_empty()); @@ -151,12 +147,6 @@ pub fn parse_config(args: Vec ) -> Config { filter: filter, cfail_regex: Regex::new(errors::EXPECTED_PATTERN).unwrap(), logfile: matches.opt_str("logfile").map(|s| Path::new(s)), - save_metrics: matches.opt_str("save-metrics").map(|s| Path::new(s)), - ratchet_metrics: - matches.opt_str("ratchet-metrics").map(|s| Path::new(s)), - ratchet_noise_percent: - matches.opt_str("ratchet-noise-percent") - .and_then(|s| s.as_slice().parse::()), runtool: matches.opt_str("runtool"), host_rustcflags: matches.opt_str("host-rustcflags"), target_rustcflags: matches.opt_str("target-rustcflags"), @@ -175,7 +165,6 @@ pub fn parse_config(args: Vec ) -> Config { opt_str2(matches.opt_str("adb-test-dir")).as_slice() && !opt_str2(matches.opt_str("adb-test-dir")).is_empty(), lldb_python_dir: matches.opt_str("lldb-python-dir"), - test_shard: test::opt_shard(matches.opt_str("test-shard")), verbose: matches.opt_present("verbose"), } } @@ -209,10 +198,6 @@ pub fn log_config(config: &Config) { logv(c, format!("adb_test_dir: {:?}", config.adb_test_dir)); logv(c, format!("adb_device_status: {}", config.adb_device_status)); - match config.test_shard { - None => logv(c, "test_shard: (all)".to_string()), - Some((a,b)) => logv(c, format!("test_shard: {}.{}", a, b)) - } logv(c, format!("verbose: {}", config.verbose)); logv(c, format!("\n")); } @@ -283,15 +268,8 @@ pub fn test_opts(config: &Config) -> test::TestOpts { logfile: config.logfile.clone(), run_tests: true, run_benchmarks: true, - ratchet_metrics: config.ratchet_metrics.clone(), - ratchet_noise_percent: config.ratchet_noise_percent.clone(), - save_metrics: config.save_metrics.clone(), - test_shard: config.test_shard.clone(), nocapture: false, color: test::AutoColor, - show_boxplot: false, - boxplot_width: 50, - show_all_stats: false, } } diff --git a/src/compiletest/header.rs b/src/compiletest/header.rs index 2413a001ee805..d7af767688e81 100644 --- a/src/compiletest/header.rs +++ b/src/compiletest/header.rs @@ -332,8 +332,7 @@ pub fn parse_name_value_directive(line: &str, directive: &str) let keycolon = format!("{}:", directive); match line.find_str(keycolon.as_slice()) { Some(colon) => { - let value = line.slice(colon + keycolon.len(), - line.len()).to_string(); + let value = line[(colon + keycolon.len()) .. line.len()].to_string(); debug!("{}: {}", directive, value); Some(value) } diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs index 5579479c5e5ac..f075cff769fba 100644 --- a/src/compiletest/runtest.rs +++ b/src/compiletest/runtest.rs @@ -294,6 +294,7 @@ fn run_pretty_test(config: &Config, props: &TestProps, testfile: &Path) { let aux_dir = aux_output_dir_name(config, testfile); // FIXME (#9639): This needs to handle non-utf8 paths let mut args = vec!("-".to_string(), + "-Zunstable-options".to_string(), "--pretty".to_string(), pretty_type, format!("--target={}", config.target), @@ -340,7 +341,7 @@ actual:\n\ }; // FIXME (#9639): This needs to handle non-utf8 paths let mut args = vec!("-".to_string(), - "--no-trans".to_string(), + "-Zno-trans".to_string(), "--crate-type=lib".to_string(), format!("--target={}", target), "-L".to_string(), @@ -547,7 +548,7 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) { // Add line breakpoints for line in breakpoint_lines.iter() { - script_str.push_str(&format!("break '{:?}':{}\n", + script_str.push_str(&format!("break '{}':{}\n", testfile.filename_display(), *line)[]); } @@ -750,7 +751,7 @@ fn run_debuginfo_lldb_test(config: &Config, props: &TestProps, testfile: &Path) status: status, stdout: out, stderr: err, - cmdline: format!("{}", cmd) + cmdline: format!("{:?}", cmd) }; } } @@ -862,7 +863,7 @@ fn check_debugger_output(debugger_run_result: &ProcRes, check_lines: &[String]) break; } Some(i) => { - rest = rest.slice_from(i + frag.len()); + rest = &rest[(i + frag.len())..]; } } first = false; @@ -953,7 +954,7 @@ fn check_expected_errors(expected_errors: Vec , } let prefixes = expected_errors.iter().map(|ee| { - format!("{:?}:{}:", testfile.display(), ee.line) + format!("{}:{}:", testfile.display(), ee.line) }).collect:: >(); #[cfg(windows)] @@ -1045,7 +1046,7 @@ fn scan_until_char(haystack: &str, needle: char, idx: &mut uint) -> bool { if *idx >= haystack.len() { return false; } - let opt = haystack.slice_from(*idx).find(needle); + let opt = haystack[(*idx)..].find(needle); if opt.is_none() { return false; } diff --git a/src/doc/grammar.md b/src/doc/grammar.md new file mode 100644 index 0000000000000..c2cbb3ae3fb2f --- /dev/null +++ b/src/doc/grammar.md @@ -0,0 +1,777 @@ +# **This is a work in progress** + +% The Rust Grammar + +# Introduction + +This document is the primary reference for the Rust programming language grammar. It +provides only one kind of material: + + - Chapters that formally define the language grammar and, for each + construct. + +This document does not serve as an introduction to the language. Background +familiarity with the language is assumed. A separate [guide] is available to +help acquire such background familiarity. + +This document also does not serve as a reference to the [standard] library +included in the language distribution. Those libraries are documented +separately by extracting documentation attributes from their source code. Many +of the features that one might expect to be language features are library +features in Rust, so what you're looking for may be there, not here. + +[guide]: guide.html +[standard]: std/index.html + +# Notation + +Rust's grammar is defined over Unicode codepoints, each conventionally denoted +`U+XXXX`, for 4 or more hexadecimal digits `X`. _Most_ of Rust's grammar is +confined to the ASCII range of Unicode, and is described in this document by a +dialect of Extended Backus-Naur Form (EBNF), specifically a dialect of EBNF +supported by common automated LL(k) parsing tools such as `llgen`, rather than +the dialect given in ISO 14977. The dialect can be defined self-referentially +as follows: + +```antlr +grammar : rule + ; +rule : nonterminal ':' productionrule ';' ; +productionrule : production [ '|' production ] * ; +production : term * ; +term : element repeats ; +element : LITERAL | IDENTIFIER | '[' productionrule ']' ; +repeats : [ '*' | '+' ] NUMBER ? | NUMBER ? | '?' ; +``` + +Where: + +- Whitespace in the grammar is ignored. +- Square brackets are used to group rules. +- `LITERAL` is a single printable ASCII character, or an escaped hexadecimal + ASCII code of the form `\xQQ`, in single quotes, denoting the corresponding + Unicode codepoint `U+00QQ`. +- `IDENTIFIER` is a nonempty string of ASCII letters and underscores. +- The `repeat` forms apply to the adjacent `element`, and are as follows: + - `?` means zero or one repetition + - `*` means zero or more repetitions + - `+` means one or more repetitions + - NUMBER trailing a repeat symbol gives a maximum repetition count + - NUMBER on its own gives an exact repetition count + +This EBNF dialect should hopefully be familiar to many readers. + +## Unicode productions + +A few productions in Rust's grammar permit Unicode codepoints outside the ASCII +range. We define these productions in terms of character properties specified +in the Unicode standard, rather than in terms of ASCII-range codepoints. The +section [Special Unicode Productions](#special-unicode-productions) lists these +productions. + +## String table productions + +Some rules in the grammar — notably [unary +operators](#unary-operator-expressions), [binary +operators](#binary-operator-expressions), and [keywords](#keywords) — are +given in a simplified form: as a listing of a table of unquoted, printable +whitespace-separated strings. These cases form a subset of the rules regarding +the [token](#tokens) rule, and are assumed to be the result of a +lexical-analysis phase feeding the parser, driven by a DFA, operating over the +disjunction of all such string table entries. + +When such a string enclosed in double-quotes (`"`) occurs inside the grammar, +it is an implicit reference to a single member of such a string table +production. See [tokens](#tokens) for more information. + +# Lexical structure + +## Input format + +Rust input is interpreted as a sequence of Unicode codepoints encoded in UTF-8. +Most Rust grammar rules are defined in terms of printable ASCII-range +codepoints, but a small number are defined in terms of Unicode properties or +explicit codepoint lists. [^inputformat] + +[^inputformat]: Substitute definitions for the special Unicode productions are + provided to the grammar verifier, restricted to ASCII range, when verifying the + grammar in this document. + +## Special Unicode Productions + +The following productions in the Rust grammar are defined in terms of Unicode +properties: `ident`, `non_null`, `non_star`, `non_eol`, `non_slash_or_star`, +`non_single_quote` and `non_double_quote`. + +### Identifiers + +The `ident` production is any nonempty Unicode string of the following form: + +- The first character has property `XID_start` +- The remaining characters have property `XID_continue` + +that does _not_ occur in the set of [keywords](#keywords). + +> **Note**: `XID_start` and `XID_continue` as character properties cover the +> character ranges used to form the more familiar C and Java language-family +> identifiers. + +### Delimiter-restricted productions + +Some productions are defined by exclusion of particular Unicode characters: + +- `non_null` is any single Unicode character aside from `U+0000` (null) +- `non_eol` is `non_null` restricted to exclude `U+000A` (`'\n'`) +- `non_star` is `non_null` restricted to exclude `U+002A` (`*`) +- `non_slash_or_star` is `non_null` restricted to exclude `U+002F` (`/`) and `U+002A` (`*`) +- `non_single_quote` is `non_null` restricted to exclude `U+0027` (`'`) +- `non_double_quote` is `non_null` restricted to exclude `U+0022` (`"`) + +## Comments + +```antlr +comment : block_comment | line_comment ; +block_comment : "/*" block_comment_body * "*/" ; +block_comment_body : [block_comment | character] * ; +line_comment : "//" non_eol * ; +``` + +**FIXME:** add doc grammar? + +## Whitespace + +```antlr +whitespace_char : '\x20' | '\x09' | '\x0a' | '\x0d' ; +whitespace : [ whitespace_char | comment ] + ; +``` + +## Tokens + +```antlr +simple_token : keyword | unop | binop ; +token : simple_token | ident | literal | symbol | whitespace token ; +``` + +### Keywords + +

+ +| | | | | | +|----------|----------|----------|----------|--------| +| abstract | alignof | as | be | box | +| break | const | continue | crate | do | +| else | enum | extern | false | final | +| fn | for | if | impl | in | +| let | loop | match | mod | move | +| mut | offsetof | once | override | priv | +| proc | pub | pure | ref | return | +| sizeof | static | self | struct | super | +| true | trait | type | typeof | unsafe | +| unsized | use | virtual | where | while | +| yield | | | | | + + +Each of these keywords has special meaning in its grammar, and all of them are +excluded from the `ident` rule. + +### Literals + +```antlr +lit_suffix : ident; +literal : [ string_lit | char_lit | byte_string_lit | byte_lit | num_lit ] lit_suffix ?; +``` + +#### Character and string literals + +```antlr +char_lit : '\x27' char_body '\x27' ; +string_lit : '"' string_body * '"' | 'r' raw_string ; + +char_body : non_single_quote + | '\x5c' [ '\x27' | common_escape | unicode_escape ] ; + +string_body : non_double_quote + | '\x5c' [ '\x22' | common_escape | unicode_escape ] ; +raw_string : '"' raw_string_body '"' | '#' raw_string '#' ; + +common_escape : '\x5c' + | 'n' | 'r' | 't' | '0' + | 'x' hex_digit 2 +unicode_escape : 'u' hex_digit 4 + | 'U' hex_digit 8 ; + +hex_digit : 'a' | 'b' | 'c' | 'd' | 'e' | 'f' + | 'A' | 'B' | 'C' | 'D' | 'E' | 'F' + | dec_digit ; +oct_digit : '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' ; +dec_digit : '0' | nonzero_dec ; +nonzero_dec: '1' | '2' | '3' | '4' + | '5' | '6' | '7' | '8' | '9' ; +``` + +#### Byte and byte string literals + +```antlr +byte_lit : "b\x27" byte_body '\x27' ; +byte_string_lit : "b\x22" string_body * '\x22' | "br" raw_byte_string ; + +byte_body : ascii_non_single_quote + | '\x5c' [ '\x27' | common_escape ] ; + +byte_string_body : ascii_non_double_quote + | '\x5c' [ '\x22' | common_escape ] ; +raw_byte_string : '"' raw_byte_string_body '"' | '#' raw_byte_string '#' ; + +``` + +#### Number literals + +```antlr +num_lit : nonzero_dec [ dec_digit | '_' ] * float_suffix ? + | '0' [ [ dec_digit | '_' ] * float_suffix ? + | 'b' [ '1' | '0' | '_' ] + + | 'o' [ oct_digit | '_' ] + + | 'x' [ hex_digit | '_' ] + ] ; + +float_suffix : [ exponent | '.' dec_lit exponent ? ] ? ; + +exponent : ['E' | 'e'] ['-' | '+' ] ? dec_lit ; +dec_lit : [ dec_digit | '_' ] + ; +``` + +#### Boolean literals + +**FIXME:** write grammar + +The two values of the boolean type are written `true` and `false`. + +### Symbols + +```antlr +symbol : "::" "->" + | '#' | '[' | ']' | '(' | ')' | '{' | '}' + | ',' | ';' ; +``` + +Symbols are a general class of printable [token](#tokens) that play structural +roles in a variety of grammar productions. They are catalogued here for +completeness as the set of remaining miscellaneous printable tokens that do not +otherwise appear as [unary operators](#unary-operator-expressions), [binary +operators](#binary-operator-expressions), or [keywords](#keywords). + +## Paths + +```antlr +expr_path : [ "::" ] ident [ "::" expr_path_tail ] + ; +expr_path_tail : '<' type_expr [ ',' type_expr ] + '>' + | expr_path ; + +type_path : ident [ type_path_tail ] + ; +type_path_tail : '<' type_expr [ ',' type_expr ] + '>' + | "::" type_path ; +``` + +# Syntax extensions + +## Macros + +```antlr +expr_macro_rules : "macro_rules" '!' ident '(' macro_rule * ')' ; +macro_rule : '(' matcher * ')' "=>" '(' transcriber * ')' ';' ; +matcher : '(' matcher * ')' | '[' matcher * ']' + | '{' matcher * '}' | '$' ident ':' ident + | '$' '(' matcher * ')' sep_token? [ '*' | '+' ] + | non_special_token ; +transcriber : '(' transcriber * ')' | '[' transcriber * ']' + | '{' transcriber * '}' | '$' ident + | '$' '(' transcriber * ')' sep_token? [ '*' | '+' ] + | non_special_token ; +``` + +# Crates and source files + +**FIXME:** grammar? What production covers #![crate_id = "foo"] ? + +# Items and attributes + +**FIXME:** grammar? + +## Items + +```antlr +item : mod_item | fn_item | type_item | struct_item | enum_item + | static_item | trait_item | impl_item | extern_block ; +``` + +### Type Parameters + +**FIXME:** grammar? + +### Modules + +```antlr +mod_item : "mod" ident ( ';' | '{' mod '}' ); +mod : [ view_item | item ] * ; +``` + +#### View items + +```antlr +view_item : extern_crate_decl | use_decl ; +``` + +##### Extern crate declarations + +```antlr +extern_crate_decl : "extern" "crate" crate_name +crate_name: ident | ( string_lit as ident ) +``` + +##### Use declarations + +```antlr +use_decl : "pub" ? "use" [ path "as" ident + | path_glob ] ; + +path_glob : ident [ "::" [ path_glob + | '*' ] ] ? + | '{' path_item [ ',' path_item ] * '}' ; + +path_item : ident | "mod" ; +``` + +### Functions + +**FIXME:** grammar? + +#### Generic functions + +**FIXME:** grammar? + +#### Unsafety + +**FIXME:** grammar? + +##### Unsafe functions + +**FIXME:** grammar? + +##### Unsafe blocks + +**FIXME:** grammar? + +#### Diverging functions + +**FIXME:** grammar? + +### Type definitions + +**FIXME:** grammar? + +### Structures + +**FIXME:** grammar? + +### Constant items + +```antlr +const_item : "const" ident ':' type '=' expr ';' ; +``` + +### Static items + +```antlr +static_item : "static" ident ':' type '=' expr ';' ; +``` + +#### Mutable statics + +**FIXME:** grammar? + +### Traits + +**FIXME:** grammar? + +### Implementations + +**FIXME:** grammar? + +### External blocks + +```antlr +extern_block_item : "extern" '{' extern_block '}' ; +extern_block : [ foreign_fn ] * ; +``` + +## Visibility and Privacy + +**FIXME:** grammar? + +### Re-exporting and Visibility + +**FIXME:** grammar? + +## Attributes + +```antlr +attribute : "#!" ? '[' meta_item ']' ; +meta_item : ident [ '=' literal + | '(' meta_seq ')' ] ? ; +meta_seq : meta_item [ ',' meta_seq ] ? ; +``` + +# Statements and expressions + +## Statements + +**FIXME:** grammar? + +### Declaration statements + +**FIXME:** grammar? + +A _declaration statement_ is one that introduces one or more *names* into the +enclosing statement block. The declared names may denote new slots or new +items. + +#### Item declarations + +**FIXME:** grammar? + +An _item declaration statement_ has a syntactic form identical to an +[item](#items) declaration within a module. Declaring an item — a +function, enumeration, structure, type, static, trait, implementation or module +— locally within a statement block is simply a way of restricting its +scope to a narrow region containing all of its uses; it is otherwise identical +in meaning to declaring the item outside the statement block. + +#### Slot declarations + +```antlr +let_decl : "let" pat [':' type ] ? [ init ] ? ';' ; +init : [ '=' ] expr ; +``` + +### Expression statements + +**FIXME:** grammar? + +## Expressions + +**FIXME:** grammar? + +#### Lvalues, rvalues and temporaries + +**FIXME:** grammar? + +#### Moved and copied types + +**FIXME:** Do we want to capture this in the grammar as different productions? + +### Literal expressions + +**FIXME:** grammar? + +### Path expressions + +**FIXME:** grammar? + +### Tuple expressions + +**FIXME:** grammar? + +### Unit expressions + +**FIXME:** grammar? + +### Structure expressions + +```antlr +struct_expr : expr_path '{' ident ':' expr + [ ',' ident ':' expr ] * + [ ".." expr ] '}' | + expr_path '(' expr + [ ',' expr ] * ')' | + expr_path ; +``` + +### Block expressions + +```antlr +block_expr : '{' [ view_item ] * + [ stmt ';' | item ] * + [ expr ] '}' ; +``` + +### Method-call expressions + +```antlr +method_call_expr : expr '.' ident paren_expr_list ; +``` + +### Field expressions + +```antlr +field_expr : expr '.' ident ; +``` + +### Array expressions + +```antlr +array_expr : '[' "mut" ? vec_elems? ']' ; + +array_elems : [expr [',' expr]*] | [expr ',' ".." expr] ; +``` + +### Index expressions + +```antlr +idx_expr : expr '[' expr ']' ; +``` + +### Unary operator expressions + +**FIXME:** grammar? + +### Binary operator expressions + +```antlr +binop_expr : expr binop expr ; +``` + +#### Arithmetic operators + +**FIXME:** grammar? + +#### Bitwise operators + +**FIXME:** grammar? + +#### Lazy boolean operators + +**FIXME:** grammar? + +#### Comparison operators + +**FIXME:** grammar? + +#### Type cast expressions + +**FIXME:** grammar? + +#### Assignment expressions + +**FIXME:** grammar? + +#### Compound assignment expressions + +**FIXME:** grammar? + +#### Operator precedence + +The precedence of Rust binary operators is ordered as follows, going from +strong to weak: + +``` +* / % +as ++ - +<< >> +& +^ +| +< > <= >= +== != +&& +|| += +``` + +Operators at the same precedence level are evaluated left-to-right. [Unary +operators](#unary-operator-expressions) have the same precedence level and it +is stronger than any of the binary operators'. + +### Grouped expressions + +```antlr +paren_expr : '(' expr ')' ; +``` + +### Call expressions + +```antlr +expr_list : [ expr [ ',' expr ]* ] ? ; +paren_expr_list : '(' expr_list ')' ; +call_expr : expr paren_expr_list ; +``` + +### Lambda expressions + +```antlr +ident_list : [ ident [ ',' ident ]* ] ? ; +lambda_expr : '|' ident_list '|' expr ; +``` + +### While loops + +```antlr +while_expr : "while" no_struct_literal_expr '{' block '}' ; +``` + +### Infinite loops + +```antlr +loop_expr : [ lifetime ':' ] "loop" '{' block '}'; +``` + +### Break expressions + +```antlr +break_expr : "break" [ lifetime ]; +``` + +### Continue expressions + +```antlr +continue_expr : "continue" [ lifetime ]; +``` + +### For expressions + +```antlr +for_expr : "for" pat "in" no_struct_literal_expr '{' block '}' ; +``` + +### If expressions + +```antlr +if_expr : "if" no_struct_literal_expr '{' block '}' + else_tail ? ; + +else_tail : "else" [ if_expr | if_let_expr + | '{' block '}' ] ; +``` + +### Match expressions + +```antlr +match_expr : "match" no_struct_literal_expr '{' match_arm * '}' ; + +match_arm : attribute * match_pat "=>" [ expr "," | '{' block '}' ] ; + +match_pat : pat [ '|' pat ] * [ "if" expr ] ? ; +``` + +### If let expressions + +```antlr +if_let_expr : "if" "let" pat '=' expr '{' block '}' + else_tail ? ; +else_tail : "else" [ if_expr | if_let_expr | '{' block '}' ] ; +``` + +### While let loops + +```antlr +while_let_expr : "while" "let" pat '=' expr '{' block '}' ; +``` + +### Return expressions + +```antlr +return_expr : "return" expr ? ; +``` + +# Type system + +**FIXME:** is this entire chapter relevant here? Or should it all have been covered by some production already? + +## Types + +### Primitive types + +**FIXME:** grammar? + +#### Machine types + +**FIXME:** grammar? + +#### Machine-dependent integer types + +**FIXME:** grammar? + +### Textual types + +**FIXME:** grammar? + +### Tuple types + +**FIXME:** grammar? + +### Array, and Slice types + +**FIXME:** grammar? + +### Structure types + +**FIXME:** grammar? + +### Enumerated types + +**FIXME:** grammar? + +### Pointer types + +**FIXME:** grammar? + +### Function types + +**FIXME:** grammar? + +### Closure types + +```antlr +closure_type := [ 'unsafe' ] [ '<' lifetime-list '>' ] '|' arg-list '|' + [ ':' bound-list ] [ '->' type ] +procedure_type := 'proc' [ '<' lifetime-list '>' ] '(' arg-list ')' + [ ':' bound-list ] [ '->' type ] +lifetime-list := lifetime | lifetime ',' lifetime-list +arg-list := ident ':' type | ident ':' type ',' arg-list +bound-list := bound | bound '+' bound-list +bound := path | lifetime +``` + +### Object types + +**FIXME:** grammar? + +### Type parameters + +**FIXME:** grammar? + +### Self types + +**FIXME:** grammar? + +## Type kinds + +**FIXME:** this this probably not relevant to the grammar... + +# Memory and concurrency models + +**FIXME:** is this entire chapter relevant here? Or should it all have been covered by some production already? + +## Memory model + +### Memory allocation and lifetime + +### Memory ownership + +### Memory slots + +### Boxes + +## Tasks + +### Communication between tasks + +### Task lifecycle diff --git a/src/doc/guide-crates.md b/src/doc/guide-crates.md index 8277988b7fe29..85badc11d64f0 100644 --- a/src/doc/guide-crates.md +++ b/src/doc/guide-crates.md @@ -1,4 +1,4 @@ % The (old) Rust Crates and Modules Guide -This content has moved into the +This content has moved into [the Rust Programming Language book](book/crates-and-modules.html). diff --git a/src/doc/guide-error-handling.md b/src/doc/guide-error-handling.md index 215fe6a441e0e..54fa529f3aa8e 100644 --- a/src/doc/guide-error-handling.md +++ b/src/doc/guide-error-handling.md @@ -1,4 +1,4 @@ % Error Handling in Rust -This content has moved into the +This content has moved into [the Rust Programming Language book](book/error-handling.html). diff --git a/src/doc/guide-ffi.md b/src/doc/guide-ffi.md index 4c818cacbfaf3..1130a10bd1c55 100644 --- a/src/doc/guide-ffi.md +++ b/src/doc/guide-ffi.md @@ -1,4 +1,4 @@ % The (old) Rust Foreign Function Interface Guide -This content has moved into the +This content has moved into [the Rust Programming Language book](book/ffi.html). diff --git a/src/doc/guide-macros.md b/src/doc/guide-macros.md index 534ae3504c3a2..228cb3c624f89 100644 --- a/src/doc/guide-macros.md +++ b/src/doc/guide-macros.md @@ -1,4 +1,4 @@ % The (old) Rust Macros Guide -This content has moved into the +This content has moved into [the Rust Programming Language book](book/macros.html). diff --git a/src/doc/guide-ownership.md b/src/doc/guide-ownership.md index 26e059aeb2680..884f14726ca87 100644 --- a/src/doc/guide-ownership.md +++ b/src/doc/guide-ownership.md @@ -1,4 +1,4 @@ % The (old) Rust Ownership Guide -This content has moved into the +This content has moved into [the Rust Programming Language book](book/ownership.html). diff --git a/src/doc/guide-plugins.md b/src/doc/guide-plugins.md index abfe7a44703a2..d6495d02e1189 100644 --- a/src/doc/guide-plugins.md +++ b/src/doc/guide-plugins.md @@ -1,4 +1,4 @@ % The (old) Rust Compiler Plugins Guide -This content has moved into the +This content has moved into [the Rust Programming Language book](book/plugins.html). diff --git a/src/doc/guide-pointers.md b/src/doc/guide-pointers.md index e72eaf62720b7..0374166405c62 100644 --- a/src/doc/guide-pointers.md +++ b/src/doc/guide-pointers.md @@ -1,4 +1,4 @@ % The (old) Rust Pointer Guide -This content has moved into the +This content has moved into [the Rust Programming Language book](book/pointers.html). diff --git a/src/doc/guide-strings.md b/src/doc/guide-strings.md index fd1420024c665..d030614489bcc 100644 --- a/src/doc/guide-strings.md +++ b/src/doc/guide-strings.md @@ -1,4 +1,4 @@ % The (old) Guide to Rust Strings -This content has moved into the +This content has moved into [the Rust Programming Language book](book/strings.html). diff --git a/src/doc/guide-tasks.md b/src/doc/guide-tasks.md index be8cb67098620..197559bef0408 100644 --- a/src/doc/guide-tasks.md +++ b/src/doc/guide-tasks.md @@ -1,4 +1,4 @@ % The (old) Rust Threads and Communication Guide -This content has moved into the +This content has moved into [the Rust Programming Language book](book/tasks.html). diff --git a/src/doc/guide-testing.md b/src/doc/guide-testing.md index 79721300d941d..67bcb0a5e546a 100644 --- a/src/doc/guide-testing.md +++ b/src/doc/guide-testing.md @@ -1,4 +1,4 @@ % The (old) Rust Testing Guide -This content has moved into the +This content has moved into [the Rust Programming Language book](book/testing.html). diff --git a/src/doc/guide-unsafe.md b/src/doc/guide-unsafe.md index fe8fcc4c19d84..3c1a82d017449 100644 --- a/src/doc/guide-unsafe.md +++ b/src/doc/guide-unsafe.md @@ -1,4 +1,4 @@ % Writing Safe Low-level and Unsafe Code in Rust -This content has moved into the +This content has moved into [the Rust Programming Language book](book/unsafe.html). diff --git a/src/doc/guide.md b/src/doc/guide.md index ba1e2590e7fa5..b9e70e7cfd7e0 100644 --- a/src/doc/guide.md +++ b/src/doc/guide.md @@ -1,4 +1,4 @@ % The (old) Rust Guide -This content has moved into the +This content has moved into [the Rust Programming Language book](book/README.html). diff --git a/src/doc/intro.md b/src/doc/intro.md index d93b680ae6de7..b92d38215c29b 100644 --- a/src/doc/intro.md +++ b/src/doc/intro.md @@ -424,11 +424,11 @@ Let's see an example. This Rust code will not compile: use std::thread::Thread; fn main() { - let mut numbers = vec![1i, 2i, 3i]; + let mut numbers = vec![1is, 2, 3]; - for i in range(0u, 3u) { + for i in 0..3 { Thread::spawn(move || { - for j in range(0, 3) { numbers[j] += 1 } + for j in 0..3 { numbers[j] += 1 } }); } } @@ -438,15 +438,15 @@ It gives us this error: ```text 6:71 error: capture of moved value: `numbers` - for j in range(0, 3) { numbers[j] += 1 } - ^~~~~~~ + for j in 0..3 { numbers[j] += 1 } + ^~~~~~~ 7:50 note: `numbers` moved into closure environment here spawn(move || { - for j in range(0, 3) { numbers[j] += 1 } + for j in 0..3 { numbers[j] += 1 } }); 6:79 error: cannot assign to immutable dereference (dereference is implicit, due to indexing) - for j in range(0, 3) { numbers[j] += 1 } - ^~~~~~~~~~~~~~~ + for j in 0..3 { numbers[j] += 1 } + ^~~~~~~~~~~~~~~ ``` It mentions that "numbers moved into closure environment". Because we @@ -478,16 +478,14 @@ use std::thread::Thread; use std::sync::{Arc,Mutex}; fn main() { - let numbers = Arc::new(Mutex::new(vec![1i, 2i, 3i])); + let numbers = Arc::new(Mutex::new(vec![1is, 2, 3])); - for i in range(0u, 3u) { + for i in 0us..3 { let number = numbers.clone(); Thread::spawn(move || { let mut array = number.lock().unwrap(); - - (*array)[i] += 1; - - println!("numbers[{}] is {}", i, (*array)[i]); + array[i] += 1; + println!("numbers[{}] is {}", i, array[i]); }); } } @@ -541,12 +539,12 @@ safety check that makes this an error about moved values: use std::thread::Thread; fn main() { - let vec = vec![1i, 2, 3]; + let vec = vec![1is, 2, 3]; - for i in range(0u, 3) { + for i in 0us..3 { Thread::spawn(move || { println!("{}", vec[i]); - }).detach(); + }); } } ``` @@ -557,9 +555,9 @@ you can remove it. As an example, this is a poor way to iterate through a vector: ```{rust} -let vec = vec![1i, 2, 3]; +let vec = vec![1, 2, 3]; -for i in range(0u, vec.len()) { +for i in 0..vec.len() { println!("{}", vec[i]); } ``` @@ -569,7 +567,7 @@ that we don't try to access an invalid index. However, we can remove this while retaining safety. The answer is iterators: ```{rust} -let vec = vec![1i, 2, 3]; +let vec = vec![1, 2, 3]; for x in vec.iter() { println!("{}", x); diff --git a/src/doc/reference.md b/src/doc/reference.md index c8e31f27b3507..9ec4708eb2f36 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -257,10 +257,10 @@ cases mentioned in [Number literals](#number-literals) below. | [Number literals](#number-literals)`*` | Example | Exponentiation | Suffixes | |----------------------------------------|---------|----------------|----------| -| Decimal integer | `98_222i` | `N/A` | Integer suffixes | -| Hex integer | `0xffi` | `N/A` | Integer suffixes | -| Octal integer | `0o77i` | `N/A` | Integer suffixes | -| Binary integer | `0b1111_0000i` | `N/A` | Integer suffixes | +| Decimal integer | `98_222is` | `N/A` | Integer suffixes | +| Hex integer | `0xffis` | `N/A` | Integer suffixes | +| Octal integer | `0o77is` | `N/A` | Integer suffixes | +| Binary integer | `0b1111_0000is` | `N/A` | Integer suffixes | | Floating-point | `123.0E+77f64` | `Optional` | Floating-point suffixes | `*` All number literals allow `_` as a visual separator: `1_234.0E+18f64` @@ -268,7 +268,7 @@ cases mentioned in [Number literals](#number-literals) below. ##### Suffixes | Integer | Floating-point | |---------|----------------| -| `i` (`int`), `u` (`uint`), `u8`, `i8`, `u16`, `i16`, `u32`, `i32`, `u64`, `i64` | `f32`, `f64` | +| `is` (`isize`), `us` (`usize`), `u8`, `i8`, `u16`, `i16`, `u32`, `i32`, `u64`, `i64` | `f32`, `f64` | #### Character and string literals @@ -468,7 +468,7 @@ Like any literal, an integer literal may be followed (immediately, without any spaces) by an _integer suffix_, which forcibly sets the type of the literal. There are 10 valid values for an integer suffix: -* The `i` and `u` suffixes give the literal type `int` or `uint`, +* The `is` and `us` suffixes give the literal type `isize` or `usize`, respectively. * Each of the signed and unsigned machine types `u8`, `i8`, `u16`, `i16`, `u32`, `i32`, `u64` and `i64` @@ -483,9 +483,9 @@ context overconstrains the type, it is also considered a static type error. Examples of integer literals of various forms: ``` -123i; // type int -123u; // type uint -123_u; // type uint +123is; // type isize +123us; // type usize +123_us; // type usize 0xff_u8; // type u8 0o70_i16; // type i16 0b1111_1111_1001_0000_i32; // type i32 @@ -578,8 +578,8 @@ Two examples of paths with type arguments: # struct HashMap; # fn f() { # fn id(t: T) -> T { t } -type T = HashMap; // Type arguments used in a type expression -let x = id::(10); // Type arguments used in a call expression +type T = HashMap; // Type arguments used in a type expression +let x = id::(10); // Type arguments used in a call expression # } ``` @@ -803,8 +803,9 @@ Crates contain [items](#items), each of which may have some number of ## Items ```{.ebnf .gram} -item : mod_item | fn_item | type_item | struct_item | enum_item - | static_item | trait_item | impl_item | extern_block ; +item : extern_crate_decl | use_decl | mod_item | fn_item | type_item + | struct_item | enum_item | static_item | trait_item | impl_item + | extern_block ; ``` An _item_ is a component of a crate; some module items can be defined in crate @@ -818,6 +819,8 @@ execution, and may reside in read-only memory. There are several kinds of item: +* [`extern crate` declarations](#extern-crate-declarations) +* [`use` declarations](#use-declarations) * [modules](#modules) * [functions](#functions) * [type definitions](#type-definitions) @@ -854,13 +857,10 @@ no notion of type abstraction: there are no first-class "forall" types. ```{.ebnf .gram} mod_item : "mod" ident ( ';' | '{' mod '}' ); -mod : [ view_item | item ] * ; +mod : item * ; ``` -A module is a container for zero or more [view items](#view-items) and zero or -more [items](#items). The view items manage the visibility of the items defined -within the module, as well as the visibility of names from outside the module -when referenced from inside the module. +A module is a container for zero or more [items](#items). A _module item_ is a module, surrounded in braces, named, and prefixed with the keyword `mod`. A module item introduces a new, named module into the tree of @@ -918,19 +918,6 @@ mod thread { } ``` -#### View items - -```{.ebnf .gram} -view_item : extern_crate_decl | use_decl ; -``` - -A view item manages the namespace of a module. View items do not define new -items, but rather, simply change other items' visibility. There are two -kinds of view items: - -* [`extern crate` declarations](#extern-crate-declarations) -* [`use` declarations](#use-declarations) - ##### Extern crate declarations ```{.ebnf .gram} @@ -971,7 +958,7 @@ path_glob : ident [ "::" [ path_glob | '*' ] ] ? | '{' path_item [ ',' path_item ] * '}' ; -path_item : ident | "mod" ; +path_item : ident | "self" ; ``` A _use declaration_ creates one or more local name bindings synonymous with @@ -991,22 +978,22 @@ Use declarations support a number of convenient shortcuts: * Binding all paths matching a given prefix, using the asterisk wildcard syntax `use a::b::*;` * Simultaneously binding a list of paths differing only in their final element - and their immediate parent module, using the `mod` keyword, such as - `use a::b::{mod, c, d};` + and their immediate parent module, using the `self` keyword, such as + `use a::b::{self, c, d};` An example of `use` declarations: ``` use std::iter::range_step; use std::option::Option::{Some, None}; -use std::collections::hash_map::{mod, HashMap}; +use std::collections::hash_map::{self, HashMap}; fn foo(_: T){} -fn bar(map1: HashMap, map2: hash_map::HashMap){} +fn bar(map1: HashMap, map2: hash_map::HashMap){} fn main() { - // Equivalent to 'std::iter::range_step(0u, 10u, 2u);' - range_step(0u, 10u, 2u); + // Equivalent to 'std::iter::range_step(0us, 10, 2);' + range_step(0us, 10, 2); // Equivalent to 'foo(vec![std::option::Option::Some(1.0f64), // std::option::Option::None]);' @@ -1104,7 +1091,7 @@ interpreted as an implicit `return` expression applied to the final-expression. An example of a function: ``` -fn add(x: int, y: int) -> int { +fn add(x: i32, y: i32) -> i32 { return x + y; } ``` @@ -1113,7 +1100,7 @@ As with `let` bindings, function arguments are irrefutable patterns, so any pattern that is valid in a let binding is also valid as an argument. ``` -fn first((value, _): (int, int)) -> int { value } +fn first((value, _): (i32, i32)) -> i32 { value } ``` @@ -1139,8 +1126,8 @@ used as a type name. When a generic function is referenced, its type is instantiated based on the context of the reference. For example, calling the `iter` function defined -above on `[1, 2]` will instantiate type parameter `T` with `int`, and require -the closure parameter to have type `fn(int)`. +above on `[1, 2]` will instantiate type parameter `T` with `isize`, and require +the closure parameter to have type `fn(isize)`. The type parameters can also be explicitly supplied in a trailing [path](#paths) component after the function name. This might be necessary if @@ -1272,7 +1259,7 @@ typecheck: ``` # fn my_err(s: &str) -> ! { panic!() } -fn f(i: int) -> int { +fn f(i: i32) -> i32 { if i == 42 { return 42; } @@ -1283,7 +1270,7 @@ fn f(i: int) -> int { ``` This will not compile without the `!` annotation on `my_err`, since the `else` -branch of the conditional in `f` does not return an `int`, as required by the +branch of the conditional in `f` does not return an `i32`, as required by the signature of `f`. Adding the `!` annotation to `my_err` informs the typechecker that, should control ever enter `my_err`, no further type judgments about `f` need to hold, since control will never resume in any context that @@ -1301,18 +1288,18 @@ modifier. ``` // Declares an extern fn, the ABI defaults to "C" -extern fn new_int() -> int { 0 } +extern fn new_i32() -> i32 { 0 } // Declares an extern fn with "stdcall" ABI -extern "stdcall" fn new_int_stdcall() -> int { 0 } +extern "stdcall" fn new_i32_stdcall() -> i32 { 0 } ``` Unlike normal functions, extern fns have an `extern "ABI" fn()`. This is the same type as the functions declared in an extern block. ``` -# extern fn new_int() -> int { 0 } -let fptr: extern "C" fn() -> int = new_int; +# extern fn new_i32() -> i32 { 0 } +let fptr: extern "C" fn() -> i32 = new_i32; ``` Extern functions may be called directly from Rust code as Rust uses large, @@ -1348,18 +1335,18 @@ keyword `struct`. An example of a `struct` item and its use: ``` -struct Point {x: int, y: int} +struct Point {x: i32, y: i32} let p = Point {x: 10, y: 11}; -let px: int = p.x; +let px: i32 = p.x; ``` A _tuple structure_ is a nominal [tuple type](#tuple-types), also defined with the keyword `struct`. For example: ``` -struct Point(int, int); +struct Point(i32, i32); let p = Point(10, 11); -let px: int = match p { Point(x, _) => x }; +let px: i32 = match p { Point(x, _) => x }; ``` A _unit-like struct_ is a structure without any fields, defined by leaving off @@ -1413,6 +1400,27 @@ a = Animal::Cat { name: "Spotty".to_string(), weight: 2.7 }; In this example, `Cat` is a _struct-like enum variant_, whereas `Dog` is simply called an enum variant. +Enums have a discriminant. You can assign them explicitly: + +``` +enum Foo { + Bar = 123, +} +``` + +If a discriminant isn't assigned, they start at zero, and add one for each +variant, in order. + +You can cast an enum to get this value: + +``` +# enum Foo { Bar = 123 } +let x = Foo::Bar as u32; // x is now 123u32 +``` + +This only works as long as none of the variants have data attached. If +it were `Bar(i32)`, this is disallowed. + ### Constant items ```{.ebnf .gram} @@ -1436,14 +1444,14 @@ a type derived from those primitive types. The derived types are references with the `static` lifetime, fixed-size arrays, tuples, enum variants, and structs. ``` -const BIT1: uint = 1 << 0; -const BIT2: uint = 1 << 1; +const BIT1: u32 = 1 << 0; +const BIT2: u32 = 1 << 1; -const BITS: [uint; 2] = [BIT1, BIT2]; +const BITS: [u32; 2] = [BIT1, BIT2]; const STRING: &'static str = "bitstring"; struct BitsNStrings<'a> { - mybits: [uint; 2], + mybits: [u32; 2], mystring: &'a str } @@ -1479,14 +1487,14 @@ Constants should in general be preferred over statics, unless large amounts of data are being stored, or single-address and mutability properties are required. ``` -use std::sync::atomic::{AtomicUint, Ordering, ATOMIC_UINT_INIT};; +use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT}; -// Note that ATOMIC_UINT_INIT is a *const*, but it may be used to initialize a +// Note that ATOMIC_USIZE_INIT is a *const*, but it may be used to initialize a // static. This static can be modified, so it is not placed in read-only memory. -static COUNTER: AtomicUint = ATOMIC_UINT_INIT; +static COUNTER: AtomicUsize = ATOMIC_USIZE_INIT; // This table is a candidate to be placed in read-only memory. -static TABLE: &'static [uint] = &[1, 2, 3, /* ... */]; +static TABLE: &'static [usize] = &[1, 2, 3, /* ... */]; for slot in TABLE.iter() { println!("{}", slot); @@ -1508,13 +1516,13 @@ Mutable statics are still very useful, however. They can be used with C libraries and can also be bound from C libraries (in an `extern` block). ``` -# fn atomic_add(_: &mut uint, _: uint) -> uint { 2 } +# fn atomic_add(_: &mut u32, _: u32) -> u32 { 2 } -static mut LEVELS: uint = 0; +static mut LEVELS: u32 = 0; // This violates the idea of no shared state, and this doesn't internally // protect against races, so this function is `unsafe` -unsafe fn bump_levels_unsafe1() -> uint { +unsafe fn bump_levels_unsafe1() -> u32 { let ret = LEVELS; LEVELS += 1; return ret; @@ -1523,7 +1531,7 @@ unsafe fn bump_levels_unsafe1() -> uint { // Assuming that we have an atomic_add function which returns the old value, // this function is "safe" but the meaning of the return value may not be what // callers expect, so it's still marked as `unsafe` -unsafe fn bump_levels_unsafe2() -> uint { +unsafe fn bump_levels_unsafe2() -> u32 { return atomic_add(&mut LEVELS, 1); } ``` @@ -1543,8 +1551,8 @@ Traits are implemented for specific types through separate [implementations](#implementations). ``` -# type Surface = int; -# type BoundingBox = int; +# type Surface = i32; +# type BoundingBox = i32; trait Shape { fn draw(&self, Surface); fn bounding_box(&self) -> BoundingBox; @@ -1562,8 +1570,8 @@ functions](#generic-functions). ``` trait Seq { - fn len(&self) -> uint; - fn elt_at(&self, n: uint) -> T; + fn len(&self) -> u32; + fn elt_at(&self, n: u32) -> T; fn iter(&self, F) where F: Fn(T); } ``` @@ -1574,7 +1582,7 @@ parameter, and within the generic function, the methods of the trait can be called on values that have the parameter's type. For example: ``` -# type Surface = int; +# type Surface = i32; # trait Shape { fn draw(&self, Surface); } fn draw_twice(surface: Surface, sh: T) { sh.draw(surface); @@ -1589,8 +1597,8 @@ trait is in scope) to pointers to the trait name, used as a type. ``` # trait Shape { } -# impl Shape for int { } -# let mycircle = 0i; +# impl Shape for i32 { } +# let mycircle = 0i32; let myshape: Box = Box::new(mycircle) as Box; ``` @@ -1608,12 +1616,12 @@ module. For example: ``` trait Num { - fn from_int(n: int) -> Self; + fn from_i32(n: i32) -> Self; } impl Num for f64 { - fn from_int(n: int) -> f64 { n as f64 } + fn from_i32(n: i32) -> f64 { n as f64 } } -let x: f64 = Num::from_int(42); +let x: f64 = Num::from_i32(42); ``` Traits may inherit from other traits. For example, in @@ -1648,9 +1656,9 @@ Likewise, supertrait methods may also be called on trait objects. ```{.ignore} # trait Shape { fn area(&self) -> f64; } # trait Circle : Shape { fn radius(&self) -> f64; } -# impl Shape for int { fn area(&self) -> f64 { 0.0 } } -# impl Circle for int { fn radius(&self) -> f64 { 0.0 } } -# let mycircle = 0; +# impl Shape for i32 { fn area(&self) -> f64 { 0.0 } } +# impl Circle for i32 { fn radius(&self) -> f64 { 0.0 } } +# let mycircle = 0i32; let mycircle = Box::new(mycircle) as Box; let nonsense = mycircle.radius() * mycircle.area(); ``` @@ -1665,7 +1673,7 @@ Implementations are defined with the keyword `impl`. ``` # struct Point {x: f64, y: f64}; # impl Copy for Point {} -# type Surface = int; +# type Surface = i32; # struct BoundingBox {x: f64, y: f64, width: f64, height: f64}; # trait Shape { fn draw(&self, Surface); fn bounding_box(&self) -> BoundingBox; } # fn do_draw_circle(s: Surface, c: Circle) { } @@ -1694,7 +1702,7 @@ limited to nominal types (enums, structs), and the implementation must appear in the same module or a sub-module as the `self` type: ``` -struct Point {x: int, y: int} +struct Point {x: i32, y: i32} impl Point { fn log(&self) { @@ -1805,7 +1813,7 @@ struct Foo; // Declare a public struct with a private field pub struct Bar { - field: int + field: i32 } // Declare a public enum with two public variants @@ -2205,15 +2213,15 @@ plugins](book/plugin.html#lint-plugins) can provide additional lint checks. mod m1 { // Missing documentation is ignored here #[allow(missing_docs)] - pub fn undocumented_one() -> int { 1 } + pub fn undocumented_one() -> i32 { 1 } // Missing documentation signals a warning here #[warn(missing_docs)] - pub fn undocumented_too() -> int { 2 } + pub fn undocumented_too() -> i32 { 2 } // Missing documentation signals an error here #[deny(missing_docs)] - pub fn undocumented_end() -> int { 3 } + pub fn undocumented_end() -> i32 { 3 } } ``` @@ -2226,16 +2234,16 @@ mod m2{ #[allow(missing_docs)] mod nested { // Missing documentation is ignored here - pub fn undocumented_one() -> int { 1 } + pub fn undocumented_one() -> i32 { 1 } // Missing documentation signals a warning here, // despite the allow above. #[warn(missing_docs)] - pub fn undocumented_two() -> int { 2 } + pub fn undocumented_two() -> i32 { 2 } } // Missing documentation signals a warning here - pub fn undocumented_too() -> int { 3 } + pub fn undocumented_too() -> i32 { 3 } } ``` @@ -2248,7 +2256,7 @@ mod m3 { // Attempting to toggle warning signals an error here #[allow(missing_docs)] /// Returns 2. - pub fn undocumented_too() -> int { 2 } + pub fn undocumented_too() -> i32 { 2 } } ``` @@ -2356,10 +2364,6 @@ These types help drive the compiler's analysis : ___Needs filling in___ * `no_copy_bound` : This type does not implement "copy", even if eligible. -* `no_send_bound` - : This type does not implement "send", even if eligible. -* `no_sync_bound` - : This type does not implement "sync", even if eligible. * `eh_personality` : ___Needs filling in___ * `exchange_free` @@ -2430,7 +2434,7 @@ There are three different types of inline attributes: * `#[inline(always)]` asks the compiler to always perform an inline expansion. * `#[inline(never)]` asks the compiler to never perform an inline expansion. -### Derive +### `derive` The `derive` attribute allows certain traits to be automatically implemented for data structures. For example, the following will create an `impl` for the @@ -2440,7 +2444,7 @@ the `PartialEq` or `Clone` constraints for the appropriate `impl`: ``` #[derive(PartialEq, Clone)] struct Foo { - a: int, + a: i32, b: T } ``` @@ -2448,7 +2452,7 @@ struct Foo { The generated `impl` for `PartialEq` is equivalent to ``` -# struct Foo { a: int, b: T } +# struct Foo { a: i32, b: T } impl PartialEq for Foo { fn eq(&self, other: &Foo) -> bool { self.a == other.a && self.b == other.b @@ -2800,7 +2804,7 @@ parentheses. They are used to create [tuple-typed](#tuple-types) values. ```{.tuple} (0,); (0.0, 4.5); -("a", 4u, true); +("a", 4us, true); ``` ### Unit expressions @@ -2841,7 +2845,7 @@ The following are examples of structure expressions: ``` # struct Point { x: f64, y: f64 } # struct TuplePoint(f64, f64); -# mod game { pub struct User<'a> { pub name: &'a str, pub age: uint, pub score: uint } } +# mod game { pub struct User<'a> { pub name: &'a str, pub age: u32, pub score: uint } } # struct Cookie; fn some_fn(t: T) {} Point {x: 10.0, y: 20.0}; TuplePoint(10.0, 20.0); @@ -2862,7 +2866,7 @@ were explicitly specified and the values in the base expression for all other fields. ``` -# struct Point3d { x: int, y: int, z: int } +# struct Point3d { x: i32, y: i32, z: i32 } let base = Point3d {x: 1, y: 2, z: 3}; Point3d {y: 0, z: 10, .. base}; ``` @@ -2870,13 +2874,12 @@ Point3d {y: 0, z: 10, .. base}; ### Block expressions ```{.ebnf .gram} -block_expr : '{' [ view_item ] * - [ stmt ';' | item ] * +block_expr : '{' [ stmt ';' | item ] * [ expr ] '}' ; ``` A _block expression_ is similar to a module in terms of the declarations that -are possible. Each block conceptually introduces a new namespace scope. View +are possible. Each block conceptually introduces a new namespace scope. Use items can bring new names into scopes and declared items are in scope for only the block itself. @@ -2937,9 +2940,9 @@ constant expression that can be evaluated at compile time, such as a [literal](#literals) or a [static item](#static-items). ``` -[1i, 2, 3, 4]; +[1is, 2, 3, 4]; ["a", "b", "c", "d"]; -[0i; 128]; // array with 128 zeros +[0is; 128]; // array with 128 zeros [0u8, 0u8, 0u8, 0u8]; ``` @@ -3092,7 +3095,7 @@ An example of an `as` expression: ``` # fn sum(v: &[f64]) -> f64 { 0.0 } -# fn len(v: &[f64]) -> int { 0 } +# fn len(v: &[f64]) -> i32 { 0 } fn avg(v: &[f64]) -> f64 { let sum: f64 = sum(v); @@ -3112,7 +3115,7 @@ moves](#moved-and-copied-types) its right-hand operand to its left-hand operand. ``` -# let mut x = 0i; +# let mut x = 0is; # let y = 0; x = y; @@ -3163,7 +3166,7 @@ paren_expr : '(' expr ')' ; An example of a parenthesized expression: ``` -let x: int = (2 + 3) * 4; +let x: i32 = (2 + 3) * 4; ``` @@ -3183,9 +3186,9 @@ then the expression completes. Some examples of call expressions: ``` -# fn add(x: int, y: int) -> int { 0 } +# fn add(x: i32, y: i32) -> i32 { 0 } -let x: int = add(1, 2); +let x: i32 = add(1i32, 2i32); let pi: Option = "3.14".parse(); ``` @@ -3224,8 +3227,8 @@ In this example, we define a function `ten_times` that takes a higher-order function argument, and call it with a lambda expression as an argument: ``` -fn ten_times(f: F) where F: Fn(int) { - let mut i = 0; +fn ten_times(f: F) where F: Fn(i32) { + let mut i = 0i32; while i < 10 { f(i); i += 1; @@ -3249,7 +3252,7 @@ conditional expression evaluates to `false`, the `while` expression completes. An example: ``` -let mut i = 0u; +let mut i = 0us; while i < 10 { println!("hello"); @@ -3312,7 +3315,7 @@ by an implementation of `std::iter::Iterator`. An example of a for loop over the contents of an array: ``` -# type Foo = int; +# type Foo = i32; # fn bar(f: Foo) { } # let a = 0; # let b = 0; @@ -3328,8 +3331,8 @@ for e in v.iter() { An example of a for loop over a series of integers: ``` -# fn bar(b:uint) { } -for i in range(0u, 256) { +# fn bar(b:usize) { } +for i in range(0us, 256) { bar(i); } ``` @@ -3381,7 +3384,7 @@ fields of a particular variant. For example: enum List { Nil, Cons(X, Box>) } fn main() { - let x: List = List::Cons(10, box List::Cons(11, box List::Nil)); + let x: List = List::Cons(10, box List::Cons(11, box List::Nil)); match x { List::Cons(_, box List::Nil) => panic!("singleton list"), @@ -3402,12 +3405,12 @@ Used inside an array pattern, `..` stands for any number of elements, when the `advanced_slice_patterns` feature gate is turned on. This wildcard can be used at most once for a given array, which implies that it cannot be used to specifically match elements that are at an unknown distance from both ends of a -array, like `[.., 42, ..]`. If followed by a variable name, it will bind the +array, like `[.., 42, ..]`. If preceded by a variable name, it will bind the corresponding slice to the variable. Example: ``` # #![feature(advanced_slice_patterns)] -fn is_symmetric(list: &[uint]) -> bool { +fn is_symmetric(list: &[u32]) -> bool { match list { [] | [_] => true, [x, inside.., y] if x == y => is_symmetric(inside), @@ -3441,13 +3444,13 @@ An example of a `match` expression: ``` #![feature(box_syntax)] -# fn process_pair(a: int, b: int) { } +# fn process_pair(a: i32, b: i32) { } # fn process_ten() { } enum List { Nil, Cons(X, Box>) } fn main() { - let x: List = List::Cons(10, box List::Cons(11, box List::Nil)); + let x: List = List::Cons(10, box List::Cons(11, box List::Nil)); match x { List::Cons(a, box List::Cons(b, _)) => { @@ -3499,11 +3502,11 @@ fn main() { ``` Patterns can also dereference pointers by using the `&`, `&mut` and `box` -symbols, as appropriate. For example, these two matches on `x: &int` are +symbols, as appropriate. For example, these two matches on `x: &isize` are equivalent: ``` -# let x = &3i; +# let x = &3is; let y = match *x { 0 => "zero", _ => "some" }; let z = match x { &0 => "zero", _ => "some" }; @@ -3524,7 +3527,7 @@ Multiple match patterns may be joined with the `|` operator. A range of values may be specified with `...`. For example: ``` -# let x = 2i; +# let x = 2is; let message = match x { 0 | 1 => "not many", @@ -3544,8 +3547,8 @@ may refer to the variables bound within the pattern they follow. ``` # let maybe_digit = Some(0); -# fn process_digit(i: int) { } -# fn process_other(i: int) { } +# fn process_digit(i: i32) { } +# fn process_other(i: i32) { } let message = match maybe_digit { Some(x) if x < 10 => process_digit(x), @@ -3593,7 +3596,7 @@ caller frame. An example of a `return` expression: ``` -fn max(a: int, b: int) -> int { +fn max(a: i32, b: i32) -> i32 { if a > b { return a; } @@ -3645,12 +3648,12 @@ The machine types are the following: #### Machine-dependent integer types -The `uint` type is an unsigned integer type with the same number of bits as the +The `usize` type is an unsigned integer type with the same number of bits as the platform's pointer type. It can represent every memory address in the process. -The `int` type is a signed integer type with the same number of bits as the +The `isize` type is a signed integer type with the same number of bits as the platform's pointer type. The theoretical upper bound on object and array size -is the maximum `int` value. This ensures that `int` can be used to calculate +is the maximum `isize` value. This ensures that `isize` can be used to calculate differences between pointers into an object or array and can address every byte within an object along with one byte past the end. @@ -3686,7 +3689,7 @@ by the tuple type. An example of a tuple type and its use: ``` -type Pair<'a> = (int, &'a str); +type Pair<'a> = (i32, &'a str); let p: Pair<'static> = (10, "hello"); let (a, b) = p; assert!(b != "world"); @@ -3837,13 +3840,13 @@ or `extern`), a sequence of input types and an output type. An example of a `fn` type: ``` -fn add(x: int, y: int) -> int { +fn add(x: i32, y: i32) -> i32 { return x + y; } let mut x = add(5,7); -type Binop = fn(int, int) -> int; +type Binop = fn(i32, i32) -> i32; let bo: Binop = add; x = bo(5,7); ``` @@ -3865,16 +3868,16 @@ The type of a closure mapping an input of type `A` to an output of type `B` is An example of creating and calling a closure: ```rust -let captured_var = 10i; +let captured_var = 10is; let closure_no_args = |&:| println!("captured_var={}", captured_var); -let closure_args = |&: arg: int| -> int { +let closure_args = |&: arg: isize| -> isize { println!("captured_var={}, arg={}", captured_var, arg); arg // Note lack of semicolon after 'arg' }; -fn call_closure int>(c1: F, c2: G) { +fn call_closure isize>(c1: F, c2: G) { c1(); c2(2); } @@ -3906,7 +3909,7 @@ trait Printable { fn stringify(&self) -> String; } -impl Printable for int { +impl Printable for isize { fn stringify(&self) -> String { self.to_string() } } @@ -3915,7 +3918,7 @@ fn print(a: Box) { } fn main() { - print(Box::new(10i) as Box); + print(Box::new(10is) as Box); } ``` @@ -4081,7 +4084,7 @@ Local variables are immutable unless declared otherwise like: `let mut x = ...`. Function parameters are immutable unless declared with `mut`. The `mut` keyword applies only to the following parameter (so `|mut x, y|` and `fn f(mut x: -Box, y: Box)` declare one mutable variable `x` and one immutable +Box, y: Box)` declare one mutable variable `x` and one immutable variable `y`). Methods that take either `self` or `Box` can optionally place them in a @@ -4109,7 +4112,7 @@ the type of a box is `std::owned::Box`. An example of a box type and value: ``` -let x: Box = Box::new(10); +let x: Box = Box::new(10); ``` Box values exist in 1:1 correspondence with their heap allocation, copying a @@ -4118,7 +4121,7 @@ copy of a box to move ownership of the value. After a value has been moved, the source location cannot be used unless it is reinitialized. ``` -let x: Box = Box::new(10); +let x: Box = Box::new(10); let y = x; // attempting to use `x` will result in an error here ``` diff --git a/src/doc/trpl/arrays-vectors-and-slices.md b/src/doc/trpl/arrays-vectors-and-slices.md index e7ac55bfbd30d..2df769b3c2c67 100644 --- a/src/doc/trpl/arrays-vectors-and-slices.md +++ b/src/doc/trpl/arrays-vectors-and-slices.md @@ -5,7 +5,7 @@ things. The most basic is the *array*, a fixed-size list of elements of the same type. By default, arrays are immutable. ```{rust} -let a = [1, 2, 3]; // a: [i32; 3] +let a = [1, 2, 3]; // a: [i32; 3] let mut m = [1, 2, 3]; // mut m: [i32; 3] ``` @@ -68,7 +68,7 @@ let mut nums = vec![1, 2, 3]; // mut nums: Vec nums.push(4); -println!("The length of nums is now {}", nums.len()); // Prints 4 +println!("The length of nums is now {}", nums.len()); // Prints 4 ``` Vectors have many more useful methods. @@ -82,10 +82,10 @@ arrays: ```{rust} let a = [0, 1, 2, 3, 4]; -let middle = &a[1..4]; // A slice of a: just the elements 1, 2, and 3 +let middle = &a[1..4]; // A slice of a: just the elements 1, 2, and 3 for e in middle.iter() { - println!("{}", e); // Prints 1, 2, 3 + println!("{}", e); // Prints 1, 2, 3 } ``` diff --git a/src/doc/trpl/compound-data-types.md b/src/doc/trpl/compound-data-types.md index 5ad9fcd41f554..901b44661b04c 100644 --- a/src/doc/trpl/compound-data-types.md +++ b/src/doc/trpl/compound-data-types.md @@ -51,7 +51,7 @@ arity and contained types. ```rust let mut x = (1, 2); // x: (i32, i32) -let y = (2, 3); // y: (i32, i32) +let y = (2, 3); // y: (i32, i32) x = y; ``` @@ -156,7 +156,7 @@ These two will not be equal, even if they have the same values: ```{rust} # struct Color(i32, i32, i32); # struct Point(i32, i32, i32); -let black = Color(0, 0, 0); +let black = Color(0, 0, 0); let origin = Point(0, 0, 0); ``` @@ -254,7 +254,7 @@ things from the standard library if you need them. Okay, let's talk about the actual code in the example. `cmp` is a function that compares two things, and returns an `Ordering`. We return either `Ordering::Less`, `Ordering::Greater`, or `Ordering::Equal`, depending on if -the two values are greater, less, or equal. Note that each variant of the +the two values are less, greater, or equal. Note that each variant of the `enum` is namespaced under the `enum` itself: it's `Ordering::Greater` not `Greater`. @@ -297,7 +297,7 @@ enum StringResult { } ``` Where a `StringResult` is either a `StringResult::StringOK`, with the result of -a computation, or an `StringResult::ErrorReason` with a `String` explaining +a computation, or a `StringResult::ErrorReason` with a `String` explaining what caused the computation to fail. These kinds of `enum`s are actually very useful and are even part of the standard library. diff --git a/src/doc/trpl/crates-and-modules.md b/src/doc/trpl/crates-and-modules.md index c12090e2a614c..79bb5c182f49a 100644 --- a/src/doc/trpl/crates-and-modules.md +++ b/src/doc/trpl/crates-and-modules.md @@ -1,4 +1,4 @@ -% The Rust Crates and Modules Guide +% Crates and Modules When a project starts getting large, it's considered a good software engineering practice to split it up into a bunch of smaller pieces, and then @@ -208,9 +208,8 @@ Again, these declarations tell Rust to look for either these sub-modules don't have their own sub-modules, we've chosen to make them `src/english/greetings.rs` and `src/japanese/farewells.rs`. Whew! -Right now, the contents of `src/english/greetings.rs` and -`src/japanese/farewells.rs` are both empty at the moment. Let's add some -functions. +The contents of `src/english/greetings.rs` and `src/japanese/farewells.rs` are +both empty at the moment. Let's add some functions. Put this in `src/english/greetings.rs`: @@ -258,7 +257,7 @@ fn goodbye() -> String { (This is "Sayōnara", if you're curious.) -Now that we have our some functionality in our crate, let's try to use it from +Now that we have some functionality in our crate, let's try to use it from another crate. # Importing External Crates diff --git a/src/doc/trpl/error-handling.md b/src/doc/trpl/error-handling.md index 4b1c92239aed3..d66142edf3fc9 100644 --- a/src/doc/trpl/error-handling.md +++ b/src/doc/trpl/error-handling.md @@ -1,4 +1,4 @@ -% Error Handling in Rust +% Error Handling > The best-laid plans of mice and men > Often go awry @@ -60,12 +60,12 @@ fn probability(_: &Event) -> f64 { fn descriptive_probability(event: Event) -> &'static str { match probability(&event) { - 1.00 => "certain", - 0.00 => "impossible", + 1.00 => "certain", + 0.00 => "impossible", 0.00 ... 0.25 => "very unlikely", 0.25 ... 0.50 => "unlikely", 0.50 ... 0.75 => "likely", - 0.75 ... 1.00 => "very likely", + 0.75 ... 1.00 => "very likely", } } @@ -97,12 +97,12 @@ fn probability(_: &Event) -> f64 { fn descriptive_probability(event: Event) -> &'static str { match probability(&event) { - 1.00 => "certain", - 0.00 => "impossible", + 1.00 => "certain", + 0.00 => "impossible", 0.00 ... 0.25 => "very unlikely", 0.25 ... 0.50 => "unlikely", 0.50 ... 0.75 => "likely", - 0.75 ... 1.00 => "very likely", + 0.75 ... 1.00 => "very likely", _ => unreachable!() } } diff --git a/src/doc/trpl/ffi.md b/src/doc/trpl/ffi.md index 940d2c968be67..640f9cc388ef0 100644 --- a/src/doc/trpl/ffi.md +++ b/src/doc/trpl/ffi.md @@ -1,4 +1,4 @@ -% The Rust Foreign Function Interface Guide +% Foreign Function Interface # Introduction @@ -11,7 +11,7 @@ snappy includes a C interface (documented in The following is a minimal example of calling a foreign function which will compile if snappy is installed: -~~~~no_run +```no_run extern crate libc; use libc::size_t; @@ -24,7 +24,7 @@ fn main() { let x = unsafe { snappy_max_compressed_length(100) }; println!("max compressed length of a 100 byte buffer: {}", x); } -~~~~ +``` The `extern` block is a list of function signatures in a foreign library, in this case with the platform's C ABI. The `#[link(...)]` attribute is used to @@ -44,7 +44,7 @@ keeping the binding correct at runtime. The `extern` block can be extended to cover the entire snappy API: -~~~~no_run +```no_run extern crate libc; use libc::{c_int, size_t}; @@ -66,7 +66,7 @@ extern { compressed_length: size_t) -> c_int; } # fn main() {} -~~~~ +``` # Creating a safe interface @@ -79,7 +79,7 @@ vectors as pointers to memory. Rust's vectors are guaranteed to be a contiguous length is number of elements currently contained, and the capacity is the total size in elements of the allocated memory. The length is less than or equal to the capacity. -~~~~ +``` # extern crate libc; # use libc::{c_int, size_t}; # unsafe fn snappy_validate_compressed_buffer(_: *const u8, _: size_t) -> c_int { 0 } @@ -89,7 +89,7 @@ pub fn validate_compressed_buffer(src: &[u8]) -> bool { snappy_validate_compressed_buffer(src.as_ptr(), src.len() as size_t) == 0 } } -~~~~ +``` The `validate_compressed_buffer` wrapper above makes use of an `unsafe` block, but it makes the guarantee that calling it is safe for all inputs by leaving off `unsafe` from the function @@ -103,7 +103,7 @@ required capacity to hold the compressed output. The vector can then be passed t `snappy_compress` function as an output parameter. An output parameter is also passed to retrieve the true length after compression for setting the length. -~~~~ +``` # extern crate libc; # use libc::{size_t, c_int}; # unsafe fn snappy_compress(a: *const u8, b: size_t, c: *mut u8, @@ -116,20 +116,20 @@ pub fn compress(src: &[u8]) -> Vec { let psrc = src.as_ptr(); let mut dstlen = snappy_max_compressed_length(srclen); - let mut dst = Vec::with_capacity(dstlen as uint); + let mut dst = Vec::with_capacity(dstlen as usize); let pdst = dst.as_mut_ptr(); snappy_compress(psrc, srclen, pdst, &mut dstlen); - dst.set_len(dstlen as uint); + dst.set_len(dstlen as usize); dst } } -~~~~ +``` Decompression is similar, because snappy stores the uncompressed size as part of the compression format and `snappy_uncompressed_length` will retrieve the exact buffer size required. -~~~~ +``` # extern crate libc; # use libc::{size_t, c_int}; # unsafe fn snappy_uncompress(compressed: *const u8, @@ -148,45 +148,22 @@ pub fn uncompress(src: &[u8]) -> Option> { let mut dstlen: size_t = 0; snappy_uncompressed_length(psrc, srclen, &mut dstlen); - let mut dst = Vec::with_capacity(dstlen as uint); + let mut dst = Vec::with_capacity(dstlen as usize); let pdst = dst.as_mut_ptr(); if snappy_uncompress(psrc, srclen, pdst, &mut dstlen) == 0 { - dst.set_len(dstlen as uint); + dst.set_len(dstlen as usize); Some(dst) } else { None // SNAPPY_INVALID_INPUT } } } -~~~~ +``` For reference, the examples used here are also available as an [library on GitHub](https://github.com/thestinger/rust-snappy). -# Stack management - -Rust threads by default run on a *large stack*. This is actually implemented as a -reserving a large segment of the address space and then lazily mapping in pages -as they are needed. When calling an external C function, the code is invoked on -the same stack as the rust stack. This means that there is no extra -stack-switching mechanism in place because it is assumed that the large stack -for the rust thread is plenty for the C function to have. - -A planned future improvement (not yet implemented at the time of this writing) -is to have a guard page at the end of every rust stack. No rust function will -hit this guard page (due to Rust's usage of LLVM's `__morestack`). The intention -for this unmapped page is to prevent infinite recursion in C from overflowing -onto other rust stacks. If the guard page is hit, then the process will be -terminated with a message saying that the guard page was hit. - -For normal external function usage, this all means that there shouldn't be any -need for any extra effort on a user's perspective. The C stack naturally -interleaves with the rust stack, and it's "large enough" for both to -interoperate. If, however, it is determined that a larger stack is necessary, -there are appropriate functions in the thread spawning API to control the size of -the stack of the thread which is spawned. - # Destructors Foreign libraries often hand off ownership of resources to the calling code. @@ -208,7 +185,7 @@ A basic example is: Rust code: -~~~~no_run +```no_run extern fn callback(a: i32) { println!("I'm called from C with value {0}", a); } @@ -225,11 +202,11 @@ fn main() { trigger_callback(); // Triggers the callback } } -~~~~ +``` C code: -~~~~c +```c typedef void (*rust_callback)(int32_t); rust_callback cb; @@ -241,7 +218,7 @@ int32_t register_callback(rust_callback callback) { void trigger_callback() { cb(7); // Will call callback(7) in Rust } -~~~~ +``` In this example Rust's `main()` will call `trigger_callback()` in C, which would, in turn, call back to `callback()` in Rust. @@ -261,7 +238,7 @@ referenced Rust object. Rust code: -~~~~no_run +```no_run #[repr(C)] struct RustObject { a: i32, @@ -292,11 +269,11 @@ fn main() { trigger_callback(); } } -~~~~ +``` C code: -~~~~c +```c typedef void (*rust_callback)(void*, int32_t); void* cb_target; rust_callback cb; @@ -310,7 +287,7 @@ int32_t register_callback(void* callback_target, rust_callback callback) { void trigger_callback() { cb(cb_target, 7); // Will call callback(&rustObject, 7) in Rust } -~~~~ +``` ## Asynchronous callbacks @@ -389,13 +366,13 @@ the `link_args` attribute. This attribute is applied to `extern` blocks and specifies raw flags which need to get passed to the linker when producing an artifact. An example usage would be: -~~~ no_run +``` no_run #![feature(link_args)] #[link_args = "-foo -bar -baz"] extern {} # fn main() {} -~~~ +``` Note that this feature is currently hidden behind the `feature(link_args)` gate because this is not a sanctioned way of performing linking. Right now rustc @@ -416,9 +393,9 @@ the compiler that the unsafety does not leak out of the block. Unsafe functions, on the other hand, advertise it to the world. An unsafe function is written like this: -~~~~ +``` unsafe fn kaboom(ptr: *const int) -> int { *ptr } -~~~~ +``` This function can only be called from an `unsafe` block or another `unsafe` function. @@ -428,7 +405,7 @@ Foreign APIs often export a global variable which could do something like track global state. In order to access these variables, you declare them in `extern` blocks with the `static` keyword: -~~~no_run +```no_run extern crate libc; #[link(name = "readline")] @@ -440,13 +417,13 @@ fn main() { println!("You have readline version {} installed.", rl_readline_version as int); } -~~~ +``` Alternatively, you may need to alter global state provided by a foreign interface. To do this, statics can be declared with `mut` so rust can mutate them. -~~~no_run +```no_run extern crate libc; use std::ffi::CString; @@ -463,7 +440,7 @@ fn main() { // get a line, process it unsafe { rl_prompt = ptr::null(); } } -~~~ +``` # Foreign calling conventions @@ -471,7 +448,7 @@ Most foreign code exposes a C ABI, and Rust uses the platform's C calling conven calling foreign functions. Some foreign functions, most notably the Windows API, use other calling conventions. Rust provides a way to tell the compiler which convention to use: -~~~~ +``` extern crate libc; #[cfg(all(target_os = "win32", target_arch = "x86"))] @@ -481,7 +458,7 @@ extern "stdcall" { fn SetEnvironmentVariableA(n: *const u8, v: *const u8) -> libc::c_int; } # fn main() { } -~~~~ +``` This applies to the entire `extern` block. The list of supported ABI constraints are: @@ -541,3 +518,22 @@ with one of the non-nullable types, it is represented as a single pointer, and the non-data variant is represented as the null pointer. So `Option c_int>` is how one represents a nullable function pointer using the C ABI. + +# Calling Rust code from C + +You may wish to compile Rust code in a way so that it can be called from C. This is +fairly easy, but requires a few things: + +``` +#[no_mangle] +pub extern fn hello_rust() -> *const u8 { + "Hello, world!\0".as_ptr() +} +# fn main() {} +``` + +The `extern` makes this function adhere to the C calling convention, as +discussed above in "[Foreign Calling +Conventions](guide-ffi.html#foreign-calling-conventions)". The `no_mangle` +attribute turns off Rust's name mangling, so that it is easier to link to. + diff --git a/src/doc/trpl/functions.md b/src/doc/trpl/functions.md index eae7fc1989506..d0ecb6067955d 100644 --- a/src/doc/trpl/functions.md +++ b/src/doc/trpl/functions.md @@ -143,7 +143,7 @@ fn foo(x: i32) -> i32 { ``` The previous definition without `return` may look a bit strange if you haven't -worked in an expression-based language before, but it becomes intutive over +worked in an expression-based language before, but it becomes intuitive over time. If this were production code, we wouldn't write it in that way anyway, we'd write this: diff --git a/src/doc/trpl/generics.md b/src/doc/trpl/generics.md index 023143ae64e26..3e4e0a66eae05 100644 --- a/src/doc/trpl/generics.md +++ b/src/doc/trpl/generics.md @@ -5,7 +5,7 @@ multiple types of arguments. For example, remember our `OptionalInt` type? ```{rust} enum OptionalInt { - Value(int), + Value(i32), Missing, } ``` @@ -40,26 +40,26 @@ we substitute that type for the same type used in the generic. Here's an example of using `Option`, with some extra type annotations: ```{rust} -let x: Option = Some(5i); +let x: Option = Some(5); ``` -In the type declaration, we say `Option`. Note how similar this looks to -`Option`. So, in this particular `Option`, `T` has the value of `int`. On -the right-hand side of the binding, we do make a `Some(T)`, where `T` is `5i`. -Since that's an `int`, the two sides match, and Rust is happy. If they didn't +In the type declaration, we say `Option`. Note how similar this looks to +`Option`. So, in this particular `Option`, `T` has the value of `i32`. On +the right-hand side of the binding, we do make a `Some(T)`, where `T` is `5`. +Since that's an `i32`, the two sides match, and Rust is happy. If they didn't match, we'd get an error: ```{rust,ignore} -let x: Option = Some(5i); -// error: mismatched types: expected `core::option::Option` -// but found `core::option::Option` (expected f64 but found int) +let x: Option = Some(5); +// error: mismatched types: expected `core::option::Option`, +// found `core::option::Option<_>` (expected f64 but found integral variable) ``` That doesn't mean we can't make `Option`s that hold an `f64`! They just have to match up: ```{rust} -let x: Option = Some(5i); +let x: Option = Some(5); let y: Option = Some(5.0f64); ``` @@ -79,9 +79,9 @@ This type is generic over _two_ types: `T` and `E`. By the way, the capital lett can be any letter you'd like. We could define `Result` as: ```{rust} -enum Result { - Ok(H), - Err(N), +enum Result { + Ok(A), + Err(Z), } ``` diff --git a/src/doc/trpl/guessing-game.md b/src/doc/trpl/guessing-game.md index 474e7db6942e1..6f67c88f2c0cc 100644 --- a/src/doc/trpl/guessing-game.md +++ b/src/doc/trpl/guessing-game.md @@ -297,9 +297,9 @@ fn main() { println!("You guessed: {}", input); match cmp(input, secret_number) { - Ordering::Less => println!("Too small!"), + Ordering::Less => println!("Too small!"), Ordering::Greater => println!("Too big!"), - Ordering::Equal => println!("You win!"), + Ordering::Equal => println!("You win!"), } } @@ -352,9 +352,9 @@ fn main() { println!("You guessed: {}", input); match cmp(input, secret_number) { - Ordering::Less => println!("Too small!"), + Ordering::Less => println!("Too small!"), Ordering::Greater => println!("Too big!"), - Ordering::Equal => println!("You win!"), + Ordering::Equal => println!("You win!"), } } @@ -422,8 +422,8 @@ In this case, we say `x` is a `u32` explicitly, so Rust is able to properly tell `random()` what to generate. In a similar fashion, both of these work: ```{rust,ignore} -let input_num = "5".parse::(); // input_num: Option -let input_num: Option = "5".parse(); // input_num: Option +let input_num = "5".parse::(); // input_num: Option +let input_num: Option = "5".parse(); // input_num: Option ``` Anyway, with us now converting our input to a number, our code looks like this: @@ -450,9 +450,9 @@ fn main() { println!("You guessed: {}", input_num); match cmp(input_num, secret_number) { - Ordering::Less => println!("Too small!"), + Ordering::Less => println!("Too small!"), Ordering::Greater => println!("Too big!"), - Ordering::Equal => println!("You win!"), + Ordering::Equal => println!("You win!"), } } @@ -499,7 +499,7 @@ fn main() { let num = match input_num { Some(num) => num, - None => { + None => { println!("Please input a number!"); return; } @@ -509,9 +509,9 @@ fn main() { println!("You guessed: {}", num); match cmp(num, secret_number) { - Ordering::Less => println!("Too small!"), + Ordering::Less => println!("Too small!"), Ordering::Greater => println!("Too big!"), - Ordering::Equal => println!("You win!"), + Ordering::Equal => println!("You win!"), } } @@ -566,7 +566,7 @@ fn main() { let num = match input_num { Some(num) => num, - None => { + None => { println!("Please input a number!"); return; } @@ -576,9 +576,9 @@ fn main() { println!("You guessed: {}", num); match cmp(num, secret_number) { - Ordering::Less => println!("Too small!"), + Ordering::Less => println!("Too small!"), Ordering::Greater => println!("Too big!"), - Ordering::Equal => println!("You win!"), + Ordering::Equal => println!("You win!"), } } @@ -642,7 +642,7 @@ fn main() { let num = match input_num { Some(num) => num, - None => { + None => { println!("Please input a number!"); return; } @@ -652,9 +652,9 @@ fn main() { println!("You guessed: {}", num); match cmp(num, secret_number) { - Ordering::Less => println!("Too small!"), + Ordering::Less => println!("Too small!"), Ordering::Greater => println!("Too big!"), - Ordering::Equal => println!("You win!"), + Ordering::Equal => println!("You win!"), } } } @@ -718,7 +718,7 @@ fn main() { let num = match input_num { Some(num) => num, - None => { + None => { println!("Please input a number!"); return; } @@ -728,9 +728,9 @@ fn main() { println!("You guessed: {}", num); match cmp(num, secret_number) { - Ordering::Less => println!("Too small!"), + Ordering::Less => println!("Too small!"), Ordering::Greater => println!("Too big!"), - Ordering::Equal => { + Ordering::Equal => { println!("You win!"); return; }, @@ -774,7 +774,7 @@ fn main() { let num = match input_num { Some(num) => num, - None => { + None => { println!("Please input a number!"); continue; } @@ -784,9 +784,9 @@ fn main() { println!("You guessed: {}", num); match cmp(num, secret_number) { - Ordering::Less => println!("Too small!"), + Ordering::Less => println!("Too small!"), Ordering::Greater => println!("Too big!"), - Ordering::Equal => { + Ordering::Equal => { println!("You win!"); return; }, @@ -851,7 +851,7 @@ fn main() { let num = match input_num { Some(num) => num, - None => { + None => { println!("Please input a number!"); continue; } @@ -861,9 +861,9 @@ fn main() { println!("You guessed: {}", num); match cmp(num, secret_number) { - Ordering::Less => println!("Too small!"), + Ordering::Less => println!("Too small!"), Ordering::Greater => println!("Too big!"), - Ordering::Equal => { + Ordering::Equal => { println!("You win!"); return; }, diff --git a/src/doc/trpl/if.md b/src/doc/trpl/if.md index ea1da167458ab..a350df67b1759 100644 --- a/src/doc/trpl/if.md +++ b/src/doc/trpl/if.md @@ -1,4 +1,4 @@ -% `if` +% If Rust's take on `if` is not particularly complex, but it's much more like the `if` you'll find in a dynamically typed language than in a more traditional diff --git a/src/doc/trpl/iterators.md b/src/doc/trpl/iterators.md index 8312f762c113a..75b3f8b06fc3b 100644 --- a/src/doc/trpl/iterators.md +++ b/src/doc/trpl/iterators.md @@ -5,7 +5,7 @@ Let's talk about loops. Remember Rust's `for` loop? Here's an example: ```{rust} -for x in range(0i, 10i) { +for x in range(0, 10) { println!("{}", x); } ``` @@ -17,7 +17,7 @@ call the `.next()` method on repeatedly, and it gives us a sequence of things. Like this: ```{rust} -let mut range = range(0i, 10i); +let mut range = range(0, 10); loop { match range.next() { @@ -32,8 +32,8 @@ loop { We make a mutable binding to the return value of `range`, which is our iterator. We then `loop`, with an inner `match`. This `match` is used on the result of `range.next()`, which gives us a reference to the next value of the iterator. -`next` returns an `Option`, in this case, which will be `Some(int)` when -we have a value and `None` once we run out. If we get `Some(int)`, we print it +`next` returns an `Option`, in this case, which will be `Some(i32)` when +we have a value and `None` once we run out. If we get `Some(i32)`, we print it out, and if we get `None`, we `break` out of the loop. This code sample is basically the same as our `for` loop version. The `for` @@ -50,9 +50,9 @@ primitive. For example, if you needed to iterate over the contents of a vector, you may be tempted to write this: ```{rust} -let nums = vec![1i, 2i, 3i]; +let nums = vec![1, 2, 3]; -for i in range(0u, nums.len()) { +for i in range(0, nums.len()) { println!("{}", nums[i]); } ``` @@ -62,7 +62,7 @@ vectors returns an iterator which iterates through a reference to each element of the vector in turn. So write this: ```{rust} -let nums = vec![1i, 2i, 3i]; +let nums = vec![1, 2, 3]; for num in nums.iter() { println!("{}", num); @@ -79,12 +79,12 @@ very common with iterators: we can ignore unnecessary bounds checks, but still know that we're safe. There's another detail here that's not 100% clear because of how `println!` -works. `num` is actually of type `&int`. That is, it's a reference to an `int`, -not an `int` itself. `println!` handles the dereferencing for us, so we don't +works. `num` is actually of type `&i32`. That is, it's a reference to an `i32`, +not an `i32` itself. `println!` handles the dereferencing for us, so we don't see it. This code works fine too: ```{rust} -let nums = vec![1i, 2i, 3i]; +let nums = vec![1, 2, 3]; for num in nums.iter() { println!("{}", *num); @@ -118,7 +118,7 @@ The most common consumer is `collect()`. This code doesn't quite compile, but it shows the intention: ```{rust,ignore} -let one_to_one_hundred = range(1i, 101i).collect(); +let one_to_one_hundred = range(1, 101).collect(); ``` As you can see, we call `collect()` on our iterator. `collect()` takes @@ -128,7 +128,7 @@ type of things you want to collect, and so you need to let it know. Here's the version that does compile: ```{rust} -let one_to_one_hundred = range(1i, 101i).collect::>(); +let one_to_one_hundred = range(1, 101).collect::>(); ``` If you remember, the `::<>` syntax allows us to give a type hint, @@ -138,12 +138,12 @@ and so we tell it that we want a vector of integers. is one: ```{rust} -let greater_than_forty_two = range(0i, 100i) +let greater_than_forty_two = range(0, 100) .find(|x| *x > 42); match greater_than_forty_two { Some(_) => println!("We got some numbers!"), - None => println!("No numbers found :("), + None => println!("No numbers found :("), } ``` @@ -155,8 +155,8 @@ element, `find` returns an `Option` rather than the element itself. Another important consumer is `fold`. Here's what it looks like: ```{rust} -let sum = range(1i, 4i) - .fold(0i, |sum, x| sum + x); +let sum = range(1, 4) + .fold(0, |sum, x| sum + x); ``` `fold()` is a consumer that looks like this: @@ -172,24 +172,24 @@ in this iterator: | base | accumulator | element | closure result | |------|-------------|---------|----------------| -| 0i | 0i | 1i | 1i | -| 0i | 1i | 2i | 3i | -| 0i | 3i | 3i | 6i | +| 0 | 0 | 1 | 1 | +| 0 | 1 | 2 | 3 | +| 0 | 3 | 3 | 6 | We called `fold()` with these arguments: ```{rust} -# range(1i, 4i) -.fold(0i, |sum, x| sum + x); +# range(1, 4) +.fold(0, |sum, x| sum + x); ``` -So, `0i` is our base, `sum` is our accumulator, and `x` is our element. On the -first iteration, we set `sum` to `0i`, and `x` is the first element of `nums`, -`1i`. We then add `sum` and `x`, which gives us `0i + 1i = 1i`. On the second +So, `0` is our base, `sum` is our accumulator, and `x` is our element. On the +first iteration, we set `sum` to `0`, and `x` is the first element of `nums`, +`1`. We then add `sum` and `x`, which gives us `0 + 1 = 1`. On the second iteration, that value becomes our accumulator, `sum`, and the element is -the second element of the array, `2i`. `1i + 2i = 3i`, and so that becomes +the second element of the array, `2`. `1 + 2 = 3`, and so that becomes the value of the accumulator for the last iteration. On that iteration, -`x` is the last element, `3i`, and `3i + 3i = 6i`, which is our final +`x` is the last element, `3`, and `3 + 3 = 6`, which is our final result for our sum. `1 + 2 + 3 = 6`, and that's the result we got. Whew. `fold` can be a bit strange the first few times you see it, but once it @@ -210,14 +210,14 @@ This code, for example, does not actually generate the numbers `1-100`, and just creates a value that represents the sequence: ```{rust} -let nums = range(1i, 100i); +let nums = range(1, 100); ``` Since we didn't do anything with the range, it didn't generate the sequence. Let's add the consumer: ```{rust} -let nums = range(1i, 100i).collect::>(); +let nums = range(1, 100).collect::>(); ``` Now, `collect()` will require that `range()` give it some numbers, and so @@ -228,7 +228,7 @@ which you've used before. `iter()` can turn a vector into a simple iterator that gives you each element in turn: ```{rust} -let nums = [1i, 2i, 3i]; +let nums = [1, 2, 3]; for num in nums.iter() { println!("{}", num); @@ -239,12 +239,12 @@ These two basic iterators should serve you well. There are some more advanced iterators, including ones that are infinite. Like `count`: ```{rust} -std::iter::count(1i, 5i); +std::iter::count(1, 5); ``` This iterator counts up from one, adding five each time. It will give you a new integer every time, forever (well, technically, until it reaches the -maximum number representable by an `int`). But since iterators are lazy, +maximum number representable by an `i32`). But since iterators are lazy, that's okay! You probably don't want to use `collect()` on it, though... That's enough about iterators. Iterator adapters are the last concept @@ -256,7 +256,7 @@ we need to talk about with regards to iterators. Let's get to it! a new iterator. The simplest one is called `map`: ```{rust,ignore} -range(1i, 100i).map(|x| x + 1i); +range(1, 100).map(|x| x + 1); ``` `map` is called upon another iterator, and produces a new iterator where each @@ -267,7 +267,7 @@ compile the example, you'll get a warning: ```{notrust,ignore} warning: unused result which must be used: iterator adaptors are lazy and do nothing unless consumed, #[warn(unused_must_use)] on by default - range(1i, 100i).map(|x| x + 1i); + range(1, 100).map(|x| x + 1); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``` @@ -275,7 +275,7 @@ Laziness strikes again! That closure will never execute. This example doesn't print any numbers: ```{rust,ignore} -range(1i, 100i).map(|x| println!("{}", x)); +range(1, 100).map(|x| println!("{}", x)); ``` If you are trying to execute a closure on an iterator for its side effects, @@ -287,7 +287,7 @@ has no side effect on the original iterator. Let's try it out with our infinite iterator from before, `count()`: ```{rust} -for i in std::iter::count(1i, 5i).take(5) { +for i in std::iter::count(1, 5).take(5) { println!("{}", i); } ``` @@ -307,7 +307,7 @@ returns `true` or `false`. The new iterator `filter()` produces only the elements that that closure returns `true` for: ```{rust} -for i in range(1i, 100i).filter(|&x| x % 2 == 0) { +for i in range(1, 100).filter(|&x| x % 2 == 0) { println!("{}", i); } ``` @@ -322,11 +322,11 @@ You can chain all three things together: start with an iterator, adapt it a few times, and then consume the result. Check it out: ```{rust} -range(1i, 1000i) +range(1, 1000) .filter(|&x| x % 2 == 0) .filter(|&x| x % 3 == 0) .take(5) - .collect::>(); + .collect::>(); ``` This will give you a vector containing `6`, `12`, `18`, `24`, and `30`. diff --git a/src/doc/trpl/looping.md b/src/doc/trpl/looping.md index 2985477085e94..4301149d1f8b3 100644 --- a/src/doc/trpl/looping.md +++ b/src/doc/trpl/looping.md @@ -54,7 +54,7 @@ The other kind of looping construct in Rust is the `while` loop. It looks like this: ```{rust} -let mut x = 5u32; // mut x: u32 +let mut x = 5; // mut x: u32 let mut done = false; // mut done: bool while !done { @@ -91,7 +91,7 @@ can do with safety and code generation, so you should always prefer Let's take a look at that `while` loop we had earlier: ```{rust} -let mut x = 5u32; +let mut x = 5; let mut done = false; while !done { @@ -108,7 +108,7 @@ modifying iteration: `break` and `continue`. In this case, we can write the loop in a better way with `break`: ```{rust} -let mut x = 5u32; +let mut x = 5; loop { x += x - 3; @@ -123,7 +123,7 @@ We now loop forever with `loop` and use `break` to break out early. iteration. This will only print the odd numbers: ```{rust} -for x in 0..10 { +for x in 0u32..10 { if x % 2 == 0 { continue; } println!("{}", x); diff --git a/src/doc/trpl/macros.md b/src/doc/trpl/macros.md index 8f4db3eee5ae7..f429e9df19657 100644 --- a/src/doc/trpl/macros.md +++ b/src/doc/trpl/macros.md @@ -1,4 +1,4 @@ -% The Rust Macros Guide +% Macros # Introduction @@ -11,8 +11,8 @@ which both pattern-match on their input and both return early in one case, doing nothing otherwise: ~~~~ -# enum T { SpecialA(uint), SpecialB(uint) } -# fn f() -> uint { +# enum T { SpecialA(u32), SpecialB(u32) } +# fn f() -> u32 { # let input_1 = T::SpecialA(0); # let input_2 = T::SpecialA(0); match input_1 { @@ -24,7 +24,7 @@ match input_2 { T::SpecialB(x) => { return x; } _ => {} } -# return 0u; +# return 0; # } ~~~~ @@ -37,8 +37,8 @@ lightweight custom syntax extensions, themselves defined using the the pattern in the above code: ~~~~ -# enum T { SpecialA(uint), SpecialB(uint) } -# fn f() -> uint { +# enum T { SpecialA(u32), SpecialB(u32) } +# fn f() -> u32 { # let input_1 = T::SpecialA(0); # let input_2 = T::SpecialA(0); macro_rules! early_return { @@ -101,6 +101,7 @@ So `($x:ident -> (($e:expr)))`, though excessively fancy, would designate a macr that could be invoked like: `my_macro!(i->(( 2+2 )))`. To avoid ambiguity, macro invocation syntax must conform to the following rules: + * `expr` must be followed by `=>`, `,` or `;`. * `ty` and `path` must be followed by `=>`, `,`, `:`, `=`, `>` or `as`. * `pat` must be followed by `=>`, `,` or `=`. @@ -165,8 +166,8 @@ separator token (a comma-separated list could be written `$(...),*`), and `+` instead of `*` to mean "at least one". ~~~~ -# enum T { SpecialA(uint),SpecialB(uint),SpecialC(uint),SpecialD(uint)} -# fn f() -> uint { +# enum T { SpecialA(u32), SpecialB(u32), SpecialC(u32), SpecialD(u32) } +# fn f() -> u32 { # let input_1 = T::SpecialA(0); # let input_2 = T::SpecialA(0); macro_rules! early_return { @@ -226,10 +227,10 @@ solves the problem. Now consider code like the following: ~~~~ -# enum T1 { Good1(T2, uint), Bad1} +# enum T1 { Good1(T2, u32), Bad1} # struct T2 { body: T3 } -# enum T3 { Good2(uint), Bad2} -# fn f(x: T1) -> uint { +# enum T3 { Good2(u32), Bad2} +# fn f(x: T1) -> u32 { match x { T1::Good1(g1, val) => { match g1.body { @@ -273,10 +274,10 @@ macro_rules! biased_match { ) } -# enum T1 { Good1(T2, uint), Bad1} +# enum T1 { Good1(T2, u32), Bad1} # struct T2 { body: T3 } -# enum T3 { Good2(uint), Bad2} -# fn f(x: T1) -> uint { +# enum T3 { Good2(u32), Bad2} +# fn f(x: T1) -> u32 { biased_match!((x) -> (T1::Good1(g1, val)) else { return 0 }; binds g1, val ); biased_match!((g1.body) -> (T3::Good2(result) ) @@ -383,10 +384,10 @@ macro_rules! biased_match { } -# enum T1 { Good1(T2, uint), Bad1} +# enum T1 { Good1(T2, u32), Bad1} # struct T2 { body: T3 } -# enum T3 { Good2(uint), Bad2} -# fn f(x: T1) -> uint { +# enum T3 { Good2(u32), Bad2} +# fn f(x: T1) -> u32 { biased_match!( (x) -> (T1::Good1(g1, val)) else { return 0 }; (g1.body) -> (T3::Good2(result) ) else { panic!("Didn't get Good2") }; @@ -528,7 +529,7 @@ A further difficulty occurs when a macro is used in multiple crates. Say that `mylib` defines ```rust -pub fn increment(x: uint) -> uint { +pub fn increment(x: u32) -> u32 { x + 1 } diff --git a/src/doc/trpl/match.md b/src/doc/trpl/match.md index 1833b05591be9..73bc775a1b290 100644 --- a/src/doc/trpl/match.md +++ b/src/doc/trpl/match.md @@ -84,9 +84,9 @@ fn main() { let y = 10; match cmp(x, y) { - Ordering::Less => println!("less"), + Ordering::Less => println!("less"), Ordering::Greater => println!("greater"), - Ordering::Equal => println!("equal"), + Ordering::Equal => println!("equal"), } } ``` @@ -112,12 +112,12 @@ fn main() { match x { OptionalInt::Value(n) => println!("x is {}", n), - OptionalInt::Missing => println!("x is missing!"), + OptionalInt::Missing => println!("x is missing!"), } match y { OptionalInt::Value(n) => println!("y is {}", n), - OptionalInt::Missing => println!("y is missing!"), + OptionalInt::Missing => println!("y is missing!"), } } ``` @@ -146,9 +146,9 @@ fn main() { let y = 10; println!("{}", match cmp(x, y) { - Ordering::Less => "less", + Ordering::Less => "less", Ordering::Greater => "greater", - Ordering::Equal => "equal", + Ordering::Equal => "equal", }); } ``` diff --git a/src/doc/trpl/ownership.md b/src/doc/trpl/ownership.md index 7a397ce535470..8b7e37dd4c2fd 100644 --- a/src/doc/trpl/ownership.md +++ b/src/doc/trpl/ownership.md @@ -1,4 +1,4 @@ -% The Rust Ownership Guide +% Ownership This guide presents Rust's ownership system. This is one of Rust's most unique and compelling features, with which Rust developers should become quite @@ -395,7 +395,7 @@ static FOO: i32 = 5; let x: &'static i32 = &FOO; ``` -This adds an `i32` to the data segment of the binary, and `FOO` is a reference +This adds an `i32` to the data segment of the binary, and `x` is a reference to it. # Shared Ownership @@ -418,7 +418,7 @@ struct Wheel { fn main() { let car = Car { name: "DeLorean".to_string() }; - for _ in range(0u, 4) { + for _ in range(0, 4) { Wheel { size: 360, owner: car }; } } @@ -456,7 +456,7 @@ fn main() { let car_owner = Rc::new(car); - for _ in range(0u, 4) { + for _ in range(0, 4) { Wheel { size: 360, owner: car_owner.clone() }; } } @@ -517,31 +517,31 @@ Here are some examples of functions with elided lifetimes, and the version of what the elided lifetimes are expand to: ```{rust,ignore} -fn print(s: &str); // elided -fn print<'a>(s: &'a str); // expanded +fn print(s: &str); // elided +fn print<'a>(s: &'a str); // expanded -fn debug(lvl: u32, s: &str); // elided -fn debug<'a>(lvl: u32, s: &'a str); // expanded +fn debug(lvl: u32, s: &str); // elided +fn debug<'a>(lvl: u32, s: &'a str); // expanded // In the preceeding example, `lvl` doesn't need a lifetime because it's not a // reference (`&`). Only things relating to references (such as a `struct` // which contains a reference) need lifetimes. -fn substr(s: &str, until: u32) -> &str; // elided -fn substr<'a>(s: &'a str, until: u32) -> &'a str; // expanded +fn substr(s: &str, until: u32) -> &str; // elided +fn substr<'a>(s: &'a str, until: u32) -> &'a str; // expanded -fn get_str() -> &str; // ILLEGAL, no inputs +fn get_str() -> &str; // ILLEGAL, no inputs -fn frob(s: &str, t: &str) -> &str; // ILLEGAL, two inputs +fn frob(s: &str, t: &str) -> &str; // ILLEGAL, two inputs -fn get_mut(&mut self) -> &mut T; // elided -fn get_mut<'a>(&'a mut self) -> &'a mut T; // expanded +fn get_mut(&mut self) -> &mut T; // elided +fn get_mut<'a>(&'a mut self) -> &'a mut T; // expanded -fn args(&mut self, args: &[T]) -> &mut Command // elided +fn args(&mut self, args: &[T]) -> &mut Command // elided fn args<'a, 'b, T:ToCStr>(&'a mut self, args: &'b [T]) -> &'a mut Command // expanded -fn new(buf: &mut [u8]) -> BufWriter; // elided -fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a> // expanded +fn new(buf: &mut [u8]) -> BufWriter; // elided +fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a> // expanded ``` # Related Resources diff --git a/src/doc/trpl/patterns.md b/src/doc/trpl/patterns.md index c54d502b4edde..5c7b406a6fc43 100644 --- a/src/doc/trpl/patterns.md +++ b/src/doc/trpl/patterns.md @@ -8,7 +8,7 @@ A quick refresher: you can match against literals directly, and `_` acts as an *any* case: ```{rust} -let x = 1i; +let x = 1; match x { 1 => println!("one"), @@ -21,7 +21,7 @@ match x { You can match multiple patterns with `|`: ```{rust} -let x = 1i; +let x = 1; match x { 1 | 2 => println!("one or two"), @@ -33,7 +33,7 @@ match x { You can match a range of values with `...`: ```{rust} -let x = 1i; +let x = 1; match x { 1 ... 5 => println!("one through five"), @@ -47,7 +47,7 @@ If you're matching multiple things, via a `|` or a `...`, you can bind the value to a name with `@`: ```{rust} -let x = 1i; +let x = 1; match x { e @ 1 ... 5 => println!("got a range element {}", e), @@ -60,15 +60,15 @@ ignore the value and type in the variant: ```{rust} enum OptionalInt { - Value(int), + Value(i32), Missing, } -let x = OptionalInt::Value(5i); +let x = OptionalInt::Value(5); match x { OptionalInt::Value(..) => println!("Got an int!"), - OptionalInt::Missing => println!("No such luck."), + OptionalInt::Missing => println!("No such luck."), } ``` @@ -76,16 +76,16 @@ You can introduce *match guards* with `if`: ```{rust} enum OptionalInt { - Value(int), + Value(i32), Missing, } -let x = OptionalInt::Value(5i); +let x = OptionalInt::Value(5); match x { OptionalInt::Value(i) if i > 5 => println!("Got an int bigger than five!"), OptionalInt::Value(..) => println!("Got an int!"), - OptionalInt::Missing => println!("No such luck."), + OptionalInt::Missing => println!("No such luck."), } ``` @@ -93,33 +93,33 @@ If you're matching on a pointer, you can use the same syntax as you declared it with. First, `&`: ```{rust} -let x = &5i; +let x = &5; match x { &val => println!("Got a value: {}", val), } ``` -Here, the `val` inside the `match` has type `int`. In other words, the left-hand -side of the pattern destructures the value. If we have `&5i`, then in `&val`, `val` -would be `5i`. +Here, the `val` inside the `match` has type `i32`. In other words, the left-hand +side of the pattern destructures the value. If we have `&5`, then in `&val`, `val` +would be `5`. If you want to get a reference, use the `ref` keyword: ```{rust} -let x = 5i; +let x = 5; match x { ref r => println!("Got a reference to {}", r), } ``` -Here, the `r` inside the `match` has the type `&int`. In other words, the `ref` +Here, the `r` inside the `match` has the type `&i32`. In other words, the `ref` keyword _creates_ a reference, for use in the pattern. If you need a mutable reference, `ref mut` will work in the same way: ```{rust} -let mut x = 5i; +let mut x = 5; match x { ref mut mr => println!("Got a mutable reference to {}", mr), @@ -131,11 +131,11 @@ If you have a struct, you can destructure it inside of a pattern: ```{rust} # #![allow(non_shorthand_field_patterns)] struct Point { - x: int, - y: int, + x: i32, + y: i32, } -let origin = Point { x: 0i, y: 0i }; +let origin = Point { x: 0, y: 0 }; match origin { Point { x: x, y: y } => println!("({},{})", x, y), @@ -147,11 +147,11 @@ If we only care about some of the values, we don't have to give them all names: ```{rust} # #![allow(non_shorthand_field_patterns)] struct Point { - x: int, - y: int, + x: i32, + y: i32, } -let origin = Point { x: 0i, y: 0i }; +let origin = Point { x: 0, y: 0 }; match origin { Point { x: x, .. } => println!("x is {}", x), @@ -163,11 +163,11 @@ You can do this kind of match on any member, not just the first: ```{rust} # #![allow(non_shorthand_field_patterns)] struct Point { - x: int, - y: int, + x: i32, + y: i32, } -let origin = Point { x: 0i, y: 0i }; +let origin = Point { x: 0, y: 0 }; match origin { Point { y: y, .. } => println!("y is {}", y), diff --git a/src/doc/trpl/plugins.md b/src/doc/trpl/plugins.md index 4cd39d407a243..6e8e2c7ffe292 100644 --- a/src/doc/trpl/plugins.md +++ b/src/doc/trpl/plugins.md @@ -1,4 +1,4 @@ -% The Rust Compiler Plugins Guide +% Compiler Plugins
@@ -68,7 +68,7 @@ use rustc::plugin::Registry; fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) -> Box { - static NUMERALS: &'static [(&'static str, uint)] = &[ + static NUMERALS: &'static [(&'static str, u32)] = &[ ("M", 1000), ("CM", 900), ("D", 500), ("CD", 400), ("C", 100), ("XC", 90), ("L", 50), ("XL", 40), ("X", 10), ("IX", 9), ("V", 5), ("IV", 4), @@ -83,7 +83,7 @@ fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) }; let mut text = text.as_slice(); - let mut total = 0u; + let mut total = 0; while !text.is_empty() { match NUMERALS.iter().find(|&&(rn, _)| text.starts_with(rn)) { Some(&(rn, val)) => { @@ -118,7 +118,7 @@ fn main() { } ``` -The advantages over a simple `fn(&str) -> uint` are: +The advantages over a simple `fn(&str) -> u32` are: * The (arbitrarily complex) conversion is done at compile time. * Input validation is also performed at compile time. diff --git a/src/doc/trpl/pointers.md b/src/doc/trpl/pointers.md index 6832d75245e5c..d74c10b814507 100644 --- a/src/doc/trpl/pointers.md +++ b/src/doc/trpl/pointers.md @@ -1,4 +1,4 @@ -% The Rust Pointer Guide +% Pointers Rust's pointers are one of its more unique and compelling features. Pointers are also one of the more confusing topics for newcomers to Rust. They can also @@ -28,9 +28,10 @@ question](http://stackoverflow.com/questions/79923/what-and-where-are-the-stack- as the rest of this guide assumes you know the difference.) Like this: ```{rust} -let x = 5i; -let y = 8i; +let x = 5; +let y = 8; ``` + | location | value | |----------|-------| | 0xd3e030 | 5 | @@ -46,10 +47,11 @@ Let's introduce a pointer. In some languages, there is just one type of *reference*, which is the simplest kind of pointer. ```{rust} -let x = 5i; -let y = 8i; +let x = 5; +let y = 8; let z = &y; ``` + |location | value | |-------- |----------| |0xd3e030 | 5 | @@ -58,12 +60,12 @@ let z = &y; See the difference? Rather than contain a value, the value of a pointer is a location in memory. In this case, the location of `y`. `x` and `y` have the -type `int`, but `z` has the type `&int`. We can print this location using the +type `i32`, but `z` has the type `&i32`. We can print this location using the `{:p}` format string: ```{rust} -let x = 5i; -let y = 8i; +let x = 5; +let y = 8; let z = &y; println!("{:p}", z); @@ -71,12 +73,12 @@ println!("{:p}", z); This would print `0xd3e028`, with our fictional memory addresses. -Because `int` and `&int` are different types, we can't, for example, add them +Because `i32` and `&i32` are different types, we can't, for example, add them together: ```{rust,ignore} -let x = 5i; -let y = 8i; +let x = 5; +let y = 8; let z = &y; println!("{}", x + z); @@ -85,7 +87,7 @@ println!("{}", x + z); This gives us an error: ```text -hello.rs:6:24: 6:25 error: mismatched types: expected `int` but found `&int` (expected int but found &-ptr) +hello.rs:6:24: 6:25 error: mismatched types: expected `i32` but found `&i32` (expected i32 but found &-ptr) hello.rs:6 println!("{}", x + z); ^ ``` @@ -95,8 +97,8 @@ pointer means accessing the value at the location stored in the pointer. This will work: ```{rust} -let x = 5i; -let y = 8i; +let x = 5; +let y = 8; let z = &y; println!("{}", x + *z); @@ -153,7 +155,7 @@ So what do pointers have to do with this? Well, since pointers point to a location in memory... ```text -func foo(&int x) { +func foo(&i32 x) { *x = 5 } @@ -252,7 +254,7 @@ The most basic type of pointer that Rust has is called a *reference*. Rust references look like this: ```{rust} -let x = 5i; +let x = 5; let y = &x; println!("{}", *y); @@ -269,18 +271,18 @@ referent, because `println!` will automatically dereference it for us. Here's a function that takes a reference: ```{rust} -fn succ(x: &int) -> int { *x + 1 } +fn succ(x: &i32) -> i32 { *x + 1 } ``` You can also use `&` as an operator to create a reference, so we can call this function in two different ways: ```{rust} -fn succ(x: &int) -> int { *x + 1 } +fn succ(x: &i32) -> i32 { *x + 1 } fn main() { - let x = 5i; + let x = 5; let y = &x; println!("{}", succ(y)); @@ -294,13 +296,13 @@ Of course, if this were real code, we wouldn't bother with the reference, and just write: ```{rust} -fn succ(x: int) -> int { x + 1 } +fn succ(x: i32) -> i32 { x + 1 } ``` References are immutable by default: ```{rust,ignore} -let x = 5i; +let x = 5; let y = &x; *y = 5; // error: cannot assign to immutable dereference of `&`-pointer `*y` @@ -310,21 +312,21 @@ They can be made mutable with `mut`, but only if its referent is also mutable. This works: ```{rust} -let mut x = 5i; +let mut x = 5; let y = &mut x; ``` This does not: ```{rust,ignore} -let x = 5i; +let x = 5; let y = &mut x; // error: cannot borrow immutable local variable `x` as mutable ``` Immutable pointers are allowed to alias: ```{rust} -let x = 5i; +let x = 5; let y = &x; let z = &x; ``` @@ -332,7 +334,7 @@ let z = &x; Mutable ones, however, are not: ```{rust,ignore} -let mut x = 5i; +let mut x = 5; let y = &mut x; let z = &mut x; // error: cannot borrow `x` as mutable more than once at a time ``` @@ -359,7 +361,7 @@ duration a *lifetime*. Let's try a more complex example: ```{rust} fn main() { - let x = &mut 5i; + let x = &mut 5; if *x < 10 { let y = &x; @@ -380,7 +382,7 @@ mutated, and therefore, lets us pass. This wouldn't work: ```{rust,ignore} fn main() { - let x = &mut 5i; + let x = &mut 5; if *x < 10 { let y = &x; @@ -425,13 +427,13 @@ References just borrow ownership, which is more polite if you don't need the ownership. In other words, prefer: ```{rust} -fn succ(x: &int) -> int { *x + 1 } +fn succ(x: &i32) -> i32 { *x + 1 } ``` to ```{rust} -fn succ(x: Box) -> int { *x + 1 } +fn succ(x: Box) -> i32 { *x + 1 } ``` As a corollary to that rule, references allow you to accept a wide variety of @@ -439,7 +441,7 @@ other pointers, and so are useful so that you don't have to write a number of variants per pointer. In other words, prefer: ```{rust} -fn succ(x: &int) -> int { *x + 1 } +fn succ(x: &i32) -> i32 { *x + 1 } ``` to @@ -447,9 +449,9 @@ to ```{rust} use std::rc::Rc; -fn box_succ(x: Box) -> int { *x + 1 } +fn box_succ(x: Box) -> i32 { *x + 1 } -fn rc_succ(x: Rc) -> int { *x + 1 } +fn rc_succ(x: Rc) -> i32 { *x + 1 } ``` Note that the caller of your function will have to modify their calls slightly: @@ -457,11 +459,11 @@ Note that the caller of your function will have to modify their calls slightly: ```{rust} use std::rc::Rc; -fn succ(x: &int) -> int { *x + 1 } +fn succ(x: &i32) -> i32 { *x + 1 } -let ref_x = &5i; -let box_x = Box::new(5i); -let rc_x = Rc::new(5i); +let ref_x = &5; +let box_x = Box::new(5); +let rc_x = Rc::new(5); succ(ref_x); succ(&*box_x); @@ -477,7 +479,7 @@ those contents. heap allocation in Rust. Creating a box looks like this: ```{rust} -let x = Box::new(5i); +let x = Box::new(5); ``` Boxes are heap allocated and they are deallocated automatically by Rust when @@ -485,7 +487,7 @@ they go out of scope: ```{rust} { - let x = Box::new(5i); + let x = Box::new(5); // stuff happens @@ -505,7 +507,7 @@ boxes, though. As a rough approximation, you can treat this Rust code: ```{rust} { - let x = Box::new(5i); + let x = Box::new(5); // stuff happens } @@ -544,12 +546,12 @@ for more detail on how lifetimes work. Using boxes and references together is very common. For example: ```{rust} -fn add_one(x: &int) -> int { +fn add_one(x: &i32) -> i32 { *x + 1 } fn main() { - let x = Box::new(5i); + let x = Box::new(5); println!("{}", add_one(&*x)); } @@ -561,12 +563,12 @@ function, and since it's only reading the value, allows it. We can borrow `x` multiple times, as long as it's not simultaneous: ```{rust} -fn add_one(x: &int) -> int { +fn add_one(x: &i32) -> i32 { *x + 1 } fn main() { - let x = Box::new(5i); + let x = Box::new(5); println!("{}", add_one(&*x)); println!("{}", add_one(&*x)); @@ -577,12 +579,12 @@ fn main() { Or as long as it's not a mutable borrow. This will error: ```{rust,ignore} -fn add_one(x: &mut int) -> int { +fn add_one(x: &mut i32) -> i32 { *x + 1 } fn main() { - let x = Box::new(5i); + let x = Box::new(5); println!("{}", add_one(&*x)); // error: cannot borrow immutable dereference // of `&`-pointer as mutable @@ -610,7 +612,7 @@ enum List { } fn main() { - let list: List = List::Cons(1, Box::new(List::Cons(2, Box::new(List::Cons(3, Box::new(List::Nil)))))); + let list: List = List::Cons(1, Box::new(List::Cons(2, Box::new(List::Cons(3, Box::new(List::Nil)))))); println!("{:?}", list); } ``` @@ -659,10 +661,10 @@ so as to avoid copying a large data structure. For example: ```{rust} struct BigStruct { - one: int, - two: int, + one: i32, + two: i32, // etc - one_hundred: int, + one_hundred: i32, } fn foo(x: Box) -> Box { @@ -687,10 +689,10 @@ This is an antipattern in Rust. Instead, write this: ```{rust} struct BigStruct { - one: int, - two: int, + one: i32, + two: i32, // etc - one_hundred: int, + one_hundred: i32, } fn foo(x: Box) -> BigStruct { diff --git a/src/doc/trpl/standard-input.md b/src/doc/trpl/standard-input.md index c4d171bb3a900..7145139bba57e 100644 --- a/src/doc/trpl/standard-input.md +++ b/src/doc/trpl/standard-input.md @@ -83,12 +83,12 @@ fn main() { match x { OptionalInt::Value(n) => println!("x is {}", n), - OptionalInt::Missing => println!("x is missing!"), + OptionalInt::Missing => println!("x is missing!"), } match y { OptionalInt::Value(n) => println!("y is {}", n), - OptionalInt::Missing => println!("y is missing!"), + OptionalInt::Missing => println!("y is missing!"), } } ``` @@ -141,11 +141,11 @@ use std::io; fn main() { println!("Type something!"); - // here, we'll show the types at each step + // here, we'll show the types at each step - let input = io::stdin() // std::io::stdio::StdinReader - .read_line() // IoResult - .ok() // Option + let input = io::stdin() // std::io::stdio::StdinReader + .read_line() // IoResult + .ok() // Option .expect("Failed to read line"); // String println!("{}", input); diff --git a/src/doc/trpl/testing.md b/src/doc/trpl/testing.md index aefc7d7aa3d3c..1c93fd351b6e4 100644 --- a/src/doc/trpl/testing.md +++ b/src/doc/trpl/testing.md @@ -1,4 +1,4 @@ -% The Rust Testing Guide +% Testing > Program testing can be a very effective way to show the presence of bugs, but > it is hopelessly inadequate for showing their absence. @@ -512,7 +512,7 @@ use test::Bencher; #[bench] fn bench_xor_1000_ints(b: &mut Bencher) { b.iter(|| { - range(0u, 1000).fold(0, |old, new| old ^ new); + range(0, 1000).fold(0, |old, new| old ^ new); }); } ``` @@ -537,7 +537,7 @@ computation entirely. This could be done for the example above by adjusting the # impl X { fn iter(&self, _: F) where F: FnMut() -> T {} } let b = X; b.iter(|| { // note lack of `;` (could also use an explicit `return`). - range(0u, 1000).fold(0, |old, new| old ^ new) + range(0, 1000).fold(0, |old, new| old ^ new) }); ``` diff --git a/src/doc/trpl/threads.md b/src/doc/trpl/threads.md index 4c6a7f1323fb1..a801a1ab0e921 100644 --- a/src/doc/trpl/threads.md +++ b/src/doc/trpl/threads.md @@ -51,13 +51,15 @@ closure is limited to capturing `Send`-able data from its environment ensures that `spawn` can safely move the entire closure and all its associated state into an entirely different thread for execution. -```{rust,ignore} -# use std::thread::spawn; -# fn generate_thread_number() -> int { 0 } +```rust +use std::thread::Thread; + +fn generate_thread_number() -> i32 { 4 } // a very simple generation + // Generate some state locally let child_thread_number = generate_thread_number(); -spawn(move || { +Thread::spawn(move || { // Capture it in the remote thread. The `move` keyword indicates // that this closure should move `child_thread_number` into its // environment, rather than capturing a reference into the @@ -77,20 +79,22 @@ The simplest way to create a channel is to use the `channel` function to create of a channel, and a *receiver* is the receiving endpoint. Consider the following example of calculating two results concurrently: -```{rust,ignore} -# use std::thread::spawn; +```rust +use std::thread::Thread; +use std::sync::mpsc; -let (tx, rx): (Sender, Receiver) = channel(); +let (tx, rx): (mpsc::Sender, mpsc::Receiver) = mpsc::channel(); -spawn(move || { +Thread::spawn(move || { let result = some_expensive_computation(); tx.send(result); }); some_other_expensive_computation(); let result = rx.recv(); -# fn some_expensive_computation() -> int { 42 } -# fn some_other_expensive_computation() {} + +fn some_expensive_computation() -> u32 { 42 } // very expensive ;) +fn some_other_expensive_computation() {} // even more so ``` Let's examine this example in detail. First, the `let` statement creates a @@ -98,19 +102,21 @@ stream for sending and receiving integers (the left-hand side of the `let`, `(tx, rx)`, is an example of a destructuring let: the pattern separates a tuple into its component parts). -```{rust,ignore} -let (tx, rx): (Sender, Receiver) = channel(); +```rust +# use std::sync::mpsc; +let (tx, rx): (mpsc::Sender, mpsc::Receiver) = mpsc::channel(); ``` The child thread will use the sender to send data to the parent thread, which will wait to receive the data on the receiver. The next statement spawns the child thread. -```{rust,ignore} -# use std::thread::spawn; -# fn some_expensive_computation() -> int { 42 } -# let (tx, rx) = channel(); -spawn(move || { +```rust +# use std::thread::Thread; +# use std::sync::mpsc; +# fn some_expensive_computation() -> u32 { 42 } +# let (tx, rx) = mpsc::channel(); +Thread::spawn(move || { let result = some_expensive_computation(); tx.send(result); }); @@ -125,9 +131,10 @@ computation, then sends the result over the captured channel. Finally, the parent continues with some other expensive computation, then waits for the child's result to arrive on the receiver: -```{rust,ignore} +```rust +# use std::sync::mpsc; # fn some_other_expensive_computation() {} -# let (tx, rx) = channel::(); +# let (tx, rx) = mpsc::channel::(); # tx.send(0); some_other_expensive_computation(); let result = rx.recv(); @@ -140,8 +147,9 @@ single `Receiver` value. What if our example needed to compute multiple results across a number of threads? The following program is ill-typed: ```{rust,ignore} -# fn some_expensive_computation() -> int { 42 } -let (tx, rx) = channel(); +# use std::sync::mpsc; +# fn some_expensive_computation() -> u32 { 42 } +let (tx, rx) = mpsc::channel(); spawn(move || { tx.send(some_expensive_computation()); @@ -156,19 +164,22 @@ spawn(move || { Instead we can clone the `tx`, which allows for multiple senders. -```{rust,ignore} -let (tx, rx) = channel(); +```rust +use std::thread::Thread; +use std::sync::mpsc; + +let (tx, rx) = mpsc::channel(); -for init_val in range(0u, 3) { +for init_val in 0 .. 3 { // Create a new channel handle to distribute to the child thread let child_tx = tx.clone(); - spawn(move || { + Thread::spawn(move || { child_tx.send(some_expensive_computation(init_val)); }); } -let result = rx.recv() + rx.recv() + rx.recv(); -# fn some_expensive_computation(_i: uint) -> int { 42 } +let result = rx.recv().unwrap() + rx.recv().unwrap() + rx.recv().unwrap(); +# fn some_expensive_computation(_i: i32) -> i32 { 42 } ``` Cloning a `Sender` produces a new handle to the same channel, allowing multiple @@ -181,21 +192,22 @@ Note that the above cloning example is somewhat contrived since you could also simply use three `Sender` pairs, but it serves to illustrate the point. For reference, written with multiple streams, it might look like the example below. -```{rust,ignore} -# use std::thread::spawn; +```rust +use std::thread::Thread; +use std::sync::mpsc; // Create a vector of ports, one for each child thread -let rxs = Vec::from_fn(3, |init_val| { - let (tx, rx) = channel(); - spawn(move || { +let rxs = (0 .. 3).map(|&:init_val| { + let (tx, rx) = mpsc::channel(); + Thread::spawn(move || { tx.send(some_expensive_computation(init_val)); }); rx -}); +}).collect::>(); // Wait on each port, accumulating the results -let result = rxs.iter().fold(0, |accum, rx| accum + rx.recv() ); -# fn some_expensive_computation(_i: uint) -> int { 42 } +let result = rxs.iter().fold(0, |&:accum, rx| accum + rx.recv().unwrap() ); +# fn some_expensive_computation(_i: i32) -> i32 { 42 } ``` ## Backgrounding computations: Futures @@ -212,7 +224,7 @@ use std::sync::Future; # fn main() { # fn make_a_sandwich() {}; fn fib(n: u64) -> u64 { - // lengthy computation returning an uint + // lengthy computation returning an 64 12586269025 } @@ -237,7 +249,7 @@ computations. The workload will be distributed on the available cores. # #![allow(deprecated)] # use std::num::Float; # use std::sync::Future; -fn partial_sum(start: uint) -> f64 { +fn partial_sum(start: u64) -> f64 { let mut local_sum = 0f64; for num in range(start*100000, (start+1)*100000) { local_sum += (num as f64 + 1.0).powf(-2.0); @@ -277,7 +289,7 @@ use std::num::Float; use std::rand; use std::sync::Arc; -fn pnorm(nums: &[f64], p: uint) -> f64 { +fn pnorm(nums: &[f64], p: u64) -> f64 { nums.iter().fold(0.0, |a, b| a + b.powf(p as f64)).powf(1.0 / (p as f64)) } @@ -285,7 +297,7 @@ fn main() { let numbers = Vec::from_fn(1000000, |_| rand::random::()); let numbers_arc = Arc::new(numbers); - for num in range(1u, 10) { + for num in range(1, 10) { let thread_numbers = numbers_arc.clone(); spawn(move || { @@ -316,7 +328,7 @@ if it were local. ```{rust,ignore} # use std::rand; # use std::sync::Arc; -# fn pnorm(nums: &[f64], p: uint) -> f64 { 4.0 } +# fn pnorm(nums: &[f64], p: u64) -> f64 { 4.0 } # fn main() { # let numbers=Vec::from_fn(1000000, |_| rand::random::()); # let numbers_arc = Arc::new(numbers); @@ -345,16 +357,16 @@ each other if they panic. The simplest way of handling a panic is with the `try` function, which is similar to `spawn`, but immediately blocks and waits for the child thread to finish. `try` returns a value of type `Result>`. `Result` is an `enum` type with two variants: -`Ok` and `Err`. In this case, because the type arguments to `Result` are `int` +`Ok` and `Err`. In this case, because the type arguments to `Result` are `i32` and `()`, callers can pattern-match on a result to check whether it's an `Ok` -result with an `int` field (representing a successful result) or an `Err` result +result with an `i32` field (representing a successful result) or an `Err` result (representing termination with an error). ```{rust,ignore} # use std::thread::Thread; # fn some_condition() -> bool { false } -# fn calculate_result() -> int { 0 } -let result: Result> = Thread::spawn(move || { +# fn calculate_result() -> i32 { 0 } +let result: Result> = Thread::spawn(move || { if some_condition() { calculate_result() } else { diff --git a/src/doc/trpl/traits.md b/src/doc/trpl/traits.md index 96322296407f3..d12480d7dd9fa 100644 --- a/src/doc/trpl/traits.md +++ b/src/doc/trpl/traits.md @@ -145,7 +145,7 @@ As you can see, `print_area` is now generic, but also ensures that we have passed in the correct types. If we pass in an incorrect type: ```{rust,ignore} -print_area(5i); +print_area(5); ``` We get a compile-time error: @@ -156,14 +156,14 @@ error: failed to find an implementation of trait main::HasArea for int So far, we've only added trait implementations to structs, but you can implement a trait for any type. So technically, we _could_ implement -`HasArea` for `int`: +`HasArea` for `i32`: ```{rust} trait HasArea { fn area(&self) -> f64; } -impl HasArea for int { +impl HasArea for i32 { fn area(&self) -> f64 { println!("this is silly"); @@ -171,7 +171,7 @@ impl HasArea for int { } } -5i.area(); +5.area(); ``` It is considered poor style to implement methods on such primitive types, even @@ -264,8 +264,8 @@ it won't affect you, unless you `use` that trait. There's one more restriction on implementing traits. Either the trait or the type you're writing the `impl` for must be inside your crate. So, we could -implement the `HasArea` type for `int`, because `HasArea` is in our crate. But -if we tried to implement `Float`, a trait provided by Rust, for `int`, we could +implement the `HasArea` type for `i32`, because `HasArea` is in our crate. But +if we tried to implement `Float`, a trait provided by Rust, for `i32`, we could not, because both the trait and the type aren't in our crate. One last thing about traits: generic functions with a trait bound use diff --git a/src/doc/trpl/unsafe.md b/src/doc/trpl/unsafe.md index 075340660df15..3acd1eefe89d0 100644 --- a/src/doc/trpl/unsafe.md +++ b/src/doc/trpl/unsafe.md @@ -1,4 +1,4 @@ -% Writing Unsafe and Low-Level Code in Rust +% Unsafe and Low-Level Code # Introduction @@ -95,7 +95,7 @@ offered by the Rust language and libraries. For example, they use-after-free; - are considered sendable (if their contents is considered sendable), so the compiler offers no assistance with ensuring their use is - thread-safe; for example, one can concurrently access a `*mut int` + thread-safe; for example, one can concurrently access a `*mut i32` from two threads without synchronization. - lack any form of lifetimes, unlike `&`, and so the compiler cannot reason about dangling pointers; and @@ -254,7 +254,7 @@ impl Drop for Unique { // Copy the object out from the pointer onto the stack, // where it is covered by normal Rust destructor semantics // and cleans itself up, if necessary - ptr::read(self.ptr as *const T); + ptr::read(self.ptr); // clean-up our allocation free(self.ptr as *mut c_void) @@ -265,12 +265,12 @@ impl Drop for Unique { // A comparison between the built-in `Box` and this reimplementation fn main() { { - let mut x = Box::new(5i); + let mut x = Box::new(5); *x = 10; } // `x` is freed here { - let mut y = Unique::new(5i); + let mut y = Unique::new(5); *y.borrow_mut() = 10; } // `y` is freed here } @@ -367,7 +367,7 @@ expressions must be mutable lvalues: ``` # #![feature(asm)] # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -fn add(a: int, b: int) -> int { +fn add(a: i32, b: i32) -> i32 { let mut c = 0; unsafe { asm!("add $2, $0" @@ -378,7 +378,7 @@ fn add(a: int, b: int) -> int { c } # #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] -# fn add(a: int, b: int) -> int { a + b } +# fn add(a: i32, b: i32) -> i32 { a + b } fn main() { assert_eq!(add(3, 14159), 14162) @@ -447,14 +447,14 @@ in the same format as C: ``` #![no_std] -#![feature(lang_items)] +#![feature(lang_items, start)] // Pull in the system libc library for what crt0.o likely requires extern crate libc; // Entry point for this program #[start] -fn start(_argc: int, _argv: *const *const u8) -> int { +fn start(_argc: isize, _argv: *const *const u8) -> isize { 0 } @@ -475,12 +475,12 @@ compiler's name mangling too: ```ignore #![no_std] #![no_main] -#![feature(lang_items)] +#![feature(lang_items, start)] extern crate libc; #[no_mangle] // ensure that this symbol is called `main` in the output -pub extern fn main(argc: int, argv: *const *const u8) -> int { +pub extern fn main(argc: i32, argv: *const *const u8) -> i32 { 0 } @@ -529,7 +529,7 @@ vectors provided from C, using idiomatic Rust practices. ``` #![no_std] -#![feature(lang_items)] +#![feature(lang_items, start)] # extern crate libc; extern crate core; @@ -552,8 +552,8 @@ pub extern fn dot_product(a: *const u32, a_len: u32, // cannot tell the pointers are valid. let (a_slice, b_slice): (&[u32], &[u32]) = unsafe { mem::transmute(( - Slice { data: a, len: a_len as uint }, - Slice { data: b, len: b_len as uint }, + Slice { data: a, len: a_len as usize }, + Slice { data: b, len: b_len as usize }, )) }; @@ -567,14 +567,14 @@ pub extern fn dot_product(a: *const u32, a_len: u32, #[lang = "panic_fmt"] extern fn panic_fmt(args: &core::fmt::Arguments, - file: &str, - line: uint) -> ! { + file: &str, + line: u32) -> ! { loop {} } #[lang = "stack_exhausted"] extern fn stack_exhausted() {} #[lang = "eh_personality"] extern fn eh_personality() {} -# #[start] fn start(argc: int, argv: *const *const u8) -> int { 0 } +# #[start] fn start(argc: isize, argv: *const *const u8) -> isize { 0 } # fn main() {} ``` @@ -628,7 +628,7 @@ via a declaration like extern "rust-intrinsic" { fn transmute(x: T) -> U; - fn offset(dst: *const T, offset: int) -> *const T; + fn offset(dst: *const T, offset: isize) -> *const T; } ``` @@ -653,7 +653,7 @@ sugar for dynamic allocations via `malloc` and `free`: ``` #![no_std] -#![feature(lang_items, box_syntax)] +#![feature(lang_items, box_syntax, start)] extern crate libc; @@ -665,24 +665,24 @@ extern { pub struct Box(*mut T); #[lang="exchange_malloc"] -unsafe fn allocate(size: uint, _align: uint) -> *mut u8 { +unsafe fn allocate(size: usize, _align: usize) -> *mut u8 { let p = libc::malloc(size as libc::size_t) as *mut u8; // malloc failed - if p as uint == 0 { + if p as usize == 0 { abort(); } p } #[lang="exchange_free"] -unsafe fn deallocate(ptr: *mut u8, _size: uint, _align: uint) { +unsafe fn deallocate(ptr: *mut u8, _size: usize, _align: usize) { libc::free(ptr as *mut libc::c_void) } #[start] -fn main(argc: int, argv: *const *const u8) -> int { - let x = box 1i; +fn main(argc: isize, argv: *const *const u8) -> isize { + let x = box 1; 0 } @@ -703,11 +703,11 @@ Other features provided by lang items include: `deref`, and `add` respectively. - stack unwinding and general failure; the `eh_personality`, `fail` and `fail_bounds_checks` lang items. -- the traits in `std::markers` used to indicate types of +- the traits in `std::marker` used to indicate types of various kinds; lang items `send`, `sync` and `copy`. - the marker types and variance indicators found in - `std::markers`; lang items `covariant_type`, - `contravariant_lifetime`, `no_sync_bound`, etc. + `std::marker`; lang items `covariant_type`, + `contravariant_lifetime`, etc. Lang items are loaded lazily by the compiler; e.g. if one never uses `Box` then there is no need to define functions for `exchange_malloc` diff --git a/src/doc/trpl/variable-bindings.md b/src/doc/trpl/variable-bindings.md index e57fc7a120653..41c0e9de9b505 100644 --- a/src/doc/trpl/variable-bindings.md +++ b/src/doc/trpl/variable-bindings.md @@ -1,4 +1,4 @@ -% Variable bindings +% Variable Bindings The first thing we'll learn about are *variable bindings*. They look like this: diff --git a/src/driver/driver.rs b/src/driver/driver.rs index 5c29cb4ec7276..5f086280a65a5 100644 --- a/src/driver/driver.rs +++ b/src/driver/driver.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unstable)] + #[cfg(rustdoc)] extern crate "rustdoc" as this; diff --git a/src/etc/check-links.pl b/src/etc/check-links.pl deleted file mode 100755 index 3818c0f840139..0000000000000 --- a/src/etc/check-links.pl +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/perl -w -# 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. - -my $file = $ARGV[0]; - -my @lines = <>; - -my $anchors = {}; - -my $i = 0; -for $line (@lines) { - $i++; - if ($line =~ m/id="([^"]+)"/) { - $anchors->{$1} = $i; - } -} - -$i = 0; -for $line (@lines) { - $i++; - while ($line =~ m/href="#([^"]+)"/g) { - if (! exists($anchors->{$1})) { - print "$file:$i: $1 referenced\n"; - } - } -} diff --git a/src/etc/emacs/rust-mode.el b/src/etc/emacs/rust-mode.el index f25a59015fcdb..dae685f3a540a 100644 --- a/src/etc/emacs/rust-mode.el +++ b/src/etc/emacs/rust-mode.el @@ -54,6 +54,11 @@ :type 'integer :group 'rust-mode) +(defcustom rust-indent-method-chain nil + "Indent Rust method chains, aligned by the '.' operators" + :type 'boolean + :group 'rust-mode) + (defun rust-paren-level () (nth 0 (syntax-ppss))) (defun rust-in-str-or-cmnt () (nth 8 (syntax-ppss))) (defun rust-rewind-past-str-cmnt () (goto-char (nth 8 (syntax-ppss)))) @@ -73,10 +78,19 @@ ;; open bracket ends the line (when (not (looking-at "[[:blank:]]*\\(?://.*\\)?$")) (when (looking-at "[[:space:]]") - (forward-word 1) - (backward-word 1)) + (forward-word 1) + (backward-word 1)) (current-column)))) +(defun rust-align-to-method-chain () + (save-excursion + (previous-line) + (end-of-line) + (backward-word 1) + (backward-char) + (when (looking-at "\\..+\(.*\)\n") + (- (current-column) rust-indent-offset)))) + (defun rust-rewind-to-beginning-of-current-level-expr () (let ((current-level (rust-paren-level))) (back-to-indentation) @@ -99,10 +113,13 @@ ;; the inside of it correctly relative to the outside. (if (= 0 level) 0 + (or + (when rust-indent-method-chain + (rust-align-to-method-chain)) (save-excursion (backward-up-list) (rust-rewind-to-beginning-of-current-level-expr) - (+ (current-column) rust-indent-offset))))) + (+ (current-column) rust-indent-offset)))))) (cond ;; A function return type is indented to the corresponding function arguments ((looking-at "->") @@ -114,6 +131,16 @@ ;; A closing brace is 1 level unindended ((looking-at "}") (- baseline rust-indent-offset)) + ;;Line up method chains by their .'s + ((when (and rust-indent-method-chain + (looking-at "\..+\(.*\);?\n")) + (or + (let ((method-indent (rust-align-to-method-chain))) + (when method-indent + (+ method-indent rust-indent-offset))) + (+ baseline rust-indent-offset)))) + + ;; Doc comments in /** style with leading * indent to line up the *s ((and (nth 4 (syntax-ppss)) (looking-at "*")) (+ 1 baseline)) diff --git a/src/etc/errorck.py b/src/etc/errorck.py new file mode 100644 index 0000000000000..17659309d3b0d --- /dev/null +++ b/src/etc/errorck.py @@ -0,0 +1,70 @@ +# Copyright 2015 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. + +# Digs error codes out of files named 'diagnostics.rs' across +# the tree, and ensures thare are no duplicates. + +import sys, os, re + +src_dir = sys.argv[1] + +errcode_map = { } + +for (dirpath, dirnames, filenames) in os.walk(src_dir): + + if "src/test" in dirpath or "src/llvm" in dirpath: + # Short circuit for fast + continue + + for filename in filenames: + if filename != "diagnostics.rs": + continue + + path = os.path.join(dirpath, filename) + line_num = 1 + with open(path, 'r') as f: + for line in f: + + p = re.compile("(E\d\d\d\d)") + m = p.search(line) + if not m is None: + errcode = m.group(1) + + new_record = [(errcode, path, line_num, line)] + existing = errcode_map.get(errcode) + if existing is not None: + # This is a dupe + errcode_map[errcode] = existing + new_record + else: + errcode_map[errcode] = new_record + + line_num += 1 + +errors = False +all_errors = [] +for errcode in errcode_map: + entries = errcode_map[errcode] + all_errors += [entries[0][0]] + if len(entries) > 1: + print "error: duplicate error code " + errcode + for entry in entries: + print entry[1] + ": " + str(entry[2]) + print entry[3] + errors = True + +print str(len(errcode_map)) + " error codes" + +all_errors.sort() +all_errors.reverse() + +print "highest error code: " + all_errors[0] + +if errors: + sys.exit(1) diff --git a/src/etc/generate-deriving-span-tests.py b/src/etc/generate-deriving-span-tests.py index 1e5d5ccf339c3..eeb1b89472b3d 100755 --- a/src/etc/generate-deriving-span-tests.py +++ b/src/etc/generate-deriving-span-tests.py @@ -12,8 +12,8 @@ """ This script creates a pile of compile-fail tests check that all the -derivings have spans that point to the fields, rather than the -#[deriving(...)] line. +derives have spans that point to the fields, rather than the +#[derive(...)] line. sample usage: src/etc/generate-deriving-span-tests.py """ @@ -46,7 +46,7 @@ """ ENUM_STRING = """ -#[deriving({traits})] +#[derive({traits})] enum Enum {{ A( Error {errors} @@ -54,7 +54,7 @@ }} """ ENUM_STRUCT_VARIANT_STRING = """ -#[deriving({traits})] +#[derive({traits})] enum Enum {{ A {{ x: Error {errors} @@ -62,13 +62,13 @@ }} """ STRUCT_STRING = """ -#[deriving({traits})] +#[derive({traits})] struct Struct {{ x: Error {errors} }} """ STRUCT_TUPLE_STRING = """ -#[deriving({traits})] +#[derive({traits})] struct Struct( Error {errors} ); @@ -80,14 +80,14 @@ def create_test_case(type, trait, super_traits, number_of_errors): string = [ENUM_STRING, ENUM_STRUCT_VARIANT_STRING, STRUCT_STRING, STRUCT_TUPLE_STRING][type] all_traits = ','.join([trait] + super_traits) super_traits = ','.join(super_traits) - error_deriving = '#[deriving(%s)]' % super_traits if super_traits else '' + error_deriving = '#[derive(%s)]' % super_traits if super_traits else '' errors = '\n'.join('//~%s ERROR' % ('^' * n) for n in range(error_count)) code = string.format(traits = all_traits, errors = errors) return TEMPLATE.format(year = YEAR, error_deriving=error_deriving, code = code) def write_file(name, string): - test_file = os.path.join(TEST_DIR, 'deriving-span-%s.rs' % name) + test_file = os.path.join(TEST_DIR, 'derives-span-%s.rs' % name) # set write permission if file exists, so it can be changed if os.path.exists(test_file): diff --git a/src/etc/htmldocck.py b/src/etc/htmldocck.py new file mode 100644 index 0000000000000..ad78e13ca259b --- /dev/null +++ b/src/etc/htmldocck.py @@ -0,0 +1,351 @@ +# Copyright 2015 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. + +r""" +htmldocck.py is a custom checker script for Rustdoc HTML outputs. + +# How and why? + +The principle is simple: This script receives a path to generated HTML +documentation and a "template" script, which has a series of check +commands like `@has` or `@matches`. Each command can be used to check if +some pattern is present or not present in the particular file or in +the particular node of HTML tree. In many cases, the template script +happens to be a source code given to rustdoc. + +While it indeed is possible to test in smaller portions, it has been +hard to construct tests in this fashion and major rendering errors were +discovered much later. This script is designed for making the black-box +and regression testing of Rustdoc easy. This does not preclude the needs +for unit testing, but can be used to complement related tests by quickly +showing the expected renderings. + +In order to avoid one-off dependencies for this task, this script uses +a reasonably working HTML parser and the existing XPath implementation +from Python 2's standard library. Hopefully we won't render +non-well-formed HTML. + +# Commands + +Commands start with an `@` followed by a command name (letters and +hyphens), and zero or more arguments separated by one or more whitespace +and optionally delimited with single or double quotes. The `@` mark +cannot be preceded by a non-whitespace character. Other lines (including +every text up to the first `@`) are ignored, but it is recommended to +avoid the use of `@` in the template file. + +There are a number of supported commands: + +* `@has PATH` checks for the existence of given file. + + `PATH` is relative to the output directory. It can be given as `-` + which repeats the most recently used `PATH`. + +* `@has PATH PATTERN` and `@matches PATH PATTERN` checks for + the occurrence of given `PATTERN` in the given file. Only one + occurrence of given pattern is enough. + + For `@has`, `PATTERN` is a whitespace-normalized (every consecutive + whitespace being replaced by one single space character) string. + The entire file is also whitespace-normalized including newlines. + + For `@matches`, `PATTERN` is a Python-supported regular expression. + The file remains intact but the regexp is matched with no `MULTILINE` + and `IGNORECASE` option. You can still use a prefix `(?m)` or `(?i)` + to override them, and `\A` and `\Z` for definitely matching + the beginning and end of the file. + + (The same distinction goes to other variants of these commands.) + +* `@has PATH XPATH PATTERN` and `@matches PATH XPATH PATTERN` checks for + the presence of given `XPATH` in the given HTML file, and also + the occurrence of given `PATTERN` in the matching node or attribute. + Only one occurrence of given pattern in the match is enough. + + `PATH` should be a valid and well-formed HTML file. It does *not* + accept arbitrary HTML5; it should have matching open and close tags + and correct entity references at least. + + `XPATH` is an XPath expression to match. This is fairly limited: + `tag`, `*`, `.`, `//`, `..`, `[@attr]`, `[@attr='value']`, `[tag]`, + `[POS]` (element located in given `POS`), `[last()-POS]`, `text()` + and `@attr` (both as the last segment) are supported. Some examples: + + - `//pre` or `.//pre` matches any element with a name `pre`. + - `//a[@href]` matches any element with an `href` attribute. + - `//*[@class="impl"]//code` matches any element with a name `code`, + which is an ancestor of some element which `class` attr is `impl`. + - `//h1[@class="fqn"]/span[1]/a[last()]/@class` matches a value of + `class` attribute in the last `a` element (can be followed by more + elements that are not `a`) inside the first `span` in the `h1` with + a class of `fqn`. Note that there cannot be no additional elements + between them due to the use of `/` instead of `//`. + + Do not try to use non-absolute paths, it won't work due to the flawed + ElementTree implementation. The script rejects them. + + For the text matches (i.e. paths not ending with `@attr`), any + subelements are flattened into one string; this is handy for ignoring + highlights for example. If you want to simply check the presence of + given node or attribute, use an empty string (`""`) as a `PATTERN`. + +All conditions can be negated with `!`. `@!has foo/type.NoSuch.html` +checks if the given file does not exist, for example. + +""" + +import sys +import os.path +import re +import shlex +from collections import namedtuple +from HTMLParser import HTMLParser +from xml.etree import cElementTree as ET + +# ⇤/⇥ are not in HTML 4 but are in HTML 5 +from htmlentitydefs import entitydefs +entitydefs['larrb'] = u'\u21e4' +entitydefs['rarrb'] = u'\u21e5' + +# "void elements" (no closing tag) from the HTML Standard section 12.1.2 +VOID_ELEMENTS = set(['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen', + 'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr']) + +# simplified HTML parser. +# this is possible because we are dealing with very regular HTML from rustdoc; +# we only have to deal with i) void elements and ii) empty attributes. +class CustomHTMLParser(HTMLParser): + def __init__(self, target=None): + HTMLParser.__init__(self) + self.__builder = target or ET.TreeBuilder() + def handle_starttag(self, tag, attrs): + attrs = dict((k, v or '') for k, v in attrs) + self.__builder.start(tag, attrs) + if tag in VOID_ELEMENTS: self.__builder.end(tag) + def handle_endtag(self, tag): + self.__builder.end(tag) + def handle_startendtag(self, tag, attrs): + attrs = dict((k, v or '') for k, v in attrs) + self.__builder.start(tag, attrs) + self.__builder.end(tag) + def handle_data(self, data): + self.__builder.data(data) + def handle_entityref(self, name): + self.__builder.data(entitydefs[name]) + def handle_charref(self, name): + code = int(name[1:], 16) if name.startswith(('x', 'X')) else int(name, 10) + self.__builder.data(unichr(code).encode('utf-8')) + def close(self): + HTMLParser.close(self) + return self.__builder.close() + +Command = namedtuple('Command', 'negated cmd args lineno') + +# returns a generator out of the file object, which +# - removes `\\` then `\n` then a shared prefix with the previous line then optional whitespace; +# - keeps a line number (starting from 0) of the first line being concatenated. +def concat_multi_lines(f): + lastline = None # set to the last line when the last line has a backslash + firstlineno = None + catenated = '' + for lineno, line in enumerate(f): + line = line.rstrip('\r\n') + + # strip the common prefix from the current line if needed + if lastline is not None: + maxprefix = 0 + for i in xrange(min(len(line), len(lastline))): + if line[i] != lastline[i]: break + maxprefix += 1 + line = line[maxprefix:].lstrip() + + firstlineno = firstlineno or lineno + if line.endswith('\\'): + lastline = line[:-1] + catenated += line[:-1] + else: + yield firstlineno, catenated + line + lastline = None + firstlineno = None + catenated = '' + + if lastline is not None: + raise RuntimeError('Trailing backslash in the end of file') + +LINE_PATTERN = re.compile(r''' + (?<=(?!?) + (?P[A-Za-z]+(?:-[A-Za-z]+)*) + (?P.*)$ +''', re.X) +def get_commands(template): + with open(template, 'rUb') as f: + for lineno, line in concat_multi_lines(f): + m = LINE_PATTERN.search(line) + if not m: continue + + negated = (m.group('negated') == '!') + cmd = m.group('cmd') + args = m.group('args') + if args and not args[:1].isspace(): + raise RuntimeError('Invalid template syntax at line {}'.format(lineno+1)) + args = shlex.split(args) + yield Command(negated=negated, cmd=cmd, args=args, lineno=lineno+1) + +def _flatten(node, acc): + if node.text: acc.append(node.text) + for e in node: + _flatten(e, acc) + if e.tail: acc.append(e.tail) + +def flatten(node): + acc = [] + _flatten(node, acc) + return ''.join(acc) + +def normalize_xpath(path): + if path.startswith('//'): + return '.' + path # avoid warnings + elif path.startswith('.//'): + return path + else: + raise RuntimeError('Non-absolute XPath is not supported due to \ + the implementation issue.') + +class CachedFiles(object): + def __init__(self, root): + self.root = root + self.files = {} + self.trees = {} + self.last_path = None + + def resolve_path(self, path): + if path != '-': + path = os.path.normpath(path) + self.last_path = path + return path + elif self.last_path is None: + raise RuntimeError('Tried to use the previous path in the first command') + else: + return self.last_path + + def get_file(self, path): + path = self.resolve_path(path) + try: + return self.files[path] + except KeyError: + try: + with open(os.path.join(self.root, path)) as f: + data = f.read() + except Exception as e: + raise RuntimeError('Cannot open file {!r}: {}'.format(path, e)) + else: + self.files[path] = data + return data + + def get_tree(self, path): + path = self.resolve_path(path) + try: + return self.trees[path] + except KeyError: + try: + f = open(os.path.join(self.root, path)) + except Exception as e: + raise RuntimeError('Cannot open file {!r}: {}'.format(path, e)) + try: + with f: + tree = ET.parse(f, CustomHTMLParser()) + except Exception as e: + raise RuntimeError('Cannot parse an HTML file {!r}: {}'.format(path, e)) + else: + self.trees[path] = tree + return self.trees[path] + +def check_string(data, pat, regexp): + if not pat: + return True # special case a presence testing + elif regexp: + return re.search(pat, data) is not None + else: + data = ' '.join(data.split()) + pat = ' '.join(pat.split()) + return pat in data + +def check_tree_attr(tree, path, attr, pat, regexp): + path = normalize_xpath(path) + ret = False + for e in tree.findall(path): + try: + value = e.attrib[attr] + except KeyError: + continue + else: + ret = check_string(value, pat, regexp) + if ret: break + return ret + +def check_tree_text(tree, path, pat, regexp): + path = normalize_xpath(path) + ret = False + for e in tree.findall(path): + try: + value = flatten(e) + except KeyError: + continue + else: + ret = check_string(value, pat, regexp) + if ret: break + return ret + +def check(target, commands): + cache = CachedFiles(target) + for c in commands: + if c.cmd == 'has' or c.cmd == 'matches': # string test + regexp = (c.cmd == 'matches') + if len(c.args) == 1 and not regexp: # @has = file existence + try: + cache.get_file(c.args[0]) + ret = True + except RuntimeError: + ret = False + elif len(c.args) == 2: # @has/matches = string test + ret = check_string(cache.get_file(c.args[0]), c.args[1], regexp) + elif len(c.args) == 3: # @has/matches = XML tree test + tree = cache.get_tree(c.args[0]) + pat, sep, attr = c.args[1].partition('/@') + if sep: # attribute + ret = check_tree_attr(cache.get_tree(c.args[0]), pat, attr, c.args[2], regexp) + else: # normalized text + pat = c.args[1] + if pat.endswith('/text()'): pat = pat[:-7] + ret = check_tree_text(cache.get_tree(c.args[0]), pat, c.args[2], regexp) + else: + raise RuntimeError('Invalid number of @{} arguments \ + at line {}'.format(c.cmd, c.lineno)) + + elif c.cmd == 'valid-html': + raise RuntimeError('Unimplemented @valid-html at line {}'.format(c.lineno)) + + elif c.cmd == 'valid-links': + raise RuntimeError('Unimplemented @valid-links at line {}'.format(c.lineno)) + + else: + raise RuntimeError('Unrecognized @{} at line {}'.format(c.cmd, c.lineno)) + + if ret == c.negated: + raise RuntimeError('@{}{} check failed at line {}'.format('!' if c.negated else '', + c.cmd, c.lineno)) + +if __name__ == '__main__': + if len(sys.argv) < 3: + print >>sys.stderr, 'Usage: {}