diff --git a/configure b/configure index b14eac4b77e1..b2f8c33380ce 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" diff --git a/mk/cfg/aarch64-linux-android.mk b/mk/cfg/aarch64-linux-android.mk new file mode 100644 index 000000000000..a6f7f2ba1d66 --- /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/crates.mk b/mk/crates.mk index 5957405f0f9e..be1965b7edad 100644 --- a/mk/crates.mk +++ b/mk/crates.mk @@ -51,7 +51,7 @@ TARGET_CRATES := libc std flate arena term \ serialize getopts collections test rand \ - log regex graphviz core rbml alloc \ + log graphviz core rbml alloc \ unicode rustc_bitflags RUSTC_CRATES := rustc rustc_typeck rustc_borrowck rustc_resolve rustc_driver \ rustc_trans rustc_back rustc_llvm rustc_privacy @@ -95,16 +95,15 @@ DEPS_term := std log DEPS_getopts := std DEPS_collections := core alloc unicode DEPS_num := std -DEPS_test := std getopts serialize rbml term regex native:rust_test_helpers +DEPS_test := std getopts serialize rbml term native:rust_test_helpers DEPS_rand := core -DEPS_log := std regex -DEPS_regex := std +DEPS_log := std DEPS_fmt_macros = std TOOL_DEPS_compiletest := test getopts TOOL_DEPS_rustdoc := rustdoc TOOL_DEPS_rustc := rustc_driver -TOOL_DEPS_rustbook := std regex rustdoc +TOOL_DEPS_rustbook := std rustdoc TOOL_SOURCE_compiletest := $(S)src/compiletest/compiletest.rs TOOL_SOURCE_rustdoc := $(S)src/driver/driver.rs TOOL_SOURCE_rustc := $(S)src/driver/driver.rs @@ -130,9 +129,8 @@ DOC_CRATES := $(filter-out rustc, \ $(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_privacy diff --git a/mk/rt.mk b/mk/rt.mk index 6a7be26c7a68..a8bbeb415170 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 bf0b58f70a9a..e28f56fffe41 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -300,7 +300,8 @@ 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/featureck.py $(S)src/ + $(Q) $(CFG_PYTHON) $(S)src/etc/errorck.py $(S)src/ + $(Q) $(CFG_PYTHON) $(S)src/etc/featureck.py $(S)src/ endif diff --git a/src/compiletest/common.rs b/src/compiletest/common.rs index c29f74d74181..1f4f444634dc 100644 --- a/src/compiletest/common.rs +++ b/src/compiletest/common.rs @@ -11,9 +11,8 @@ pub use self::Mode::*; use std::fmt; use std::str::FromStr; -use regex::Regex; -#[derive(Clone, PartialEq)] +#[derive(Clone, PartialEq, Debug)] pub enum Mode { CompileFail, RunFail, @@ -43,9 +42,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 +57,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 @@ -107,28 +100,11 @@ pub struct Config { pub run_ignored: bool, // Only run tests that match this filter - pub filter: Option, - - // Precompiled regex for finding expected errors in cfail - pub cfail_regex: Regex, + pub filter: Option, // 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 802fb05796d6..d2d1d3d83685 100644 --- a/src/compiletest/compiletest.rs +++ b/src/compiletest/compiletest.rs @@ -13,6 +13,15 @@ #![feature(slicing_syntax, unboxed_closures)] #![feature(box_syntax)] #![feature(int_uint)] +#![feature(test)] +#![feature(rustc_private)] +#![feature(std_misc)] +#![feature(path)] +#![feature(io)] +#![feature(core)] +#![feature(collections)] +#![feature(os)] +#![feature(unicode)] #![deny(warnings)] @@ -21,7 +30,6 @@ extern crate getopts; #[macro_use] extern crate log; -extern crate regex; use std::os; use std::io; @@ -32,7 +40,6 @@ use getopts::{optopt, optflag, reqopt}; use common::Config; use common::{Pretty, DebugInfoGdb, DebugInfoLldb, Codegen}; use util::logv; -use regex::Regex; pub mod procsrv; pub mod util; @@ -76,10 +83,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 +92,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()); @@ -120,14 +122,7 @@ pub fn parse_config(args: Vec ) -> Config { } let filter = if !matches.free.is_empty() { - let s = matches.free[0].as_slice(); - match regex::Regex::new(s) { - Ok(re) => Some(re), - Err(e) => { - println!("failed to parse filter /{}/: {:?}", s, e); - panic!() - } - } + Some(matches.free[0].clone()) } else { None }; @@ -149,14 +144,7 @@ pub fn parse_config(args: Vec ) -> Config { .as_slice()).expect("invalid mode"), run_ignored: matches.opt_present("ignored"), 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 +163,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 +196,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")); } @@ -263,6 +246,9 @@ pub fn run_tests(config: &Config) { // parallel (especially when we have lots and lots of child processes). // For context, see #8904 io::test::raise_fd_limit(); + // Prevent issue #21352 UAC blocking .exe containing 'patch' etc. on Windows + // If #11207 is resolved (adding manifest to .exe) this becomes unnecessary + os::setenv("__COMPAT_LAYER", "RunAsInvoker"); let res = test::run_tests_console(&opts, tests.into_iter().collect()); match res { Ok(true) => {} @@ -283,15 +269,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, } } @@ -393,18 +372,24 @@ fn extract_gdb_version(full_version_line: Option) -> Option { if full_version_line.as_slice().trim().len() > 0 => { let full_version_line = full_version_line.as_slice().trim(); - let re = Regex::new(r"(^|[^0-9])([0-9]\.[0-9])([^0-9]|$)").unwrap(); - - match re.captures(full_version_line) { - Some(captures) => { - Some(captures.at(2).unwrap_or("").to_string()) + // used to be a regex "(^|[^0-9])([0-9]\.[0-9])([^0-9]|$)" + for (pos, c) in full_version_line.char_indices() { + if !c.is_digit(10) { continue } + if pos + 2 >= full_version_line.len() { continue } + if full_version_line.char_at(pos + 1) != '.' { continue } + if !full_version_line.char_at(pos + 2).is_digit(10) { continue } + if pos > 0 && full_version_line.char_at_reverse(pos).is_digit(10) { + continue } - None => { - println!("Could not extract GDB version from line '{}'", - full_version_line); - None + if pos + 3 < full_version_line.len() && + full_version_line.char_at(pos + 3).is_digit(10) { + continue } + return Some(full_version_line[pos..pos+3].to_string()); } + println!("Could not extract GDB version from line '{}'", + full_version_line); + None }, _ => None } @@ -427,18 +412,26 @@ fn extract_lldb_version(full_version_line: Option) -> Option { if full_version_line.as_slice().trim().len() > 0 => { let full_version_line = full_version_line.as_slice().trim(); - let re = Regex::new(r"[Ll][Ll][Dd][Bb]-([0-9]+)").unwrap(); + for (pos, l) in full_version_line.char_indices() { + if l != 'l' && l != 'L' { continue } + if pos + 5 >= full_version_line.len() { continue } + let l = full_version_line.char_at(pos + 1); + if l != 'l' && l != 'L' { continue } + let d = full_version_line.char_at(pos + 2); + if d != 'd' && d != 'D' { continue } + let b = full_version_line.char_at(pos + 3); + if b != 'b' && b != 'B' { continue } + let dash = full_version_line.char_at(pos + 4); + if dash != '-' { continue } - match re.captures(full_version_line) { - Some(captures) => { - Some(captures.at(1).unwrap_or("").to_string()) - } - None => { - println!("Could not extract LLDB version from line '{}'", - full_version_line); - None - } + let vers = full_version_line[pos + 5..].chars().take_while(|c| { + c.is_digit(10) + }).collect::(); + if vers.len() > 0 { return Some(vers) } } + println!("Could not extract LLDB version from line '{}'", + full_version_line); + None }, _ => None } diff --git a/src/compiletest/errors.rs b/src/compiletest/errors.rs index dcfac688c7f6..fc815d66a4d4 100644 --- a/src/compiletest/errors.rs +++ b/src/compiletest/errors.rs @@ -9,9 +9,7 @@ // except according to those terms. use self::WhichLine::*; -use std::ascii::AsciiExt; use std::io::{BufferedReader, File}; -use regex::Regex; pub struct ExpectedError { pub line: uint, @@ -19,6 +17,9 @@ pub struct ExpectedError { pub msg: String, } +#[derive(PartialEq, Show)] +enum WhichLine { ThisLine, FollowPrevious(uint), AdjustBackward(uint) } + /// Looks for either "//~| KIND MESSAGE" or "//~^^... KIND MESSAGE" /// The former is a "follow" that inherits its target from the preceding line; /// the latter is an "adjusts" that goes that many lines up. @@ -26,15 +27,8 @@ pub struct ExpectedError { /// Goal is to enable tests both like: //~^^^ ERROR go up three /// and also //~^ ERROR message one for the preceding line, and /// //~| ERROR message two for that same line. - -pub static EXPECTED_PATTERN : &'static str = - r"//~(?P\|)?(?P\^*)\s*(?P\S*)\s*(?P.*)"; - -#[derive(PartialEq, Show)] -enum WhichLine { ThisLine, FollowPrevious(uint), AdjustBackward(uint) } - // Load any test directives embedded in the file -pub fn load_errors(re: &Regex, testfile: &Path) -> Vec { +pub fn load_errors(testfile: &Path) -> Vec { let mut rdr = BufferedReader::new(File::open(testfile).unwrap()); // `last_nonfollow_error` tracks the most recently seen @@ -50,7 +44,7 @@ pub fn load_errors(re: &Regex, testfile: &Path) -> Vec { rdr.lines().enumerate().filter_map(|(line_no, ln)| { parse_expected(last_nonfollow_error, line_no + 1, - ln.unwrap().as_slice(), re) + ln.unwrap().as_slice()) .map(|(which, error)| { match which { FollowPrevious(_) => {} @@ -63,30 +57,39 @@ pub fn load_errors(re: &Regex, testfile: &Path) -> Vec { fn parse_expected(last_nonfollow_error: Option, line_num: uint, - line: &str, - re: &Regex) -> Option<(WhichLine, ExpectedError)> { - re.captures(line).and_then(|caps| { - let adjusts = caps.name("adjusts").unwrap_or("").len(); - let kind = caps.name("kind").unwrap_or("").to_ascii_lowercase(); - let msg = caps.name("msg").unwrap_or("").trim().to_string(); - let follow = caps.name("follow").unwrap_or("").len() > 0; + line: &str) -> Option<(WhichLine, ExpectedError)> { + let start = match line.find_str("//~") { Some(i) => i, None => return None }; + let (follow, adjusts) = if line.char_at(start + 3) == '|' { + (true, 0) + } else { + (false, line[start + 3..].chars().take_while(|c| *c == '^').count()) + }; + let kind_start = start + 3 + adjusts + (follow as usize); + let letters = line[kind_start..].chars(); + let kind = letters.skip_while(|c| c.is_whitespace()) + .take_while(|c| !c.is_whitespace()) + .map(|c| c.to_lowercase()) + .collect::(); + let letters = line[kind_start..].chars(); + let msg = letters.skip_while(|c| c.is_whitespace()) + .skip_while(|c| !c.is_whitespace()) + .collect::().trim().to_string(); - let (which, line) = if follow { - assert!(adjusts == 0, "use either //~| or //~^, not both."); - let line = last_nonfollow_error.unwrap_or_else(|| { - panic!("encountered //~| without preceding //~^ line.") - }); - (FollowPrevious(line), line) - } else { - let which = - if adjusts > 0 { AdjustBackward(adjusts) } else { ThisLine }; - let line = line_num - adjusts; - (which, line) - }; + let (which, line) = if follow { + assert!(adjusts == 0, "use either //~| or //~^, not both."); + let line = last_nonfollow_error.unwrap_or_else(|| { + panic!("encountered //~| without preceding //~^ line.") + }); + (FollowPrevious(line), line) + } else { + let which = + if adjusts > 0 { AdjustBackward(adjusts) } else { ThisLine }; + let line = line_num - adjusts; + (which, line) + }; - debug!("line={} which={:?} kind={:?} msg={:?}", line_num, which, kind, msg); - Some((which, ExpectedError { line: line, - kind: kind, - msg: msg, })) - }) + debug!("line={} which={:?} kind={:?} msg={:?}", line_num, which, kind, msg); + Some((which, ExpectedError { line: line, + kind: kind, + msg: msg, })) } diff --git a/src/compiletest/header.rs b/src/compiletest/header.rs index 2413a001ee80..d7af767688e8 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 5579479c5e5a..e5a973e7501a 100644 --- a/src/compiletest/runtest.rs +++ b/src/compiletest/runtest.rs @@ -99,7 +99,7 @@ fn run_cfail_test(config: &Config, props: &TestProps, testfile: &Path) { } let output_to_check = get_output(props, &proc_res); - let expected_errors = errors::load_errors(&config.cfail_regex, testfile); + let expected_errors = errors::load_errors(testfile); if !expected_errors.is_empty() { if !props.error_patterns.is_empty() { fatal("both error pattern and expected errors specified"); @@ -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/intro.md b/src/doc/intro.md index 3487738467fb..b92d38215c29 100644 --- a/src/doc/intro.md +++ b/src/doc/intro.md @@ -480,14 +480,12 @@ use std::sync::{Arc,Mutex}; fn main() { let numbers = Arc::new(Mutex::new(vec![1is, 2, 3])); - for i in 0..3 { + 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]); }); } } diff --git a/src/doc/reference.md b/src/doc/reference.md index 2883bc005364..f2d94d10ec69 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -739,6 +739,15 @@ Rust syntax is restricted in two ways: * `concat!` : concatenates a comma-separated list of literals * `concat_idents!` : create a new identifier by concatenating the arguments +The following attributes are used for quasiquoting in procedural macros: + +* `quote_expr!` +* `quote_item!` +* `quote_pat!` +* `quote_stmt!` +* `quote_tokens!` +* `quote_ty!` + # Crates and source files Rust is a *compiled* language. Its semantics obey a *phase distinction* @@ -803,8 +812,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 +828,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 +866,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 +927,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} @@ -2041,6 +2037,9 @@ type int8_t = i8; item](#language-items) for more details. - `test` - indicates that this function is a test function, to only be compiled in case of `--test`. +- `should_fail` - indicates that this test function should panic, inverting the success condition. +- `cold` - The function is unlikely to be executed, so optimize it (and calls + to it) differently. ### Static-only attributes @@ -2377,10 +2376,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` @@ -2820,13 +2815,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. @@ -3082,18 +3076,17 @@ The precedence of Rust binary operators is ordered as follows, going from strong to weak: ```{.text .precedence} -* / % as +* / % + - << >> & ^ | -< > <= >= -== != +== != < > <= >= && || -= += .. ``` Operators at the same precedence level are evaluated left-to-right. [Unary diff --git a/src/doc/rustdoc.md b/src/doc/rustdoc.md index 0b686eb76dbf..d4a25efec17f 100644 --- a/src/doc/rustdoc.md +++ b/src/doc/rustdoc.md @@ -1,296 +1,3 @@ % Rust Documentation -`rustdoc` is the built-in tool for generating documentation. It integrates -with the compiler to provide accurate hyperlinking between usage of types and -their documentation. Furthermore, by not using a separate parser, it will -never reject your valid Rust code. - -# Creating Documentation - -Documenting Rust APIs is quite simple. To document a given item, we have "doc -comments": - -~~~ -# #![allow(unused_attribute)] -// the "link" crate attribute is currently required for rustdoc, but normally -// isn't needed. -#![crate_id = "universe"] -#![crate_type="lib"] - -//! Tools for dealing with universes (this is a doc comment, and is shown on -//! the crate index page. The ! makes it apply to the parent of the comment, -//! rather than what follows). - -# mod workaround_the_outer_function_rustdoc_inserts { -/// Widgets are very common (this is a doc comment, and will show up on -/// Widget's documentation). -pub struct Widget { - /// All widgets have a purpose (this is a doc comment, and will show up - /// the field's documentation). - purpose: String, - /// Humans are not allowed to understand some widgets - understandable: bool -} - -pub fn recalibrate() { - //! Recalibrate a pesky universe (this is also a doc comment, like above, - //! the documentation will be applied to the *parent* item, so - //! `recalibrate`). - /* ... */ -} -# } -~~~ - -Documentation can also be controlled via the `doc` attribute on items. This is -implicitly done by the compiler when using the above form of doc comments -(converting the slash-based comments to `#[doc]` attributes). - -~~~ -#[doc = " -Calculates the factorial of a number. - -Given the input integer `n`, this function will calculate `n!` and return it. -"] -pub fn factorial(n: int) -> int { if n < 2 {1} else {n * factorial(n - 1)} } -# fn main() {} -~~~ - -The `doc` attribute can also be used to control how rustdoc emits documentation -in some cases. - -``` -// Rustdoc will inline documentation of a `pub use` into this crate when the -// `pub use` reaches across crates, but this behavior can also be disabled. -#[doc(no_inline)] -pub use std::option::Option; -# fn main() {} -``` - -Doc comments are markdown, and are currently parsed with the -[hoedown][hoedown] library. rustdoc does not yet do any fanciness such as -referencing other items inline, like javadoc's `@see`. One exception to this -is that the first paragraph will be used as the "summary" of an item in the -generated documentation: - -~~~ -/// A whizbang. Does stuff. (this line is the summary) -/// -/// Whizbangs are ... -struct Whizbang; -~~~ - -To generate the docs, run `rustdoc universe.rs`. By default, it generates a -directory called `doc`, with the documentation for `universe` being in -`doc/universe/index.html`. If you are using other crates with `extern crate`, -rustdoc will even link to them when you use their types, as long as their -documentation has already been generated by a previous run of rustdoc, or the -crate advertises that its documentation is hosted at a given URL. - -The generated output can be controlled with the `doc` crate attribute, which -is how the above advertisement works. An example from the `libstd` -documentation: - -~~~ -#[doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", - html_favicon_url = "http://www.rust-lang.org/favicon.ico", - html_root_url = "http://doc.rust-lang.org/")]; -~~~ - -The `html_root_url` is the prefix that rustdoc will apply to any references to -that crate's types etc. - -rustdoc can also generate JSON, for consumption by other tools, with -`rustdoc --output-format json`, and also consume already-generated JSON with -`rustdoc --input-format json`. - -rustdoc also supports personalizing the output from crates' documentation, -similar to markdown options. - -- `--html-in-header FILE`: includes the contents of `FILE` at the - end of the `...` section. -- `--html-before-content FILE`: includes the contents of `FILE` - directly after ``, before the rendered content (including the - search bar). -- `--html-after-content FILE`: includes the contents of `FILE` - after all the rendered content. - -# Using the Documentation - -The web pages generated by rustdoc present the same logical hierarchy that one -writes a library with. Every kind of item (function, struct, etc) has its own -color, and one can always click on a colored type to jump to its -documentation. There is a search bar at the top, which is powered by some -JavaScript and a statically-generated search index. No special web server is -required for the search. - -[hoedown]: https://github.com/hoedown/hoedown - -# Testing the Documentation - -`rustdoc` has support for testing code examples which appear in the -documentation. This is helpful for keeping code examples up to date with the -source code. - -To test documentation, the `--test` argument is passed to rustdoc: - -~~~ {.sh} -rustdoc --test crate.rs -~~~ - -## Defining tests - -Rust documentation currently uses the markdown format, and rustdoc treats all -code blocks as testable-by-default unless they carry a language tag of another -language. In order to not run a test over a block of code, the `ignore` string -can be added to the three-backtick form of markdown code block. - -~~~md -``` -// This is a testable code block -``` - -```rust{.example} -// This is rust and also testable -``` - -```ignore -// This is not a testable code block -``` - - // This is a testable code block (4-space indent) - -```sh -# this is shell code and not tested -``` -~~~ - -You can specify that the test's execution should fail with the `should_fail` -directive. - -~~~md -```should_fail -// This code block is expected to generate a panic when run -``` -~~~ - -You can specify that the code block should be compiled but not run with the -`no_run` directive. - -~~~md -```no_run -// This code will be compiled but not executed -``` -~~~ - -Lastly, you can specify that a code block be compiled as if `--test` -were passed to the compiler using the `test_harness` directive. - -~~~md -```test_harness -#[test] -fn foo() { - panic!("oops! (will run & register as a failed test)") -} -``` -~~~ - -Rustdoc also supplies some extra sugar for helping with some tedious -documentation examples. If a line is prefixed with `# `, then the line -will not show up in the HTML documentation, but it will be used when -testing the code block (NB. the space after the `#` is required, so -that one can still write things like `#[derive(Eq)]`). - -~~~md -``` -# /!\ The three following lines are comments, which are usually stripped off by -# the doc-generating tool. In order to display them anyway in this particular -# case, the character following the leading '#' is not a usual space like in -# these first five lines but a non breakable one. -# // showing 'fib' in this documentation would just be tedious and detracts from -# // what's actually being documented. -# fn fib(n: int) { n + 2 } - -spawn(move || { fib(200); }) -``` -~~~ - -The documentation online would look like `spawn(move || { fib(200); })`, but when -testing this code, the `fib` function will be included (so it can compile). - -Rustdoc will automatically add a `main()` wrapper around your code, and in the right -place. For example: - -``` -/// ``` -/// use std::rc::Rc; -/// -/// let five = Rc::new(5); -/// ``` -# fn foo() {} -``` - -This will end up testing: - -``` -fn main() { - use std::rc::Rc; - let five = Rc::new(5); -} -``` - -Here's the full algorithm: - -1. Given a code block, if it does not contain `fn main`, it is wrapped in `fn main() { your_code }` -2. Given that result, if it contains no `extern crate` directives but it also - contains the name of the crate being tested, then `extern crate ` is - injected at the top. -3. Some common `allow` attributes are added for documentation examples at the top. - -## Running tests (advanced) - -Running tests often requires some special configuration to filter tests, find -libraries, or try running ignored examples. The testing framework that rustdoc -uses is built on crate `test`, which is also used when you compile crates with -rustc's `--test` flag. Extra arguments can be passed to rustdoc's test harness -with the `--test-args` flag. - -~~~console -# Only run tests containing 'foo' in their name -$ rustdoc --test lib.rs --test-args 'foo' - -# See what's possible when running tests -$ rustdoc --test lib.rs --test-args '--help' -~~~ - -When testing a library, code examples will often show how functions are used, -and this code often requires `use`-ing paths from the crate. To accommodate this, -rustdoc will implicitly add `extern crate ;` where `` is the name of -the crate being tested to the top of each code example. This means that rustdoc -must be able to find a compiled version of the library crate being tested. Extra -search paths may be added via the `-L` flag to `rustdoc`. - -# Standalone Markdown files - -As well as Rust crates, rustdoc supports rendering pure Markdown files -into HTML and testing the code snippets from them. A Markdown file is -detected by a `.md` or `.markdown` extension. - -There are 4 options to modify the output that Rustdoc creates. - -- `--markdown-css PATH`: adds a `` tag pointing to `PATH`. -- `--html-in-header FILE`: includes the contents of `FILE` at the - end of the `...` section. -- `--html-before-content FILE`: includes the contents of `FILE` - directly after ``, before the rendered content (including the - title). -- `--html-after-content FILE`: includes the contents of `FILE` - directly before ``, after all the rendered content. - -All of these can be specified multiple times, and they are output in -the order in which they are specified. The first line of the file being rendered must -be the title, prefixed with `%` (e.g. this page has `% Rust -Documentation` on the first line). - -Like with a Rust crate, the `--test` argument will run the code -examples to check they compile, and obeys any `--test-args` flags. The -tests are named after the last `#` heading. +This has been moved [into the book](book/documentation.html). diff --git a/src/doc/trpl/SUMMARY.md b/src/doc/trpl/SUMMARY.md index aab03add905b..6131e1b8a707 100644 --- a/src/doc/trpl/SUMMARY.md +++ b/src/doc/trpl/SUMMARY.md @@ -16,6 +16,7 @@ * [Standard Input](standard-input.md) * [Guessing Game](guessing-game.md) * [II: Intermediate Rust](intermediate.md) + * [More Strings](more-strings.md) * [Crates and Modules](crates-and-modules.md) * [Testing](testing.md) * [Pointers](pointers.md) @@ -28,6 +29,7 @@ * [Traits](traits.md) * [Threads](threads.md) * [Error Handling](error-handling.md) + * [Documentation](documentation.md) * [III: Advanced Topics](advanced.md) * [FFI](ffi.md) * [Unsafe Code](unsafe.md) diff --git a/src/doc/trpl/closures.md b/src/doc/trpl/closures.md index 51a0bb69a7ce..bfb1494efc78 100644 --- a/src/doc/trpl/closures.md +++ b/src/doc/trpl/closures.md @@ -117,14 +117,7 @@ fn twice i32>(x: i32, f: F) -> i32 { arguments. `x` is an `i32`, we've done that a ton of times. `f` is a function, though, and that function takes an `i32` and returns an `i32`. This is what the requirement `Fn(i32) -> i32` for the type parameter `F` says. -You might ask yourself: why do we need to introduce a type parameter here? -That is because in Rust each closure has its own unique type. -So, not only do closures with different signatures have different types, -but different closures with the *same* signature have *different* types! -You can think of it this way: the behaviour of a closure is part of its type. -And since we want to support many different closures that all take -an `i32` and return an `i32` we introduced a type parameter that is able -to represent all these closures. +Now `F` represents *any* function that takes an `i32` and returns an `i32`. This is the most complicated function signature we've seen yet! Give it a read a few times until you can see how it works. It takes a teeny bit of practice, and @@ -181,6 +174,40 @@ fn main() { Doing this is not particularly common, but it's useful every once in a while. +Before we move on, let us look at a function that accepts two closures. + +```{rust} +fn compose(x: i32, f: F, g: G) -> i32 + where F: Fn(i32) -> i32, G: Fn(i32) -> i32 { + g(f(x)) +} + +fn main() { + compose(5, + |&: n: i32| { n + 42 }, + |&: n: i32| { n * 2 }); // evaluates to 94 +} +``` + +You might ask yourself: why do we need to introduce two type +parameters `F` and `G` here? Evidently, both `f` and `g` have the +same signature: `Fn(i32) -> i32`. + +That is because in Rust each closure has its own unique type. +So, not only do closures with different signatures have different types, +but different closures with the *same* signature have *different* +types, as well! + +You can think of it this way: the behavior of a closure is part of its +type. Therefore, using a single type parameter for both closures +will accept the first of them, rejecting the second. The distinct +type of the second closure does not allow it to be represented by the +same type parameter as that of the first. We acknowledge this, and +use two different type parameters `F` and `G`. + +This also introduces the `where` clause, which lets us describe type +parameters in a more flexible manner. + That's all you need to get the hang of closures! Closures are a little bit strange at first, but once you're used to them, you'll miss them in other languages. Passing functions to other functions is diff --git a/src/doc/trpl/crates-and-modules.md b/src/doc/trpl/crates-and-modules.md index 25870d84a754..efeb201efe84 100644 --- a/src/doc/trpl/crates-and-modules.md +++ b/src/doc/trpl/crates-and-modules.md @@ -257,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 @@ -287,8 +287,7 @@ mentioned earlier, you can use double colons to refer to sub-modules and the functions inside of them. Also, Cargo assumes that `src/main.rs` is the crate root of a binary crate, -rather than a library crate. Once we compile `src/main.rs`, we'll get an -executable that we can run. Our package now has two crates: `src/lib.rs` and +rather than a library crate. Our package now has two crates: `src/lib.rs` and `src/main.rs`. This pattern is quite common for executable crates: most functionality is in a library crate, and the executable crate uses that library. This way, other programs can also use the library crate, and it's also diff --git a/src/doc/trpl/documentation.md b/src/doc/trpl/documentation.md new file mode 100644 index 000000000000..0b686eb76dbf --- /dev/null +++ b/src/doc/trpl/documentation.md @@ -0,0 +1,296 @@ +% Rust Documentation + +`rustdoc` is the built-in tool for generating documentation. It integrates +with the compiler to provide accurate hyperlinking between usage of types and +their documentation. Furthermore, by not using a separate parser, it will +never reject your valid Rust code. + +# Creating Documentation + +Documenting Rust APIs is quite simple. To document a given item, we have "doc +comments": + +~~~ +# #![allow(unused_attribute)] +// the "link" crate attribute is currently required for rustdoc, but normally +// isn't needed. +#![crate_id = "universe"] +#![crate_type="lib"] + +//! Tools for dealing with universes (this is a doc comment, and is shown on +//! the crate index page. The ! makes it apply to the parent of the comment, +//! rather than what follows). + +# mod workaround_the_outer_function_rustdoc_inserts { +/// Widgets are very common (this is a doc comment, and will show up on +/// Widget's documentation). +pub struct Widget { + /// All widgets have a purpose (this is a doc comment, and will show up + /// the field's documentation). + purpose: String, + /// Humans are not allowed to understand some widgets + understandable: bool +} + +pub fn recalibrate() { + //! Recalibrate a pesky universe (this is also a doc comment, like above, + //! the documentation will be applied to the *parent* item, so + //! `recalibrate`). + /* ... */ +} +# } +~~~ + +Documentation can also be controlled via the `doc` attribute on items. This is +implicitly done by the compiler when using the above form of doc comments +(converting the slash-based comments to `#[doc]` attributes). + +~~~ +#[doc = " +Calculates the factorial of a number. + +Given the input integer `n`, this function will calculate `n!` and return it. +"] +pub fn factorial(n: int) -> int { if n < 2 {1} else {n * factorial(n - 1)} } +# fn main() {} +~~~ + +The `doc` attribute can also be used to control how rustdoc emits documentation +in some cases. + +``` +// Rustdoc will inline documentation of a `pub use` into this crate when the +// `pub use` reaches across crates, but this behavior can also be disabled. +#[doc(no_inline)] +pub use std::option::Option; +# fn main() {} +``` + +Doc comments are markdown, and are currently parsed with the +[hoedown][hoedown] library. rustdoc does not yet do any fanciness such as +referencing other items inline, like javadoc's `@see`. One exception to this +is that the first paragraph will be used as the "summary" of an item in the +generated documentation: + +~~~ +/// A whizbang. Does stuff. (this line is the summary) +/// +/// Whizbangs are ... +struct Whizbang; +~~~ + +To generate the docs, run `rustdoc universe.rs`. By default, it generates a +directory called `doc`, with the documentation for `universe` being in +`doc/universe/index.html`. If you are using other crates with `extern crate`, +rustdoc will even link to them when you use their types, as long as their +documentation has already been generated by a previous run of rustdoc, or the +crate advertises that its documentation is hosted at a given URL. + +The generated output can be controlled with the `doc` crate attribute, which +is how the above advertisement works. An example from the `libstd` +documentation: + +~~~ +#[doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", + html_favicon_url = "http://www.rust-lang.org/favicon.ico", + html_root_url = "http://doc.rust-lang.org/")]; +~~~ + +The `html_root_url` is the prefix that rustdoc will apply to any references to +that crate's types etc. + +rustdoc can also generate JSON, for consumption by other tools, with +`rustdoc --output-format json`, and also consume already-generated JSON with +`rustdoc --input-format json`. + +rustdoc also supports personalizing the output from crates' documentation, +similar to markdown options. + +- `--html-in-header FILE`: includes the contents of `FILE` at the + end of the `...` section. +- `--html-before-content FILE`: includes the contents of `FILE` + directly after ``, before the rendered content (including the + search bar). +- `--html-after-content FILE`: includes the contents of `FILE` + after all the rendered content. + +# Using the Documentation + +The web pages generated by rustdoc present the same logical hierarchy that one +writes a library with. Every kind of item (function, struct, etc) has its own +color, and one can always click on a colored type to jump to its +documentation. There is a search bar at the top, which is powered by some +JavaScript and a statically-generated search index. No special web server is +required for the search. + +[hoedown]: https://github.com/hoedown/hoedown + +# Testing the Documentation + +`rustdoc` has support for testing code examples which appear in the +documentation. This is helpful for keeping code examples up to date with the +source code. + +To test documentation, the `--test` argument is passed to rustdoc: + +~~~ {.sh} +rustdoc --test crate.rs +~~~ + +## Defining tests + +Rust documentation currently uses the markdown format, and rustdoc treats all +code blocks as testable-by-default unless they carry a language tag of another +language. In order to not run a test over a block of code, the `ignore` string +can be added to the three-backtick form of markdown code block. + +~~~md +``` +// This is a testable code block +``` + +```rust{.example} +// This is rust and also testable +``` + +```ignore +// This is not a testable code block +``` + + // This is a testable code block (4-space indent) + +```sh +# this is shell code and not tested +``` +~~~ + +You can specify that the test's execution should fail with the `should_fail` +directive. + +~~~md +```should_fail +// This code block is expected to generate a panic when run +``` +~~~ + +You can specify that the code block should be compiled but not run with the +`no_run` directive. + +~~~md +```no_run +// This code will be compiled but not executed +``` +~~~ + +Lastly, you can specify that a code block be compiled as if `--test` +were passed to the compiler using the `test_harness` directive. + +~~~md +```test_harness +#[test] +fn foo() { + panic!("oops! (will run & register as a failed test)") +} +``` +~~~ + +Rustdoc also supplies some extra sugar for helping with some tedious +documentation examples. If a line is prefixed with `# `, then the line +will not show up in the HTML documentation, but it will be used when +testing the code block (NB. the space after the `#` is required, so +that one can still write things like `#[derive(Eq)]`). + +~~~md +``` +# /!\ The three following lines are comments, which are usually stripped off by +# the doc-generating tool. In order to display them anyway in this particular +# case, the character following the leading '#' is not a usual space like in +# these first five lines but a non breakable one. +# // showing 'fib' in this documentation would just be tedious and detracts from +# // what's actually being documented. +# fn fib(n: int) { n + 2 } + +spawn(move || { fib(200); }) +``` +~~~ + +The documentation online would look like `spawn(move || { fib(200); })`, but when +testing this code, the `fib` function will be included (so it can compile). + +Rustdoc will automatically add a `main()` wrapper around your code, and in the right +place. For example: + +``` +/// ``` +/// use std::rc::Rc; +/// +/// let five = Rc::new(5); +/// ``` +# fn foo() {} +``` + +This will end up testing: + +``` +fn main() { + use std::rc::Rc; + let five = Rc::new(5); +} +``` + +Here's the full algorithm: + +1. Given a code block, if it does not contain `fn main`, it is wrapped in `fn main() { your_code }` +2. Given that result, if it contains no `extern crate` directives but it also + contains the name of the crate being tested, then `extern crate ` is + injected at the top. +3. Some common `allow` attributes are added for documentation examples at the top. + +## Running tests (advanced) + +Running tests often requires some special configuration to filter tests, find +libraries, or try running ignored examples. The testing framework that rustdoc +uses is built on crate `test`, which is also used when you compile crates with +rustc's `--test` flag. Extra arguments can be passed to rustdoc's test harness +with the `--test-args` flag. + +~~~console +# Only run tests containing 'foo' in their name +$ rustdoc --test lib.rs --test-args 'foo' + +# See what's possible when running tests +$ rustdoc --test lib.rs --test-args '--help' +~~~ + +When testing a library, code examples will often show how functions are used, +and this code often requires `use`-ing paths from the crate. To accommodate this, +rustdoc will implicitly add `extern crate ;` where `` is the name of +the crate being tested to the top of each code example. This means that rustdoc +must be able to find a compiled version of the library crate being tested. Extra +search paths may be added via the `-L` flag to `rustdoc`. + +# Standalone Markdown files + +As well as Rust crates, rustdoc supports rendering pure Markdown files +into HTML and testing the code snippets from them. A Markdown file is +detected by a `.md` or `.markdown` extension. + +There are 4 options to modify the output that Rustdoc creates. + +- `--markdown-css PATH`: adds a `` tag pointing to `PATH`. +- `--html-in-header FILE`: includes the contents of `FILE` at the + end of the `...` section. +- `--html-before-content FILE`: includes the contents of `FILE` + directly after ``, before the rendered content (including the + title). +- `--html-after-content FILE`: includes the contents of `FILE` + directly before ``, after all the rendered content. + +All of these can be specified multiple times, and they are output in +the order in which they are specified. The first line of the file being rendered must +be the title, prefixed with `%` (e.g. this page has `% Rust +Documentation` on the first line). + +Like with a Rust crate, the `--test` argument will run the code +examples to check they compile, and obeys any `--test-args` flags. The +tests are named after the last `#` heading. diff --git a/src/doc/trpl/if.md b/src/doc/trpl/if.md index ea1da167458a..a350df67b175 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/looping.md b/src/doc/trpl/looping.md index 28f02b1ffe15..4301149d1f8b 100644 --- a/src/doc/trpl/looping.md +++ b/src/doc/trpl/looping.md @@ -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/more-strings.md b/src/doc/trpl/more-strings.md new file mode 100644 index 000000000000..07b49751b10a --- /dev/null +++ b/src/doc/trpl/more-strings.md @@ -0,0 +1,283 @@ +% More Strings + +Strings are an important concept to master in any programming language. If you +come from a managed language background, you may be surprised at the complexity +of string handling in a systems programming language. Efficient access and +allocation of memory for a dynamically sized structure involves a lot of +details. Luckily, Rust has lots of tools to help us here. + +A **string** is a sequence of unicode scalar values encoded as a stream of +UTF-8 bytes. All strings are guaranteed to be validly-encoded UTF-8 sequences. +Additionally, strings are not null-terminated and can contain null bytes. + +Rust has two main types of strings: `&str` and `String`. + +# &str + +The first kind is a `&str`. This is pronounced a 'string slice'. +String literals are of the type `&str`: + +``` +let string = "Hello there."; +``` + +Like any Rust reference, string slices have an associated lifetime. A string +literal is a `&'static str`. A string slice can be written without an explicit +lifetime in many cases, such as in function arguments. In these cases the +lifetime will be inferred: + +``` +fn takes_slice(slice: &str) { + println!("Got: {}", slice); +} +``` + +Like vector slices, string slices are simply a pointer plus a length. This +means that they're a 'view' into an already-allocated string, such as a +string literal or a `String`. + +# String + +A `String` is a heap-allocated string. This string is growable, and is also +guaranteed to be UTF-8. + +``` +let mut s = "Hello".to_string(); +println!("{}", s); + +s.push_str(", world."); +println!("{}", s); +``` + +You can coerce a `String` into a `&str` by dereferencing it: + +``` +fn takes_slice(slice: &str) { + println!("Got: {}", slice); +} + +fn main() { + let s = "Hello".to_string(); + takes_slice(&*s); +} +``` + +You can also get a `&str` from a stack-allocated array of bytes: + +``` +use std::str; + +let x: &[u8] = &[b'a', b'b']; +let stack_str: &str = str::from_utf8(x).unwrap(); +``` + +# Best Practices + +## `String` vs. `&str` + +In general, you should prefer `String` when you need ownership, and `&str` when +you just need to borrow a string. This is very similar to using `Vec` vs. `&[T]`, +and `T` vs `&T` in general. + +This means starting off with this: + +```{rust,ignore} +fn foo(s: &str) { +``` + +and only moving to this: + +```{rust,ignore} +fn foo(s: String) { +``` + +If you have good reason. It's not polite to hold on to ownership you don't +need, and it can make your lifetimes more complex. + +## Generic functions + +To write a function that's generic over types of strings, use `&str`. + +``` +fn some_string_length(x: &str) -> uint { + x.len() +} + +fn main() { + let s = "Hello, world"; + + println!("{}", some_string_length(s)); + + let s = "Hello, world".to_string(); + + println!("{}", some_string_length(s.as_slice())); +} +``` + +Both of these lines will print `12`. + +## Indexing strings + +You may be tempted to try to access a certain character of a `String`, like +this: + +```{rust,ignore} +let s = "hello".to_string(); + +println!("{}", s[0]); +``` + +This does not compile. This is on purpose. In the world of UTF-8, direct +indexing is basically never what you want to do. The reason is that each +character can be a variable number of bytes. This means that you have to iterate +through the characters anyway, which is an O(n) operation. + +There's 3 basic levels of unicode (and its encodings): + +- code units, the underlying data type used to store everything +- code points/unicode scalar values (char) +- graphemes (visible characters) + +Rust provides iterators for each of these situations: + +- `.bytes()` will iterate over the underlying bytes +- `.chars()` will iterate over the code points +- `.graphemes()` will iterate over each grapheme + +Usually, the `graphemes()` method on `&str` is what you want: + +``` +let s = "u͔n͈̰̎i̙̮͚̦c͚̉o̼̩̰͗d͔̆̓ͥé"; + +for l in s.graphemes(true) { + println!("{}", l); +} +``` + +This prints: + +```text +u͔ +n͈̰̎ +i̙̮͚̦ +c͚̉ +o̼̩̰͗ +d͔̆̓ͥ +é +``` + +Note that `l` has the type `&str` here, since a single grapheme can consist of +multiple codepoints, so a `char` wouldn't be appropriate. + +This will print out each visible character in turn, as you'd expect: first "u͔", then +"n͈̰̎", etc. If you wanted each individual codepoint of each grapheme, you can use `.chars()`: + +``` +let s = "u͔n͈̰̎i̙̮͚̦c͚̉o̼̩̰͗d͔̆̓ͥé"; + +for l in s.chars() { + println!("{}", l); +} +``` + +This prints: + +```text +u +͔ +n +̎ +͈ +̰ +i +̙ +̮ +͚ +̦ +c +̉ +͚ +o +͗ +̼ +̩ +̰ +d +̆ +̓ +ͥ +͔ +e +́ +``` + +You can see how some of them are combining characters, and therefore the output +looks a bit odd. + +If you want the individual byte representation of each codepoint, you can use +`.bytes()`: + +``` +let s = "u͔n͈̰̎i̙̮͚̦c͚̉o̼̩̰͗d͔̆̓ͥé"; + +for l in s.bytes() { + println!("{}", l); +} +``` + +This will print: + +```text +117 +205 +148 +110 +204 +142 +205 +136 +204 +176 +105 +204 +153 +204 +174 +205 +154 +204 +166 +99 +204 +137 +205 +154 +111 +205 +151 +204 +188 +204 +169 +204 +176 +100 +204 +134 +205 +131 +205 +165 +205 +148 +101 +204 +129 +``` + +Many more bytes than graphemes! + +# Other Documentation + +* [the `&str` API documentation](std/str/index.html) +* [the `String` API documentation](std/string/index.html) diff --git a/src/doc/trpl/ownership.md b/src/doc/trpl/ownership.md index 8b7e37dd4c2f..56cb5b1de699 100644 --- a/src/doc/trpl/ownership.md +++ b/src/doc/trpl/ownership.md @@ -244,8 +244,8 @@ three. The ownership system in Rust does this through a concept called Remember the function that borrowed an `i32`? Let's look at it again. ```rust -fn add_one(num: &i32) -> i32 { - *num + 1 +fn add_one(num: &mut i32) { + *num += 1; } ``` @@ -255,8 +255,8 @@ cover the others later. Without eliding the lifetimes, `add_one` looks like this: ```rust -fn add_one<'a>(num: &'a i32) -> i32 { - *num + 1 +fn add_one<'a>(num: &'a mut i32) { + *num += 1; } ``` @@ -278,12 +278,12 @@ fn add_two<'a, 'b>(...) Then in our parameter list, we use the lifetimes we've named: ```{rust,ignore} -...(num: &'a i32) -> ... +...(num: &'a mut i32) ``` -If you compare `&i32` to `&'a i32`, they're the same, it's just that the -lifetime `'a` has snuck in between the `&` and the `i32`. We read `&i32` as "a -reference to an i32" and `&'a i32` as "a reference to an i32 with the lifetime 'a.'" +If you compare `&mut i32` to `&'a mut i32`, they're the same, it's just that the +lifetime `'a` has snuck in between the `&` and the `mut i32`. We read `&mut i32` as "a +mutable reference to an i32" and `&'a mut i32` as "a mutable reference to an i32 with the lifetime 'a.'" Why do lifetimes matter? Well, for example, here's some code: diff --git a/src/doc/trpl/pointers.md b/src/doc/trpl/pointers.md index d74c10b81450..29986d7f2357 100644 --- a/src/doc/trpl/pointers.md +++ b/src/doc/trpl/pointers.md @@ -87,7 +87,7 @@ println!("{}", x + z); This gives us an error: ```text -hello.rs:6:24: 6:25 error: mismatched types: expected `i32` but found `&i32` (expected i32 but found &-ptr) +hello.rs:6:24: 6:25 error: mismatched types: expected `_`, found `&_` (expected integral variable, found &-ptr) hello.rs:6 println!("{}", x + z); ^ ``` @@ -305,7 +305,7 @@ References are immutable by default: let x = 5; let y = &x; -*y = 5; // error: cannot assign to immutable dereference of `&`-pointer `*y` +*y = 5; // error: cannot assign to immutable borrowed content `*y` ``` They can be made mutable with `mut`, but only if its referent is also mutable. @@ -668,7 +668,7 @@ struct BigStruct { } fn foo(x: Box) -> Box { - return Box::new(*x); + Box::new(*x) } fn main() { @@ -696,7 +696,7 @@ struct BigStruct { } fn foo(x: Box) -> BigStruct { - return *x; + *x } fn main() { diff --git a/src/doc/trpl/threads.md b/src/doc/trpl/threads.md index 1bad09b4b6e5..a801a1ab0e92 100644 --- a/src/doc/trpl/threads.md +++ b/src/doc/trpl/threads.md @@ -179,7 +179,7 @@ for init_val in 0 .. 3 { } let result = rx.recv().unwrap() + rx.recv().unwrap() + rx.recv().unwrap(); -# fn some_expensive_computation(_i: u32) -> u32 { 42 } +# fn some_expensive_computation(_i: i32) -> i32 { 42 } ``` Cloning a `Sender` produces a new handle to the same channel, allowing multiple @@ -207,7 +207,7 @@ let rxs = (0 .. 3).map(|&:init_val| { // Wait on each port, accumulating the results let result = rxs.iter().fold(0, |&:accum, rx| accum + rx.recv().unwrap() ); -# fn some_expensive_computation(_i: u32) -> u32 { 42 } +# fn some_expensive_computation(_i: i32) -> i32 { 42 } ``` ## Backgrounding computations: Futures diff --git a/src/doc/trpl/unsafe.md b/src/doc/trpl/unsafe.md index 2a66b4a01f7a..3acd1eefe89d 100644 --- a/src/doc/trpl/unsafe.md +++ b/src/doc/trpl/unsafe.md @@ -707,7 +707,7 @@ Other features provided by lang items include: various kinds; lang items `send`, `sync` and `copy`. - the marker types and variance indicators found in `std::marker`; lang items `covariant_type`, - `contravariant_lifetime`, `no_sync_bound`, etc. + `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/etc/emacs/rust-mode.el b/src/etc/emacs/rust-mode.el index f25a59015fcd..dae685f3a540 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 000000000000..17659309d3b0 --- /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/rustup.sh b/src/etc/rustup.sh index 749d9eaa173e..07e832d317ad 100755 --- a/src/etc/rustup.sh +++ b/src/etc/rustup.sh @@ -433,11 +433,16 @@ CFG_TMP_DIR=$(mktemp -d 2>/dev/null \ || mktemp -d -t 'rustup-tmp-install' 2>/dev/null \ || create_tmp_dir) -# If we're saving nightlies and we didn't specify which one, grab todays. -# Otherwise we'll use the latest version. +# If we're saving nightlies and we didn't specify which one, grab the latest +# verison from the perspective of the server. Buildbot has typically finished +# building and uploading by ~8UTC, but we want to include a little buffer. +# +# FIXME It would be better to use the known most recent nightly that has been +# built. This is waiting on a change to have buildbot publish metadata that +# can be queried. if [ -n "${CFG_SAVE}" -a -z "${CFG_DATE}" ]; then - CFG_DATE=`date "+%Y-%m-%d"` + CFG_DATE=`TZ=Etc/UTC+9 date "+%Y-%m-%d"` fi RUST_URL="https://static.rust-lang.org/dist" @@ -453,16 +458,33 @@ then RUST_URL="${RUST_URL}/${CFG_DATE}" fi -verify_hash() { - remote_sha256="$1" - local_file="$2" - +download_hash() { msg "Downloading ${remote_sha256}" remote_sha256=`"${CFG_CURL}" -f "${remote_sha256}"` + if [ -n "${CFG_SAVE}" ]; then + echo "${remote_sha256}" > "${local_sha_file}" + fi if [ "$?" -ne 0 ]; then rm -Rf "${CFG_TMP_DIR}" err "Failed to download ${remote_url}" fi +} + +verify_hash() { + remote_sha256="$1" + local_file="$2" + local_sha_file="${local_file}.sha256" + + if [ -n "${CFG_SAVE}" ]; then + if [ -f "${local_sha_file}" ]; then + msg "Local ${local_sha_file} exists, treating as remote hash" + remote_sha256=`cat "${local_sha_file}"` + else + download_hash + fi + else + download_hash + fi msg "Verifying hash" local_sha256=$(calculate_hash "${local_file}") diff --git a/src/grammar/verify.rs b/src/grammar/verify.rs index e9409a610613..1288110df330 100644 --- a/src/grammar/verify.rs +++ b/src/grammar/verify.rs @@ -13,14 +13,11 @@ extern crate syntax; extern crate rustc; -extern crate regex; - #[macro_use] extern crate log; use std::collections::HashMap; use std::io::File; -use regex::Regex; use syntax::parse; use syntax::parse::lexer; @@ -167,15 +164,19 @@ fn count(lit: &str) -> usize { } fn parse_antlr_token(s: &str, tokens: &HashMap) -> TokenAndSpan { - let re = Regex::new( - r"\[@(?P\d+),(?P\d+):(?P\d+)='(?P.+?)',<(?P-?\d+)>,\d+:\d+]" - ).unwrap(); + // old regex: + // \[@(?P\d+),(?P\d+):(?P\d+)='(?P.+?)',<(?P-?\d+)>,\d+:\d+] + let start = s.find_str("[@").unwrap(); + let comma = start + s[start..].find_str(",").unwrap(); + let colon = comma + s[comma..].find_str(":").unwrap(); + let content_start = colon + s[colon..].find_str("='").unwrap(); + let content_end = content_start + s[content_start..].find_str("',<").unwrap(); + let toknum_end = content_end + s[content_end..].find_str(">,").unwrap(); - let m = re.captures(s).expect(format!("The regex didn't match {}", s).as_slice()); - let start = m.name("start").unwrap_or(""); - let end = m.name("end").unwrap_or(""); - let toknum = m.name("toknum").unwrap_or(""); - let content = m.name("content").unwrap_or(""); + let start = &s[comma + 1 .. colon]; + let end = &s[colon + 1 .. content_start]; + let content = &s[content_start + 2 .. content_end]; + let toknum = &s[content_end + 3 .. toknum_end]; let proto_tok = tokens.get(toknum).expect(format!("didn't find token {:?} in the map", toknum).as_slice()); diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index c8f568b07cba..1b75289c64f9 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -72,7 +72,7 @@ use core::prelude::*; use core::atomic; use core::atomic::Ordering::{Relaxed, Release, Acquire, SeqCst}; use core::borrow::BorrowFrom; -use core::fmt::{self, Show}; +use core::fmt; use core::cmp::{Ordering}; use core::default::Default; use core::mem::{min_align_of, size_of}; @@ -582,16 +582,17 @@ impl Ord for Arc { #[stable(feature = "rust1", since = "1.0.0")] impl Eq for Arc {} -impl fmt::Show for Arc { +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for Arc { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "Arc({:?})", (**self)) + fmt::Display::fmt(&**self, f) } } #[stable(feature = "rust1", since = "1.0.0")] -impl fmt::String for Arc { +impl fmt::Debug for Arc { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::String::fmt(&**self, f) + fmt::Debug::fmt(&**self, f) } } @@ -809,7 +810,7 @@ mod tests { #[test] fn show_arc() { let a = Arc::new(5u32); - assert!(format!("{:?}", a) == "Arc(5u32)") + assert_eq!(format!("{:?}", a), "5"); } // Make sure deriving works with Arc diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 19fa6771fb7b..51e5fc5820cb 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -8,7 +8,40 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! A unique pointer type. +//! A pointer type for heap allocation. +//! +//! `Box`, casually referred to as a 'box', provides the simplest form of heap allocation in +//! Rust. Boxes provide ownership for this allocation, and drop their contents when they go out of +//! scope. +//! +//! Boxes are useful in two situations: recursive data structures, and occasionally when returning +//! data. [The Pointer chapter of the Book](../../../book/pointers.html#best-practices-1) explains +//! these cases in detail. +//! +//! # Examples +//! +//! Creating a box: +//! +//! ``` +//! let x = Box::new(5); +//! ``` +//! +//! Creating a recursive data structure: +//! +//! ``` +//! #[derive(Show)] +//! enum List { +//! Cons(T, Box>), +//! Nil, +//! } +//! +//! fn main() { +//! let list: List = List::Cons(1, Box::new(List::Cons(2, Box::new(List::Nil)))); +//! println!("{:?}", list); +//! } +//! ``` +//! +//! This will print `Cons(1i32, Box(Cons(2i32, Box(Nil))))`. #![stable(feature = "rust1", since = "1.0.0")] @@ -16,19 +49,21 @@ use core::any::Any; use core::clone::Clone; use core::cmp::{PartialEq, PartialOrd, Eq, Ord, Ordering}; use core::default::Default; +use core::error::{Error, FromError}; use core::fmt; use core::hash::{self, Hash}; +use core::iter::Iterator; use core::marker::Sized; use core::mem; +use core::ops::{Deref, DerefMut}; use core::option::Option; use core::ptr::Unique; use core::raw::TraitObject; -use core::result::Result; use core::result::Result::{Ok, Err}; -use core::ops::{Deref, DerefMut}; +use core::result::Result; -/// A value that represents the global exchange heap. This is the default -/// place that the `box` keyword allocates into when no place is supplied. +/// A value that represents the heap. This is the default place that the `box` keyword allocates +/// into when no place is supplied. /// /// The following two examples are equivalent: /// @@ -37,10 +72,8 @@ use core::ops::{Deref, DerefMut}; /// use std::boxed::HEAP; /// /// fn main() { -/// # struct Bar; -/// # impl Bar { fn new(_a: int) { } } -/// let foo = box(HEAP) Bar::new(2); -/// let foo = box Bar::new(2); +/// let foo = box(HEAP) 5; +/// let foo = box 5; /// } /// ``` #[lang = "exchange_heap"] @@ -48,13 +81,21 @@ use core::ops::{Deref, DerefMut}; reason = "may be renamed; uncertain about custom allocator design")] pub static HEAP: () = (); -/// A type that represents a uniquely-owned value. +/// A pointer type for heap allocation. +/// +/// See the [module-level documentation](../../std/boxed/index.html) for more. #[lang = "owned_box"] #[stable(feature = "rust1", since = "1.0.0")] pub struct Box(Unique); impl Box { - /// Moves `x` into a freshly allocated box on the global exchange heap. + /// Allocates memory on the heap and then moves `x` into it. + /// + /// # Examples + /// + /// ``` + /// let x = Box::new(5); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn new(x: T) -> Box { box x @@ -75,11 +116,29 @@ impl Default for Box<[T]> { #[stable(feature = "rust1", since = "1.0.0")] impl Clone for Box { - /// Returns a copy of the owned box. + /// Returns a new box with a `clone()` of this box's contents. + /// + /// # Examples + /// + /// ``` + /// let x = Box::new(5); + /// let y = x.clone(); + /// ``` #[inline] fn clone(&self) -> Box { box {(**self).clone()} } - /// Performs copy-assignment from `source` by reusing the existing allocation. + /// Copies `source`'s contents into `self` without creating a new allocation. + /// + /// # Examples + /// + /// ``` + /// let x = Box::new(5); + /// let mut y = Box::new(10); + /// + /// y.clone_from(&x); + /// + /// assert_eq!(*y, 5); + /// ``` #[inline] fn clone_from(&mut self, source: &Box) { (**self).clone_from(&(**source)); @@ -158,20 +217,22 @@ impl BoxAny for Box { } } -impl fmt::Show for Box { +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for Box { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "Box({:?})", &**self) + fmt::Display::fmt(&**self, f) } } #[stable(feature = "rust1", since = "1.0.0")] -impl fmt::String for Box { +impl fmt::Debug for Box { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::String::fmt(&**self, f) + fmt::Debug::fmt(&**self, f) } } -impl fmt::Show for Box { +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for Box { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("Box") } @@ -189,56 +250,22 @@ impl DerefMut for Box { fn deref_mut(&mut self) -> &mut T { &mut **self } } -#[cfg(test)] -mod test { - #[test] - fn test_owned_clone() { - let a = Box::new(5i); - let b: Box = a.clone(); - assert!(a == b); +// FIXME(#21363) remove `old_impl_check` when bug is fixed +#[old_impl_check] +impl<'a, T> Iterator for Box + 'a> { + type Item = T; + + fn next(&mut self) -> Option { + (**self).next() } - #[test] - fn any_move() { - let a = Box::new(8u) as Box; - let b = Box::new(Test) as Box; - - match a.downcast::() { - Ok(a) => { assert!(a == Box::new(8u)); } - Err(..) => panic!() - } - match b.downcast::() { - Ok(a) => { assert!(a == Box::new(Test)); } - Err(..) => panic!() - } - - let a = Box::new(8u) as Box; - let b = Box::new(Test) as Box; - - assert!(a.downcast::>().is_err()); - assert!(b.downcast::>().is_err()); - } - - #[test] - fn test_show() { - let a = Box::new(8u) as Box; - let b = Box::new(Test) as Box; - let a_str = a.to_str(); - let b_str = b.to_str(); - assert_eq!(a_str, "Box"); - assert_eq!(b_str, "Box"); - - let a = &8u as &Any; - let b = &Test as &Any; - let s = format!("{}", a); - assert_eq!(s, "&Any"); - let s = format!("{}", b); - assert_eq!(s, "&Any"); - } - - #[test] - fn deref() { - fn homura>(_: T) { } - homura(Box::new(765i32)); + fn size_hint(&self) -> (usize, Option) { + (**self).size_hint() + } +} + +impl<'a, E: Error + 'a> FromError for Box { + fn from_error(err: E) -> Box { + Box::new(err) } } diff --git a/src/liballoc/boxed_test.rs b/src/liballoc/boxed_test.rs new file mode 100644 index 000000000000..c47a771f60d0 --- /dev/null +++ b/src/liballoc/boxed_test.rs @@ -0,0 +1,75 @@ +// Copyright 2012-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. + +//! Test for `boxed` mod. + +use core::any::Any; +use core::ops::Deref; +use core::result::Result::{Ok, Err}; +use core::clone::Clone; + +use std::boxed::Box; +use std::boxed::BoxAny; + +#[test] +fn test_owned_clone() { + let a = Box::new(5i); + let b: Box = a.clone(); + assert!(a == b); +} + +#[derive(PartialEq, Eq)] +struct Test; + +#[test] +fn any_move() { + let a = Box::new(8u) as Box; + let b = Box::new(Test) as Box; + + match a.downcast::() { + Ok(a) => { assert!(a == Box::new(8u)); } + Err(..) => panic!() + } + match b.downcast::() { + Ok(a) => { assert!(a == Box::new(Test)); } + Err(..) => panic!() + } + + let a = Box::new(8u) as Box; + let b = Box::new(Test) as Box; + + assert!(a.downcast::>().is_err()); + assert!(b.downcast::>().is_err()); +} + +#[test] +fn test_show() { + let a = Box::new(8u) as Box; + let b = Box::new(Test) as Box; + let a_str = format!("{:?}", a); + let b_str = format!("{:?}", b); + assert_eq!(a_str, "Box"); + assert_eq!(b_str, "Box"); + + static EIGHT: usize = 8us; + static TEST: Test = Test; + let a = &EIGHT as &Any; + let b = &TEST as &Any; + let s = format!("{:?}", a); + assert_eq!(s, "&Any"); + let s = format!("{:?}", b); + assert_eq!(s, "&Any"); +} + +#[test] +fn deref() { + fn homura>(_: T) { } + homura(Box::new(765i32)); +} diff --git a/src/liballoc/heap.rs b/src/liballoc/heap.rs index 9a72d7d05108..dcbd4d57cf99 100644 --- a/src/liballoc/heap.rs +++ b/src/liballoc/heap.rs @@ -280,7 +280,7 @@ mod imp { if align <= MIN_ALIGN { libc::malloc(size as libc::size_t) as *mut u8 } else { - let mut out = 0 as *mut libc::c_void; + let mut out = ptr::null_mut(); let ret = posix_memalign(&mut out, align as libc::size_t, size as libc::size_t); diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index cadb8907cf80..6830a1c33dfa 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -70,6 +70,8 @@ #![feature(lang_items, unsafe_destructor)] #![feature(box_syntax)] #![feature(optin_builtin_traits)] +// FIXME(#21363) remove `old_impl_check` when bug is fixed +#![feature(old_impl_check)] #![allow(unknown_features)] #![feature(int_uint)] #![feature(core)] #![feature(hash)] @@ -94,6 +96,8 @@ pub mod heap; #[cfg(not(test))] pub mod boxed; +#[cfg(test)] +mod boxed_test; pub mod arc; pub mod rc; diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 27153b12d871..d41673f56edd 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -173,32 +173,15 @@ struct RcBox { /// /// See the [module level documentation](../index.html) for more details. #[unsafe_no_drop_flag] -#[cfg(stage0)] // NOTE remove impl after next snapshot #[stable(feature = "rust1", since = "1.0.0")] -pub struct Rc { - // FIXME #12808: strange names to try to avoid interfering with field accesses of the contained - // type via Deref - _ptr: NonZero<*mut RcBox>, - _nosend: marker::NoSend, - _noshare: marker::NoSync -} - -/// An immutable reference-counted pointer type. -/// -/// See the [module level documentation](../index.html) for more details. -#[unsafe_no_drop_flag] -#[stable(feature = "rust1", since = "1.0.0")] -#[cfg(not(stage0))] // NOTE remove cfg after next snapshot pub struct Rc { // FIXME #12808: strange names to try to avoid interfering with field accesses of the contained // type via Deref _ptr: NonZero<*mut RcBox>, } -#[cfg(not(stage0))] // NOTE remove cfg after next snapshot impl !marker::Send for Rc {} -#[cfg(not(stage0))] // NOTE remove cfg after next snapshot impl !marker::Sync for Rc {} impl Rc { @@ -211,36 +194,7 @@ impl Rc { /// /// let five = Rc::new(5i); /// ``` - #[cfg(stage0)] // NOTE remove after next snapshot #[stable(feature = "rust1", since = "1.0.0")] - pub fn new(value: T) -> Rc { - unsafe { - Rc { - // there is an implicit weak pointer owned by all the strong pointers, which - // ensures that the weak destructor never frees the allocation while the strong - // destructor is running, even if the weak pointer is stored inside the strong one. - _ptr: NonZero::new(transmute(box RcBox { - value: value, - strong: Cell::new(1), - weak: Cell::new(1) - })), - _nosend: marker::NoSend, - _noshare: marker::NoSync - } - } - } - - /// Constructs a new `Rc`. - /// - /// # Examples - /// - /// ``` - /// use std::rc::Rc; - /// - /// let five = Rc::new(5i); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[cfg(not(stage0))] // NOTE remove cfg after next snapshot pub fn new(value: T) -> Rc { unsafe { Rc { @@ -267,30 +221,6 @@ impl Rc { /// /// let weak_five = five.downgrade(); /// ``` - #[cfg(stage0)] // NOTE remove after next snapshot - #[unstable(feature = "alloc", - reason = "Weak pointers may not belong in this module")] - pub fn downgrade(&self) -> Weak { - self.inc_weak(); - Weak { - _ptr: self._ptr, - _nosend: marker::NoSend, - _noshare: marker::NoSync - } - } - - /// Downgrades the `Rc` to a `Weak` reference. - /// - /// # Examples - /// - /// ``` - /// use std::rc::Rc; - /// - /// let five = Rc::new(5i); - /// - /// let weak_five = five.downgrade(); - /// ``` - #[cfg(not(stage0))] // NOTE remove cfg after next snapshot #[unstable(feature = "alloc", reason = "Weak pointers may not belong in this module")] pub fn downgrade(&self) -> Weak { @@ -485,25 +415,6 @@ impl Drop for Rc { #[stable(feature = "rust1", since = "1.0.0")] impl Clone for Rc { - /// Makes a clone of the `Rc`. - /// - /// This increases the strong reference count. - /// - /// # Examples - /// - /// ``` - /// use std::rc::Rc; - /// - /// let five = Rc::new(5i); - /// - /// five.clone(); - /// ``` - #[inline] - #[cfg(stage0)] // NOTE remove after next snapshot - fn clone(&self) -> Rc { - self.inc_strong(); - Rc { _ptr: self._ptr, _nosend: marker::NoSend, _noshare: marker::NoSync } - } /// Makes a clone of the `Rc`. /// @@ -519,7 +430,6 @@ impl Clone for Rc { /// five.clone(); /// ``` #[inline] - #[cfg(not(stage0))] // NOTE remove cfg after next snapshot fn clone(&self) -> Rc { self.inc_strong(); Rc { _ptr: self._ptr } @@ -695,17 +605,17 @@ impl> Hash for Rc { } } -#[unstable(feature = "alloc", reason = "Show is experimental.")] -impl fmt::Show for Rc { +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for Rc { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "Rc({:?})", **self) + fmt::Display::fmt(&**self, f) } } #[stable(feature = "rust1", since = "1.0.0")] -impl fmt::String for Rc { +impl fmt::Debug for Rc { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::String::fmt(&**self, f) + fmt::Debug::fmt(&**self, f) } } @@ -715,68 +625,22 @@ impl fmt::String for Rc { /// /// See the [module level documentation](../index.html) for more. #[unsafe_no_drop_flag] -#[cfg(stage0)] // NOTE remove impl after next snapshot #[unstable(feature = "alloc", reason = "Weak pointers may not belong in this module.")] pub struct Weak { // FIXME #12808: strange names to try to avoid interfering with // field accesses of the contained type via Deref _ptr: NonZero<*mut RcBox>, - _nosend: marker::NoSend, - _noshare: marker::NoSync } -/// A weak version of `Rc`. -/// -/// Weak references do not count when determining if the inner value should be dropped. -/// -/// See the [module level documentation](../index.html) for more. -#[unsafe_no_drop_flag] -#[unstable(feature = "alloc", - reason = "Weak pointers may not belong in this module.")] -#[cfg(not(stage0))] // NOTE remove cfg after next snapshot -pub struct Weak { - // FIXME #12808: strange names to try to avoid interfering with - // field accesses of the contained type via Deref - _ptr: NonZero<*mut RcBox>, -} - -#[cfg(not(stage0))] // NOTE remove cfg after next snapshot impl !marker::Send for Weak {} -#[cfg(not(stage0))] // NOTE remove cfg after next snapshot impl !marker::Sync for Weak {} #[unstable(feature = "alloc", reason = "Weak pointers may not belong in this module.")] impl Weak { - /// Upgrades a weak reference to a strong reference. - /// - /// Upgrades the `Weak` reference to an `Rc`, if possible. - /// - /// Returns `None` if there were no strong references and the data was destroyed. - /// - /// # Examples - /// - /// ``` - /// use std::rc::Rc; - /// - /// let five = Rc::new(5i); - /// - /// let weak_five = five.downgrade(); - /// - /// let strong_five: Option> = weak_five.upgrade(); - /// ``` - #[cfg(stage0)] // NOTE remove after next snapshot - pub fn upgrade(&self) -> Option> { - if self.strong() == 0 { - None - } else { - self.inc_strong(); - Some(Rc { _ptr: self._ptr, _nosend: marker::NoSend, _noshare: marker::NoSync }) - } - } /// Upgrades a weak reference to a strong reference. /// @@ -795,7 +659,6 @@ impl Weak { /// /// let strong_five: Option> = weak_five.upgrade(); /// ``` - #[cfg(not(stage0))] // NOTE remove cfg after next snapshot pub fn upgrade(&self) -> Option> { if self.strong() == 0 { None @@ -853,25 +716,6 @@ impl Drop for Weak { #[unstable(feature = "alloc", reason = "Weak pointers may not belong in this module.")] impl Clone for Weak { - /// Makes a clone of the `Weak`. - /// - /// This increases the weak reference count. - /// - /// # Examples - /// - /// ``` - /// use std::rc::Rc; - /// - /// let weak_five = Rc::new(5i).downgrade(); - /// - /// weak_five.clone(); - /// ``` - #[inline] - #[cfg(stage0)] // NOTE remove after next snapshot - fn clone(&self) -> Weak { - self.inc_weak(); - Weak { _ptr: self._ptr, _nosend: marker::NoSend, _noshare: marker::NoSync } - } /// Makes a clone of the `Weak`. /// @@ -887,15 +731,14 @@ impl Clone for Weak { /// weak_five.clone(); /// ``` #[inline] - #[cfg(not(stage0))] // NOTE remove cfg after next snapshot fn clone(&self) -> Weak { self.inc_weak(); Weak { _ptr: self._ptr } } } -#[unstable(feature = "alloc", reason = "Show is experimental.")] -impl fmt::Show for Weak { +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for Weak { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "(Weak)") } @@ -1137,7 +980,7 @@ mod tests { #[test] fn test_show() { let foo = Rc::new(75u); - assert!(format!("{:?}", foo) == "Rc(75u)") + assert_eq!(format!("{:?}", foo), "75"); } } diff --git a/src/libcollections/bit.rs b/src/libcollections/bit.rs index 5ce88fff53af..2c9a502a2098 100644 --- a/src/libcollections/bit.rs +++ b/src/libcollections/bit.rs @@ -331,7 +331,7 @@ impl Bitv { if extra_bytes > 0 { let mut last_word = 0u32; - for (i, &byte) in bytes[(complete_words*4)..].iter().enumerate() { + for (i, &byte) in bytes[complete_words*4..].iter().enumerate() { last_word |= (reverse_bits(byte) as u32) << (i * 8); } bitv.storage.push(last_word); @@ -974,7 +974,7 @@ impl Ord for Bitv { } #[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Show for Bitv { +impl fmt::Debug for Bitv { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { for bit in self.iter() { try!(write!(fmt, "{}", if bit { 1u32 } else { 0u32 })); @@ -1730,7 +1730,7 @@ impl BitvSet { } } -impl fmt::Show for BitvSet { +impl fmt::Debug for BitvSet { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { try!(write!(fmt, "BitvSet {{")); let mut first = true; @@ -2625,7 +2625,7 @@ mod bitv_set_test { s.insert(10); s.insert(50); s.insert(2); - assert_eq!("BitvSet {1u, 2u, 10u, 50u}", format!("{:?}", s)); + assert_eq!("BitvSet {1, 2, 10, 50}", format!("{:?}", s)); } #[test] diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index 8749c12abdbe..17d26ed1a21e 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -22,7 +22,7 @@ use core::prelude::*; use core::borrow::BorrowFrom; use core::cmp::Ordering; use core::default::Default; -use core::fmt::Show; +use core::fmt::Debug; use core::hash::{Hash, Hasher}; use core::iter::{Map, FromIterator}; use core::ops::{Index, IndexMut}; @@ -874,7 +874,7 @@ impl Ord for BTreeMap { } #[stable(feature = "rust1", since = "1.0.0")] -impl Show for BTreeMap { +impl Debug for BTreeMap { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { try!(write!(f, "BTreeMap {{")); diff --git a/src/libcollections/btree/node.rs b/src/libcollections/btree/node.rs index 77dfac289358..95e424fb7a03 100644 --- a/src/libcollections/btree/node.rs +++ b/src/libcollections/btree/node.rs @@ -21,7 +21,7 @@ use core::prelude::*; use core::borrow::BorrowFrom; use core::cmp::Ordering::{Greater, Less, Equal}; use core::iter::Zip; -use core::ops::{Deref, DerefMut}; +use core::ops::{Deref, DerefMut, Index, IndexMut}; use core::ptr::Unique; use core::{slice, mem, ptr, cmp, num, raw}; use alloc::heap; @@ -1487,7 +1487,7 @@ impl AbsTraversal macro_rules! node_slice_impl { ($NodeSlice:ident, $Traversal:ident, - $as_slices_internal:ident, $slice_from:ident, $slice_to:ident, $iter:ident) => { + $as_slices_internal:ident, $index:ident, $iter:ident) => { impl<'a, K: Ord + 'a, V: 'a> $NodeSlice<'a, K, V> { /// Performs linear search in a slice. Returns a tuple of (index, is_exact_match). fn search_linear(&self, key: &Q) -> (uint, bool) @@ -1521,10 +1521,10 @@ macro_rules! node_slice_impl { edges: if !self.has_edges { self.edges } else { - self.edges.$slice_from(pos) + self.edges.$index(&(pos ..)) }, - keys: self.keys.slice_from(pos), - vals: self.vals.$slice_from(pos), + keys: &self.keys[pos ..], + vals: self.vals.$index(&(pos ..)), head_is_edge: !pos_is_kv, tail_is_edge: self.tail_is_edge, } @@ -1550,10 +1550,10 @@ macro_rules! node_slice_impl { edges: if !self.has_edges { self.edges } else { - self.edges.$slice_to(pos + 1) + self.edges.$index(&(.. (pos + 1))) }, - keys: self.keys.slice_to(pos), - vals: self.vals.$slice_to(pos), + keys: &self.keys[..pos], + vals: self.vals.$index(&(.. pos)), head_is_edge: self.head_is_edge, tail_is_edge: !pos_is_kv, } @@ -1583,6 +1583,5 @@ macro_rules! node_slice_impl { } } -node_slice_impl!(NodeSlice, Traversal, as_slices_internal, slice_from, slice_to, iter); -node_slice_impl!(MutNodeSlice, MutTraversal, as_slices_internal_mut, slice_from_mut, - slice_to_mut, iter_mut); +node_slice_impl!(NodeSlice, Traversal, as_slices_internal, index, iter); +node_slice_impl!(MutNodeSlice, MutTraversal, as_slices_internal_mut, index_mut, iter_mut); diff --git a/src/libcollections/btree/set.rs b/src/libcollections/btree/set.rs index ef48074be490..e95087fa8468 100644 --- a/src/libcollections/btree/set.rs +++ b/src/libcollections/btree/set.rs @@ -16,11 +16,8 @@ use core::prelude::*; use core::borrow::BorrowFrom; use core::cmp::Ordering::{self, Less, Greater, Equal}; use core::default::Default; -use core::fmt::Show; +use core::fmt::Debug; use core::fmt; -// NOTE(stage0) remove import after a snapshot -#[cfg(stage0)] -use core::hash::Hash; use core::iter::{Peekable, Map, FromIterator}; use core::ops::{BitOr, BitAnd, BitXor, Sub}; @@ -594,7 +591,7 @@ impl<'a, 'b, T: Ord + Clone> BitOr<&'b BTreeSet> for &'a BTreeSet { } #[stable(feature = "rust1", since = "1.0.0")] -impl Show for BTreeSet { +impl Debug for BTreeSet { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { try!(write!(f, "BTreeSet {{")); @@ -894,7 +891,7 @@ mod test { let set_str = format!("{:?}", set); - assert_eq!(set_str, "BTreeSet {1i, 2i}"); + assert_eq!(set_str, "BTreeSet {1, 2}"); assert_eq!(format!("{:?}", empty), "BTreeSet {}"); } } diff --git a/src/libcollections/dlist.rs b/src/libcollections/dlist.rs index b580dfbdbf9e..08f7cea4e924 100644 --- a/src/libcollections/dlist.rs +++ b/src/libcollections/dlist.rs @@ -876,7 +876,7 @@ impl Clone for DList { } #[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Show for DList { +impl fmt::Debug for DList { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { try!(write!(f, "DList [")); @@ -1335,7 +1335,7 @@ mod tests { #[test] fn test_show() { let list: DList = range(0i, 10).collect(); - assert_eq!(format!("{:?}", list), "DList [0i, 1i, 2i, 3i, 4i, 5i, 6i, 7i, 8i, 9i]"); + assert_eq!(format!("{:?}", list), "DList [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]"); let list: DList<&str> = vec!["just", "one", "test", "more"].iter() .map(|&s| s) diff --git a/src/libcollections/enum_set.rs b/src/libcollections/enum_set.rs index fddea51c534f..f36da6f82eb7 100644 --- a/src/libcollections/enum_set.rs +++ b/src/libcollections/enum_set.rs @@ -31,7 +31,7 @@ pub struct EnumSet { impl Copy for EnumSet {} -impl fmt::Show for EnumSet { +impl fmt::Debug for EnumSet { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { try!(write!(fmt, "EnumSet {{")); let mut first = true; diff --git a/src/libcollections/macros.rs b/src/libcollections/macros.rs index 15ab7be7d909..15048998592a 100644 --- a/src/libcollections/macros.rs +++ b/src/libcollections/macros.rs @@ -12,13 +12,13 @@ #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] macro_rules! vec { - ($x:expr; $y:expr) => ({ - let xs: $crate::boxed::Box<[_]> = $crate::boxed::Box::new([$x; $y]); - $crate::slice::SliceExt::into_vec(xs) - }); - ($($x:expr),*) => ({ - let xs: $crate::boxed::Box<[_]> = $crate::boxed::Box::new([$($x),*]); - $crate::slice::SliceExt::into_vec(xs) - }); + ($x:expr; $y:expr) => ( + <[_] as $crate::slice::SliceExt>::into_vec( + $crate::boxed::Box::new([$x; $y])) + ); + ($($x:expr),*) => ( + <[_] as $crate::slice::SliceExt>::into_vec( + $crate::boxed::Box::new([$($x),*])) + ); ($($x:expr,)*) => (vec![$($x),*]) } diff --git a/src/libcollections/ring_buf.rs b/src/libcollections/ring_buf.rs index ff20716a1abb..2e3f61981122 100644 --- a/src/libcollections/ring_buf.rs +++ b/src/libcollections/ring_buf.rs @@ -581,7 +581,7 @@ impl RingBuf { if contiguous { let (empty, buf) = buf.split_at_mut(0); - (buf.slice_mut(tail, head), empty) + (&mut buf[tail .. head], empty) } else { let (mid, right) = buf.split_at_mut(tail); let (left, _) = mid.split_at_mut(head); @@ -1619,7 +1619,7 @@ impl Extend for RingBuf { } #[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Show for RingBuf { +impl fmt::Debug for RingBuf { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { try!(write!(f, "RingBuf [")); @@ -1638,7 +1638,7 @@ mod tests { use self::Taggypar::*; use prelude::*; use core::iter; - use std::fmt::Show; + use std::fmt::Debug; use std::hash::{self, SipHasher}; use test::Bencher; use test; @@ -1686,7 +1686,7 @@ mod tests { } #[cfg(test)] - fn test_parameterized(a: T, b: T, c: T, d: T) { + fn test_parameterized(a: T, b: T, c: T, d: T) { let mut deq = RingBuf::new(); assert_eq!(deq.len(), 0); deq.push_front(a.clone()); @@ -2310,7 +2310,7 @@ mod tests { #[test] fn test_show() { let ringbuf: RingBuf = range(0i, 10).collect(); - assert_eq!(format!("{:?}", ringbuf), "RingBuf [0i, 1i, 2i, 3i, 4i, 5i, 6i, 7i, 8i, 9i]"); + assert_eq!(format!("{:?}", ringbuf), "RingBuf [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]"); let ringbuf: RingBuf<&str> = vec!["just", "one", "test", "more"].iter() .map(|&s| s) diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index ae34c2de5d2d..dff95711d49e 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -170,32 +170,22 @@ pub trait SliceExt { reason = "uncertain about this API approach")] fn move_from(&mut self, src: Vec, start: uint, end: uint) -> uint; - /// Returns a subslice spanning the interval [`start`, `end`). - /// - /// Panics when the end of the new slice lies beyond the end of the - /// original slice (i.e. when `end > self.len()`) or when `start > end`. - /// - /// Slicing with `start` equal to `end` yields an empty slice. + /// Deprecated: use `&s[start .. end]` notation instead. #[unstable(feature = "collections", reason = "will be replaced by slice syntax")] + #[deprecated(since = "1.0.0", reason = "use &s[start .. end] instead")] fn slice(&self, start: uint, end: uint) -> &[Self::Item]; - /// Returns a subslice from `start` to the end of the slice. - /// - /// Panics when `start` is strictly greater than the length of the original slice. - /// - /// Slicing from `self.len()` yields an empty slice. + /// Deprecated: use `&s[start..]` notation instead. #[unstable(feature = "collections", reason = "will be replaced by slice syntax")] + #[deprecated(since = "1.0.0", reason = "use &s[start..] isntead")] fn slice_from(&self, start: uint) -> &[Self::Item]; - /// Returns a subslice from the start of the slice to `end`. - /// - /// Panics when `end` is strictly greater than the length of the original slice. - /// - /// Slicing to `0` yields an empty slice. + /// Deprecated: use `&s[..end]` notation instead. #[unstable(feature = "collections", reason = "will be replaced by slice syntax")] + #[deprecated(since = "1.0.0", reason = "use &s[..end] instead")] fn slice_to(&self, end: uint) -> &[Self::Item]; /// Divides one slice into two at an index. @@ -382,32 +372,22 @@ pub trait SliceExt { #[stable(feature = "rust1", since = "1.0.0")] fn as_mut_slice(&mut self) -> &mut [Self::Item]; - /// Returns a mutable subslice spanning the interval [`start`, `end`). - /// - /// Panics when the end of the new slice lies beyond the end of the - /// original slice (i.e. when `end > self.len()`) or when `start > end`. - /// - /// Slicing with `start` equal to `end` yields an empty slice. + /// Deprecated: use `&mut s[start .. end]` instead. #[unstable(feature = "collections", reason = "will be replaced by slice syntax")] + #[deprecated(since = "1.0.0", reason = "use &mut s[start .. end] instead")] fn slice_mut(&mut self, start: uint, end: uint) -> &mut [Self::Item]; - /// Returns a mutable subslice from `start` to the end of the slice. - /// - /// Panics when `start` is strictly greater than the length of the original slice. - /// - /// Slicing from `self.len()` yields an empty slice. + /// Deprecated: use `&mut s[start ..]` instead. #[unstable(feature = "collections", reason = "will be replaced by slice syntax")] + #[deprecated(since = "1.0.0", reason = "use &mut s[start ..] instead")] fn slice_from_mut(&mut self, start: uint) -> &mut [Self::Item]; - /// Returns a mutable subslice from the start of the slice to `end`. - /// - /// Panics when `end` is strictly greater than the length of the original slice. - /// - /// Slicing to `0` yields an empty slice. + /// Deprecated: use `&mut s[.. end]` instead. #[unstable(feature = "collections", reason = "will be replaced by slice syntax")] + #[deprecated(since = "1.0.0", reason = "use &mut s[.. end] instead")] fn slice_to_mut(&mut self, end: uint) -> &mut [Self::Item]; /// Returns an iterator that allows modifying each value @@ -724,7 +704,7 @@ impl SliceExt for [T] { #[inline] fn move_from(&mut self, mut src: Vec, start: uint, end: uint) -> uint { - for (a, b) in self.iter_mut().zip(src.slice_mut(start, end).iter_mut()) { + for (a, b) in self.iter_mut().zip(src[start .. end].iter_mut()) { mem::swap(a, b); } cmp::min(self.len(), end-start) @@ -732,17 +712,17 @@ impl SliceExt for [T] { #[inline] fn slice<'a>(&'a self, start: uint, end: uint) -> &'a [T] { - core_slice::SliceExt::slice(self, start, end) + &self[start .. end] } #[inline] fn slice_from<'a>(&'a self, start: uint) -> &'a [T] { - core_slice::SliceExt::slice_from(self, start) + &self[start ..] } #[inline] fn slice_to<'a>(&'a self, end: uint) -> &'a [T] { - core_slice::SliceExt::slice_to(self, end) + &self[.. end] } #[inline] @@ -846,17 +826,17 @@ impl SliceExt for [T] { #[inline] fn slice_mut<'a>(&'a mut self, start: uint, end: uint) -> &'a mut [T] { - core_slice::SliceExt::slice_mut(self, start, end) + &mut self[start .. end] } #[inline] fn slice_from_mut<'a>(&'a mut self, start: uint) -> &'a mut [T] { - core_slice::SliceExt::slice_from_mut(self, start) + &mut self[start ..] } #[inline] fn slice_to_mut<'a>(&'a mut self, end: uint) -> &'a mut [T] { - core_slice::SliceExt::slice_to_mut(self, end) + &mut self[.. end] } #[inline] @@ -1005,11 +985,30 @@ impl SliceExt for [T] { /// An extension trait for concatenating slices pub trait SliceConcatExt { /// Flattens a slice of `T` into a single value `U`. + /// + /// # Examples + /// + /// ``` + /// let v = vec!["hello", "world"]; + /// + /// let s: String = v.concat(); + /// + /// println!("{}", s); // prints "helloworld" + /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn concat(&self) -> U; - /// Flattens a slice of `T` into a single value `U`, placing a - /// given separator between each. + /// Flattens a slice of `T` into a single value `U`, placing a given separator between each. + /// + /// # Examples + /// + /// ``` + /// let v = vec!["hello", "world"]; + /// + /// let s: String = v.connect(" "); + /// + /// println!("{}", s); // prints "hello world" + /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn connect(&self, sep: &T) -> U; } @@ -2421,8 +2420,12 @@ mod tests { #[test] fn test_chunksator() { + use core::iter::ExactSizeIterator; + let v = &[1i,2,3,4,5]; + assert_eq!(v.chunks(2).len(), 3); + let chunks: &[&[int]] = &[&[1i,2], &[3,4], &[5]]; assert_eq!(v.chunks(2).collect::>(), chunks); let chunks: &[&[int]] = &[&[1i,2,3], &[4,5]]; @@ -2488,19 +2491,19 @@ mod tests { } let empty: Vec = vec![]; test_show_vec!(empty, "[]"); - test_show_vec!(vec![1i], "[1i]"); - test_show_vec!(vec![1i, 2, 3], "[1i, 2i, 3i]"); + test_show_vec!(vec![1i], "[1]"); + test_show_vec!(vec![1i, 2, 3], "[1, 2, 3]"); test_show_vec!(vec![vec![], vec![1u], vec![1u, 1u]], - "[[], [1u], [1u, 1u]]"); + "[[], [1], [1, 1]]"); let empty_mut: &mut [int] = &mut[]; test_show_vec!(empty_mut, "[]"); let v: &mut[int] = &mut[1]; - test_show_vec!(v, "[1i]"); + test_show_vec!(v, "[1]"); let v: &mut[int] = &mut[1, 2, 3]; - test_show_vec!(v, "[1i, 2i, 3i]"); + test_show_vec!(v, "[1, 2, 3]"); let v: &mut [&mut[uint]] = &mut[&mut[], &mut[1u], &mut[1u, 1u]]; - test_show_vec!(v, "[[], [1u], [1u, 1u]]"); + test_show_vec!(v, "[[], [1], [1, 1]]"); } #[test] @@ -2687,7 +2690,10 @@ mod tests { #[test] fn test_mut_chunks() { + use core::iter::ExactSizeIterator; + let mut v = [0u8, 1, 2, 3, 4, 5, 6]; + assert_eq!(v.chunks_mut(2).len(), 4); for (i, chunk) in v.chunks_mut(3).enumerate() { for x in chunk.iter_mut() { *x = i as u8; diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index 200637bb3992..63ae743b421b 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -759,70 +759,23 @@ pub trait StrExt: Index { core_str::StrExt::lines_any(&self[]) } - /// Returns a slice of the given string from the byte range - /// [`begin`..`end`). - /// - /// This operation is `O(1)`. - /// - /// Panics when `begin` and `end` do not point to valid characters - /// or point beyond the last character of the string. - /// - /// See also `slice_to` and `slice_from` for slicing prefixes and - /// suffixes of strings, and `slice_chars` for slicing based on - /// code point counts. - /// - /// # Example - /// - /// ```rust - /// let s = "Löwe 老虎 Léopard"; - /// assert_eq!(s.slice(0, 1), "L"); - /// - /// assert_eq!(s.slice(1, 9), "öwe 老"); - /// - /// // these will panic: - /// // byte 2 lies within `ö`: - /// // s.slice(2, 3); - /// - /// // byte 8 lies within `老` - /// // s.slice(1, 8); - /// - /// // byte 100 is outside the string - /// // s.slice(3, 100); - /// ``` + /// Deprecated: use `s[a .. b]` instead. #[unstable(feature = "collections", reason = "use slice notation [a..b] instead")] - fn slice(&self, begin: uint, end: uint) -> &str { - core_str::StrExt::slice(&self[], begin, end) - } + #[deprecated(since = "1.0.0", reason = "use slice notation [a..b] instead")] + fn slice(&self, begin: uint, end: uint) -> &str; - /// Returns a slice of the string from `begin` to its end. - /// - /// Equivalent to `self.slice(begin, self.len())`. - /// - /// Panics when `begin` does not point to a valid character, or is - /// out of bounds. - /// - /// See also `slice`, `slice_to` and `slice_chars`. + /// Deprecated: use `s[a..]` instead. #[unstable(feature = "collections", - reason = "use slice notation [a..] instead")] - fn slice_from(&self, begin: uint) -> &str { - core_str::StrExt::slice_from(&self[], begin) - } + reason = "use slice notation [a..b] instead")] + #[deprecated(since = "1.0.0", reason = "use slice notation [a..] instead")] + fn slice_from(&self, begin: uint) -> &str; - /// Returns a slice of the string from the beginning to byte - /// `end`. - /// - /// Equivalent to `self.slice(0, end)`. - /// - /// Panics when `end` does not point to a valid character, or is - /// out of bounds. - /// - /// See also `slice`, `slice_from` and `slice_chars`. + /// Deprecated: use `s[..a]` instead. #[unstable(feature = "collections", - reason = "use slice notation [..a] instead")] - fn slice_to(&self, end: uint) -> &str { - core_str::StrExt::slice_to(&self[], end) - } + reason = "use slice notation [a..b] instead")] + #[deprecated(since = "1.0.0", reason = "use slice notation [..a] instead")] + fn slice_to(&self, end: uint) -> &str; /// Returns a slice of the string from the character range /// [`begin`..`end`). @@ -1374,7 +1327,19 @@ pub trait StrExt: Index { } #[stable(feature = "rust1", since = "1.0.0")] -impl StrExt for str {} +impl StrExt for str { + fn slice(&self, begin: uint, end: uint) -> &str { + &self[begin..end] + } + + fn slice_from(&self, begin: uint) -> &str { + &self[begin..] + } + + fn slice_to(&self, end: uint) -> &str { + &self[..end] + } +} #[cfg(test)] mod tests { diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index 00abe734d40c..cdceca7176d0 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -18,6 +18,7 @@ use core::prelude::*; use core::borrow::{Cow, IntoCow}; use core::default::Default; +use core::error::Error; use core::fmt; use core::hash; use core::iter::FromIterator; @@ -40,6 +41,7 @@ pub struct String { /// A possible error value from the `String::from_utf8` function. #[stable(feature = "rust1", since = "1.0.0")] +#[derive(Show)] pub struct FromUtf8Error { bytes: Vec, error: Utf8Error, @@ -48,6 +50,7 @@ pub struct FromUtf8Error { /// A possible error value from the `String::from_utf16` function. #[stable(feature = "rust1", since = "1.0.0")] #[allow(missing_copy_implementations)] +#[derive(Show)] pub struct FromUtf16Error(()); impl String { @@ -681,30 +684,28 @@ impl FromUtf8Error { pub fn utf8_error(&self) -> Utf8Error { self.error } } -impl fmt::Show for FromUtf8Error { +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for FromUtf8Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::String::fmt(self, f) + fmt::Display::fmt(&self.error, f) } } #[stable(feature = "rust1", since = "1.0.0")] -impl fmt::String for FromUtf8Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::String::fmt(&self.error, f) - } +impl Error for FromUtf8Error { + fn description(&self) -> &str { "invalid utf-8" } } -impl fmt::Show for FromUtf16Error { +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for FromUtf16Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::String::fmt(self, f) + fmt::Display::fmt("invalid utf-16: lone surrogate found", f) } } #[stable(feature = "rust1", since = "1.0.0")] -impl fmt::String for FromUtf16Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::String::fmt("invalid utf-16: lone surrogate found", f) - } +impl Error for FromUtf16Error { + fn description(&self) -> &str { "invalid utf-16" } } #[stable(feature = "rust1", since = "1.0.0")] @@ -817,18 +818,18 @@ impl Default for String { } #[stable(feature = "rust1", since = "1.0.0")] -impl fmt::String for String { +impl fmt::Display for String { #[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::String::fmt(&**self, f) + fmt::Display::fmt(&**self, f) } } -#[unstable(feature = "collections", reason = "waiting on fmt stabilization")] -impl fmt::Show for String { +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for String { #[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Show::fmt(&**self, f) + fmt::Debug::fmt(&**self, f) } } @@ -852,6 +853,7 @@ impl<'a> Add<&'a str> for String { } } +#[stable(feature = "rust1", since = "1.0.0")] impl ops::Index> for String { type Output = str; #[inline] @@ -859,6 +861,7 @@ impl ops::Index> for String { &self[][*index] } } +#[stable(feature = "rust1", since = "1.0.0")] impl ops::Index> for String { type Output = str; #[inline] @@ -866,6 +869,7 @@ impl ops::Index> for String { &self[][*index] } } +#[stable(feature = "rust1", since = "1.0.0")] impl ops::Index> for String { type Output = str; #[inline] @@ -873,6 +877,7 @@ impl ops::Index> for String { &self[][*index] } } +#[stable(feature = "rust1", since = "1.0.0")] impl ops::Index for String { type Output = str; #[inline] @@ -938,7 +943,7 @@ pub trait ToString { fn to_string(&self) -> String; } -impl ToString for T { +impl ToString for T { #[inline] fn to_string(&self) -> String { use core::fmt::Writer; @@ -1299,10 +1304,10 @@ mod tests { fn test_vectors() { let x: Vec = vec![]; assert_eq!(format!("{:?}", x), "[]"); - assert_eq!(format!("{:?}", vec![1i]), "[1i]"); - assert_eq!(format!("{:?}", vec![1i, 2, 3]), "[1i, 2i, 3i]"); + assert_eq!(format!("{:?}", vec![1i]), "[1]"); + assert_eq!(format!("{:?}", vec![1i, 2, 3]), "[1, 2, 3]"); assert!(format!("{:?}", vec![vec![], vec![1i], vec![1i, 1]]) == - "[[], [1i], [1i, 1i]]"); + "[[], [1], [1, 1]]"); } #[test] diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 567157e7d8fe..53f75a3e778b 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -1235,7 +1235,7 @@ impl> Hash for Vec { } } -#[unstable(feature = "collections", reason = "waiting on Index stability")] +#[stable(feature = "rust1", since = "1.0.0")] impl Index for Vec { type Output = T; @@ -1245,6 +1245,7 @@ impl Index for Vec { } } +#[stable(feature = "rust1", since = "1.0.0")] impl IndexMut for Vec { type Output = T; @@ -1255,6 +1256,7 @@ impl IndexMut for Vec { } +#[stable(feature = "rust1", since = "1.0.0")] impl ops::Index> for Vec { type Output = [T]; #[inline] @@ -1262,6 +1264,7 @@ impl ops::Index> for Vec { self.as_slice().index(index) } } +#[stable(feature = "rust1", since = "1.0.0")] impl ops::Index> for Vec { type Output = [T]; #[inline] @@ -1269,6 +1272,7 @@ impl ops::Index> for Vec { self.as_slice().index(index) } } +#[stable(feature = "rust1", since = "1.0.0")] impl ops::Index> for Vec { type Output = [T]; #[inline] @@ -1276,6 +1280,7 @@ impl ops::Index> for Vec { self.as_slice().index(index) } } +#[stable(feature = "rust1", since = "1.0.0")] impl ops::Index for Vec { type Output = [T]; #[inline] @@ -1284,6 +1289,7 @@ impl ops::Index for Vec { } } +#[stable(feature = "rust1", since = "1.0.0")] impl ops::IndexMut> for Vec { type Output = [T]; #[inline] @@ -1291,6 +1297,7 @@ impl ops::IndexMut> for Vec { self.as_mut_slice().index_mut(index) } } +#[stable(feature = "rust1", since = "1.0.0")] impl ops::IndexMut> for Vec { type Output = [T]; #[inline] @@ -1298,6 +1305,7 @@ impl ops::IndexMut> for Vec { self.as_mut_slice().index_mut(index) } } +#[stable(feature = "rust1", since = "1.0.0")] impl ops::IndexMut> for Vec { type Output = [T]; #[inline] @@ -1305,6 +1313,7 @@ impl ops::IndexMut> for Vec { self.as_mut_slice().index_mut(index) } } +#[stable(feature = "rust1", since = "1.0.0")] impl ops::IndexMut for Vec { type Output = [T]; #[inline] @@ -1313,7 +1322,6 @@ impl ops::IndexMut for Vec { } } - #[stable(feature = "rust1", since = "1.0.0")] impl ops::Deref for Vec { type Target = [T]; @@ -1494,10 +1502,10 @@ impl Default for Vec { } } -#[unstable(feature = "collections", reason = "waiting on Show stability")] -impl fmt::Show for Vec { +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for Vec { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Show::fmt(self.as_slice(), f) + fmt::Debug::fmt(self.as_slice(), f) } } @@ -2168,7 +2176,7 @@ mod tests { #[should_fail] fn test_slice_out_of_bounds_1() { let x: Vec = vec![1, 2, 3, 4, 5]; - &x[(-1)..]; + &x[-1..]; } #[test] @@ -2182,7 +2190,7 @@ mod tests { #[should_fail] fn test_slice_out_of_bounds_3() { let x: Vec = vec![1, 2, 3, 4, 5]; - &x[(-1)..4]; + &x[-1..4]; } #[test] diff --git a/src/libcollections/vec_map.rs b/src/libcollections/vec_map.rs index f257d9a53e49..3d28284c9bf9 100644 --- a/src/libcollections/vec_map.rs +++ b/src/libcollections/vec_map.rs @@ -514,7 +514,7 @@ impl Ord for VecMap { } #[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Show for VecMap { +impl fmt::Debug for VecMap { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { try!(write!(f, "VecMap {{")); @@ -991,7 +991,7 @@ mod test_map { map.insert(3, 4i); let map_str = format!("{:?}", map); - assert!(map_str == "VecMap {1: 2i, 3: 4i}" || map_str == "{3: 4i, 1: 2i}"); + assert!(map_str == "VecMap {1: 2, 3: 4}" || map_str == "{3: 4, 1: 2}"); assert_eq!(format!("{:?}", empty), "VecMap {}"); } diff --git a/src/libcore/any.rs b/src/libcore/any.rs index 955497861f57..87030ed778da 100644 --- a/src/libcore/any.rs +++ b/src/libcore/any.rs @@ -34,11 +34,11 @@ //! use runtime reflection instead. //! //! ```rust -//! use std::fmt::Show; +//! use std::fmt::Debug; //! use std::any::Any; //! -//! // Logger function for any type that implements Show. -//! fn log(value: &T) { +//! // Logger function for any type that implements Debug. +//! fn log(value: &T) { //! let value_any = value as &Any; //! //! // try to convert our value to a String. If successful, we want to @@ -55,7 +55,7 @@ //! } //! //! // This function wants to log its parameter out prior to doing work with it. -//! fn do_work(value: &T) { +//! fn do_work(value: &T) { //! log(value); //! // ...do some other work //! } @@ -75,7 +75,7 @@ use mem::transmute; use option::Option::{self, Some, None}; use raw::TraitObject; use intrinsics; -#[cfg(not(stage0))] use marker::Sized; +use marker::Sized; /////////////////////////////////////////////////////////////////////////////// // Any trait @@ -176,7 +176,6 @@ pub struct TypeId { impl TypeId { /// Returns the `TypeId` of the type this generic function has been /// instantiated with - #[cfg(not(stage0))] #[unstable(feature = "core", reason = "may grow a `Reflect` bound soon via marker traits")] pub fn of() -> TypeId { @@ -184,10 +183,4 @@ impl TypeId { t: unsafe { intrinsics::type_id::() }, } } - - /// dox - #[cfg(stage0)] - pub fn of() -> TypeId { - unsafe { intrinsics::type_id::() } - } } diff --git a/src/libcore/array.rs b/src/libcore/array.rs index c38c1b279ccc..44541c34ee27 100644 --- a/src/libcore/array.rs +++ b/src/libcore/array.rs @@ -39,11 +39,10 @@ macro_rules! array_impls { } } - #[unstable(feature = "core", - reason = "waiting for Show to stabilize")] - impl fmt::Show for [T; $N] { + #[stable(feature = "rust1", since = "1.0.0")] + impl fmt::Debug for [T; $N] { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Show::fmt(&&self[], f) + fmt::Debug::fmt(&&self[], f) } } diff --git a/src/libcore/borrow.rs b/src/libcore/borrow.rs index 0897710aaaac..be144b052c78 100644 --- a/src/libcore/borrow.rs +++ b/src/libcore/borrow.rs @@ -134,7 +134,6 @@ impl ToOwned for T where T: Clone { /// } /// } /// ``` -#[derive(Show)] pub enum Cow<'a, T, B: ?Sized + 'a> where B: ToOwned { /// Borrowed data. Borrowed(&'a B), @@ -240,14 +239,27 @@ impl<'a, T, B: ?Sized> PartialOrd for Cow<'a, T, B> where B: PartialOrd + ToOwne } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T, B: ?Sized> fmt::String for Cow<'a, T, B> where - B: fmt::String + ToOwned, - T: fmt::String, +impl<'a, T, B: ?Sized> fmt::Debug for Cow<'a, T, B> where + B: fmt::Debug + ToOwned, + T: fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - Borrowed(ref b) => fmt::String::fmt(b, f), - Owned(ref o) => fmt::String::fmt(o, f), + Borrowed(ref b) => fmt::Debug::fmt(b, f), + Owned(ref o) => fmt::Debug::fmt(o, f), + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T, B: ?Sized> fmt::Display for Cow<'a, T, B> where + B: fmt::Display + ToOwned, + T: fmt::Display, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Borrowed(ref b) => fmt::Display::fmt(b, f), + Owned(ref o) => fmt::Display::fmt(o, f), } } } diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index aa04f9c1b206..3f25432e87ab 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -74,6 +74,10 @@ //! } //! ``` //! +//! Note that this example uses `Rc` and not `Arc`. `RefCell`s are for single-threaded +//! scenarios. Consider using `Mutex` if you need shared mutability in a multi-threaded +//! situation. +//! //! ## Implementation details of logically-immutable methods //! //! Occasionally it may be desirable not to expose in an API that diff --git a/src/libstd/error.rs b/src/libcore/error.rs similarity index 75% rename from src/libstd/error.rs rename to src/libcore/error.rs index 68ad3193e74b..9519539f0004 100644 --- a/src/libstd/error.rs +++ b/src/libcore/error.rs @@ -14,14 +14,15 @@ //! //! `Error` is a trait representing the basic expectations for error values, //! i.e. values of type `E` in `Result`. At a minimum, errors must provide -//! a description, but they may optionally provide additional detail and cause -//! chain information: +//! a description, but they may optionally provide additional detail (via +//! `Display`) and cause chain information: //! //! ``` -//! trait Error { +//! use std::fmt::Display; +//! +//! trait Error: Display { //! fn description(&self) -> &str; //! -//! fn detail(&self) -> Option { None } //! fn cause(&self) -> Option<&Error> { None } //! } //! ``` @@ -80,21 +81,16 @@ #![stable(feature = "rust1", since = "1.0.0")] -use prelude::v1::*; - -use str::Utf8Error; -use string::{FromUtf8Error, FromUtf16Error}; +use prelude::*; +use fmt::Display; /// Base functionality for all errors in Rust. -#[unstable(feature = "std_misc", +#[unstable(feature = "core", reason = "the exact API of this trait may change")] -pub trait Error { +pub trait Error: Display { /// A short description of the error; usually a static string. fn description(&self) -> &str; - /// A detailed description of the error, usually including dynamic information. - fn detail(&self) -> Option { None } - /// The lower-level cause of this error, if any. fn cause(&self) -> Option<&Error> { None } } @@ -114,26 +110,3 @@ impl FromError for E { err } } - -#[stable(feature = "rust1", since = "1.0.0")] -impl Error for Utf8Error { - fn description(&self) -> &str { - match *self { - Utf8Error::TooShort => "invalid utf-8: not enough bytes", - Utf8Error::InvalidByte(..) => "invalid utf-8: corrupt contents", - } - } - - fn detail(&self) -> Option { Some(self.to_string()) } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Error for FromUtf8Error { - fn description(&self) -> &str { "invalid utf-8" } - fn detail(&self) -> Option { Some(self.to_string()) } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Error for FromUtf16Error { - fn description(&self) -> &str { "invalid utf-16" } -} diff --git a/src/libcore/fmt/float.rs b/src/libcore/fmt/float.rs index f1b9ebe6d905..245dc00d8382 100644 --- a/src/libcore/fmt/float.rs +++ b/src/libcore/fmt/float.rs @@ -179,7 +179,7 @@ pub fn float_to_str_bytes_common( _ => () } - buf.slice_to_mut(end).reverse(); + buf[..end].reverse(); // Remember start of the fractional digits. // Points one beyond end of buf if none get generated, @@ -316,7 +316,7 @@ pub fn float_to_str_bytes_common( impl<'a> fmt::Writer for Filler<'a> { fn write_str(&mut self, s: &str) -> fmt::Result { - slice::bytes::copy_memory(self.buf.slice_from_mut(*self.end), + slice::bytes::copy_memory(&mut self.buf[(*self.end)..], s.as_bytes()); *self.end += s.len(); Ok(()) diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index fceb301cc04d..b4e141b9bc75 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -26,12 +26,15 @@ use ops::{Deref, FnOnce}; use result; use slice::SliceExt; use slice; -use str::{self, StrExt, Utf8Error}; +use str::{self, StrExt}; pub use self::num::radix; pub use self::num::Radix; pub use self::num::RadixFmt; +#[cfg(stage0)] pub use self::Debug as Show; +#[cfg(stage0)] pub use self::Display as String; + mod num; mod float; pub mod rt; @@ -48,7 +51,7 @@ pub type Result = result::Result<(), Error>; /// some other means. #[unstable(feature = "core", reason = "core and I/O reconciliation may alter this definition")] -#[derive(Copy)] +#[derive(Copy, Show)] pub struct Error; /// A collection of methods that are required to format a message into a stream. @@ -138,7 +141,7 @@ pub struct Argument<'a> { impl<'a> Argument<'a> { #[inline(never)] fn show_uint(x: &uint, f: &mut Formatter) -> Result { - Show::fmt(x, f) + Display::fmt(x, f) } fn new<'b, T>(x: &'b T, f: fn(&T, &mut Formatter) -> Result) -> Argument<'b> { @@ -221,14 +224,15 @@ pub struct Arguments<'a> { args: &'a [Argument<'a>], } -impl<'a> Show for Arguments<'a> { +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a> Debug for Arguments<'a> { fn fmt(&self, fmt: &mut Formatter) -> Result { - String::fmt(self, fmt) + Display::fmt(self, fmt) } } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a> String for Arguments<'a> { +impl<'a> Display for Arguments<'a> { fn fmt(&self, fmt: &mut Formatter) -> Result { write(fmt.buf, *self) } @@ -238,20 +242,52 @@ impl<'a> String for Arguments<'a> { /// should implement this. #[unstable(feature = "core", reason = "I/O and core have yet to be reconciled")] +#[deprecated(since = "1.0.0", reason = "renamed to Debug")] +#[cfg(not(stage0))] pub trait Show { /// Formats the value using the given formatter. fn fmt(&self, &mut Formatter) -> Result; } +/// Format trait for the `:?` format. Useful for debugging, most all types +/// should implement this. +#[unstable(feature = "core", + reason = "I/O and core have yet to be reconciled")] +pub trait Debug { + /// Formats the value using the given formatter. + fn fmt(&self, &mut Formatter) -> Result; +} + +#[cfg(not(stage0))] +impl Debug for T { + #[allow(deprecated)] + fn fmt(&self, f: &mut Formatter) -> Result { Show::fmt(self, f) } +} + +/// When a value can be semantically expressed as a String, this trait may be +/// used. It corresponds to the default format, `{}`. +#[unstable(feature = "core")] +#[deprecated(since = "1.0.0", reason = "renamed to Display")] +#[cfg(not(stage0))] +pub trait String { + /// Formats the value using the given formatter. + fn fmt(&self, &mut Formatter) -> Result; +} + /// When a value can be semantically expressed as a String, this trait may be /// used. It corresponds to the default format, `{}`. #[unstable(feature = "core", reason = "I/O and core have yet to be reconciled")] -pub trait String { +pub trait Display { /// Formats the value using the given formatter. fn fmt(&self, &mut Formatter) -> Result; } +#[cfg(not(stage0))] +impl Display for T { + #[allow(deprecated)] + fn fmt(&self, f: &mut Formatter) -> Result { String::fmt(self, f) } +} /// Format trait for the `o` character #[unstable(feature = "core", @@ -605,9 +641,10 @@ impl<'a> Formatter<'a> { pub fn precision(&self) -> Option { self.precision } } -impl Show for Error { +#[stable(feature = "rust1", since = "1.0.0")] +impl Display for Error { fn fmt(&self, f: &mut Formatter) -> Result { - String::fmt("an error occurred when formatting an argument", f) + Display::fmt("an error occurred when formatting an argument", f) } } @@ -635,9 +672,11 @@ pub fn argumentuint<'a>(s: &'a uint) -> Argument<'a> { macro_rules! fmt_refs { ($($tr:ident),*) => { $( + #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T: ?Sized + $tr> $tr for &'a T { fn fmt(&self, f: &mut Formatter) -> Result { $tr::fmt(&**self, f) } } + #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T: ?Sized + $tr> $tr for &'a mut T { fn fmt(&self, f: &mut Formatter) -> Result { $tr::fmt(&**self, f) } } @@ -645,22 +684,24 @@ macro_rules! fmt_refs { } } -fmt_refs! { Show, String, Octal, Binary, LowerHex, UpperHex, LowerExp, UpperExp } +fmt_refs! { Debug, Display, Octal, Binary, LowerHex, UpperHex, LowerExp, UpperExp } -impl Show for bool { +#[stable(feature = "rust1", since = "1.0.0")] +impl Debug for bool { fn fmt(&self, f: &mut Formatter) -> Result { - String::fmt(self, f) + Display::fmt(self, f) } } #[stable(feature = "rust1", since = "1.0.0")] -impl String for bool { +impl Display for bool { fn fmt(&self, f: &mut Formatter) -> Result { - String::fmt(if *self { "true" } else { "false" }, f) + Display::fmt(if *self { "true" } else { "false" }, f) } } -impl Show for str { +#[stable(feature = "rust1", since = "1.0.0")] +impl Debug for str { fn fmt(&self, f: &mut Formatter) -> Result { try!(write!(f, "\"")); for c in self.chars().flat_map(|c| c.escape_default()) { @@ -671,13 +712,14 @@ impl Show for str { } #[stable(feature = "rust1", since = "1.0.0")] -impl String for str { +impl Display for str { fn fmt(&self, f: &mut Formatter) -> Result { f.pad(self) } } -impl Show for char { +#[stable(feature = "rust1", since = "1.0.0")] +impl Debug for char { fn fmt(&self, f: &mut Formatter) -> Result { use char::CharExt; try!(write!(f, "'")); @@ -689,15 +731,16 @@ impl Show for char { } #[stable(feature = "rust1", since = "1.0.0")] -impl String for char { +impl Display for char { fn fmt(&self, f: &mut Formatter) -> Result { let mut utf8 = [0u8; 4]; let amt = self.encode_utf8(&mut utf8).unwrap_or(0); let s: &str = unsafe { mem::transmute(&utf8[..amt]) }; - String::fmt(s, f) + Display::fmt(s, f) } } +#[stable(feature = "rust1", since = "1.0.0")] impl Pointer for *const T { fn fmt(&self, f: &mut Formatter) -> Result { f.flags |= 1 << (rt::FlagAlternate as uint); @@ -707,18 +750,21 @@ impl Pointer for *const T { } } +#[stable(feature = "rust1", since = "1.0.0")] impl Pointer for *mut T { fn fmt(&self, f: &mut Formatter) -> Result { Pointer::fmt(&(*self as *const T), f) } } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> Pointer for &'a T { fn fmt(&self, f: &mut Formatter) -> Result { Pointer::fmt(&(*self as *const T), f) } } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> Pointer for &'a mut T { fn fmt(&self, f: &mut Formatter) -> Result { Pointer::fmt(&(&**self as *const T), f) @@ -727,15 +773,15 @@ impl<'a, T> Pointer for &'a mut T { macro_rules! floating { ($ty:ident) => { - impl Show for $ty { + #[stable(feature = "rust1", since = "1.0.0")] + impl Debug for $ty { fn fmt(&self, fmt: &mut Formatter) -> Result { - try!(String::fmt(self, fmt)); - fmt.write_str(stringify!($ty)) + Display::fmt(self, fmt) } } #[stable(feature = "rust1", since = "1.0.0")] - impl String for $ty { + impl Display for $ty { fn fmt(&self, fmt: &mut Formatter) -> Result { use num::Float; @@ -756,6 +802,7 @@ macro_rules! floating { ($ty:ident) => { } } + #[stable(feature = "rust1", since = "1.0.0")] impl LowerExp for $ty { fn fmt(&self, fmt: &mut Formatter) -> Result { use num::Float; @@ -777,6 +824,7 @@ macro_rules! floating { ($ty:ident) => { } } + #[stable(feature = "rust1", since = "1.0.0")] impl UpperExp for $ty { fn fmt(&self, fmt: &mut Formatter) -> Result { use num::Float; @@ -801,12 +849,14 @@ macro_rules! floating { ($ty:ident) => { floating! { f32 } floating! { f64 } -// Implementation of Show for various core types +// Implementation of Display/Debug for various core types -impl Show for *const T { +#[stable(feature = "rust1", since = "1.0.0")] +impl Debug for *const T { fn fmt(&self, f: &mut Formatter) -> Result { Pointer::fmt(self, f) } } -impl Show for *mut T { +#[stable(feature = "rust1", since = "1.0.0")] +impl Debug for *mut T { fn fmt(&self, f: &mut Formatter) -> Result { Pointer::fmt(self, f) } } @@ -817,7 +867,8 @@ macro_rules! peel { macro_rules! tuple { () => (); ( $($name:ident,)+ ) => ( - impl<$($name:Show),*> Show for ($($name,)*) { + #[stable(feature = "rust1", since = "1.0.0")] + impl<$($name:Debug),*> Debug for ($($name,)*) { #[allow(non_snake_case, unused_assignments)] fn fmt(&self, f: &mut Formatter) -> Result { try!(write!(f, "(")); @@ -842,11 +893,13 @@ macro_rules! tuple { tuple! { T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, } -impl<'a> Show for &'a (any::Any+'a) { +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a> Debug for &'a (any::Any+'a) { fn fmt(&self, f: &mut Formatter) -> Result { f.pad("&Any") } } -impl Show for [T] { +#[stable(feature = "rust1", since = "1.0.0")] +impl Debug for [T] { fn fmt(&self, f: &mut Formatter) -> Result { if f.flags & (1 << (rt::FlagAlternate as uint)) == 0 { try!(write!(f, "[")); @@ -867,20 +920,22 @@ impl Show for [T] { } } -impl Show for () { +#[stable(feature = "rust1", since = "1.0.0")] +impl Debug for () { fn fmt(&self, f: &mut Formatter) -> Result { f.pad("()") } } -impl Show for Cell { +#[stable(feature = "rust1", since = "1.0.0")] +impl Debug for Cell { fn fmt(&self, f: &mut Formatter) -> Result { write!(f, "Cell {{ value: {:?} }}", self.get()) } } -#[unstable(feature = "core")] -impl Show for RefCell { +#[stable(feature = "rust1", since = "1.0.0")] +impl Debug for RefCell { fn fmt(&self, f: &mut Formatter) -> Result { match self.try_borrow() { Some(val) => write!(f, "RefCell {{ value: {:?} }}", val), @@ -889,29 +944,17 @@ impl Show for RefCell { } } -impl<'b, T: Show> Show for Ref<'b, T> { +#[stable(feature = "rust1", since = "1.0.0")] +impl<'b, T: Debug> Debug for Ref<'b, T> { fn fmt(&self, f: &mut Formatter) -> Result { - Show::fmt(&**self, f) - } -} - -impl<'b, T: Show> Show for RefMut<'b, T> { - fn fmt(&self, f: &mut Formatter) -> Result { - Show::fmt(&*(self.deref()), f) + Debug::fmt(&**self, f) } } #[stable(feature = "rust1", since = "1.0.0")] -impl String for Utf8Error { +impl<'b, T: Debug> Debug for RefMut<'b, T> { fn fmt(&self, f: &mut Formatter) -> Result { - match *self { - Utf8Error::InvalidByte(n) => { - write!(f, "invalid utf-8: invalid byte at index {}", n) - } - Utf8Error::TooShort => { - write!(f, "invalid utf-8: byte slice too short") - } - } + Debug::fmt(&*(self.deref()), f) } } diff --git a/src/libcore/fmt/num.rs b/src/libcore/fmt/num.rs index 83397e5dc99a..47da8d0c419b 100644 --- a/src/libcore/fmt/num.rs +++ b/src/libcore/fmt/num.rs @@ -157,13 +157,14 @@ pub fn radix(x: T, base: u8) -> RadixFmt { macro_rules! radix_fmt { ($T:ty as $U:ty, $fmt:ident, $S:expr) => { - impl fmt::Show for RadixFmt<$T, Radix> { + #[stable(feature = "rust1", since = "1.0.0")] + impl fmt::Debug for RadixFmt<$T, Radix> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - try!(fmt::String::fmt(self, f)); - f.write_str($S) + fmt::Display::fmt(self, f) } } - impl fmt::String for RadixFmt<$T, Radix> { + #[stable(feature = "rust1", since = "1.0.0")] + impl fmt::Display for RadixFmt<$T, Radix> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { RadixFmt(ref x, radix) => radix.$fmt(*x as $U, f) } } @@ -172,6 +173,7 @@ macro_rules! radix_fmt { } macro_rules! int_base { ($Trait:ident for $T:ident as $U:ident -> $Radix:ident) => { + #[stable(feature = "rust1", since = "1.0.0")] impl fmt::$Trait for $T { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { $Radix.fmt_int(*self as $U, f) @@ -182,10 +184,10 @@ macro_rules! int_base { macro_rules! show { ($T:ident with $S:expr) => { - impl fmt::Show for $T { + #[stable(feature = "rust1", since = "1.0.0")] + impl fmt::Debug for $T { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - try!(fmt::String::fmt(self, f)); - f.write_str($S) + fmt::Display::fmt(self, f) } } } @@ -195,7 +197,7 @@ macro_rules! integer { integer! { $Int, $Uint, stringify!($Int), stringify!($Uint) } }; ($Int:ident, $Uint:ident, $SI:expr, $SU:expr) => { - int_base! { String for $Int as $Int -> Decimal } + int_base! { Display for $Int as $Int -> Decimal } int_base! { Binary for $Int as $Uint -> Binary } int_base! { Octal for $Int as $Uint -> Octal } int_base! { LowerHex for $Int as $Uint -> LowerHex } @@ -203,7 +205,7 @@ macro_rules! integer { radix_fmt! { $Int as $Int, fmt_int, $SI } show! { $Int with $SI } - int_base! { String for $Uint as $Uint -> Decimal } + int_base! { Display for $Uint as $Uint -> Decimal } int_base! { Binary for $Uint as $Uint -> Binary } int_base! { Octal for $Uint as $Uint -> Octal } int_base! { LowerHex for $Uint as $Uint -> LowerHex } diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index c48df72e446d..dd6b1e7b4e83 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -44,8 +44,6 @@ use marker::Sized; -#[cfg(stage0)] use any::TypeId; - pub type GlueFn = extern "Rust" fn(*const i8); #[lang="ty_desc"] @@ -208,12 +206,8 @@ extern "rust-intrinsic" { /// Gets an identifier which is globally unique to the specified type. This /// function will return the same value for a type regardless of whichever /// crate it is invoked in. - #[cfg(not(stage0))] pub fn type_id() -> u64; - #[cfg(stage0)] - pub fn type_id() -> TypeId; - /// Create a value initialized to zero. /// /// `init` is unsafe because it returns a zeroed-out datum, diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index 9cf6d6ac64ec..8289c7403d29 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -32,7 +32,7 @@ //! into a `loop`, for example, the `for` loop in this example is essentially //! translated to the `loop` below. //! -//! ```rust +//! ``` //! let values = vec![1i, 2, 3]; //! //! // "Syntactical sugar" taking advantage of an iterator @@ -68,7 +68,7 @@ use ops::{Add, Deref, FnMut}; use option::Option; use option::Option::{Some, None}; use std::marker::Sized; -use uint; +use usize; /// An interface for dealing with "external iterators". These types of iterators /// can be resumed at any time as all state is stored internally as opposed to @@ -93,10 +93,24 @@ pub trait Iterator { /// Returns a lower and upper bound on the remaining length of the iterator. /// /// An upper bound of `None` means either there is no known upper bound, or the upper bound - /// does not fit within a `uint`. + /// does not fit within a `usize`. #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn size_hint(&self) -> (uint, Option) { (0, None) } + fn size_hint(&self) -> (usize, Option) { (0, None) } +} + +// FIXME(#21363) remove `old_impl_check` when bug is fixed +#[old_impl_check] +impl<'a, T> Iterator for &'a mut (Iterator + 'a) { + type Item = T; + + fn next(&mut self) -> Option { + (**self).next() + } + + fn size_hint(&self) -> (usize, Option) { + (**self).size_hint() + } } /// Conversion from an `Iterator` @@ -121,26 +135,25 @@ pub trait Extend { pub trait IteratorExt: Iterator + Sized { /// Counts the number of elements in this iterator. /// - /// # Example + /// # Examples /// - /// ```rust - /// let a = [1i, 2, 3, 4, 5]; - /// let mut it = a.iter(); - /// assert!(it.count() == 5); + /// ``` + /// let a = [1, 2, 3, 4, 5]; + /// assert_eq!(a.iter().count(), 5); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn count(self) -> uint { + fn count(self) -> usize { self.fold(0, |cnt, _x| cnt + 1) } /// Loops through the entire iterator, returning the last element of the /// iterator. /// - /// # Example + /// # Examples /// - /// ```rust - /// let a = [1i, 2, 3, 4, 5]; + /// ``` + /// let a = [1, 2, 3, 4, 5]; /// assert!(a.iter().last().unwrap() == &5); /// ``` #[inline] @@ -154,17 +167,17 @@ pub trait IteratorExt: Iterator + Sized { /// Loops through `n` iterations, returning the `n`th element of the /// iterator. /// - /// # Example + /// # Examples /// - /// ```rust - /// let a = [1i, 2, 3, 4, 5]; + /// ``` + /// let a = [1, 2, 3, 4, 5]; /// let mut it = a.iter(); /// assert!(it.nth(2).unwrap() == &3); /// assert!(it.nth(2) == None); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn nth(&mut self, mut n: uint) -> Option { + fn nth(&mut self, mut n: usize) -> Option { for x in *self { if n == 0 { return Some(x) } n -= 1; @@ -176,11 +189,11 @@ pub trait IteratorExt: Iterator + Sized { /// finish iterating over the current iterator, and then iterate /// over the other specified iterator. /// - /// # Example + /// # Examples /// - /// ```rust - /// let a = [0i]; - /// let b = [1i]; + /// ``` + /// let a = [0]; + /// let b = [1]; /// let mut it = a.iter().chain(b.iter()); /// assert_eq!(it.next().unwrap(), &0); /// assert_eq!(it.next().unwrap(), &1); @@ -199,14 +212,13 @@ pub trait IteratorExt: Iterator + Sized { /// either iterator returns None, all further invocations of next() will /// return None. /// - /// # Example + /// # Examples /// - /// ```rust - /// let a = [0i]; - /// let b = [1i]; + /// ``` + /// let a = [0]; + /// let b = [1]; /// let mut it = a.iter().zip(b.iter()); - /// let (x0, x1) = (0i, 1i); - /// assert_eq!(it.next().unwrap(), (&x0, &x1)); + /// assert_eq!(it.next().unwrap(), (&0, &1)); /// assert!(it.next().is_none()); /// ``` #[inline] @@ -220,10 +232,10 @@ pub trait IteratorExt: Iterator + Sized { /// Creates a new iterator that will apply the specified function to each /// element returned by the first, yielding the mapped element instead. /// - /// # Example + /// # Examples /// - /// ```rust - /// let a = [1i, 2]; + /// ``` + /// let a = [1, 2]; /// let mut it = a.iter().map(|&x| 2 * x); /// assert_eq!(it.next().unwrap(), 2); /// assert_eq!(it.next().unwrap(), 4); @@ -238,13 +250,13 @@ pub trait IteratorExt: Iterator + Sized { } /// Creates an iterator that applies the predicate to each element returned - /// by this iterator. Only elements that have the predicate evaluate to - /// `true` will be yielded. + /// by this iterator. The only elements that will be yieled are those that + /// make the predicate evaluate to `true`. /// - /// # Example + /// # Examples /// - /// ```rust - /// let a = [1i, 2]; + /// ``` + /// let a = [1, 2]; /// let mut it = a.iter().filter(|&x| *x > 1); /// assert_eq!(it.next().unwrap(), &2); /// assert!(it.next().is_none()); @@ -261,10 +273,10 @@ pub trait IteratorExt: Iterator + Sized { /// If the specified function returns None, the element is skipped. /// Otherwise the option is unwrapped and the new value is yielded. /// - /// # Example + /// # Examples /// - /// ```rust - /// let a = [1i, 2]; + /// ``` + /// let a = [1, 2]; /// let mut it = a.iter().filter_map(|&x| if x > 1 {Some(2 * x)} else {None}); /// assert_eq!(it.next().unwrap(), 4); /// assert!(it.next().is_none()); @@ -280,14 +292,13 @@ pub trait IteratorExt: Iterator + Sized { /// Creates an iterator that yields a pair of the value returned by this /// iterator plus the current index of iteration. /// - /// # Example + /// # Examples /// - /// ```rust - /// let a = [100i, 200]; + /// ``` + /// let a = [100, 200]; /// let mut it = a.iter().enumerate(); - /// let (x100, x200) = (100i, 200i); - /// assert_eq!(it.next().unwrap(), (0, &x100)); - /// assert_eq!(it.next().unwrap(), (1, &x200)); + /// assert_eq!(it.next().unwrap(), (0, &100)); + /// assert_eq!(it.next().unwrap(), (1, &200)); /// assert!(it.next().is_none()); /// ``` #[inline] @@ -299,10 +310,10 @@ pub trait IteratorExt: Iterator + Sized { /// Creates an iterator that has a `.peek()` method /// that returns an optional reference to the next element. /// - /// # Example + /// # Examples /// - /// ```rust - /// let xs = [100i, 200, 300]; + /// ``` + /// let xs = [100, 200, 300]; /// let mut it = xs.iter().map(|x| *x).peekable(); /// assert_eq!(*it.peek().unwrap(), 100); /// assert_eq!(it.next().unwrap(), 100); @@ -323,14 +334,14 @@ pub trait IteratorExt: Iterator + Sized { /// until it returns false. Once the predicate returns false, that /// element and all further elements are yielded. /// - /// # Example + /// # Examples /// - /// ```rust - /// let a = [1i, 2, 3, 2, 1]; + /// ``` + /// let a = [1, 2, 3, 4, 5]; /// let mut it = a.iter().skip_while(|&a| *a < 3); /// assert_eq!(it.next().unwrap(), &3); - /// assert_eq!(it.next().unwrap(), &2); - /// assert_eq!(it.next().unwrap(), &1); + /// assert_eq!(it.next().unwrap(), &4); + /// assert_eq!(it.next().unwrap(), &5); /// assert!(it.next().is_none()); /// ``` #[inline] @@ -345,10 +356,10 @@ pub trait IteratorExt: Iterator + Sized { /// returns true. After the predicate returns false for the first time, no /// further elements will be yielded. /// - /// # Example + /// # Examples /// - /// ```rust - /// let a = [1i, 2, 3, 2, 1]; + /// ``` + /// let a = [1, 2, 3, 4, 5]; /// let mut it = a.iter().take_while(|&a| *a < 3); /// assert_eq!(it.next().unwrap(), &1); /// assert_eq!(it.next().unwrap(), &2); @@ -365,10 +376,10 @@ pub trait IteratorExt: Iterator + Sized { /// Creates an iterator that skips the first `n` elements of this iterator, /// and then yields all further items. /// - /// # Example + /// # Examples /// - /// ```rust - /// let a = [1i, 2, 3, 4, 5]; + /// ``` + /// let a = [1, 2, 3, 4, 5]; /// let mut it = a.iter().skip(3); /// assert_eq!(it.next().unwrap(), &4); /// assert_eq!(it.next().unwrap(), &5); @@ -376,17 +387,17 @@ pub trait IteratorExt: Iterator + Sized { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn skip(self, n: uint) -> Skip { + fn skip(self, n: usize) -> Skip { Skip{iter: self, n: n} } /// Creates an iterator that yields the first `n` elements of this - /// iterator, and then will always return None. + /// iterator. /// - /// # Example + /// # Examples /// - /// ```rust - /// let a = [1i, 2, 3, 4, 5]; + /// ``` + /// let a = [1, 2, 3, 4, 5]; /// let mut it = a.iter().take(3); /// assert_eq!(it.next().unwrap(), &1); /// assert_eq!(it.next().unwrap(), &2); @@ -395,7 +406,7 @@ pub trait IteratorExt: Iterator + Sized { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn take(self, n: uint) -> Take { + fn take(self, n: usize) -> Take { Take{iter: self, n: n} } @@ -404,10 +415,10 @@ pub trait IteratorExt: Iterator + Sized { /// mutated as necessary. The yielded values from the closure are yielded /// from the Scan instance when not None. /// - /// # Example + /// # Examples /// - /// ```rust - /// let a = [1i, 2, 3, 4, 5]; + /// ``` + /// let a = [1, 2, 3, 4, 5]; /// let mut it = a.iter().scan(1, |fac, &x| { /// *fac = *fac * x; /// Some(*fac) @@ -432,21 +443,17 @@ pub trait IteratorExt: Iterator + Sized { } /// Creates an iterator that maps each element to an iterator, - /// and yields the elements of the produced iterators + /// and yields the elements of the produced iterators. /// - /// # Example + /// # Examples /// - /// ```rust - /// use std::iter::count; - /// - /// let xs = [2u, 3]; - /// let ys = [0u, 1, 0, 1, 2]; - /// let mut it = xs.iter().flat_map(|&x| count(0u, 1).take(x)); + /// ``` + /// let xs = [2, 3]; + /// let ys = [0, 1, 0, 1, 2]; + /// let it = xs.iter().flat_map(|&x| std::iter::count(0, 1).take(x)); /// // Check that `it` has the same elements as `ys` - /// let mut i = 0; - /// for x in it { + /// for (i, x) in it.enumerate() { /// assert_eq!(x, ys[i]); - /// i += 1; /// } /// ``` #[inline] @@ -462,10 +469,10 @@ pub trait IteratorExt: Iterator + Sized { /// iterator yields `None`. Random-access iterator behavior is not /// affected, only single and double-ended iterator behavior. /// - /// # Example + /// # Examples /// - /// ```rust - /// fn process>(it: U) -> int { + /// ``` + /// fn process>(it: U) -> isize { /// let mut it = it.fuse(); /// let mut sum = 0; /// for x in it { @@ -480,9 +487,9 @@ pub trait IteratorExt: Iterator + Sized { /// } /// sum /// } - /// let x = vec![1i,2,3,7,8,9]; + /// let x = vec![1, 2, 3, 7, 8, 9]; /// assert_eq!(process(x.into_iter()), 6); - /// let x = vec![1i,2,3]; + /// let x = vec![1, 2, 3]; /// assert_eq!(process(x.into_iter()), 1006); /// ``` #[inline] @@ -495,13 +502,13 @@ pub trait IteratorExt: Iterator + Sized { /// element before yielding it. This is often useful for debugging an /// iterator pipeline. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` /// use std::iter::AdditiveIterator; /// - /// let xs = [1u, 4, 2, 3, 8, 9, 6]; - /// let sum = xs.iter() + /// let a = [1, 4, 2, 3, 8, 9, 6]; + /// let sum = a.iter() /// .map(|&x| x) /// .inspect(|&x| println!("filtering {}", x)) /// .filter(|&x| x % 2 == 0) @@ -522,15 +529,14 @@ pub trait IteratorExt: Iterator + Sized { /// This is useful to allow applying iterator adaptors while still /// retaining ownership of the original iterator value. /// - /// # Example + /// # Examples /// - /// ```rust - /// let mut xs = range(0u, 10); + /// ``` + /// let mut it = 0..10; /// // sum the first five values - /// let partial_sum = xs.by_ref().take(5).fold(0, |a, b| a + b); + /// let partial_sum = it.by_ref().take(5).fold(0, |a, b| a + b); /// assert!(partial_sum == 10); - /// // xs.next() is now `5` - /// assert!(xs.next() == Some(5)); + /// assert!(it.next() == Some(5)); /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn by_ref<'r>(&'r mut self) -> ByRef<'r, Self> { @@ -540,12 +546,12 @@ pub trait IteratorExt: Iterator + Sized { /// Loops through the entire iterator, collecting all of the elements into /// a container implementing `FromIterator`. /// - /// # Example + /// # Examples /// - /// ```rust - /// let a = [1i, 2, 3, 4, 5]; - /// let b: Vec = a.iter().map(|&x| x).collect(); - /// assert!(a.as_slice() == b.as_slice()); + /// ``` + /// let a = [1, 2, 3, 4, 5]; + /// let b: Vec<_> = a.iter().map(|&x| x).collect(); + /// assert_eq!(a, b); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -559,8 +565,8 @@ pub trait IteratorExt: Iterator + Sized { /// do not. /// /// ``` - /// let vec = vec![1i, 2i, 3i, 4i]; - /// let (even, odd): (Vec, Vec) = vec.into_iter().partition(|&n| n % 2 == 0); + /// let vec = vec![1, 2, 3, 4]; + /// let (even, odd): (Vec<_>, Vec<_>) = vec.into_iter().partition(|&n| n % 2 == 0); /// assert_eq!(even, vec![2, 4]); /// assert_eq!(odd, vec![1, 3]); /// ``` @@ -587,10 +593,10 @@ pub trait IteratorExt: Iterator + Sized { /// Performs a fold operation over the entire iterator, returning the /// eventual state at the end of the iteration. /// - /// # Example + /// # Examples /// - /// ```rust - /// let a = [1i, 2, 3, 4, 5]; + /// ``` + /// let a = [1, 2, 3, 4, 5]; /// assert!(a.iter().fold(0, |a, &b| a + b) == 15); /// ``` #[inline] @@ -607,9 +613,9 @@ pub trait IteratorExt: Iterator + Sized { /// Tests whether the predicate holds true for all elements in the iterator. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` /// let a = [1i, 2, 3, 4, 5]; /// assert!(a.iter().all(|x| *x > 0)); /// assert!(!a.iter().all(|x| *x > 2)); @@ -621,16 +627,18 @@ pub trait IteratorExt: Iterator + Sized { true } - /// Tests whether any element of an iterator satisfies the specified - /// predicate. + /// Tests whether any element of an iterator satisfies the specified predicate. /// - /// # Example + /// Does not consume the iterator past the first found element. /// - /// ```rust - /// let a = [1i, 2, 3, 4, 5]; + /// # Examples + /// + /// ``` + /// let a = [1, 2, 3, 4, 5]; /// let mut it = a.iter(); /// assert!(it.any(|x| *x == 3)); - /// assert!(!it.any(|x| *x == 3)); + /// assert_eq!(it.as_slice(), [4, 5]); + /// /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -642,6 +650,14 @@ pub trait IteratorExt: Iterator + Sized { /// Returns the first element satisfying the specified predicate. /// /// Does not consume the iterator past the first found element. + /// + /// # Examples + /// + /// ``` + /// let a = [1, 2, 3, 4, 5]; + /// let mut it = a.iter(); + /// assert_eq!(it.find(|&x| *x == 3).unwrap(), &3); + /// assert_eq!(it.as_slice(), [4, 5]); #[inline] #[stable(feature = "rust1", since = "1.0.0")] fn find

(&mut self, mut predicate: P) -> Option where @@ -654,9 +670,19 @@ pub trait IteratorExt: Iterator + Sized { } /// Return the index of the first element satisfying the specified predicate + /// + /// Does not consume the iterator past the first found element. + /// + /// # Examples + /// + /// ``` + /// let a = [1, 2, 3, 4, 5]; + /// let mut it = a.iter(); + /// assert_eq!(it.position(|x| *x == 3).unwrap(), 2); + /// assert_eq!(it.as_slice(), [4, 5]); #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn position

(&mut self, mut predicate: P) -> Option where + fn position

(&mut self, mut predicate: P) -> Option where P: FnMut(Self::Item) -> bool, { let mut i = 0; @@ -672,9 +698,19 @@ pub trait IteratorExt: Iterator + Sized { /// Return the index of the last element satisfying the specified predicate /// /// If no element matches, None is returned. + /// + /// Does not consume the iterator *before* the first found element. + /// + /// # Examples + /// + /// ``` + /// let a = [1, 2, 2, 4, 5]; + /// let mut it = a.iter(); + /// assert_eq!(it.rposition(|x| *x == 2).unwrap(), 2); + /// assert_eq!(it.as_slice(), [1, 2]); #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn rposition

(&mut self, mut predicate: P) -> Option where + fn rposition

(&mut self, mut predicate: P) -> Option where P: FnMut(Self::Item) -> bool, Self: ExactSizeIterator + DoubleEndedIterator { @@ -689,10 +725,10 @@ pub trait IteratorExt: Iterator + Sized { /// Consumes the entire iterator to return the maximum element. /// - /// # Example + /// # Examples /// - /// ```rust - /// let a = [1i, 2, 3, 4, 5]; + /// ``` + /// let a = [1, 2, 3, 4, 5]; /// assert!(a.iter().max().unwrap() == &5); /// ``` #[inline] @@ -709,10 +745,10 @@ pub trait IteratorExt: Iterator + Sized { /// Consumes the entire iterator to return the minimum element. /// - /// # Example + /// # Examples /// - /// ```rust - /// let a = [1i, 2, 3, 4, 5]; + /// ``` + /// let a = [1, 2, 3, 4, 5]; /// assert!(a.iter().min().unwrap() == &1); /// ``` #[inline] @@ -740,25 +776,22 @@ pub trait IteratorExt: Iterator + Sized { /// On an iterator of length `n`, `min_max` does `1.5 * n` comparisons, /// and so is faster than calling `min` and `max` separately which does `2 * n` comparisons. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` /// use std::iter::MinMaxResult::{NoElements, OneElement, MinMax}; /// - /// let v: [int; 0] = []; - /// assert_eq!(v.iter().min_max(), NoElements); + /// let a: [isize; 0] = []; + /// assert_eq!(a.iter().min_max(), NoElements); /// - /// let v = [1i]; - /// assert!(v.iter().min_max() == OneElement(&1)); + /// let a = [1]; + /// assert!(a.iter().min_max() == OneElement(&1)); /// - /// let v = [1i, 2, 3, 4, 5]; - /// assert!(v.iter().min_max() == MinMax(&1, &5)); + /// let a = [1, 2, 3, 4, 5]; + /// assert!(a.iter().min_max() == MinMax(&1, &5)); /// - /// let v = [1i, 2, 3, 4, 5, 6]; - /// assert!(v.iter().min_max() == MinMax(&1, &6)); - /// - /// let v = [1i, 1, 1, 1]; - /// assert!(v.iter().min_max() == MinMax(&1, &1)); + /// let a = [1, 1, 1, 1]; + /// assert!(a.iter().min_max() == MinMax(&1, &1)); /// ``` #[unstable(feature = "core", reason = "return type may change")] fn min_max(mut self) -> MinMaxResult where Self::Item: Ord @@ -808,13 +841,13 @@ pub trait IteratorExt: Iterator + Sized { /// Return the element that gives the maximum value from the /// specified function. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` /// use core::num::SignedInt; /// - /// let xs = [-3i, 0, 1, 5, -10]; - /// assert_eq!(*xs.iter().max_by(|x| x.abs()).unwrap(), -10); + /// let a = [-3, 0, 1, 5, -10]; + /// assert_eq!(*a.iter().max_by(|x| x.abs()).unwrap(), -10); /// ``` #[inline] #[unstable(feature = "core", @@ -838,13 +871,13 @@ pub trait IteratorExt: Iterator + Sized { /// Return the element that gives the minimum value from the /// specified function. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` /// use core::num::SignedInt; /// - /// let xs = [-3i, 0, 1, 5, -10]; - /// assert_eq!(*xs.iter().min_by(|x| x.abs()).unwrap(), 0); + /// let a = [-3, 0, 1, 5, -10]; + /// assert_eq!(*a.iter().min_by(|x| x.abs()).unwrap(), 0); /// ``` #[inline] #[unstable(feature = "core", @@ -876,7 +909,7 @@ pub trait IteratorExt: Iterator + Sized { /// of the original iterator. /// /// Note: Random access with flipped indices still only applies to the first - /// `uint::MAX` elements of the original iterator. + /// `std::usize::MAX` elements of the original iterator. #[inline] #[stable(feature = "rust1", since = "1.0.0")] fn rev(self) -> Rev { @@ -887,18 +920,27 @@ pub trait IteratorExt: Iterator + Sized { /// /// Loops through the entire iterator, collecting the first component of /// each item into one new container, and the second component into another. + /// + /// # Examples + /// + /// ``` + /// let a = [(1, 2), (3, 4)]; + /// let (left, right): (Vec<_>, Vec<_>) = a.iter().map(|&x| x).unzip(); + /// assert_eq!([1, 3], left); + /// assert_eq!([2, 4], right); + /// ``` #[unstable(feature = "core", reason = "recent addition")] fn unzip(mut self) -> (FromA, FromB) where FromA: Default + Extend, FromB: Default + Extend, Self: Iterator, { - struct SizeHint(uint, Option); + struct SizeHint(usize, Option); impl Iterator for SizeHint { type Item = A; fn next(&mut self) -> Option { None } - fn size_hint(&self) -> (uint, Option) { + fn size_hint(&self) -> (usize, Option) { (self.0, self.1) } } @@ -931,15 +973,14 @@ pub trait IteratorExt: Iterator + Sized { /// Repeats an iterator endlessly /// - /// # Example + /// # Examples /// - /// ```rust - /// use std::iter::count; - /// - /// let a = count(1i,1i).take(1); - /// let mut cy = a.cycle(); - /// assert_eq!(cy.next(), Some(1)); - /// assert_eq!(cy.next(), Some(1)); + /// ``` + /// let a = [1, 2]; + /// let mut it = a.iter().cycle(); + /// assert_eq!(it.next().unwrap(), &1); + /// assert_eq!(it.next().unwrap(), &2); + /// assert_eq!(it.next().unwrap(), &1); /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -976,7 +1017,7 @@ pub trait DoubleEndedIterator: Iterator { fn next_back(&mut self) -> Option; } -/// An object implementing random access indexing by `uint` +/// An object implementing random access indexing by `usize` /// /// A `RandomAccessIterator` should be either infinite or a `DoubleEndedIterator`. /// Calling `next()` or `next_back()` on a `RandomAccessIterator` @@ -985,12 +1026,12 @@ pub trait DoubleEndedIterator: Iterator { #[unstable(feature = "core", reason = "not widely used, may be better decomposed into Index and ExactSizeIterator")] pub trait RandomAccessIterator: Iterator { - /// Return the number of indexable elements. At most `std::uint::MAX` + /// Return the number of indexable elements. At most `std::usize::MAX` /// elements are indexable, even if the iterator represents a longer range. - fn indexable(&self) -> uint; + fn indexable(&self) -> usize; /// Return an element at an index, or `None` if the index is out of bounds - fn idx(&mut self, index: uint) -> Option; + fn idx(&mut self, index: usize) -> Option; } /// An iterator that knows its exact length @@ -999,12 +1040,12 @@ pub trait RandomAccessIterator: Iterator { /// it can support double-ended enumeration. /// /// `Iterator::size_hint` *must* return the exact size of the iterator. -/// Note that the size must fit in `uint`. +/// Note that the size must fit in `usize`. #[stable(feature = "rust1", since = "1.0.0")] pub trait ExactSizeIterator: Iterator { #[inline] /// Return the exact length of the iterator. - fn len(&self) -> uint { + fn len(&self) -> usize { let (lower, upper) = self.size_hint(); // Note: This assertion is overly defensive, but it checks the invariant // guaranteed by the trait. If this trait were rust-internal, @@ -1049,7 +1090,7 @@ impl Iterator for Rev where I: DoubleEndedIterator { #[inline] fn next(&mut self) -> Option<::Item> { self.iter.next_back() } #[inline] - fn size_hint(&self) -> (uint, Option) { self.iter.size_hint() } + fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1061,9 +1102,9 @@ impl DoubleEndedIterator for Rev where I: DoubleEndedIterator { #[unstable(feature = "core", reason = "trait is experimental")] impl RandomAccessIterator for Rev where I: DoubleEndedIterator + RandomAccessIterator { #[inline] - fn indexable(&self) -> uint { self.iter.indexable() } + fn indexable(&self) -> usize { self.iter.indexable() } #[inline] - fn idx(&mut self, index: uint) -> Option<::Item> { + fn idx(&mut self, index: usize) -> Option<::Item> { let amt = self.indexable(); self.iter.idx(amt - index - 1) } @@ -1083,7 +1124,7 @@ impl<'a, I> Iterator for ByRef<'a, I> where I: 'a + Iterator { #[inline] fn next(&mut self) -> Option<::Item> { self.iter.next() } #[inline] - fn size_hint(&self) -> (uint, Option) { self.iter.size_hint() } + fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1092,15 +1133,18 @@ impl<'a, I> DoubleEndedIterator for ByRef<'a, I> where I: 'a + DoubleEndedIterat fn next_back(&mut self) -> Option<::Item> { self.iter.next_back() } } +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, I> ExactSizeIterator for ByRef<'a, I> where I: 'a + ExactSizeIterator {} + /// A trait for iterators over elements which can be added together #[unstable(feature = "core", reason = "needs to be re-evaluated as part of numerics reform")] pub trait AdditiveIterator { /// Iterates over the entire iterator, summing up all the elements /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` /// use std::iter::AdditiveIterator; /// /// let a = [1i, 2, 3, 4, 5]; @@ -1125,12 +1169,12 @@ impl_additive! { i8, 0 } impl_additive! { i16, 0 } impl_additive! { i32, 0 } impl_additive! { i64, 0 } -impl_additive! { int, 0 } +impl_additive! { isize, 0 } impl_additive! { u8, 0 } impl_additive! { u16, 0 } impl_additive! { u32, 0 } impl_additive! { u64, 0 } -impl_additive! { uint, 0 } +impl_additive! { usize, 0 } impl_additive! { f32, 0.0 } impl_additive! { f64, 0.0 } @@ -1140,12 +1184,12 @@ impl_additive! { f64, 0.0 } pub trait MultiplicativeIterator { /// Iterates over the entire iterator, multiplying all the elements /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` /// use std::iter::{count, MultiplicativeIterator}; /// - /// fn factorial(n: uint) -> uint { + /// fn factorial(n: usize) -> usize { /// count(1u, 1).take_while(|&i| i <= n).product() /// } /// assert!(factorial(0) == 1); @@ -1170,12 +1214,12 @@ impl_multiplicative! { i8, 1 } impl_multiplicative! { i16, 1 } impl_multiplicative! { i32, 1 } impl_multiplicative! { i64, 1 } -impl_multiplicative! { int, 1 } +impl_multiplicative! { isize, 1 } impl_multiplicative! { u8, 1 } impl_multiplicative! { u16, 1 } impl_multiplicative! { u32, 1 } impl_multiplicative! { u64, 1 } -impl_multiplicative! { uint, 1 } +impl_multiplicative! { usize, 1 } impl_multiplicative! { f32, 1.0 } impl_multiplicative! { f64, 1.0 } @@ -1200,19 +1244,19 @@ impl MinMaxResult { /// `Some(x,y)` is returned where `x <= y`. If `MinMaxResult` has variant `OneElement(x)`, /// performing this operation will make one clone of `x`. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` /// use std::iter::MinMaxResult::{self, NoElements, OneElement, MinMax}; /// - /// let r: MinMaxResult = NoElements; + /// let r: MinMaxResult = NoElements; /// assert_eq!(r.into_option(), None); /// - /// let r = OneElement(1i); - /// assert_eq!(r.into_option(), Some((1,1))); + /// let r = OneElement(1); + /// assert_eq!(r.into_option(), Some((1, 1))); /// - /// let r = MinMax(1i,2i); - /// assert_eq!(r.into_option(), Some((1,2))); + /// let r = MinMax(1, 2); + /// assert_eq!(r.into_option(), Some((1, 2))); /// ``` #[unstable(feature = "core", reason = "type is unstable")] pub fn into_option(self) -> Option<(T,T)> { @@ -1244,7 +1288,7 @@ impl Iterator for Cloned where self.it.next().cloned() } - fn size_hint(&self) -> (uint, Option) { + fn size_hint(&self) -> (usize, Option) { self.it.size_hint() } } @@ -1289,12 +1333,12 @@ impl Iterator for Cycle where I: Clone + Iterator { } #[inline] - fn size_hint(&self) -> (uint, Option) { + fn size_hint(&self) -> (usize, Option) { // the cycle iterator is either empty or infinite match self.orig.size_hint() { sz @ (0, Some(0)) => sz, (0, _) => (0, None), - _ => (uint::MAX, None) + _ => (usize::MAX, None) } } } @@ -1304,16 +1348,16 @@ impl RandomAccessIterator for Cycle where I: Clone + RandomAccessIterator, { #[inline] - fn indexable(&self) -> uint { + fn indexable(&self) -> usize { if self.orig.indexable() > 0 { - uint::MAX + usize::MAX } else { 0 } } #[inline] - fn idx(&mut self, index: uint) -> Option<::Item> { + fn idx(&mut self, index: usize) -> Option<::Item> { let liter = self.iter.indexable(); let lorig = self.orig.indexable(); if lorig == 0 { @@ -1355,7 +1399,7 @@ impl Iterator for Chain where A: Iterator, B: Iterator (uint, Option) { + fn size_hint(&self) -> (usize, Option) { let (a_lower, a_upper) = self.a.size_hint(); let (b_lower, b_upper) = self.b.size_hint(); @@ -1390,13 +1434,13 @@ impl RandomAccessIterator for Chain where B: RandomAccessIterator, { #[inline] - fn indexable(&self) -> uint { + fn indexable(&self) -> usize { let (a, b) = (self.a.indexable(), self.b.indexable()); a.saturating_add(b) } #[inline] - fn idx(&mut self, index: uint) -> Option { + fn idx(&mut self, index: usize) -> Option { let len = self.a.indexable(); if index < len { self.a.idx(index) @@ -1434,7 +1478,7 @@ impl Iterator for Zip where } #[inline] - fn size_hint(&self) -> (uint, Option) { + fn size_hint(&self) -> (usize, Option) { let (a_lower, a_upper) = self.a.size_hint(); let (b_lower, b_upper) = self.b.size_hint(); @@ -1482,12 +1526,12 @@ impl RandomAccessIterator for Zip where B: RandomAccessIterator, { #[inline] - fn indexable(&self) -> uint { + fn indexable(&self) -> usize { cmp::min(self.a.indexable(), self.b.indexable()) } #[inline] - fn idx(&mut self, index: uint) -> Option<(T, U)> { + fn idx(&mut self, index: usize) -> Option<(T, U)> { match self.a.idx(index) { None => None, Some(x) => match self.b.idx(index) { @@ -1541,7 +1585,7 @@ impl Iterator for Map where I: Iterator, F: FnMu } #[inline] - fn size_hint(&self) -> (uint, Option) { + fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } } @@ -1564,12 +1608,12 @@ impl RandomAccessIterator for Map where F: FnMut(A) -> B, { #[inline] - fn indexable(&self) -> uint { + fn indexable(&self) -> usize { self.iter.indexable() } #[inline] - fn idx(&mut self, index: uint) -> Option { + fn idx(&mut self, index: usize) -> Option { let elt = self.iter.idx(index); self.do_map(elt) } @@ -1614,7 +1658,7 @@ impl Iterator for Filter where I: Iterator, P: FnMut(& } #[inline] - fn size_hint(&self) -> (uint, Option) { + fn size_hint(&self) -> (usize, Option) { let (_, upper) = self.iter.size_hint(); (0, upper) // can't know a lower bound, due to the predicate } @@ -1677,7 +1721,7 @@ impl Iterator for FilterMap where } #[inline] - fn size_hint(&self) -> (uint, Option) { + fn size_hint(&self) -> (usize, Option) { let (_, upper) = self.iter.size_hint(); (0, upper) // can't know a lower bound, due to the predicate } @@ -1706,15 +1750,15 @@ impl DoubleEndedIterator for FilterMap where #[stable(feature = "rust1", since = "1.0.0")] pub struct Enumerate { iter: I, - count: uint + count: usize } #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for Enumerate where I: Iterator { - type Item = (uint, ::Item); + type Item = (usize, ::Item); #[inline] - fn next(&mut self) -> Option<(uint, ::Item)> { + fn next(&mut self) -> Option<(usize, ::Item)> { match self.iter.next() { Some(a) => { let ret = Some((self.count, a)); @@ -1726,7 +1770,7 @@ impl Iterator for Enumerate where I: Iterator { } #[inline] - fn size_hint(&self) -> (uint, Option) { + fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } } @@ -1736,7 +1780,7 @@ impl DoubleEndedIterator for Enumerate where I: ExactSizeIterator + DoubleEndedIterator { #[inline] - fn next_back(&mut self) -> Option<(uint, ::Item)> { + fn next_back(&mut self) -> Option<(usize, ::Item)> { match self.iter.next_back() { Some(a) => { let len = self.iter.len(); @@ -1750,12 +1794,12 @@ impl DoubleEndedIterator for Enumerate where #[unstable(feature = "core", reason = "trait is experimental")] impl RandomAccessIterator for Enumerate where I: RandomAccessIterator { #[inline] - fn indexable(&self) -> uint { + fn indexable(&self) -> usize { self.iter.indexable() } #[inline] - fn idx(&mut self, index: uint) -> Option<(uint, ::Item)> { + fn idx(&mut self, index: usize) -> Option<(usize, ::Item)> { match self.iter.idx(index) { Some(a) => Some((self.count + index, a)), _ => None, @@ -1783,7 +1827,7 @@ impl Iterator for Peekable where I: Iterator { } #[inline] - fn size_hint(&self) -> (uint, Option) { + fn size_hint(&self) -> (usize, Option) { let (lo, hi) = self.iter.size_hint(); if self.peeked.is_some() { let lo = lo.saturating_add(1); @@ -1798,6 +1842,9 @@ impl Iterator for Peekable where I: Iterator { } } +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for Peekable where I: ExactSizeIterator {} + #[stable(feature = "rust1", since = "1.0.0")] impl Peekable where I: Iterator { /// Return a reference to the next element of the iterator with out advancing it, @@ -1860,7 +1907,7 @@ impl Iterator for SkipWhile where I: Iterator, P: FnMu } #[inline] - fn size_hint(&self) -> (uint, Option) { + fn size_hint(&self) -> (usize, Option) { let (_, upper) = self.iter.size_hint(); (0, upper) // can't know a lower bound, due to the predicate } @@ -1914,7 +1961,7 @@ impl Iterator for TakeWhile where I: Iterator, P: FnMu } #[inline] - fn size_hint(&self) -> (uint, Option) { + fn size_hint(&self) -> (usize, Option) { let (_, upper) = self.iter.size_hint(); (0, upper) // can't know a lower bound, due to the predicate } @@ -1926,7 +1973,7 @@ impl Iterator for TakeWhile where I: Iterator, P: FnMu #[stable(feature = "rust1", since = "1.0.0")] pub struct Skip { iter: I, - n: uint + n: usize } #[stable(feature = "rust1", since = "1.0.0")] @@ -1959,7 +2006,7 @@ impl Iterator for Skip where I: Iterator { } #[inline] - fn size_hint(&self) -> (uint, Option) { + fn size_hint(&self) -> (usize, Option) { let (lower, upper) = self.iter.size_hint(); let lower = lower.saturating_sub(self.n); @@ -1976,12 +2023,12 @@ impl Iterator for Skip where I: Iterator { #[unstable(feature = "core", reason = "trait is experimental")] impl RandomAccessIterator for Skip where I: RandomAccessIterator{ #[inline] - fn indexable(&self) -> uint { + fn indexable(&self) -> usize { self.iter.indexable().saturating_sub(self.n) } #[inline] - fn idx(&mut self, index: uint) -> Option<::Item> { + fn idx(&mut self, index: usize) -> Option<::Item> { if index >= self.indexable() { None } else { @@ -1990,13 +2037,16 @@ impl RandomAccessIterator for Skip where I: RandomAccessIterator{ } } +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for Skip where I: ExactSizeIterator {} + /// An iterator that only iterates over the first `n` iterations of `iter`. #[derive(Clone)] #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] pub struct Take { iter: I, - n: uint + n: usize } #[stable(feature = "rust1", since = "1.0.0")] @@ -2014,7 +2064,7 @@ impl Iterator for Take where I: Iterator{ } #[inline] - fn size_hint(&self) -> (uint, Option) { + fn size_hint(&self) -> (usize, Option) { let (lower, upper) = self.iter.size_hint(); let lower = cmp::min(lower, self.n); @@ -2031,12 +2081,12 @@ impl Iterator for Take where I: Iterator{ #[unstable(feature = "core", reason = "trait is experimental")] impl RandomAccessIterator for Take where I: RandomAccessIterator{ #[inline] - fn indexable(&self) -> uint { + fn indexable(&self) -> usize { cmp::min(self.iter.indexable(), self.n) } #[inline] - fn idx(&mut self, index: uint) -> Option<::Item> { + fn idx(&mut self, index: usize) -> Option<::Item> { if index >= self.n { None } else { @@ -2045,6 +2095,9 @@ impl RandomAccessIterator for Take where I: RandomAccessIterator{ } } +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for Take where I: ExactSizeIterator {} + /// An iterator to maintain state while iterating another iterator #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] @@ -2086,7 +2139,7 @@ impl Iterator for Scan where } #[inline] - fn size_hint(&self) -> (uint, Option) { + fn size_hint(&self) -> (usize, Option) { let (_, upper) = self.iter.size_hint(); (0, upper) // can't know a lower bound, due to the scan function } @@ -2149,7 +2202,7 @@ impl Iterator for FlatMap where } #[inline] - fn size_hint(&self) -> (uint, Option) { + fn size_hint(&self) -> (usize, Option) { let (flo, fhi) = self.frontiter.as_ref().map_or((0, Some(0)), |it| it.size_hint()); let (blo, bhi) = self.backiter.as_ref().map_or((0, Some(0)), |it| it.size_hint()); let lo = flo.saturating_add(blo); @@ -2213,7 +2266,7 @@ impl Iterator for Fuse where I: Iterator { } #[inline] - fn size_hint(&self) -> (uint, Option) { + fn size_hint(&self) -> (usize, Option) { if self.done { (0, Some(0)) } else { @@ -2244,16 +2297,19 @@ impl DoubleEndedIterator for Fuse where I: DoubleEndedIterator { #[unstable(feature = "core", reason = "trait is experimental")] impl RandomAccessIterator for Fuse where I: RandomAccessIterator { #[inline] - fn indexable(&self) -> uint { + fn indexable(&self) -> usize { self.iter.indexable() } #[inline] - fn idx(&mut self, index: uint) -> Option<::Item> { + fn idx(&mut self, index: usize) -> Option<::Item> { self.iter.idx(index) } } +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for Fuse where I: ExactSizeIterator {} + impl Fuse { /// Resets the fuse such that the next call to .next() or .next_back() will /// call the underlying iterator again even if it previously returned None. @@ -2310,7 +2366,7 @@ impl Iterator for Inspect where I: Iterator, F: FnMut( } #[inline] - fn size_hint(&self) -> (uint, Option) { + fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } } @@ -2333,12 +2389,12 @@ impl RandomAccessIterator for Inspect where F: FnMut(&A), { #[inline] - fn indexable(&self) -> uint { + fn indexable(&self) -> usize { self.iter.indexable() } #[inline] - fn idx(&mut self, index: uint) -> Option { + fn idx(&mut self, index: usize) -> Option { let element = self.iter.idx(index); self.do_inspect(element) } @@ -2350,7 +2406,7 @@ impl RandomAccessIterator for Inspect where /// /// An iterator that yields sequential Fibonacci numbers, and stops on overflow. /// -/// ```rust +/// ``` /// use std::iter::Unfold; /// use std::num::Int; // For `.checked_add()` /// @@ -2420,7 +2476,7 @@ impl Iterator for Unfold where F: FnMut(&mut St) -> Option (uint, Option) { + fn size_hint(&self) -> (usize, Option) { // no possible known bounds at this point (0, None) } @@ -2458,8 +2514,8 @@ impl + Clone> Iterator for Counter { } #[inline] - fn size_hint(&self) -> (uint, Option) { - (uint::MAX, None) // Too bad we can't specify an infinite lower bound + fn size_hint(&self) -> (usize, Option) { + (usize::MAX, None) // Too bad we can't specify an infinite lower bound } } @@ -2476,9 +2532,9 @@ pub struct Range { /// Returns an iterator over the given range [start, stop) (that is, starting /// at start (inclusive), and ending at stop (exclusive)). /// -/// # Example +/// # Examples /// -/// ```rust +/// ``` /// let array = [0, 1, 2, 3, 4]; /// /// for i in range(0, 5u) { @@ -2515,9 +2571,9 @@ impl Iterator for Range { } #[inline] - fn size_hint(&self) -> (uint, Option) { + fn size_hint(&self) -> (usize, Option) { // This first checks if the elements are representable as i64. If they aren't, try u64 (to - // handle cases like range(huge, huger)). We don't use uint/int because the difference of + // handle cases like range(huge, huger)). We don't use usize/isize because the difference of // the i64/u64 might lie within their range. let bound = match self.state.to_i64() { Some(a) => { @@ -2604,7 +2660,7 @@ impl Iterator for RangeInclusive { } #[inline] - fn size_hint(&self) -> (uint, Option) { + fn size_hint(&self) -> (usize, Option) { let (lo, hi) = self.range.size_hint(); if self.done { (lo, hi) @@ -2725,64 +2781,93 @@ impl Iterator for RangeStepInclusive { } } +macro_rules! range_impl { + ($($t:ty)*) => ($( + #[stable(feature = "rust1", since = "1.0.0")] + impl Iterator for ::ops::Range<$t> { + type Item = $t; -/// The `Step` trait identifies objects which can be stepped over in both -/// directions. The `steps_between` function provides a way to -/// compare two Step objects (it could be provided using `step()` and `Ord`, -/// but the implementation would be so inefficient as to be useless). -#[unstable(feature = "core", - reason = "design of range notation/iteration is in flux")] -pub trait Step: Ord { - /// Change self to the next object. - fn step(&mut self); - /// Change self to the previous object. - fn step_back(&mut self); - /// The steps_between two step objects. - /// start should always be less than end, so the result should never be negative. - /// Return None if it is not possible to calculate steps_between without - /// overflow. - fn steps_between(start: &Self, end: &Self) -> Option; + #[inline] + fn next(&mut self) -> Option<$t> { + if self.start < self.end { + let result = self.start; + self.start += 1; + return Some(result); + } + + return None; + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + debug_assert!(self.end >= self.start); + let hint = (self.end - self.start) as usize; + (hint, Some(hint)) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl ExactSizeIterator for ::ops::Range<$t> {} + )*) } -macro_rules! step_impl { +macro_rules! range_impl_no_hint { ($($t:ty)*) => ($( - #[unstable(feature = "core", reason = "Trait is unstable.")] - impl Step for $t { + #[stable(feature = "rust1", since = "1.0.0")] + impl Iterator for ::ops::Range<$t> { + type Item = $t; + #[inline] - fn step(&mut self) { *self += 1; } - #[inline] - fn step_back(&mut self) { *self -= 1; } - #[inline] - fn steps_between(start: &$t, end: &$t) -> Option { - debug_assert!(end >= start); - Some((*end - *start) as uint) + fn next(&mut self) -> Option<$t> { + if self.start < self.end { + let result = self.start; + self.start += 1; + return Some(result); + } + + return None; } } )*) } -macro_rules! step_impl_no_between { +macro_rules! range_other_impls { ($($t:ty)*) => ($( - #[unstable(feature = "core", reason = "Trait is unstable.")] - impl Step for $t { + #[stable(feature = "rust1", since = "1.0.0")] + impl DoubleEndedIterator for ::ops::Range<$t> { #[inline] - fn step(&mut self) { *self += 1; } + fn next_back(&mut self) -> Option<$t> { + if self.start < self.end { + self.end -= 1; + return Some(self.end); + } + + return None; + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl Iterator for ::ops::RangeFrom<$t> { + type Item = $t; + #[inline] - fn step_back(&mut self) { *self -= 1; } - #[inline] - fn steps_between(_start: &$t, _end: &$t) -> Option { - None + fn next(&mut self) -> Option<$t> { + let result = self.start; + self.start += 1; + debug_assert!(result < self.start); + return Some(result); } } )*) } -step_impl!(uint u8 u16 u32 int i8 i16 i32); +range_impl!(usize u8 u16 u32 isize i8 i16 i32); #[cfg(target_pointer_width = "64")] -step_impl!(u64 i64); +range_impl!(u64 i64); #[cfg(target_pointer_width = "32")] -step_impl_no_between!(u64 i64); +range_impl_no_hint!(u64 i64); +range_other_impls!(usize u8 u16 u32 u64 isize i8 i16 i32 i64); /// An iterator that repeats an element endlessly #[derive(Clone)] @@ -2798,7 +2883,7 @@ impl Iterator for Repeat { #[inline] fn next(&mut self) -> Option { self.idx(0) } #[inline] - fn size_hint(&self) -> (uint, Option) { (uint::MAX, None) } + fn size_hint(&self) -> (usize, Option) { (usize::MAX, None) } } #[stable(feature = "rust1", since = "1.0.0")] @@ -2810,9 +2895,9 @@ impl DoubleEndedIterator for Repeat { #[unstable(feature = "core", reason = "trait is experimental")] impl RandomAccessIterator for Repeat { #[inline] - fn indexable(&self) -> uint { uint::MAX } + fn indexable(&self) -> usize { usize::MAX } #[inline] - fn idx(&mut self, _: uint) -> Option { Some(self.element.clone()) } + fn idx(&mut self, _: usize) -> Option { Some(self.element.clone()) } } type IterateState = (F, Option, bool); diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index ea697ed769d3..d4ca5e3f8dcb 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -64,6 +64,8 @@ #![feature(unboxed_closures)] #![allow(unknown_features)] #![feature(int_uint)] #![feature(on_unimplemented)] +// FIXME(#21363) remove `old_impl_check` when bug is fixed +#![feature(old_impl_check)] #![deny(missing_docs)] #[macro_use] @@ -137,6 +139,7 @@ pub mod slice; pub mod str; pub mod hash; pub mod fmt; +pub mod error; // note: does not need to be public mod tuple; diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index 7d9c131a7215..0a31cb01ca28 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -386,17 +386,6 @@ pub struct ContravariantLifetime<'a>; #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] pub struct InvariantLifetime<'a>; -/// A type which is considered "not sendable", meaning that it cannot -/// be safely sent between tasks, even if it is owned. This is -/// typically embedded in other types, such as `Gc`, to ensure that -/// their instances remain thread-local. -#[unstable(feature = "core", - reason = "likely to change with new variance strategy")] -#[lang="no_send_bound"] -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] -#[cfg(stage0)] // NOTE remove impl after next snapshot -pub struct NoSend; - /// A type which is considered "not POD", meaning that it is not /// implicitly copyable. This is typically embedded in other types to /// ensure that they are never copied, even if they lack a destructor. @@ -407,16 +396,6 @@ pub struct NoSend; #[allow(missing_copy_implementations)] pub struct NoCopy; -/// A type which is considered "not sync", meaning that -/// its contents are not threadsafe, hence they cannot be -/// shared between tasks. -#[unstable(feature = "core", - reason = "likely to change with new variance strategy")] -#[lang="no_sync_bound"] -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] -#[cfg(stage0)] // NOTE remove impl after next snapshot -pub struct NoSync; - /// A type which is considered managed by the GC. This is typically /// embedded in other types. #[unstable(feature = "core", diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs index 248e2f232e8a..d482888e3bc8 100644 --- a/src/libcore/ops.rs +++ b/src/libcore/ops.rs @@ -33,8 +33,6 @@ //! demonstrates adding and subtracting two `Point`s. //! //! ```rust -//! #![feature(associated_types)] -//! //! use std::ops::{Add, Sub}; //! //! #[derive(Show)] @@ -69,10 +67,7 @@ #![stable(feature = "rust1", since = "1.0.0")] -use clone::Clone; -use iter::{Step, Iterator,DoubleEndedIterator,ExactSizeIterator}; use marker::Sized; -use option::Option::{self, Some, None}; use fmt; /// The `Drop` trait is used to run some code when a value goes out of scope. This @@ -168,8 +163,6 @@ macro_rules! forward_ref_binop { /// calling `add`, and therefore, `main` prints `Adding!`. /// /// ```rust -/// #![feature(associated_types)] -/// /// use std::ops::Add; /// /// #[derive(Copy)] @@ -223,8 +216,6 @@ add_impl! { uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64 } /// calling `sub`, and therefore, `main` prints `Subtracting!`. /// /// ```rust -/// #![feature(associated_types)] -/// /// use std::ops::Sub; /// /// #[derive(Copy)] @@ -278,8 +269,6 @@ sub_impl! { uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64 } /// calling `mul`, and therefore, `main` prints `Multiplying!`. /// /// ```rust -/// #![feature(associated_types)] -/// /// use std::ops::Mul; /// /// #[derive(Copy)] @@ -333,8 +322,6 @@ mul_impl! { uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64 } /// calling `div`, and therefore, `main` prints `Dividing!`. /// /// ``` -/// #![feature(associated_types)] -/// /// use std::ops::Div; /// /// #[derive(Copy)] @@ -388,8 +375,6 @@ div_impl! { uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64 } /// calling `rem`, and therefore, `main` prints `Remainder-ing!`. /// /// ``` -/// #![feature(associated_types)] -/// /// use std::ops::Rem; /// /// #[derive(Copy)] @@ -462,8 +447,6 @@ rem_float_impl! { f64, fmod } /// `neg`, and therefore, `main` prints `Negating!`. /// /// ``` -/// #![feature(associated_types)] -/// /// use std::ops::Neg; /// /// struct Foo; @@ -541,8 +524,6 @@ neg_uint_impl! { u64, i64 } /// `not`, and therefore, `main` prints `Not-ing!`. /// /// ``` -/// #![feature(associated_types)] -/// /// use std::ops::Not; /// /// struct Foo; @@ -597,8 +578,6 @@ not_impl! { bool uint u8 u16 u32 u64 int i8 i16 i32 i64 } /// calling `bitand`, and therefore, `main` prints `Bitwise And-ing!`. /// /// ``` -/// #![feature(associated_types)] -/// /// use std::ops::BitAnd; /// /// #[derive(Copy)] @@ -652,8 +631,6 @@ bitand_impl! { bool uint u8 u16 u32 u64 int i8 i16 i32 i64 } /// calling `bitor`, and therefore, `main` prints `Bitwise Or-ing!`. /// /// ``` -/// #![feature(associated_types)] -/// /// use std::ops::BitOr; /// /// #[derive(Copy)] @@ -707,8 +684,6 @@ bitor_impl! { bool uint u8 u16 u32 u64 int i8 i16 i32 i64 } /// calling `bitxor`, and therefore, `main` prints `Bitwise Xor-ing!`. /// /// ``` -/// #![feature(associated_types)] -/// /// use std::ops::BitXor; /// /// #[derive(Copy)] @@ -762,8 +737,6 @@ bitxor_impl! { bool uint u8 u16 u32 u64 int i8 i16 i32 i64 } /// calling `shl`, and therefore, `main` prints `Shifting left!`. /// /// ``` -/// #![feature(associated_types)] -/// /// use std::ops::Shl; /// /// #[derive(Copy)] @@ -835,8 +808,6 @@ shl_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize } /// calling `shr`, and therefore, `main` prints `Shifting right!`. /// /// ``` -/// #![feature(associated_types)] -/// /// use std::ops::Shr; /// /// #[derive(Copy)] @@ -928,10 +899,12 @@ shr_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize } /// } /// ``` #[lang="index"] +#[stable(feature = "rust1", since = "1.0.0")] pub trait Index { type Output: ?Sized; /// The method for the indexing (`Foo[Bar]`) operation + #[stable(feature = "rust1", since = "1.0.0")] fn index<'a>(&'a self, index: &Index) -> &'a Self::Output; } @@ -964,30 +937,32 @@ pub trait Index { /// } /// ``` #[lang="index_mut"] +#[stable(feature = "rust1", since = "1.0.0")] pub trait IndexMut { type Output: ?Sized; /// The method for the indexing (`Foo[Bar]`) operation + #[stable(feature = "rust1", since = "1.0.0")] fn index_mut<'a>(&'a mut self, index: &Index) -> &'a mut Self::Output; } /// An unbounded range. #[derive(Copy, Clone, PartialEq, Eq)] #[lang="full_range"] -#[unstable(feature = "core", reason = "API still in development")] +#[unstable(feature = "core", reason = "may be renamed to RangeFull")] pub struct FullRange; -#[unstable(feature = "core", reason = "API still in development")] -impl fmt::Show for FullRange { +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for FullRange { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt::Show::fmt("..", fmt) + fmt::Debug::fmt("..", fmt) } } /// A (half-open) range which is bounded at both ends. #[derive(Copy, Clone, PartialEq, Eq)] #[lang="range"] -#[unstable(feature = "core", reason = "API still in development")] +#[stable(feature = "rust1", since = "1.0.0")] pub struct Range { /// The lower bound of the range (inclusive). pub start: Idx, @@ -995,49 +970,8 @@ pub struct Range { pub end: Idx, } -#[unstable(feature = "core", reason = "API still in development")] -impl Iterator for Range { - type Item = Idx; - - #[inline] - fn next(&mut self) -> Option { - if self.start < self.end { - let result = self.start.clone(); - self.start.step(); - return Some(result); - } - - return None; - } - - #[inline] - fn size_hint(&self) -> (uint, Option) { - if let Some(hint) = Step::steps_between(&self.start, &self.end) { - (hint, Some(hint)) - } else { - (0, None) - } - } -} - -#[unstable(feature = "core", reason = "API still in development")] -impl DoubleEndedIterator for Range { - #[inline] - fn next_back(&mut self) -> Option { - if self.start < self.end { - self.end.step_back(); - return Some(self.end.clone()); - } - - return None; - } -} - -#[unstable(feature = "core", reason = "API still in development")] -impl ExactSizeIterator for Range {} - -#[unstable(feature = "core", reason = "API still in development")] -impl fmt::Show for Range { +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for Range { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { write!(fmt, "{:?}..{:?}", self.start, self.end) } @@ -1046,27 +980,16 @@ impl fmt::Show for Range { /// A range which is only bounded below. #[derive(Copy, Clone, PartialEq, Eq)] #[lang="range_from"] -#[unstable(feature = "core", reason = "API still in development")] +#[stable(feature = "rust1", since = "1.0.0")] pub struct RangeFrom { /// The lower bound of the range (inclusive). pub start: Idx, } -#[unstable(feature = "core", reason = "API still in development")] -impl Iterator for RangeFrom { - type Item = Idx; - #[inline] - fn next(&mut self) -> Option { - // Deliberately overflow so we loop forever. - let result = self.start.clone(); - self.start.step(); - return Some(result); - } -} -#[unstable(feature = "core", reason = "API still in development")] -impl fmt::Show for RangeFrom { +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for RangeFrom { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { write!(fmt, "{:?}..", self.start) } @@ -1075,14 +998,14 @@ impl fmt::Show for RangeFrom { /// A range which is only bounded above. #[derive(Copy, Clone, PartialEq, Eq)] #[lang="range_to"] -#[unstable(feature = "core", reason = "API still in development")] +#[stable(feature = "rust1", since = "1.0.0")] pub struct RangeTo { /// The upper bound of the range (exclusive). pub end: Idx, } -#[unstable(feature = "core", reason = "API still in development")] -impl fmt::Show for RangeTo { +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for RangeTo { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { write!(fmt, "..{:?}", self.end) } @@ -1098,8 +1021,6 @@ impl fmt::Show for RangeTo { /// struct. /// /// ``` -/// #![feature(associated_types)] -/// /// use std::ops::Deref; /// /// struct DerefExample { @@ -1153,8 +1074,6 @@ impl<'a, T: ?Sized> Deref for &'a mut T { /// struct. /// /// ``` -/// #![feature(associated_types)] -/// /// use std::ops::{Deref, DerefMut}; /// /// struct DerefMutExample { diff --git a/src/libcore/result.rs b/src/libcore/result.rs index 4dec5fb9b3fd..3441512e5529 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -229,7 +229,7 @@ use self::Result::{Ok, Err}; use clone::Clone; -use fmt::Show; +use fmt::Display; use iter::{Iterator, IteratorExt, DoubleEndedIterator, FromIterator, ExactSizeIterator}; use ops::{FnMut, FnOnce}; use option::Option::{self, None, Some}; @@ -715,7 +715,7 @@ impl Result { } #[stable(feature = "rust1", since = "1.0.0")] -impl Result { +impl Result { /// Unwraps a result, yielding the content of an `Ok`. /// /// # Panics @@ -740,13 +740,13 @@ impl Result { match self { Ok(t) => t, Err(e) => - panic!("called `Result::unwrap()` on an `Err` value: {:?}", e) + panic!("called `Result::unwrap()` on an `Err` value: {}", e) } } } #[stable(feature = "rust1", since = "1.0.0")] -impl Result { +impl Result { /// Unwraps a result, yielding the content of an `Err`. /// /// # Panics @@ -770,7 +770,7 @@ impl Result { pub fn unwrap_err(self) -> E { match self { Ok(t) => - panic!("called `Result::unwrap_err()` on an `Ok` value: {:?}", t), + panic!("called `Result::unwrap_err()` on an `Ok` value: {}", t), Err(e) => e } } diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index 9f44fe961269..2b682111781a 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -67,9 +67,6 @@ use raw::Slice as RawSlice; pub trait SliceExt { type Item; - fn slice<'a>(&'a self, start: uint, end: uint) -> &'a [Self::Item]; - fn slice_from<'a>(&'a self, start: uint) -> &'a [Self::Item]; - fn slice_to<'a>(&'a self, end: uint) -> &'a [Self::Item]; fn split_at<'a>(&'a self, mid: uint) -> (&'a [Self::Item], &'a [Self::Item]); fn iter<'a>(&'a self) -> Iter<'a, Self::Item>; fn split<'a, P>(&'a self, pred: P) -> Split<'a, Self::Item, P> @@ -93,9 +90,6 @@ pub trait SliceExt { fn is_empty(&self) -> bool { self.len() == 0 } fn get_mut<'a>(&'a mut self, index: uint) -> Option<&'a mut Self::Item>; fn as_mut_slice<'a>(&'a mut self) -> &'a mut [Self::Item]; - fn slice_mut<'a>(&'a mut self, start: uint, end: uint) -> &'a mut [Self::Item]; - fn slice_from_mut<'a>(&'a mut self, start: uint) -> &'a mut [Self::Item]; - fn slice_to_mut<'a>(&'a mut self, end: uint) -> &'a mut [Self::Item]; fn iter_mut<'a>(&'a mut self) -> IterMut<'a, Self::Item>; fn first_mut<'a>(&'a mut self) -> Option<&'a mut Self::Item>; fn tail_mut<'a>(&'a mut self) -> &'a mut [Self::Item]; @@ -135,28 +129,6 @@ pub trait SliceExt { impl SliceExt for [T] { type Item = T; - #[inline] - fn slice(&self, start: uint, end: uint) -> &[T] { - assert!(start <= end); - assert!(end <= self.len()); - unsafe { - transmute(RawSlice { - data: self.as_ptr().offset(start as int), - len: (end - start) - }) - } - } - - #[inline] - fn slice_from(&self, start: uint) -> &[T] { - self.slice(start, self.len()) - } - - #[inline] - fn slice_to(&self, end: uint) -> &[T] { - self.slice(0, end) - } - #[inline] fn split_at(&self, mid: uint) -> (&[T], &[T]) { (&self[..mid], &self[mid..]) @@ -240,7 +212,7 @@ impl SliceExt for [T] { #[inline] fn init(&self) -> &[T] { - &self[..(self.len() - 1)] + &self[..self.len() - 1] } #[inline] @@ -291,20 +263,6 @@ impl SliceExt for [T] { #[inline] fn as_mut_slice(&mut self) -> &mut [T] { self } - fn slice_mut(&mut self, start: uint, end: uint) -> &mut [T] { - ops::IndexMut::index_mut(self, &ops::Range { start: start, end: end } ) - } - - #[inline] - fn slice_from_mut(&mut self, start: uint) -> &mut [T] { - ops::IndexMut::index_mut(self, &ops::RangeFrom { start: start } ) - } - - #[inline] - fn slice_to_mut(&mut self, end: uint) -> &mut [T] { - ops::IndexMut::index_mut(self, &ops::RangeTo { end: end } ) - } - #[inline] fn split_at_mut(&mut self, mid: uint) -> (&mut [T], &mut [T]) { unsafe { @@ -345,13 +303,13 @@ impl SliceExt for [T] { #[inline] fn tail_mut(&mut self) -> &mut [T] { - self.slice_from_mut(1) + &mut self[1 ..] } #[inline] fn init_mut(&mut self) -> &mut [T] { let len = self.len(); - self.slice_to_mut(len-1) + &mut self[.. (len - 1)] } #[inline] @@ -449,7 +407,7 @@ impl SliceExt for [T] { #[inline] fn ends_with(&self, needle: &[T]) -> bool where T: PartialEq { let (m, n) = (self.len(), needle.len()); - m >= n && needle == &self[(m-n)..] + m >= n && needle == &self[m-n..] } #[unstable(feature = "core")] @@ -483,7 +441,7 @@ impl SliceExt for [T] { self.swap(j, i-1); // Step 4: Reverse the (previously) weakly decreasing part - self.slice_from_mut(i).reverse(); + self[i..].reverse(); true } @@ -505,7 +463,7 @@ impl SliceExt for [T] { } // Step 2: Reverse the weakly increasing part - self.slice_from_mut(i).reverse(); + self[i..].reverse(); // Step 3: Find the rightmost element equal to or bigger than the pivot (i-1) let mut j = self.len() - 1; @@ -522,8 +480,8 @@ impl SliceExt for [T] { #[inline] fn clone_from_slice(&mut self, src: &[T]) -> uint where T: Clone { let min = cmp::min(self.len(), src.len()); - let dst = self.slice_to_mut(min); - let src = src.slice_to(min); + let dst = &mut self[.. min]; + let src = &src[.. min]; for i in range(0, min) { dst[i].clone_from(&src[i]); } @@ -531,6 +489,7 @@ impl SliceExt for [T] { } } +#[stable(feature = "rust1", since = "1.0.0")] impl ops::Index for [T] { type Output = T; @@ -541,6 +500,7 @@ impl ops::Index for [T] { } } +#[stable(feature = "rust1", since = "1.0.0")] impl ops::IndexMut for [T] { type Output = T; @@ -551,6 +511,7 @@ impl ops::IndexMut for [T] { } } +#[stable(feature = "rust1", since = "1.0.0")] impl ops::Index> for [T] { type Output = [T]; #[inline] @@ -565,6 +526,7 @@ impl ops::Index> for [T] { } } } +#[stable(feature = "rust1", since = "1.0.0")] impl ops::Index> for [T] { type Output = [T]; #[inline] @@ -572,6 +534,7 @@ impl ops::Index> for [T] { self.index(&ops::Range{ start: 0, end: index.end }) } } +#[stable(feature = "rust1", since = "1.0.0")] impl ops::Index> for [T] { type Output = [T]; #[inline] @@ -579,6 +542,7 @@ impl ops::Index> for [T] { self.index(&ops::Range{ start: index.start, end: self.len() }) } } +#[stable(feature = "rust1", since = "1.0.0")] impl ops::Index for [T] { type Output = [T]; #[inline] @@ -587,6 +551,7 @@ impl ops::Index for [T] { } } +#[stable(feature = "rust1", since = "1.0.0")] impl ops::IndexMut> for [T] { type Output = [T]; #[inline] @@ -601,6 +566,7 @@ impl ops::IndexMut> for [T] { } } } +#[stable(feature = "rust1", since = "1.0.0")] impl ops::IndexMut> for [T] { type Output = [T]; #[inline] @@ -608,6 +574,7 @@ impl ops::IndexMut> for [T] { self.index_mut(&ops::Range{ start: 0, end: index.end }) } } +#[stable(feature = "rust1", since = "1.0.0")] impl ops::IndexMut> for [T] { type Output = [T]; #[inline] @@ -616,6 +583,7 @@ impl ops::IndexMut> for [T] { self.index_mut(&ops::Range{ start: index.start, end: len }) } } +#[stable(feature = "rust1", since = "1.0.0")] impl ops::IndexMut for [T] { type Output = [T]; #[inline] @@ -974,7 +942,7 @@ impl<'a, T, P> Iterator for Split<'a, T, P> where P: FnMut(&T) -> bool { None => self.finish(), Some(idx) => { let ret = Some(&self.v[..idx]); - self.v = &self.v[(idx + 1)..]; + self.v = &self.v[idx + 1..]; ret } } @@ -999,7 +967,7 @@ impl<'a, T, P> DoubleEndedIterator for Split<'a, T, P> where P: FnMut(&T) -> boo match self.v.iter().rposition(|x| (self.pred)(x)) { None => self.finish(), Some(idx) => { - let ret = Some(&self.v[(idx + 1)..]); + let ret = Some(&self.v[idx + 1..]); self.v = &self.v[..idx]; ret } @@ -1052,7 +1020,7 @@ impl<'a, T, P> Iterator for SplitMut<'a, T, P> where P: FnMut(&T) -> bool { Some(idx) => { let tmp = mem::replace(&mut self.v, &mut []); let (head, tail) = tmp.split_at_mut(idx); - self.v = tail.slice_from_mut(1); + self.v = &mut tail[1..]; Some(head) } } @@ -1088,7 +1056,7 @@ impl<'a, T, P> DoubleEndedIterator for SplitMut<'a, T, P> where let tmp = mem::replace(&mut self.v, &mut []); let (head, tail) = tmp.split_at_mut(idx); self.v = head; - Some(tail.slice_from_mut(1)) + Some(&mut tail[1..]) } } } @@ -1270,6 +1238,9 @@ impl<'a, T> DoubleEndedIterator for Chunks<'a, T> { } } +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> ExactSizeIterator for Chunks<'a, T> {} + #[unstable(feature = "core", reason = "trait is experimental")] impl<'a, T> RandomAccessIterator for Chunks<'a, T> { #[inline] @@ -1348,6 +1319,8 @@ impl<'a, T> DoubleEndedIterator for ChunksMut<'a, T> { } } +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> ExactSizeIterator for ChunksMut<'a, T> {} // // Free functions diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 37f643db54e3..92c5de937cc0 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -20,8 +20,10 @@ use self::Searcher::{Naive, TwoWay, TwoWayLong}; use cmp::{self, Eq}; use default::Default; -use iter::range; +use error::Error; +use fmt; use iter::ExactSizeIterator; +use iter::range; use iter::{Map, Iterator, IteratorExt, DoubleEndedIterator}; use marker::Sized; use mem; @@ -247,6 +249,30 @@ impl<'a> CharEq for &'a [char] { } } +#[stable(feature = "rust1", since = "1.0.0")] +impl Error for Utf8Error { + fn description(&self) -> &str { + match *self { + Utf8Error::TooShort => "invalid utf-8: not enough bytes", + Utf8Error::InvalidByte(..) => "invalid utf-8: corrupt contents", + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for Utf8Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Utf8Error::InvalidByte(n) => { + write!(f, "invalid utf-8: invalid byte at index {}", n) + } + Utf8Error::TooShort => { + write!(f, "invalid utf-8: byte slice too short") + } + } + } +} + /* Section: Iterators */ @@ -907,13 +933,13 @@ impl<'a> Iterator for SplitStr<'a> { match self.it.next() { Some((from, to)) => { - let ret = Some(self.it.haystack.slice(self.last_end, from)); + let ret = Some(&self.it.haystack[self.last_end .. from]); self.last_end = to; ret } None => { self.finished = true; - Some(self.it.haystack.slice(self.last_end, self.it.haystack.len())) + Some(&self.it.haystack[self.last_end .. self.it.haystack.len()]) } } } @@ -1121,27 +1147,90 @@ mod traits { } } + /// Returns a slice of the given string from the byte range + /// [`begin`..`end`). + /// + /// This operation is `O(1)`. + /// + /// Panics when `begin` and `end` do not point to valid characters + /// or point beyond the last character of the string. + /// + /// # Example + /// + /// ```rust + /// let s = "Löwe 老虎 Léopard"; + /// assert_eq!(&s[0 .. 1], "L"); + /// + /// assert_eq!(&s[1 .. 9], "öwe 老"); + /// + /// // these will panic: + /// // byte 2 lies within `ö`: + /// // &s[2 ..3]; + /// + /// // byte 8 lies within `老` + /// // &s[1 .. 8]; + /// + /// // byte 100 is outside the string + /// // &s[3 .. 100]; + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] impl ops::Index> for str { type Output = str; #[inline] fn index(&self, index: &ops::Range) -> &str { - self.slice(index.start, index.end) + // is_char_boundary checks that the index is in [0, .len()] + if index.start <= index.end && + self.is_char_boundary(index.start) && + self.is_char_boundary(index.end) { + unsafe { self.slice_unchecked(index.start, index.end) } + } else { + super::slice_error_fail(self, index.start, index.end) + } } } + + /// Returns a slice of the string from the beginning to byte + /// `end`. + /// + /// Equivalent to `self[0 .. end]`. + /// + /// Panics when `end` does not point to a valid character, or is + /// out of bounds. + #[stable(feature = "rust1", since = "1.0.0")] impl ops::Index> for str { type Output = str; #[inline] fn index(&self, index: &ops::RangeTo) -> &str { - self.slice_to(index.end) + // is_char_boundary checks that the index is in [0, .len()] + if self.is_char_boundary(index.end) { + unsafe { self.slice_unchecked(0, index.end) } + } else { + super::slice_error_fail(self, 0, index.end) + } } } + + /// Returns a slice of the string from `begin` to its end. + /// + /// Equivalent to `self[begin .. self.len()]`. + /// + /// Panics when `begin` does not point to a valid character, or is + /// out of bounds. + #[stable(feature = "rust1", since = "1.0.0")] impl ops::Index> for str { type Output = str; #[inline] fn index(&self, index: &ops::RangeFrom) -> &str { - self.slice_from(index.start) + // is_char_boundary checks that the index is in [0, .len()] + if self.is_char_boundary(index.start) { + unsafe { self.slice_unchecked(index.start, self.len()) } + } else { + super::slice_error_fail(self, index.start, self.len()) + } } } + + #[stable(feature = "rust1", since = "1.0.0")] impl ops::Index for str { type Output = str; #[inline] @@ -1154,7 +1243,7 @@ mod traits { /// Any string that can be represented as a slice #[unstable(feature = "core", reason = "Instead of taking this bound generically, this trait will be \ - replaced with one of slicing syntax, deref coercions, or \ + replaced with one of slicing syntax (&foo[]), deref coercions, or \ a more generic conversion trait")] pub trait Str { /// Work with `self` as a slice. @@ -1216,9 +1305,6 @@ pub trait StrExt { fn lines<'a>(&'a self) -> Lines<'a>; fn lines_any<'a>(&'a self) -> LinesAny<'a>; fn char_len(&self) -> uint; - fn slice<'a>(&'a self, begin: uint, end: uint) -> &'a str; - fn slice_from<'a>(&'a self, begin: uint) -> &'a str; - fn slice_to<'a>(&'a self, end: uint) -> &'a str; fn slice_chars<'a>(&'a self, begin: uint, end: uint) -> &'a str; unsafe fn slice_unchecked<'a>(&'a self, begin: uint, end: uint) -> &'a str; fn starts_with(&self, pat: &str) -> bool; @@ -1340,7 +1426,7 @@ impl StrExt for str { fn lines_any(&self) -> LinesAny { fn f(line: &str) -> &str { let l = line.len(); - if l > 0 && line.as_bytes()[l - 1] == b'\r' { line.slice(0, l - 1) } + if l > 0 && line.as_bytes()[l - 1] == b'\r' { &line[0 .. l - 1] } else { line } } @@ -1351,38 +1437,6 @@ impl StrExt for str { #[inline] fn char_len(&self) -> uint { self.chars().count() } - #[inline] - fn slice(&self, begin: uint, end: uint) -> &str { - // is_char_boundary checks that the index is in [0, .len()] - if begin <= end && - self.is_char_boundary(begin) && - self.is_char_boundary(end) { - unsafe { self.slice_unchecked(begin, end) } - } else { - slice_error_fail(self, begin, end) - } - } - - #[inline] - fn slice_from(&self, begin: uint) -> &str { - // is_char_boundary checks that the index is in [0, .len()] - if self.is_char_boundary(begin) { - unsafe { self.slice_unchecked(begin, self.len()) } - } else { - slice_error_fail(self, begin, self.len()) - } - } - - #[inline] - fn slice_to(&self, end: uint) -> &str { - // is_char_boundary checks that the index is in [0, .len()] - if self.is_char_boundary(end) { - unsafe { self.slice_unchecked(0, end) } - } else { - slice_error_fail(self, 0, end) - } - } - fn slice_chars(&self, begin: uint, end: uint) -> &str { assert!(begin <= end); let mut count = 0; @@ -1423,7 +1477,7 @@ impl StrExt for str { #[inline] fn ends_with(&self, needle: &str) -> bool { let (m, n) = (self.len(), needle.len()); - m >= n && needle.as_bytes() == &self.as_bytes()[(m-n)..] + m >= n && needle.as_bytes() == &self.as_bytes()[m-n..] } #[inline] diff --git a/src/libcoretest/finally.rs b/src/libcoretest/finally.rs index 979ddaecb4ae..6ec87203e003 100644 --- a/src/libcoretest/finally.rs +++ b/src/libcoretest/finally.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(deprecated)] + use core::finally::{try_finally, Finally}; use std::thread::Thread; diff --git a/src/libcoretest/fmt/mod.rs b/src/libcoretest/fmt/mod.rs index 3f2208e6c2da..e77920144468 100644 --- a/src/libcoretest/fmt/mod.rs +++ b/src/libcoretest/fmt/mod.rs @@ -14,5 +14,5 @@ mod num; fn test_format_flags() { // No residual flags left by pointer formatting let p = "".as_ptr(); - assert_eq!(format!("{:p} {:x}", p, 16u), format!("{:p} 10", p)); + assert_eq!(format!("{:p} {:x}", p, 16), format!("{:p} 10", p)); } diff --git a/src/libcoretest/fmt/num.rs b/src/libcoretest/fmt/num.rs index c259e4cbb686..17180076cd80 100644 --- a/src/libcoretest/fmt/num.rs +++ b/src/libcoretest/fmt/num.rs @@ -16,115 +16,115 @@ fn test_format_int() { // Formatting integers should select the right implementation based off // the type of the argument. Also, hex/octal/binary should be defined // for integers, but they shouldn't emit the negative sign. - assert!(format!("{}", 1i) == "1"); + assert!(format!("{}", 1is) == "1"); assert!(format!("{}", 1i8) == "1"); assert!(format!("{}", 1i16) == "1"); assert!(format!("{}", 1i32) == "1"); assert!(format!("{}", 1i64) == "1"); - assert!(format!("{}", -1i) == "-1"); + assert!(format!("{}", -1is) == "-1"); assert!(format!("{}", -1i8) == "-1"); assert!(format!("{}", -1i16) == "-1"); assert!(format!("{}", -1i32) == "-1"); assert!(format!("{}", -1i64) == "-1"); - assert!(format!("{:?}", 1i) == "1i"); - assert!(format!("{:?}", 1i8) == "1i8"); - assert!(format!("{:?}", 1i16) == "1i16"); - assert!(format!("{:?}", 1i32) == "1i32"); - assert!(format!("{:?}", 1i64) == "1i64"); - assert!(format!("{:b}", 1i) == "1"); + assert!(format!("{:?}", 1is) == "1"); + assert!(format!("{:?}", 1i8) == "1"); + assert!(format!("{:?}", 1i16) == "1"); + assert!(format!("{:?}", 1i32) == "1"); + assert!(format!("{:?}", 1i64) == "1"); + assert!(format!("{:b}", 1is) == "1"); assert!(format!("{:b}", 1i8) == "1"); assert!(format!("{:b}", 1i16) == "1"); assert!(format!("{:b}", 1i32) == "1"); assert!(format!("{:b}", 1i64) == "1"); - assert!(format!("{:x}", 1i) == "1"); + assert!(format!("{:x}", 1is) == "1"); assert!(format!("{:x}", 1i8) == "1"); assert!(format!("{:x}", 1i16) == "1"); assert!(format!("{:x}", 1i32) == "1"); assert!(format!("{:x}", 1i64) == "1"); - assert!(format!("{:X}", 1i) == "1"); + assert!(format!("{:X}", 1is) == "1"); assert!(format!("{:X}", 1i8) == "1"); assert!(format!("{:X}", 1i16) == "1"); assert!(format!("{:X}", 1i32) == "1"); assert!(format!("{:X}", 1i64) == "1"); - assert!(format!("{:o}", 1i) == "1"); + assert!(format!("{:o}", 1is) == "1"); assert!(format!("{:o}", 1i8) == "1"); assert!(format!("{:o}", 1i16) == "1"); assert!(format!("{:o}", 1i32) == "1"); assert!(format!("{:o}", 1i64) == "1"); - assert!(format!("{}", 1u) == "1"); + assert!(format!("{}", 1us) == "1"); assert!(format!("{}", 1u8) == "1"); assert!(format!("{}", 1u16) == "1"); assert!(format!("{}", 1u32) == "1"); assert!(format!("{}", 1u64) == "1"); - assert!(format!("{:?}", 1u) == "1u"); - assert!(format!("{:?}", 1u8) == "1u8"); - assert!(format!("{:?}", 1u16) == "1u16"); - assert!(format!("{:?}", 1u32) == "1u32"); - assert!(format!("{:?}", 1u64) == "1u64"); - assert!(format!("{:b}", 1u) == "1"); + assert!(format!("{:?}", 1us) == "1"); + assert!(format!("{:?}", 1u8) == "1"); + assert!(format!("{:?}", 1u16) == "1"); + assert!(format!("{:?}", 1u32) == "1"); + assert!(format!("{:?}", 1u64) == "1"); + assert!(format!("{:b}", 1us) == "1"); assert!(format!("{:b}", 1u8) == "1"); assert!(format!("{:b}", 1u16) == "1"); assert!(format!("{:b}", 1u32) == "1"); assert!(format!("{:b}", 1u64) == "1"); - assert!(format!("{:x}", 1u) == "1"); + assert!(format!("{:x}", 1us) == "1"); assert!(format!("{:x}", 1u8) == "1"); assert!(format!("{:x}", 1u16) == "1"); assert!(format!("{:x}", 1u32) == "1"); assert!(format!("{:x}", 1u64) == "1"); - assert!(format!("{:X}", 1u) == "1"); + assert!(format!("{:X}", 1us) == "1"); assert!(format!("{:X}", 1u8) == "1"); assert!(format!("{:X}", 1u16) == "1"); assert!(format!("{:X}", 1u32) == "1"); assert!(format!("{:X}", 1u64) == "1"); - assert!(format!("{:o}", 1u) == "1"); + assert!(format!("{:o}", 1us) == "1"); assert!(format!("{:o}", 1u8) == "1"); assert!(format!("{:o}", 1u16) == "1"); assert!(format!("{:o}", 1u32) == "1"); assert!(format!("{:o}", 1u64) == "1"); // Test a larger number - assert!(format!("{:b}", 55i) == "110111"); - assert!(format!("{:o}", 55i) == "67"); - assert!(format!("{}", 55i) == "55"); - assert!(format!("{:x}", 55i) == "37"); - assert!(format!("{:X}", 55i) == "37"); + assert!(format!("{:b}", 55) == "110111"); + assert!(format!("{:o}", 55) == "67"); + assert!(format!("{}", 55) == "55"); + assert!(format!("{:x}", 55) == "37"); + assert!(format!("{:X}", 55) == "37"); } #[test] fn test_format_int_zero() { - assert!(format!("{}", 0i) == "0"); - assert!(format!("{:?}", 0i) == "0i"); - assert!(format!("{:b}", 0i) == "0"); - assert!(format!("{:o}", 0i) == "0"); - assert!(format!("{:x}", 0i) == "0"); - assert!(format!("{:X}", 0i) == "0"); + assert!(format!("{}", 0) == "0"); + assert!(format!("{:?}", 0) == "0"); + assert!(format!("{:b}", 0) == "0"); + assert!(format!("{:o}", 0) == "0"); + assert!(format!("{:x}", 0) == "0"); + assert!(format!("{:X}", 0) == "0"); - assert!(format!("{}", 0u) == "0"); - assert!(format!("{:?}", 0u) == "0u"); - assert!(format!("{:b}", 0u) == "0"); - assert!(format!("{:o}", 0u) == "0"); - assert!(format!("{:x}", 0u) == "0"); - assert!(format!("{:X}", 0u) == "0"); + assert!(format!("{}", 0u32) == "0"); + assert!(format!("{:?}", 0u32) == "0"); + assert!(format!("{:b}", 0u32) == "0"); + assert!(format!("{:o}", 0u32) == "0"); + assert!(format!("{:x}", 0u32) == "0"); + assert!(format!("{:X}", 0u32) == "0"); } #[test] fn test_format_int_flags() { - assert!(format!("{:3}", 1i) == " 1"); - assert!(format!("{:>3}", 1i) == " 1"); - assert!(format!("{:>+3}", 1i) == " +1"); - assert!(format!("{:<3}", 1i) == "1 "); - assert!(format!("{:#}", 1i) == "1"); - assert!(format!("{:#x}", 10i) == "0xa"); - assert!(format!("{:#X}", 10i) == "0xA"); - assert!(format!("{:#5x}", 10i) == " 0xa"); - assert!(format!("{:#o}", 10i) == "0o12"); - assert!(format!("{:08x}", 10i) == "0000000a"); - assert!(format!("{:8x}", 10i) == " a"); - assert!(format!("{:<8x}", 10i) == "a "); - assert!(format!("{:>8x}", 10i) == " a"); - assert!(format!("{:#08x}", 10i) == "0x00000a"); - assert!(format!("{:08}", -10i) == "-0000010"); + assert!(format!("{:3}", 1) == " 1"); + assert!(format!("{:>3}", 1) == " 1"); + assert!(format!("{:>+3}", 1) == " +1"); + assert!(format!("{:<3}", 1) == "1 "); + assert!(format!("{:#}", 1) == "1"); + assert!(format!("{:#x}", 10) == "0xa"); + assert!(format!("{:#X}", 10) == "0xA"); + assert!(format!("{:#5x}", 10) == " 0xa"); + assert!(format!("{:#o}", 10) == "0o12"); + assert!(format!("{:08x}", 10) == "0000000a"); + assert!(format!("{:8x}", 10) == " a"); + assert!(format!("{:<8x}", 10) == "a "); + assert!(format!("{:>8x}", 10) == " a"); + assert!(format!("{:#08x}", 10) == "0x00000a"); + assert!(format!("{:08}", -10) == "-0000010"); assert!(format!("{:x}", -1u8) == "ff"); assert!(format!("{:X}", -1u8) == "FF"); assert!(format!("{:b}", -1u8) == "11111111"); @@ -137,12 +137,12 @@ fn test_format_int_flags() { #[test] fn test_format_int_sign_padding() { - assert!(format!("{:+5}", 1i) == " +1"); - assert!(format!("{:+5}", -1i) == " -1"); - assert!(format!("{:05}", 1i) == "00001"); - assert!(format!("{:05}", -1i) == "-0001"); - assert!(format!("{:+05}", 1i) == "+0001"); - assert!(format!("{:+05}", -1i) == "-0001"); + assert!(format!("{:+5}", 1) == " +1"); + assert!(format!("{:+5}", -1) == " -1"); + assert!(format!("{:05}", 1) == "00001"); + assert!(format!("{:05}", -1) == "-0001"); + assert!(format!("{:+05}", 1) == "+0001"); + assert!(format!("{:+05}", -1) == "-0001"); } #[test] @@ -156,96 +156,98 @@ fn test_format_int_twos_complement() { #[test] fn test_format_radix() { - assert!(format!("{:04}", radix(3i, 2)) == "0011"); - assert!(format!("{}", radix(55i, 36)) == "1j"); + assert!(format!("{:04}", radix(3, 2)) == "0011"); + assert!(format!("{}", radix(55, 36)) == "1j"); } #[test] #[should_fail] fn test_radix_base_too_large() { - let _ = radix(55i, 37); + let _ = radix(55, 37); } -mod uint { +mod u32 { use test::Bencher; use core::fmt::radix; use std::rand::{weak_rng, Rng}; + use std::io::util::NullWriter; #[bench] fn format_bin(b: &mut Bencher) { let mut rng = weak_rng(); - b.iter(|| { format!("{:b}", rng.gen::()); }) + b.iter(|| { write!(&mut NullWriter, "{:b}", rng.gen::()) }) } #[bench] fn format_oct(b: &mut Bencher) { let mut rng = weak_rng(); - b.iter(|| { format!("{:o}", rng.gen::()); }) + b.iter(|| { write!(&mut NullWriter, "{:o}", rng.gen::()) }) } #[bench] fn format_dec(b: &mut Bencher) { let mut rng = weak_rng(); - b.iter(|| { format!("{}", rng.gen::()); }) + b.iter(|| { write!(&mut NullWriter, "{}", rng.gen::()) }) } #[bench] fn format_hex(b: &mut Bencher) { let mut rng = weak_rng(); - b.iter(|| { format!("{:x}", rng.gen::()); }) + b.iter(|| { write!(&mut NullWriter, "{:x}", rng.gen::()) }) } #[bench] fn format_show(b: &mut Bencher) { let mut rng = weak_rng(); - b.iter(|| { format!("{:?}", rng.gen::()); }) + b.iter(|| { write!(&mut NullWriter, "{:?}", rng.gen::()) }) } #[bench] fn format_base_36(b: &mut Bencher) { let mut rng = weak_rng(); - b.iter(|| { format!("{}", radix(rng.gen::(), 36)); }) + b.iter(|| { write!(&mut NullWriter, "{}", radix(rng.gen::(), 36)) }) } } -mod int { +mod i32 { use test::Bencher; use core::fmt::radix; use std::rand::{weak_rng, Rng}; + use std::io::util::NullWriter; #[bench] fn format_bin(b: &mut Bencher) { let mut rng = weak_rng(); - b.iter(|| { format!("{:b}", rng.gen::()); }) + b.iter(|| { write!(&mut NullWriter, "{:b}", rng.gen::()) }) } #[bench] fn format_oct(b: &mut Bencher) { let mut rng = weak_rng(); - b.iter(|| { format!("{:o}", rng.gen::()); }) + b.iter(|| { write!(&mut NullWriter, "{:o}", rng.gen::()) }) } #[bench] fn format_dec(b: &mut Bencher) { let mut rng = weak_rng(); - b.iter(|| { format!("{}", rng.gen::()); }) + b.iter(|| { write!(&mut NullWriter, "{}", rng.gen::()) }) } #[bench] fn format_hex(b: &mut Bencher) { let mut rng = weak_rng(); - b.iter(|| { format!("{:x}", rng.gen::()); }) + b.iter(|| { write!(&mut NullWriter, "{:x}", rng.gen::()) }) } #[bench] fn format_show(b: &mut Bencher) { let mut rng = weak_rng(); - b.iter(|| { format!("{:?}", rng.gen::()); }) + b.iter(|| { write!(&mut NullWriter, "{:?}", rng.gen::()) }) } #[bench] fn format_base_36(b: &mut Bencher) { let mut rng = weak_rng(); - b.iter(|| { format!("{}", radix(rng.gen::(), 36)); }) + b.iter(|| { write!(&mut NullWriter, "{}", radix(rng.gen::(), 36)) }) } } diff --git a/src/libcoretest/iter.rs b/src/libcoretest/iter.rs index 26819bf92098..9481245f1206 100644 --- a/src/libcoretest/iter.rs +++ b/src/libcoretest/iter.rs @@ -120,18 +120,32 @@ fn test_iterator_enumerate() { fn test_iterator_peekable() { let xs = vec![0u, 1, 2, 3, 4, 5]; let mut it = xs.iter().map(|&x|x).peekable(); + + assert_eq!(it.len(), 6); assert_eq!(it.peek().unwrap(), &0); + assert_eq!(it.len(), 6); assert_eq!(it.next().unwrap(), 0); + assert_eq!(it.len(), 5); assert_eq!(it.next().unwrap(), 1); + assert_eq!(it.len(), 4); assert_eq!(it.next().unwrap(), 2); + assert_eq!(it.len(), 3); assert_eq!(it.peek().unwrap(), &3); + assert_eq!(it.len(), 3); assert_eq!(it.peek().unwrap(), &3); + assert_eq!(it.len(), 3); assert_eq!(it.next().unwrap(), 3); + assert_eq!(it.len(), 2); assert_eq!(it.next().unwrap(), 4); + assert_eq!(it.len(), 1); assert_eq!(it.peek().unwrap(), &5); + assert_eq!(it.len(), 1); assert_eq!(it.next().unwrap(), 5); + assert_eq!(it.len(), 0); assert!(it.peek().is_none()); + assert_eq!(it.len(), 0); assert!(it.next().is_none()); + assert_eq!(it.len(), 0); } #[test] @@ -166,24 +180,45 @@ fn test_iterator_skip() { let ys = [13, 15, 16, 17, 19, 20, 30]; let mut it = xs.iter().skip(5); let mut i = 0; - for &x in it { + while let Some(&x) = it.next() { assert_eq!(x, ys[i]); i += 1; + assert_eq!(it.len(), xs.len()-5-i); } assert_eq!(i, ys.len()); + assert_eq!(it.len(), 0); } #[test] fn test_iterator_take() { - let xs = [0u, 1, 2, 3, 5, 13, 15, 16, 17, 19]; - let ys = [0u, 1, 2, 3, 5]; + let xs = [0us, 1, 2, 3, 5, 13, 15, 16, 17, 19]; + let ys = [0us, 1, 2, 3, 5]; let mut it = xs.iter().take(5); let mut i = 0; - for &x in it { + assert_eq!(it.len(), 5); + while let Some(&x) = it.next() { assert_eq!(x, ys[i]); i += 1; + assert_eq!(it.len(), 5-i); } assert_eq!(i, ys.len()); + assert_eq!(it.len(), 0); +} + +#[test] +fn test_iterator_take_short() { + let xs = [0us, 1, 2, 3]; + let ys = [0us, 1, 2, 3]; + let mut it = xs.iter().take(5); + let mut i = 0; + assert_eq!(it.len(), 4); + while let Some(&x) = it.next() { + assert_eq!(x, ys[i]); + i += 1; + assert_eq!(it.len(), 4-i); + } + assert_eq!(i, ys.len()); + assert_eq!(it.len(), 0); } #[test] @@ -585,7 +620,7 @@ fn check_randacc_iter(a: T, len: uint) where fn test_double_ended_flat_map() { let u = [0u,1]; let v = [5u,6,7,8]; - let mut it = u.iter().flat_map(|x| v[(*x)..v.len()].iter()); + let mut it = u.iter().flat_map(|x| v[*x..v.len()].iter()); assert_eq!(it.next_back().unwrap(), &8); assert_eq!(it.next().unwrap(), &5); assert_eq!(it.next_back().unwrap(), &7); @@ -828,6 +863,24 @@ fn test_repeat() { assert_eq!(it.next(), Some(42u)); } +#[test] +fn test_fuse() { + let mut it = 0us..3; + assert_eq!(it.len(), 3); + assert_eq!(it.next(), Some(0us)); + assert_eq!(it.len(), 2); + assert_eq!(it.next(), Some(1us)); + assert_eq!(it.len(), 1); + assert_eq!(it.next(), Some(2us)); + assert_eq!(it.len(), 0); + assert_eq!(it.next(), None); + assert_eq!(it.len(), 0); + assert_eq!(it.next(), None); + assert_eq!(it.len(), 0); + assert_eq!(it.next(), None); + assert_eq!(it.len(), 0); +} + #[bench] fn bench_rposition(b: &mut Bencher) { let it: Vec = range(0u, 300).collect(); diff --git a/src/libcoretest/num/mod.rs b/src/libcoretest/num/mod.rs index 8186a4f0904a..e0623bade5c0 100644 --- a/src/libcoretest/num/mod.rs +++ b/src/libcoretest/num/mod.rs @@ -9,7 +9,7 @@ // except according to those terms. use core::cmp::PartialEq; -use core::fmt::Show; +use core::fmt::Debug; use core::num::{NumCast, cast}; use core::ops::{Add, Sub, Mul, Div, Rem}; use core::marker::Copy; @@ -37,7 +37,7 @@ pub fn test_num(ten: T, two: T) where T: PartialEq + NumCast + Add + Sub + Mul + Div - + Rem + Show + + Rem + Debug + Copy { assert_eq!(ten.add(two), cast(12i).unwrap()); diff --git a/src/libcoretest/result.rs b/src/libcoretest/result.rs index 485549cc552a..daccb709890e 100644 --- a/src/libcoretest/result.rs +++ b/src/libcoretest/result.rs @@ -14,11 +14,11 @@ pub fn op2() -> Result { Err("sadface") } #[test] pub fn test_and() { assert_eq!(op1().and(Ok(667i)).unwrap(), 667); - assert_eq!(op1().and(Err::<(), &'static str>("bad")).unwrap_err(), + assert_eq!(op1().and(Err::("bad")).unwrap_err(), "bad"); assert_eq!(op2().and(Ok(667i)).unwrap_err(), "sadface"); - assert_eq!(op2().and(Err::<(),&'static str>("bad")).unwrap_err(), + assert_eq!(op2().and(Err::("bad")).unwrap_err(), "sadface"); } @@ -94,7 +94,7 @@ pub fn test_fmt_default() { let err: Result = Err("Err"); let s = format!("{:?}", ok); - assert_eq!(s, "Ok(100i)"); + assert_eq!(s, "Ok(100)"); let s = format!("{:?}", err); assert_eq!(s, "Err(\"Err\")"); } diff --git a/src/libcoretest/tuple.rs b/src/libcoretest/tuple.rs index 62eb9f4ad348..e524d8de0569 100644 --- a/src/libcoretest/tuple.rs +++ b/src/libcoretest/tuple.rs @@ -60,9 +60,9 @@ fn test_tuple_cmp() { #[test] fn test_show() { let s = format!("{:?}", (1i,)); - assert_eq!(s, "(1i,)"); + assert_eq!(s, "(1,)"); let s = format!("{:?}", (1i, true)); - assert_eq!(s, "(1i, true)"); + assert_eq!(s, "(1, true)"); let s = format!("{:?}", (1i, "hi", true)); - assert_eq!(s, "(1i, \"hi\", true)"); + assert_eq!(s, "(1, \"hi\", true)"); } diff --git a/src/libgetopts/lib.rs b/src/libgetopts/lib.rs index f62ffccabcca..4774262246a3 100644 --- a/src/libgetopts/lib.rs +++ b/src/libgetopts/lib.rs @@ -550,7 +550,7 @@ impl Fail { } } -impl fmt::String for Fail { +impl fmt::Display for Fail { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { ArgumentMissing(ref nm) => { @@ -899,7 +899,7 @@ fn each_split_within(ss: &str, lim: uint, mut it: F) -> bool where (B, Cr, UnderLim) => { B } (B, Cr, OverLim) if (i - last_start + 1) > lim => panic!("word starting with {} longer than limit!", - &ss[last_start..(i + 1)]), + &ss[last_start..i + 1]), (B, Cr, OverLim) => { *cont = it(&ss[slice_start..last_end]); slice_start = last_start; diff --git a/src/libgraphviz/lib.rs b/src/libgraphviz/lib.rs index 23597af68bc0..5ed93f0fd991 100644 --- a/src/libgraphviz/lib.rs +++ b/src/libgraphviz/lib.rs @@ -362,19 +362,19 @@ impl<'a> Id<'a> { /// /// Passing an invalid string (containing spaces, brackets, /// quotes, ...) will return an empty `Err` value. - pub fn new>(name: Name) -> Result, ()> { + pub fn new>(name: Name) -> Option> { let name = name.into_cow(); { let mut chars = name.chars(); match chars.next() { Some(c) if is_letter_or_underscore(c) => { ; }, - _ => return Err(()) + _ => return None } if !chars.all(is_constituent) { - return Err(()); + return None } } - return Ok(Id{ name: name }); + return Some(Id{ name: name }); fn is_letter_or_underscore(c: char) -> bool { in_range('a', c, 'z') || in_range('A', c, 'Z') || c == '_' @@ -878,8 +878,8 @@ r#"digraph syntax_tree { fn simple_id_construction() { let id1 = Id::new("hello"); match id1 { - Ok(_) => {;}, - Err(_) => panic!("'hello' is not a valid value for id anymore") + Some(_) => {;}, + None => panic!("'hello' is not a valid value for id anymore") } } @@ -887,8 +887,8 @@ r#"digraph syntax_tree { fn badly_formatted_id() { let id2 = Id::new("Weird { struct : ure } !!!"); match id2 { - Ok(_) => panic!("graphviz id suddenly allows spaces, brackets and stuff"), - Err(_) => {;} + Some(_) => panic!("graphviz id suddenly allows spaces, brackets and stuff"), + None => {;} } } } diff --git a/src/libgraphviz/maybe_owned_vec.rs b/src/libgraphviz/maybe_owned_vec.rs index 4f21ce411eec..71f117835935 100644 --- a/src/libgraphviz/maybe_owned_vec.rs +++ b/src/libgraphviz/maybe_owned_vec.rs @@ -125,7 +125,7 @@ impl<'a,T> FromIterator for MaybeOwnedVector<'a,T> { } } -impl<'a,T:fmt::Show> fmt::Show for MaybeOwnedVector<'a,T> { +impl<'a,T:fmt::Debug> fmt::Debug for MaybeOwnedVector<'a,T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.as_slice().fmt(f) } diff --git a/src/liblibc/lib.rs b/src/liblibc/lib.rs index ee5df1d6d2f4..548782216bbe 100644 --- a/src/liblibc/lib.rs +++ b/src/liblibc/lib.rs @@ -557,7 +557,8 @@ pub mod types { pub type mode_t = u16; pub type ssize_t = i32; } - #[cfg(target_arch = "x86")] + #[cfg(any(target_arch = "x86", + target_arch = "powerpc"))] pub mod posix01 { use types::os::arch::c95::{c_short, c_long, time_t}; use types::os::arch::posix88::{dev_t, gid_t, ino_t}; @@ -648,8 +649,7 @@ pub mod types { } } #[cfg(any(target_arch = "mips", - target_arch = "mipsel", - target_arch = "powerpc"))] + target_arch = "mipsel"))] pub mod posix01 { use types::os::arch::c95::{c_long, c_ulong, time_t}; use types::os::arch::posix88::{gid_t, ino_t}; @@ -2493,7 +2493,8 @@ pub mod consts { #[cfg(any(target_arch = "x86", target_arch = "x86_64", target_arch = "arm", - target_arch = "aarch64"))] + target_arch = "aarch64", + target_arch = "powerpc"))] pub mod posix88 { use types::os::arch::c95::c_int; use types::common::c95::c_void; @@ -2706,8 +2707,7 @@ pub mod consts { } #[cfg(any(target_arch = "mips", - target_arch = "mipsel", - target_arch = "powerpc"))] + target_arch = "mipsel"))] pub mod posix88 { use types::os::arch::c95::c_int; use types::common::c95::c_void; @@ -3004,7 +3004,8 @@ pub mod consts { #[cfg(any(target_arch = "arm", target_arch = "aarch64", target_arch = "x86", - target_arch = "x86_64"))] + target_arch = "x86_64", + target_arch = "powerpc"))] pub mod bsd44 { use types::os::arch::c95::c_int; @@ -3052,8 +3053,7 @@ pub mod consts { pub const SHUT_RDWR: c_int = 2; } #[cfg(any(target_arch = "mips", - target_arch = "mipsel", - target_arch = "powerpc"))] + target_arch = "mipsel"))] pub mod bsd44 { use types::os::arch::c95::c_int; @@ -3101,7 +3101,8 @@ pub mod consts { #[cfg(any(target_arch = "x86", target_arch = "x86_64", target_arch = "arm", - target_arch = "aarch64"))] + target_arch = "aarch64", + target_arch = "powerpc"))] pub mod extra { use types::os::arch::c95::c_int; @@ -3129,8 +3130,7 @@ pub mod consts { pub const MAP_STACK : c_int = 0x020000; } #[cfg(any(target_arch = "mips", - target_arch = "mipsel", - target_arch = "powerpc"))] + target_arch = "mipsel"))] pub mod extra { use types::os::arch::c95::c_int; @@ -4650,13 +4650,13 @@ pub mod funcs { use types::os::arch::c95::c_int; use types::os::common::posix01::sighandler_t; - #[cfg(not(target_os = "android"))] + #[cfg(not(all(target_os = "android", target_arch = "arm")))] extern { pub fn signal(signum: c_int, handler: sighandler_t) -> sighandler_t; } - #[cfg(target_os = "android")] + #[cfg(all(target_os = "android", target_arch = "arm"))] extern { #[link_name = "bsd_signal"] pub fn signal(signum: c_int, diff --git a/src/liblog/directive.rs b/src/liblog/directive.rs index d741019aa7b9..5efa799f5627 100644 --- a/src/liblog/directive.rs +++ b/src/liblog/directive.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use regex::Regex; use std::ascii::AsciiExt; use std::cmp; @@ -34,7 +33,7 @@ fn parse_log_level(level: &str) -> Option { /// /// Valid log levels are 0-255, with the most likely ones being 1-4 (defined in /// std::). Also supports string log levels of error, warn, info, and debug -pub fn parse_logging_spec(spec: &str) -> (Vec, Option) { +pub fn parse_logging_spec(spec: &str) -> (Vec, Option) { let mut dirs = Vec::new(); let mut parts = spec.split('/'); @@ -80,17 +79,7 @@ pub fn parse_logging_spec(spec: &str) -> (Vec, Option) { }); }}); - let filter = filter.map_or(None, |filter| { - match Regex::new(filter) { - Ok(re) => Some(re), - Err(e) => { - println!("warning: invalid regex filter - {:?}", e); - None - } - } - }); - - return (dirs, filter); + (dirs, filter.map(|s| s.to_string())) } #[cfg(test)] diff --git a/src/liblog/lib.rs b/src/liblog/lib.rs index 6fe789f3e311..05b831a5a592 100644 --- a/src/liblog/lib.rs +++ b/src/liblog/lib.rs @@ -123,11 +123,11 @@ //! //! # Filtering results //! -//! A RUST_LOG directive may include a regex filter. The syntax is to append `/` -//! followed by a regex. Each message is checked against the regex, and is only -//! logged if it matches. Note that the matching is done after formatting the log -//! string but before adding any logging meta-data. There is a single filter for all -//! modules. +//! A RUST_LOG directive may include a string filter. The syntax is to append +//! `/` followed by a string. Each message is checked against the string and is +//! only logged if it contains the string. Note that the matching is done after +//! formatting the log string but before adding any logging meta-data. There is +//! a single filter for all modules. //! //! Some examples: //! @@ -179,20 +179,17 @@ #![feature(rustc_private)] #![feature(std_misc)] -extern crate regex; - use std::cell::RefCell; use std::fmt; use std::io::LineBufferedWriter; use std::io; use std::mem; use std::os; +use std::ptr; use std::rt; use std::slice; use std::sync::{Once, ONCE_INIT}; -use regex::Regex; - use directive::LOG_LEVEL_NAMES; #[macro_use] @@ -215,8 +212,8 @@ static mut LOG_LEVEL: u32 = MAX_LOG_LEVEL; static mut DIRECTIVES: *const Vec = 0 as *const Vec; -/// Optional regex filter. -static mut FILTER: *const Regex = 0 as *const _; +/// Optional filter. +static mut FILTER: *const String = 0 as *const _; /// Debug log level pub const DEBUG: u32 = 4; @@ -246,21 +243,15 @@ struct DefaultLogger { } /// Wraps the log level with fmt implementations. -#[derive(Copy, PartialEq, PartialOrd)] +#[derive(Copy, PartialEq, PartialOrd, Show)] pub struct LogLevel(pub u32); -impl fmt::Show for LogLevel { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt::String::fmt(self, fmt) - } -} - -impl fmt::String for LogLevel { +impl fmt::Display for LogLevel { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let LogLevel(level) = *self; match LOG_LEVEL_NAMES.get(level as uint - 1) { - Some(ref name) => fmt::String::fmt(name, fmt), - None => fmt::String::fmt(&level, fmt) + Some(ref name) => fmt::Display::fmt(name, fmt), + None => fmt::Display::fmt(&level, fmt) } } } @@ -300,7 +291,7 @@ pub fn log(level: u32, loc: &'static LogLocation, args: fmt::Arguments) { // Test the literal string from args against the current filter, if there // is one. match unsafe { FILTER.as_ref() } { - Some(filter) if !filter.is_match(&args.to_string()[]) => return, + Some(filter) if !args.to_string().contains(&filter[]) => return, _ => {} } @@ -444,10 +435,10 @@ fn init() { assert!(!DIRECTIVES.is_null()); let _directives: Box> = mem::transmute(DIRECTIVES); - DIRECTIVES = 0 as *const Vec; + DIRECTIVES = ptr::null(); if !FILTER.is_null() { - let _filter: Box = mem::transmute(FILTER); + let _filter: Box = mem::transmute(FILTER); FILTER = 0 as *const _; } }); diff --git a/src/librand/chacha.rs b/src/librand/chacha.rs index 815fc0e7ec7a..3332e06e19e7 100644 --- a/src/librand/chacha.rs +++ b/src/librand/chacha.rs @@ -174,7 +174,7 @@ impl<'a> SeedableRng<&'a [u32]> for ChaChaRng { // reset state self.init(&[0u32; KEY_WORDS]); // set key in place - let key = self.state.slice_mut(4, 4+KEY_WORDS); + let key = &mut self.state[4 .. 4+KEY_WORDS]; for (k, s) in key.iter_mut().zip(seed.iter()) { *k = *s; } @@ -292,4 +292,3 @@ mod test { } } } - diff --git a/src/librbml/io.rs b/src/librbml/io.rs index f39860c8695c..9c746c69baaf 100644 --- a/src/librbml/io.rs +++ b/src/librbml/io.rs @@ -103,7 +103,7 @@ impl Writer for SeekableMemWriter { // Do the necessary writes if left.len() > 0 { - slice::bytes::copy_memory(self.buf.slice_from_mut(self.pos), left); + slice::bytes::copy_memory(&mut self.buf[self.pos..], left); } if right.len() > 0 { self.buf.push_all(right); diff --git a/src/librbml/lib.rs b/src/librbml/lib.rs index 40a29b88b997..2819dec3ebbf 100644 --- a/src/librbml/lib.rs +++ b/src/librbml/lib.rs @@ -42,6 +42,7 @@ pub use self::EbmlEncoderTag::*; pub use self::Error::*; use std::str; +use std::fmt; pub mod io; @@ -117,6 +118,13 @@ pub enum Error { IoError(std::io::IoError), ApplicationError(String) } + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + // FIXME: this should be a more useful display form + fmt::Debug::fmt(self, f) + } +} // -------------------------------------- pub mod reader { diff --git a/src/libregex/compile.rs b/src/libregex/compile.rs deleted file mode 100644 index d29a7a425c11..000000000000 --- a/src/libregex/compile.rs +++ /dev/null @@ -1,275 +0,0 @@ -// 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. - -// Enable this to squash warnings due to exporting pieces of the representation -// for use with the regex! macro. See lib.rs for explanation. - -pub use self::Inst::*; - -use std::cmp; -use std::iter::repeat; -use parse; -use parse::{ - Flags, FLAG_EMPTY, - Nothing, Literal, Dot, AstClass, Begin, End, WordBoundary, Capture, Cat, Alt, - Rep, - ZeroOne, ZeroMore, OneMore, -}; - -type InstIdx = uint; - -#[derive(Show, Clone)] -pub enum Inst { - // When a Match instruction is executed, the current thread is successful. - Match, - - // The OneChar instruction matches a literal character. - // The flags indicate whether to do a case insensitive match. - OneChar(char, Flags), - - // The CharClass instruction tries to match one input character against - // the range of characters given. - // The flags indicate whether to do a case insensitive match and whether - // the character class is negated or not. - CharClass(Vec<(char, char)>, Flags), - - // Matches any character except new lines. - // The flags indicate whether to include the '\n' character. - Any(Flags), - - // Matches the beginning of the string, consumes no characters. - // The flags indicate whether it matches if the preceding character - // is a new line. - EmptyBegin(Flags), - - // Matches the end of the string, consumes no characters. - // The flags indicate whether it matches if the proceeding character - // is a new line. - EmptyEnd(Flags), - - // Matches a word boundary (\w on one side and \W \A or \z on the other), - // and consumes no character. - // The flags indicate whether this matches a word boundary or something - // that isn't a word boundary. - EmptyWordBoundary(Flags), - - // Saves the current position in the input string to the Nth save slot. - Save(uint), - - // Jumps to the instruction at the index given. - Jump(InstIdx), - - // Jumps to the instruction at the first index given. If that leads to - // a panic state, then the instruction at the second index given is - // tried. - Split(InstIdx, InstIdx), -} - -/// Program represents a compiled regular expression. Once an expression is -/// compiled, its representation is immutable and will never change. -/// -/// All of the data in a compiled expression is wrapped in "MaybeStatic" or -/// "MaybeOwned" types so that a `Program` can be represented as static data. -/// (This makes it convenient and efficient for use with the `regex!` macro.) -#[derive(Clone)] -pub struct Program { - /// A sequence of instructions. - pub insts: Vec, - /// If the regular expression requires a literal prefix in order to have a - /// match, that prefix is stored here. (It's used in the VM to implement - /// an optimization.) - pub prefix: String, -} - -impl Program { - /// Compiles a Regex given its AST. - pub fn new(ast: parse::Ast) -> (Program, Vec>) { - let mut c = Compiler { - insts: Vec::with_capacity(100), - names: Vec::with_capacity(10), - }; - - c.insts.push(Save(0)); - c.compile(ast); - c.insts.push(Save(1)); - c.insts.push(Match); - - // Try to discover a literal string prefix. - // This is a bit hacky since we have to skip over the initial - // 'Save' instruction. - let mut pre = String::with_capacity(5); - for inst in c.insts[1..].iter() { - match *inst { - OneChar(c, FLAG_EMPTY) => pre.push(c), - _ => break - } - } - - let Compiler { insts, names } = c; - let prog = Program { - insts: insts, - prefix: pre, - }; - (prog, names) - } - - /// Returns the total number of capture groups in the regular expression. - /// This includes the zeroth capture. - pub fn num_captures(&self) -> uint { - let mut n = 0; - for inst in self.insts.iter() { - match *inst { - Save(c) => n = cmp::max(n, c+1), - _ => {} - } - } - // There's exactly 2 Save slots for every capture. - n / 2 - } -} - -struct Compiler<'r> { - insts: Vec, - names: Vec>, -} - -// The compiler implemented here is extremely simple. Most of the complexity -// in this crate is in the parser or the VM. -// The only tricky thing here is patching jump/split instructions to point to -// the right instruction. -impl<'r> Compiler<'r> { - fn compile(&mut self, ast: parse::Ast) { - match ast { - Nothing => {}, - Literal(c, flags) => self.push(OneChar(c, flags)), - Dot(nl) => self.push(Any(nl)), - AstClass(ranges, flags) => - self.push(CharClass(ranges, flags)), - Begin(flags) => self.push(EmptyBegin(flags)), - End(flags) => self.push(EmptyEnd(flags)), - WordBoundary(flags) => self.push(EmptyWordBoundary(flags)), - Capture(cap, name, x) => { - let len = self.names.len(); - if cap >= len { - self.names.extend(repeat(None).take(10 + cap - len)) - } - self.names[cap] = name; - - self.push(Save(2 * cap)); - self.compile(*x); - self.push(Save(2 * cap + 1)); - } - Cat(xs) => { - for x in xs.into_iter() { - self.compile(x) - } - } - Alt(x, y) => { - let split = self.empty_split(); // push: split 0, 0 - let j1 = self.insts.len(); - self.compile(*x); // push: insts for x - let jmp = self.empty_jump(); // push: jmp 0 - let j2 = self.insts.len(); - self.compile(*y); // push: insts for y - let j3 = self.insts.len(); - - self.set_split(split, j1, j2); // split 0, 0 -> split j1, j2 - self.set_jump(jmp, j3); // jmp 0 -> jmp j3 - } - Rep(x, ZeroOne, g) => { - let split = self.empty_split(); - let j1 = self.insts.len(); - self.compile(*x); - let j2 = self.insts.len(); - - if g.is_greedy() { - self.set_split(split, j1, j2); - } else { - self.set_split(split, j2, j1); - } - } - Rep(x, ZeroMore, g) => { - let j1 = self.insts.len(); - let split = self.empty_split(); - let j2 = self.insts.len(); - self.compile(*x); - let jmp = self.empty_jump(); - let j3 = self.insts.len(); - - self.set_jump(jmp, j1); - if g.is_greedy() { - self.set_split(split, j2, j3); - } else { - self.set_split(split, j3, j2); - } - } - Rep(x, OneMore, g) => { - let j1 = self.insts.len(); - self.compile(*x); - let split = self.empty_split(); - let j2 = self.insts.len(); - - if g.is_greedy() { - self.set_split(split, j1, j2); - } else { - self.set_split(split, j2, j1); - } - } - } - } - - /// Appends the given instruction to the program. - #[inline] - fn push(&mut self, x: Inst) { - self.insts.push(x) - } - - /// Appends an *empty* `Split` instruction to the program and returns - /// the index of that instruction. (The index can then be used to "patch" - /// the actual locations of the split in later.) - #[inline] - fn empty_split(&mut self) -> InstIdx { - self.insts.push(Split(0, 0)); - self.insts.len() - 1 - } - - /// Sets the left and right locations of a `Split` instruction at index - /// `i` to `pc1` and `pc2`, respectively. - /// If the instruction at index `i` isn't a `Split` instruction, then - /// `panic!` is called. - #[inline] - fn set_split(&mut self, i: InstIdx, pc1: InstIdx, pc2: InstIdx) { - let split = &mut self.insts[i]; - match *split { - Split(_, _) => *split = Split(pc1, pc2), - _ => panic!("BUG: Invalid split index."), - } - } - - /// Appends an *empty* `Jump` instruction to the program and returns the - /// index of that instruction. - #[inline] - fn empty_jump(&mut self) -> InstIdx { - self.insts.push(Jump(0)); - self.insts.len() - 1 - } - - /// Sets the location of a `Jump` instruction at index `i` to `pc`. - /// If the instruction at index `i` isn't a `Jump` instruction, then - /// `panic!` is called. - #[inline] - fn set_jump(&mut self, i: InstIdx, pc: InstIdx) { - let jmp = &mut self.insts[i]; - match *jmp { - Jump(_) => *jmp = Jump(pc), - _ => panic!("BUG: Invalid jump index."), - } - } -} diff --git a/src/libregex/lib.rs b/src/libregex/lib.rs deleted file mode 100644 index 9631eb36056b..000000000000 --- a/src/libregex/lib.rs +++ /dev/null @@ -1,97 +0,0 @@ -// 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. -// -// ignore-lexer-test FIXME #15679 - -//! Regular expressions implemented in Rust -//! -//! For official documentation, see the rust-lang/regex crate -#![crate_name = "regex"] -#![crate_type = "rlib"] -#![crate_type = "dylib"] -#![unstable(feature = "rustc_private", - reason = "use the crates.io `regex` library instead")] -#![feature(staged_api)] -#![staged_api] -#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", - html_favicon_url = "http://www.rust-lang.org/favicon.ico", - html_root_url = "http://doc.rust-lang.org/nightly/", - html_playground_url = "http://play.rust-lang.org/")] - -#![allow(unknown_features)] -#![feature(slicing_syntax)] -#![feature(box_syntax)] -#![allow(unknown_features)] #![feature(int_uint)] -#![deny(missing_docs)] -#![feature(collections)] -#![feature(core)] -#![feature(unicode)] - -#[cfg(test)] -extern crate "test" as stdtest; -#[cfg(test)] -extern crate rand; - -// During tests, this links with the `regex` crate so that the `regex!` macro -// can be tested. -#[cfg(test)] -extern crate regex; - -// Unicode tables for character classes are defined in libunicode -extern crate unicode; - -pub use parse::Error; -pub use re::{Regex, Captures, SubCaptures, SubCapturesPos}; -pub use re::{FindCaptures, FindMatches}; -pub use re::{Replacer, NoExpand, RegexSplits, RegexSplitsN}; -pub use re::{quote, is_match}; - -mod compile; -mod parse; -mod re; -mod vm; - -#[cfg(test)] -mod test; - -/// The `native` module exists to support the `regex!` macro. Do not use. -#[doc(hidden)] -pub mod native { - // Exporting this stuff is bad form, but it's necessary for two reasons. - // Firstly, the `regex!` syntax extension is in a different crate and - // requires access to the representation of a regex (particularly the - // instruction set) in order to compile to native Rust. This could be - // mitigated if `regex!` was defined in the same crate, but this has - // undesirable consequences (such as requiring a dependency on - // `libsyntax`). - // - // Secondly, the code generated by `regex!` must *also* be able - // to access various functions in this crate to reduce code duplication - // and to provide a value with precisely the same `Regex` type in this - // crate. This, AFAIK, is impossible to mitigate. - // - // On the bright side, `rustdoc` lets us hide this from the public API - // documentation. - pub use compile::{ - Program, - OneChar, CharClass, Any, Save, Jump, Split, - Match, EmptyBegin, EmptyEnd, EmptyWordBoundary, - }; - pub use parse::{ - FLAG_EMPTY, FLAG_NOCASE, FLAG_MULTI, FLAG_DOTNL, - FLAG_SWAP_GREED, FLAG_NEGATED, - }; - pub use re::{Dynamic, ExDynamic, Native, ExNative}; - pub use vm::{ - MatchKind, Exists, Location, Submatches, - StepState, StepMatchEarlyReturn, StepMatch, StepContinue, - CharReader, find_prefix, - }; -} diff --git a/src/libregex/parse.rs b/src/libregex/parse.rs deleted file mode 100644 index 1cc2b271e9cc..000000000000 --- a/src/libregex/parse.rs +++ /dev/null @@ -1,1086 +0,0 @@ -// 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. - -pub use self::Ast::*; -pub use self::Repeater::*; -pub use self::Greed::*; -use self::BuildAst::*; - -use std::char; -use std::cmp; -use std::fmt; -use std::iter; -use std::num; - -/// Static data containing Unicode ranges for general categories and scripts. -use unicode::regex::{UNICODE_CLASSES, PERLD, PERLS, PERLW}; - -/// The maximum number of repetitions allowed with the `{n,m}` syntax. -static MAX_REPEAT: uint = 1000; - -/// Error corresponds to something that can go wrong while parsing -/// a regular expression. -/// -/// (Once an expression is compiled, it is not possible to produce an error -/// via searching, splitting or replacing.) -pub struct Error { - /// The *approximate* character index of where the error occurred. - pub pos: uint, - /// A message describing the error. - pub msg: String, -} - -impl fmt::Show for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "Regex syntax error near position {}: {:?}", - self.pos, self.msg) - } -} - -/// Represents the abstract syntax of a regular expression. -/// It is showable so that error messages resulting from a bug can provide -/// useful information. -/// It is cloneable so that expressions can be repeated for the counted -/// repetition feature. (No other copying is done.) -/// -/// Note that this representation prevents one from reproducing the regex as -/// it was typed. (But it could be used to reproduce an equivalent regex.) -#[derive(Show, Clone)] -pub enum Ast { - Nothing, - Literal(char, Flags), - Dot(Flags), - AstClass(Vec<(char, char)>, Flags), - Begin(Flags), - End(Flags), - WordBoundary(Flags), - Capture(uint, Option, Box), - // Represent concatenation as a flat vector to avoid blowing the - // stack in the compiler. - Cat(Vec), - Alt(Box, Box), - Rep(Box, Repeater, Greed), -} - -#[derive(Show, PartialEq, Clone)] -pub enum Repeater { - ZeroOne, - ZeroMore, - OneMore, -} - -#[derive(Copy, Show, Clone)] -pub enum Greed { - Greedy, - Ungreedy, -} - -impl Greed { - pub fn is_greedy(&self) -> bool { - match *self { - Greedy => true, - _ => false, - } - } - - fn swap(self, swapped: bool) -> Greed { - if !swapped { return self } - match self { - Greedy => Ungreedy, - Ungreedy => Greedy, - } - } -} - -/// BuildAst is a regrettable type that represents intermediate state for -/// constructing an abstract syntax tree. Its central purpose is to facilitate -/// parsing groups and alternations while also maintaining a stack of flag -/// state. -#[derive(Show)] -enum BuildAst { - Expr(Ast), - Paren(Flags, uint, String), // '(' - Bar, // '|' -} - -impl BuildAst { - fn paren(&self) -> bool { - match *self { - Paren(_, _, _) => true, - _ => false, - } - } - - fn flags(&self) -> Flags { - match *self { - Paren(flags, _, _) => flags, - _ => panic!("Cannot get flags from {:?}", self), - } - } - - fn capture(&self) -> Option { - match *self { - Paren(_, 0, _) => None, - Paren(_, c, _) => Some(c), - _ => panic!("Cannot get capture group from {:?}", self), - } - } - - fn capture_name(&self) -> Option { - match *self { - Paren(_, 0, _) => None, - Paren(_, _, ref name) => { - if name.len() == 0 { - None - } else { - Some(name.clone()) - } - } - _ => panic!("Cannot get capture name from {:?}", self), - } - } - - fn bar(&self) -> bool { - match *self { - Bar => true, - _ => false, - } - } - - fn unwrap(self) -> Result { - match self { - Expr(x) => Ok(x), - _ => panic!("Tried to unwrap non-AST item: {:?}", self), - } - } -} - -/// Flags represents all options that can be twiddled by a user in an -/// expression. -pub type Flags = u8; - -pub const FLAG_EMPTY: u8 = 0; -pub const FLAG_NOCASE: u8 = 1 << 0; // i -pub const FLAG_MULTI: u8 = 1 << 1; // m -pub const FLAG_DOTNL: u8 = 1 << 2; // s -pub const FLAG_SWAP_GREED: u8 = 1 << 3; // U -pub const FLAG_NEGATED: u8 = 1 << 4; // char class or not word boundary - -struct Parser<'a> { - // The input, parsed only as a sequence of UTF8 code points. - chars: Vec, - // The index of the current character in the input. - chari: uint, - // The intermediate state representing the AST. - stack: Vec, - // The current set of flags. - flags: Flags, - // The total number of capture groups. - // Incremented each time an opening left paren is seen (assuming it is - // opening a capture group). - caps: uint, - // A set of all capture group names used only to detect duplicates. - names: Vec, -} - -pub fn parse(s: &str) -> Result { - Parser { - chars: s.chars().collect(), - chari: 0, - stack: vec!(), - flags: FLAG_EMPTY, - caps: 0, - names: vec!(), - }.parse() -} - -impl<'a> Parser<'a> { - fn parse(&mut self) -> Result { - if self.chars.len() == 0 { - return Ok(Nothing); - } - loop { - let c = self.cur(); - match c { - '?' | '*' | '+' => try!(self.push_repeater(c)), - '\\' => { - let ast = try!(self.parse_escape()); - self.push(ast) - } - '{' => try!(self.parse_counted()), - '[' => match self.try_parse_ascii() { - None => try!(self.parse_class()), - Some(class) => self.push(class), - }, - '(' => { - if self.peek_is(1, '?') { - try!(self.expect('?')); - try!(self.parse_group_opts()) - } else { - self.caps += 1; - self.stack.push(Paren(self.flags, - self.caps, - "".to_string())) - } - } - ')' => { - let catfrom = try!( - self.pos_last(false, |x| x.paren() || x.bar())); - try!(self.concat(catfrom)); - - let altfrom = try!(self.pos_last(false, |x| x.paren())); - // Before we smush the alternates together and pop off the - // left paren, let's grab the old flags and see if we - // need a capture. - let (cap, cap_name, oldflags) = { - let paren = &self.stack[altfrom-1]; - (paren.capture(), paren.capture_name(), paren.flags()) - }; - try!(self.alternate(altfrom)); - self.flags = oldflags; - - // If this was a capture, pop what we just pushed in - // alternate and make it a capture. - if cap.is_some() { - let ast = try!(self.pop_ast()); - self.push(Capture(cap.unwrap(), cap_name, box ast)); - } - } - '|' => { - let catfrom = try!( - self.pos_last(true, |x| x.paren() || x.bar())); - try!(self.concat(catfrom)); - - self.stack.push(Bar); - } - _ => try!(self.push_literal(c)), - } - if !self.next_char() { - break - } - } - - // Try to improve error handling. At this point, there should be - // no remaining open parens. - if self.stack.iter().any(|x| x.paren()) { - return self.err("Unclosed parenthesis.") - } - let catfrom = try!(self.pos_last(true, |x| x.bar())); - try!(self.concat(catfrom)); - try!(self.alternate(0)); - - assert!(self.stack.len() == 1); - self.pop_ast() - } - - fn noteof(&mut self, expected: &str) -> Result<(), Error> { - match self.next_char() { - true => Ok(()), - false => { - self.err(&format!("Expected {:?} but got EOF.", - expected)[]) - } - } - } - - fn expect(&mut self, expected: char) -> Result<(), Error> { - match self.next_char() { - true if self.cur() == expected => Ok(()), - true => self.err(&format!("Expected '{:?}' but got '{:?}'.", - expected, self.cur())[]), - false => { - self.err(&format!("Expected '{:?}' but got EOF.", - expected)[]) - } - } - } - - fn next_char(&mut self) -> bool { - self.chari += 1; - self.chari < self.chars.len() - } - - fn pop_ast(&mut self) -> Result { - match self.stack.pop().unwrap().unwrap() { - Err(e) => Err(e), - Ok(ast) => Ok(ast), - } - } - - fn push(&mut self, ast: Ast) { - self.stack.push(Expr(ast)) - } - - fn push_repeater(&mut self, c: char) -> Result<(), Error> { - match self.stack.last() { - Some(&Expr(..)) => (), - // self.stack is empty, or the top item is not an Expr - _ => return self.err("A repeat operator must be preceded by a valid expression."), - } - let rep: Repeater = match c { - '?' => ZeroOne, '*' => ZeroMore, '+' => OneMore, - _ => panic!("Not a valid repeater operator."), - }; - - match self.peek(1) { - Some('*') | Some('+') => - return self.err( - "Double repeat operators are not supported."), - _ => {}, - } - let ast = try!(self.pop_ast()); - match ast { - Begin(_) | End(_) | WordBoundary(_) => - return self.err( - "Repeat arguments cannot be empty width assertions."), - _ => {} - } - let greed = try!(self.get_next_greedy()); - self.push(Rep(box ast, rep, greed)); - Ok(()) - } - - fn push_literal(&mut self, c: char) -> Result<(), Error> { - let flags = self.flags; - match c { - '.' => { - self.push(Dot(flags)) - } - '^' => { - self.push(Begin(flags)) - } - '$' => { - self.push(End(flags)) - } - _ => { - self.push(Literal(c, flags)) - } - } - Ok(()) - } - - // Parses all forms of character classes. - // Assumes that '[' is the current character. - fn parse_class(&mut self) -> Result<(), Error> { - let negated = - if self.peek_is(1, '^') { - try!(self.expect('^')); - FLAG_NEGATED - } else { - FLAG_EMPTY - }; - let mut ranges: Vec<(char, char)> = vec!(); - let mut alts: Vec = vec!(); - - while self.peek_is(1, '-') { - try!(self.expect('-')); - ranges.push(('-', '-')) - } - loop { - try!(self.noteof("a closing ']' or a non-empty character class)")); - let mut c = self.cur(); - match c { - '[' => - match self.try_parse_ascii() { - Some(AstClass(asciis, flags)) => { - alts.push(AstClass(asciis, flags ^ negated)); - continue - } - Some(ast) => - panic!("Expected Class AST but got '{:?}'", ast), - // Just drop down and try to add as a regular character. - None => {}, - }, - '\\' => { - match try!(self.parse_escape()) { - AstClass(asciis, flags) => { - alts.push(AstClass(asciis, flags ^ negated)); - continue - } - Literal(c2, _) => c = c2, // process below - Begin(_) | End(_) | WordBoundary(_) => - return self.err( - "\\A, \\z, \\b and \\B are not valid escape \ - sequences inside a character class."), - ast => panic!("Unexpected AST item '{:?}'", ast), - } - } - ']' if ranges.len() > 0 || alts.len() > 0 => { - if ranges.len() > 0 { - let flags = negated | (self.flags & FLAG_NOCASE); - let mut ast = AstClass(combine_ranges(ranges), flags); - for alt in alts.into_iter() { - ast = Alt(box alt, box ast) - } - self.push(ast); - } else if alts.len() > 0 { - let mut ast = alts.pop().unwrap(); - for alt in alts.into_iter() { - ast = Alt(box alt, box ast) - } - self.push(ast); - } - return Ok(()) - } - _ => {} - } - - if self.peek_is(1, '-') && !self.peek_is(2, ']') { - try!(self.expect('-')); - // The regex can't end here. - try!(self.noteof("not a ']'")); - // End the range with a single character or character escape. - let mut c2 = self.cur(); - if c2 == '\\' { - match try!(self.parse_escape()) { - Literal(c3, _) => c2 = c3, // allow literal escapes below - ast => - return self.err(&format!("Expected a literal, but got {:?}.", - ast)[]), - } - } - if c2 < c { - return self.err(&format!("Invalid character class \ - range '{}-{}'", - c, - c2)[]) - } - ranges.push((c, self.cur())) - } else { - ranges.push((c, c)) - } - } - } - - // Tries to parse an ASCII character class of the form [:name:]. - // If successful, returns an AST character class corresponding to name - // and moves the parser to the final ']' character. - // If unsuccessful, no state is changed and None is returned. - // Assumes that '[' is the current character. - fn try_parse_ascii(&mut self) -> Option { - if !self.peek_is(1, ':') { - return None - } - let closer = - match self.pos(']') { - Some(i) => i, - None => return None, - }; - if self.chars[closer-1] != ':' { - return None - } - if closer - self.chari <= 3 { - return None - } - let mut name_start = self.chari + 2; - let negated = - if self.peek_is(2, '^') { - name_start += 1; - FLAG_NEGATED - } else { - FLAG_EMPTY - }; - let name = self.slice(name_start, closer - 1); - match find_class(ASCII_CLASSES, &name[]) { - None => None, - Some(ranges) => { - self.chari = closer; - let flags = negated | (self.flags & FLAG_NOCASE); - Some(AstClass(combine_ranges(ranges), flags)) - } - } - } - - // Parses counted repetition. Supports: - // {n}, {n,}, {n,m}, {n}?, {n,}? and {n,m}? - // Assumes that '{' is the current character. - // Returns either an error or moves the parser to the final '}' character. - // (Or the '?' character if not greedy.) - fn parse_counted(&mut self) -> Result<(), Error> { - // Scan until the closing '}' and grab the stuff in {}. - let start = self.chari; - let closer = - match self.pos('}') { - Some(i) => i, - None => { - return self.err(&format!("No closing brace for counted \ - repetition starting at position \ - {:?}.", - start)[]) - } - }; - self.chari = closer; - let greed = try!(self.get_next_greedy()); - let inner = self.chars[(start+1)..closer].iter().cloned() - .collect::(); - - // Parse the min and max values from the regex. - let (mut min, mut max): (uint, Option); - if !inner.contains(",") { - min = try!(self.parse_uint(&inner[])); - max = Some(min); - } else { - let pieces: Vec<&str> = inner.splitn(1, ',').collect(); - let (smin, smax) = (pieces[0], pieces[1]); - if smin.len() == 0 { - return self.err("Max repetitions cannot be specified \ - without min repetitions.") - } - min = try!(self.parse_uint(smin)); - max = - if smax.len() == 0 { - None - } else { - Some(try!(self.parse_uint(smax))) - }; - } - - // Do some bounds checking and make sure max >= min. - if min > MAX_REPEAT { - return self.err(&format!( - "{} exceeds maximum allowed repetitions ({})", - min, MAX_REPEAT)[]); - } - if max.is_some() { - let m = max.unwrap(); - if m > MAX_REPEAT { - return self.err(&format!( - "{} exceeds maximum allowed repetitions ({})", - m, MAX_REPEAT)[]); - } - if m < min { - return self.err(&format!( - "Max repetitions ({}) cannot be smaller than min \ - repetitions ({}).", m, min)[]); - } - } - - // Now manipulate the AST be repeating elements. - if max.is_none() { - // Require N copies of what's on the stack and then repeat it. - let ast = try!(self.pop_ast()); - for _ in iter::range(0, min) { - self.push(ast.clone()) - } - self.push(Rep(box ast, ZeroMore, greed)); - } else { - // Require N copies of what's on the stack and then repeat it - // up to M times optionally. - let ast = try!(self.pop_ast()); - for _ in iter::range(0, min) { - self.push(ast.clone()) - } - if max.is_some() { - for _ in iter::range(min, max.unwrap()) { - self.push(Rep(box ast.clone(), ZeroOne, greed)) - } - } - // It's possible that we popped something off the stack but - // never put anything back on it. To keep things simple, add - // a no-op expression. - if min == 0 && (max.is_none() || max == Some(0)) { - self.push(Nothing) - } - } - Ok(()) - } - - // Parses all escape sequences. - // Assumes that '\' is the current character. - fn parse_escape(&mut self) -> Result { - try!(self.noteof("an escape sequence following a '\\'")); - - let c = self.cur(); - if is_punct(c) { - return Ok(Literal(c, FLAG_EMPTY)) - } - match c { - 'a' => Ok(Literal('\x07', FLAG_EMPTY)), - 'f' => Ok(Literal('\x0C', FLAG_EMPTY)), - 't' => Ok(Literal('\t', FLAG_EMPTY)), - 'n' => Ok(Literal('\n', FLAG_EMPTY)), - 'r' => Ok(Literal('\r', FLAG_EMPTY)), - 'v' => Ok(Literal('\x0B', FLAG_EMPTY)), - 'A' => Ok(Begin(FLAG_EMPTY)), - 'z' => Ok(End(FLAG_EMPTY)), - 'b' => Ok(WordBoundary(FLAG_EMPTY)), - 'B' => Ok(WordBoundary(FLAG_NEGATED)), - '0'|'1'|'2'|'3'|'4'|'5'|'6'|'7' => Ok(try!(self.parse_octal())), - 'x' => Ok(try!(self.parse_hex())), - 'p' | 'P' => Ok(try!(self.parse_unicode_name())), - 'd' | 'D' | 's' | 'S' | 'w' | 'W' => { - let ranges = perl_unicode_class(c); - let mut flags = self.flags & FLAG_NOCASE; - if c.is_uppercase() { flags |= FLAG_NEGATED } - Ok(AstClass(ranges, flags)) - } - _ => { - self.err(&format!("Invalid escape sequence '\\\\{}'", c)[]) - } - } - } - - // Parses a Unicode character class name, either of the form \pF where - // F is a one letter Unicode class name or of the form \p{name} where - // name is the Unicode class name. - // Assumes that \p or \P has been read (and 'p' or 'P' is the current - // character). - fn parse_unicode_name(&mut self) -> Result { - let negated = if self.cur() == 'P' { FLAG_NEGATED } else { FLAG_EMPTY }; - let mut name: String; - if self.peek_is(1, '{') { - try!(self.expect('{')); - let closer = - match self.pos('}') { - Some(i) => i, - None => return self.err(&format!( - "Missing '}}' for unclosed '{{' at position {}", - self.chari)[]), - }; - if closer - self.chari + 1 == 0 { - return self.err("No Unicode class name found.") - } - name = self.slice(self.chari + 1, closer); - self.chari = closer; - } else { - if self.chari + 1 >= self.chars.len() { - return self.err("No single letter Unicode class name found.") - } - name = self.slice(self.chari + 1, self.chari + 2); - self.chari += 1; - } - match find_class(UNICODE_CLASSES, &name[]) { - None => { - return self.err(&format!("Could not find Unicode class '{}'", - name)[]) - } - Some(ranges) => { - Ok(AstClass(ranges, negated | (self.flags & FLAG_NOCASE))) - } - } - } - - // Parses an octal number, up to 3 digits. - // Assumes that \n has been read, where n is the first digit. - fn parse_octal(&mut self) -> Result { - let start = self.chari; - let mut end = start + 1; - let (d2, d3) = (self.peek(1), self.peek(2)); - if d2 >= Some('0') && d2 <= Some('7') { - try!(self.noteof("expected octal character in [0-7]")); - end += 1; - if d3 >= Some('0') && d3 <= Some('7') { - try!(self.noteof("expected octal character in [0-7]")); - end += 1; - } - } - let s = self.slice(start, end); - match num::from_str_radix::(&s[], 8) { - Some(n) => Ok(Literal(try!(self.char_from_u32(n)), FLAG_EMPTY)), - None => { - self.err(&format!("Could not parse '{:?}' as octal number.", - s)[]) - } - } - } - - // Parse a hex number. Either exactly two digits or anything in {}. - // Assumes that \x has been read. - fn parse_hex(&mut self) -> Result { - if !self.peek_is(1, '{') { - try!(self.expect('{')); - return self.parse_hex_two() - } - let start = self.chari + 2; - let closer = - match self.pos('}') { - None => { - return self.err(&format!("Missing '}}' for unclosed \ - '{{' at position {}", - start)[]) - } - Some(i) => i, - }; - self.chari = closer; - self.parse_hex_digits(&self.slice(start, closer)[]) - } - - // Parses a two-digit hex number. - // Assumes that \xn has been read, where n is the first digit and is the - // current character. - // After return, parser will point at the second digit. - fn parse_hex_two(&mut self) -> Result { - let (start, end) = (self.chari, self.chari + 2); - let bad = self.slice(start - 2, self.chars.len()); - try!(self.noteof(format!("Invalid hex escape sequence '{}'", - bad).as_slice())); - self.parse_hex_digits(self.slice(start, end).as_slice()) - } - - // Parses `s` as a hexadecimal number. - fn parse_hex_digits(&self, s: &str) -> Result { - match num::from_str_radix::(s, 16) { - Some(n) => Ok(Literal(try!(self.char_from_u32(n)), FLAG_EMPTY)), - None => { - self.err(&format!("Could not parse '{}' as hex number.", s)[]) - } - } - } - - // Parses a named capture. - // Assumes that '(?P<' has been consumed and that the current character - // is '<'. - // When done, parser will be at the closing '>' character. - fn parse_named_capture(&mut self) -> Result<(), Error> { - try!(self.noteof("a capture name")); - let closer = - match self.pos('>') { - Some(i) => i, - None => return self.err("Capture name must end with '>'."), - }; - if closer - self.chari == 0 { - return self.err("Capture names must have at least 1 character.") - } - let name = self.slice(self.chari, closer); - if !name.chars().all(is_valid_cap) { - return self.err( - "Capture names can only have underscores, letters and digits.") - } - if self.names.contains(&name) { - return self.err(&format!("Duplicate capture group name '{}'.", - name)[]) - } - self.names.push(name.clone()); - self.chari = closer; - self.caps += 1; - self.stack.push(Paren(self.flags, self.caps, name)); - Ok(()) - } - - // Parses non-capture groups and options. - // Assumes that '(?' has already been consumed and '?' is the current - // character. - fn parse_group_opts(&mut self) -> Result<(), Error> { - if self.peek_is(1, 'P') && self.peek_is(2, '<') { - try!(self.expect('P')); - try!(self.expect('<')); - return self.parse_named_capture() - } - let start = self.chari; - let mut flags = self.flags; - let mut sign = 1i; - let mut saw_flag = false; - loop { - try!(self.noteof( - "expected non-empty set of flags or closing ')'")); - match self.cur() { - 'i' => { flags = flags | FLAG_NOCASE; saw_flag = true}, - 'm' => { flags = flags | FLAG_MULTI; saw_flag = true}, - 's' => { flags = flags | FLAG_DOTNL; saw_flag = true}, - 'U' => { flags = flags | FLAG_SWAP_GREED; saw_flag = true}, - '-' => { - if sign < 0 { - return self.err(&format!( - "Cannot negate flags twice in '{}'.", - self.slice(start, self.chari + 1))[]) - } - sign = -1; - saw_flag = false; - flags = flags ^ flags; - } - ':' | ')' => { - if sign < 0 { - if !saw_flag { - return self.err(&format!( - "A valid flag does not follow negation in '{}'", - self.slice(start, self.chari + 1))[]) - } - flags = flags ^ flags; - } - if self.cur() == ':' { - // Save the old flags with the opening paren. - self.stack.push(Paren(self.flags, 0, "".to_string())); - } - self.flags = flags; - return Ok(()) - } - _ => return self.err(&format!( - "Unrecognized flag '{}'.", self.cur())[]), - } - } - } - - // Peeks at the next character and returns whether it's ungreedy or not. - // If it is, then the next character is consumed. - fn get_next_greedy(&mut self) -> Result { - Ok(if self.peek_is(1, '?') { - try!(self.expect('?')); - Ungreedy - } else { - Greedy - }.swap(self.flags & FLAG_SWAP_GREED > 0)) - } - - // Searches the stack (starting at the top) until it finds an expression - // for which `pred` returns true. The index of that expression in the - // stack is returned. - // If there's no match, then one of two things happens depending on the - // values of `allow_start`. When it's true, then `0` will be returned. - // Otherwise, an error will be returned. - // Generally, `allow_start` is only true when you're *not* expecting an - // opening parenthesis. - fn pos_last

(&self, allow_start: bool, pred: P) -> Result where - P: FnMut(&BuildAst) -> bool, - { - let from = match self.stack.iter().rev().position(pred) { - Some(i) => i, - None => { - if allow_start { - self.stack.len() - } else { - return self.err("No matching opening parenthesis.") - } - } - }; - // Adjust index since 'from' is for the reversed stack. - // Also, don't include the '(' or '|'. - Ok(self.stack.len() - from) - } - - // concat starts at `from` in the parser's stack and concatenates all - // expressions up to the top of the stack. The resulting concatenation is - // then pushed on to the stack. - // Usually `from` corresponds to the position of an opening parenthesis, - // a '|' (alternation) or the start of the entire expression. - fn concat(&mut self, from: uint) -> Result<(), Error> { - let ast = try!(self.build_from(from, concat_flatten)); - self.push(ast); - Ok(()) - } - - // concat starts at `from` in the parser's stack and alternates all - // expressions up to the top of the stack. The resulting alternation is - // then pushed on to the stack. - // Usually `from` corresponds to the position of an opening parenthesis - // or the start of the entire expression. - // This will also drop any opening parens or alternation bars found in - // the intermediate AST. - fn alternate(&mut self, mut from: uint) -> Result<(), Error> { - // Unlike in the concatenation case, we want 'build_from' to continue - // all the way to the opening left paren (so it will be popped off and - // thrown away). But be careful with overflow---we can't count on the - // open paren to be there. - if from > 0 { from = from - 1} - let ast = try!(self.build_from(from, |l,r| Alt(box l, box r))); - self.push(ast); - Ok(()) - } - - // build_from combines all AST elements starting at 'from' in the - // parser's stack using 'mk' to combine them. If any such element is not an - // AST then it is popped off the stack and ignored. - fn build_from(&mut self, from: uint, mut mk: F) -> Result where - F: FnMut(Ast, Ast) -> Ast, - { - if from >= self.stack.len() { - return self.err("Empty group or alternate not allowed.") - } - - let mut combined = try!(self.pop_ast()); - let mut i = self.stack.len(); - while i > from { - i = i - 1; - match self.stack.pop().unwrap() { - Expr(x) => combined = mk(x, combined), - _ => {}, - } - } - Ok(combined) - } - - fn parse_uint(&self, s: &str) -> Result { - match s.parse::() { - Some(i) => Ok(i), - None => { - self.err(&format!("Expected an unsigned integer but got '{}'.", - s)[]) - } - } - } - - fn char_from_u32(&self, n: u32) -> Result { - match char::from_u32(n) { - Some(c) => Ok(c), - None => { - self.err(&format!("Could not decode '{}' to unicode \ - character.", n)[]) - } - } - } - - fn pos(&self, c: char) -> Option { - self.chars.iter() - .skip(self.chari).position(|&c2| c2 == c).map(|i| self.chari + i) - } - - fn err(&self, msg: &str) -> Result { - Err(Error { - pos: self.chari, - msg: msg.to_string(), - }) - } - - fn peek(&self, offset: uint) -> Option { - if self.chari + offset >= self.chars.len() { - return None - } - Some(self.chars[self.chari + offset]) - } - - fn peek_is(&self, offset: uint, is: char) -> bool { - self.peek(offset) == Some(is) - } - - fn cur(&self) -> char { - self.chars[self.chari] - } - - fn slice(&self, start: uint, end: uint) -> String { - self.chars[start..end].iter().cloned().collect() - } -} - -// Given an unordered collection of character ranges, combine_ranges returns -// an ordered sequence of character ranges where no two ranges overlap. They -// are ordered from least to greatest (using start position). -fn combine_ranges(unordered: Vec<(char, char)>) -> Vec<(char, char)> { - // Returns true iff the two character classes overlap or share a boundary. - // e.g., ('a', 'g') and ('h', 'm') would return true. - fn should_merge((a, b): (char, char), (x, y): (char, char)) -> bool { - cmp::max(a, x) as u32 <= cmp::min(b, y) as u32 + 1 - } - - // This is currently O(n^2), but I think with sufficient cleverness, - // it can be reduced to O(n) **if necessary**. - let mut ordered: Vec<(char, char)> = Vec::with_capacity(unordered.len()); - for (us, ue) in unordered.into_iter() { - let (mut us, mut ue) = (us, ue); - assert!(us <= ue); - let mut which: Option = None; - for (i, &(os, oe)) in ordered.iter().enumerate() { - if should_merge((us, ue), (os, oe)) { - us = cmp::min(us, os); - ue = cmp::max(ue, oe); - which = Some(i); - break - } - } - match which { - None => ordered.push((us, ue)), - Some(i) => ordered[i] = (us, ue), - } - } - ordered.sort(); - ordered -} - -// Constructs a Unicode friendly Perl character class from \d, \s or \w -// (or any of their negated forms). Note that this does not handle negation. -fn perl_unicode_class(which: char) -> Vec<(char, char)> { - match which.to_lowercase() { - 'd' => PERLD.to_vec(), - 's' => PERLS.to_vec(), - 'w' => PERLW.to_vec(), - _ => unreachable!(), - } -} - -// Returns a concatenation of two expressions. This also guarantees that a -// `Cat` expression will never be a direct child of another `Cat` expression. -fn concat_flatten(x: Ast, y: Ast) -> Ast { - match (x, y) { - (Cat(mut xs), Cat(ys)) => { xs.extend(ys.into_iter()); Cat(xs) } - (Cat(mut xs), ast) => { xs.push(ast); Cat(xs) } - (ast, Cat(mut xs)) => { xs.insert(0, ast); Cat(xs) } - (ast1, ast2) => Cat(vec!(ast1, ast2)), - } -} - -pub fn is_punct(c: char) -> bool { - match c { - '\\' | '.' | '+' | '*' | '?' | '(' | ')' | '|' | - '[' | ']' | '{' | '}' | '^' | '$' => true, - _ => false, - } -} - -fn is_valid_cap(c: char) -> bool { - c == '_' || (c >= '0' && c <= '9') - || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') -} - -fn find_class(classes: NamedClasses, name: &str) -> Option> { - match classes.binary_search_by(|&(s, _)| s.cmp(name)) { - Ok(i) => Some(classes[i].1.to_vec()), - Err(_) => None, - } -} - -type Class = &'static [(char, char)]; -type NamedClasses = &'static [(&'static str, &'static Class)]; - -static ASCII_CLASSES: NamedClasses = &[ - // Classes must be in alphabetical order so that bsearch works. - // [:alnum:] alphanumeric (== [0-9A-Za-z]) - // [:alpha:] alphabetic (== [A-Za-z]) - // [:ascii:] ASCII (== [\x00-\x7F]) - // [:blank:] blank (== [\t ]) - // [:cntrl:] control (== [\x00-\x1F\x7F]) - // [:digit:] digits (== [0-9]) - // [:graph:] graphical (== [!-~]) - // [:lower:] lower case (== [a-z]) - // [:print:] printable (== [ -~] == [ [:graph:]]) - // [:punct:] punctuation (== [!-/:-@[-`{-~]) - // [:space:] whitespace (== [\t\n\v\f\r ]) - // [:upper:] upper case (== [A-Z]) - // [:word:] word characters (== [0-9A-Za-z_]) - // [:xdigit:] hex digit (== [0-9A-Fa-f]) - // Taken from: http://golang.org/pkg/regex/syntax/ - ("alnum", &ALNUM), - ("alpha", &ALPHA), - ("ascii", &ASCII), - ("blank", &BLANK), - ("cntrl", &CNTRL), - ("digit", &DIGIT), - ("graph", &GRAPH), - ("lower", &LOWER), - ("print", &PRINT), - ("punct", &PUNCT), - ("space", &SPACE), - ("upper", &UPPER), - ("word", &WORD), - ("xdigit", &XDIGIT), -]; - -static ALNUM: Class = &[('0', '9'), ('A', 'Z'), ('a', 'z')]; -static ALPHA: Class = &[('A', 'Z'), ('a', 'z')]; -static ASCII: Class = &[('\x00', '\x7F')]; -static BLANK: Class = &[(' ', ' '), ('\t', '\t')]; -static CNTRL: Class = &[('\x00', '\x1F'), ('\x7F', '\x7F')]; -static DIGIT: Class = &[('0', '9')]; -static GRAPH: Class = &[('!', '~')]; -static LOWER: Class = &[('a', 'z')]; -static PRINT: Class = &[(' ', '~')]; -static PUNCT: Class = &[('!', '/'), (':', '@'), ('[', '`'), ('{', '~')]; -static SPACE: Class = &[('\t', '\t'), ('\n', '\n'), ('\x0B', '\x0B'), - ('\x0C', '\x0C'), ('\r', '\r'), (' ', ' ')]; -static UPPER: Class = &[('A', 'Z')]; -static WORD: Class = &[('0', '9'), ('A', 'Z'), ('a', 'z'), ('_', '_')]; -static XDIGIT: Class = &[('0', '9'), ('A', 'F'), ('a', 'f')]; diff --git a/src/libregex/re.rs b/src/libregex/re.rs deleted file mode 100644 index 8c9df74635a7..000000000000 --- a/src/libregex/re.rs +++ /dev/null @@ -1,682 +0,0 @@ -// 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. - -pub use self::NamesIter::*; -pub use self::Regex::*; - -use std::borrow::IntoCow; -use std::collections::HashMap; -use std::fmt; -use std::string::CowString; - -use compile::Program; -use parse; -use vm; -use vm::{CaptureLocs, MatchKind, Exists, Location, Submatches}; - -/// Escapes all regular expression meta characters in `text`. -/// -/// The string returned may be safely used as a literal in a regular -/// expression. -pub fn quote(text: &str) -> String { - let mut quoted = String::with_capacity(text.len()); - for c in text.chars() { - if parse::is_punct(c) { - quoted.push('\\') - } - quoted.push(c); - } - quoted -} - -/// Tests if the given regular expression matches somewhere in the text given. -/// -/// If there was a problem compiling the regular expression, an error is -/// returned. -/// -/// To find submatches, split or replace text, you'll need to compile an -/// expression first. -/// -/// Note that you should prefer the `regex!` macro when possible. For example, -/// `regex!("...").is_match("...")`. -pub fn is_match(regex: &str, text: &str) -> Result { - Regex::new(regex).map(|r| r.is_match(text)) -} - -/// A compiled regular expression -#[derive(Clone)] -pub enum Regex { - // The representation of `Regex` is exported to support the `regex!` - // syntax extension. Do not rely on it. - // - // See the comments for the `program` module in `lib.rs` for a more - // detailed explanation for what `regex!` requires. - #[doc(hidden)] - Dynamic(ExDynamic), - #[doc(hidden)] - Native(ExNative), -} - -#[derive(Clone)] -#[doc(hidden)] -pub struct ExDynamic { - original: String, - names: Vec>, - #[doc(hidden)] - pub prog: Program -} - -#[doc(hidden)] -#[derive(Copy)] -pub struct ExNative { - #[doc(hidden)] - pub original: &'static str, - #[doc(hidden)] - pub names: &'static &'static [Option<&'static str>], - #[doc(hidden)] - pub prog: fn(MatchKind, &str, uint, uint) -> Vec> -} - -impl Clone for ExNative { - fn clone(&self) -> ExNative { - *self - } -} - -impl fmt::String for Regex { - /// Shows the original regular expression. - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::String::fmt(self.as_str(), f) - } -} - -impl Regex { - /// Compiles a dynamic regular expression. Once compiled, it can be - /// used repeatedly to search, split or replace text in a string. - /// - /// When possible, you should prefer the `regex!` macro since it is - /// safer and always faster. - /// - /// If an invalid expression is given, then an error is returned. - pub fn new(re: &str) -> Result { - let ast = try!(parse::parse(re)); - let (prog, names) = Program::new(ast); - Ok(Dynamic(ExDynamic { - original: re.to_string(), - names: names, - prog: prog, - })) - } - - /// Returns true if and only if the regex matches the string given. - pub fn is_match(&self, text: &str) -> bool { - has_match(&exec(self, Exists, text)) - } - - /// Returns the start and end byte range of the leftmost-first match in - /// `text`. If no match exists, then `None` is returned. - pub fn find(&self, text: &str) -> Option<(uint, uint)> { - let caps = exec(self, Location, text); - if has_match(&caps) { - Some((caps[0].unwrap(), caps[1].unwrap())) - } else { - None - } - } - - /// Returns an iterator for each successive non-overlapping match in - /// `text`, returning the start and end byte indices with respect to - /// `text`. - pub fn find_iter<'r, 't>(&'r self, text: &'t str) -> FindMatches<'r, 't> { - FindMatches { - re: self, - search: text, - last_end: 0, - last_match: None, - } - } - - /// Returns the capture groups corresponding to the leftmost-first - /// match in `text`. Capture group `0` always corresponds to the entire - /// match. If no match is found, then `None` is returned. - /// - /// You should only use `captures` if you need access to submatches. - /// Otherwise, `find` is faster for discovering the location of the overall - /// match. - pub fn captures<'t>(&self, text: &'t str) -> Option> { - let caps = exec(self, Submatches, text); - Captures::new(self, text, caps) - } - - /// Returns an iterator over all the non-overlapping capture groups matched - /// in `text`. This is operationally the same as `find_iter` (except it - /// yields information about submatches). - pub fn captures_iter<'r, 't>(&'r self, text: &'t str) - -> FindCaptures<'r, 't> { - FindCaptures { - re: self, - search: text, - last_match: None, - last_end: 0, - } - } - - /// Returns an iterator of substrings of `text` delimited by a match - /// of the regular expression. - /// Namely, each element of the iterator corresponds to text that *isn't* - /// matched by the regular expression. - /// - /// This method will *not* copy the text given. - pub fn split<'r, 't>(&'r self, text: &'t str) -> RegexSplits<'r, 't> { - RegexSplits { - finder: self.find_iter(text), - last: 0, - } - } - - /// Returns an iterator of at most `limit` substrings of `text` delimited - /// by a match of the regular expression. (A `limit` of `0` will return no - /// substrings.) - /// Namely, each element of the iterator corresponds to text that *isn't* - /// matched by the regular expression. - /// The remainder of the string that is not split will be the last element - /// in the iterator. - /// - /// This method will *not* copy the text given. - pub fn splitn<'r, 't>(&'r self, text: &'t str, limit: uint) - -> RegexSplitsN<'r, 't> { - RegexSplitsN { - splits: self.split(text), - cur: 0, - limit: limit, - } - } - - /// Replaces the leftmost-first match with the replacement provided. - /// The replacement can be a regular string (where `$N` and `$name` are - /// expanded to match capture groups) or a function that takes the matches' - /// `Captures` and returns the replaced string. - /// - /// If no match is found, then a copy of the string is returned unchanged. - pub fn replace(&self, text: &str, rep: R) -> String { - self.replacen(text, 1, rep) - } - - /// Replaces all non-overlapping matches in `text` with the - /// replacement provided. This is the same as calling `replacen` with - /// `limit` set to `0`. - /// - /// See the documentation for `replace` for details on how to access - /// submatches in the replacement string. - pub fn replace_all(&self, text: &str, rep: R) -> String { - self.replacen(text, 0, rep) - } - - /// Replaces at most `limit` non-overlapping matches in `text` with the - /// replacement provided. If `limit` is 0, then all non-overlapping matches - /// are replaced. - /// - /// See the documentation for `replace` for details on how to access - /// submatches in the replacement string. - pub fn replacen - (&self, text: &str, limit: uint, mut rep: R) -> String { - let mut new = String::with_capacity(text.len()); - let mut last_match = 0u; - - for (i, cap) in self.captures_iter(text).enumerate() { - // It'd be nicer to use the 'take' iterator instead, but it seemed - // awkward given that '0' => no limit. - if limit > 0 && i >= limit { - break - } - - let (s, e) = cap.pos(0).unwrap(); // captures only reports matches - new.push_str(&text[last_match..s]); - new.push_str(&rep.reg_replace(&cap)[]); - last_match = e; - } - new.push_str(&text[last_match..text.len()]); - return new; - } - - /// Returns the original string of this regex. - pub fn as_str<'a>(&'a self) -> &'a str { - match *self { - Dynamic(ExDynamic { ref original, .. }) => &original[], - Native(ExNative { ref original, .. }) => &original[], - } - } - - #[doc(hidden)] - pub fn names_iter<'a>(&'a self) -> NamesIter<'a> { - match *self { - Native(ref n) => NamesIterNative(n.names.iter()), - Dynamic(ref d) => NamesIterDynamic(d.names.iter()) - } - } - - fn names_len(&self) -> uint { - match *self { - Native(ref n) => n.names.len(), - Dynamic(ref d) => d.names.len() - } - } - -} - -#[derive(Clone)] -pub enum NamesIter<'a> { - NamesIterNative(::std::slice::Iter<'a, Option<&'static str>>), - NamesIterDynamic(::std::slice::Iter<'a, Option>) -} - -impl<'a> Iterator for NamesIter<'a> { - type Item = Option; - - fn next(&mut self) -> Option> { - match *self { - NamesIterNative(ref mut i) => i.next().map(|x| x.map(|s| s.to_string())), - NamesIterDynamic(ref mut i) => i.next().map(|x| x.as_ref().map(|s| s.to_string())), - } - } -} - -/// NoExpand indicates literal string replacement. -/// -/// It can be used with `replace` and `replace_all` to do a literal -/// string replacement without expanding `$name` to their corresponding -/// capture groups. -/// -/// `'r` is the lifetime of the literal text. -pub struct NoExpand<'t>(pub &'t str); - -/// Replacer describes types that can be used to replace matches in a string. -pub trait Replacer { - /// Returns a possibly owned string that is used to replace the match - /// corresponding to the `caps` capture group. - /// - /// The `'a` lifetime refers to the lifetime of a borrowed string when - /// a new owned string isn't needed (e.g., for `NoExpand`). - fn reg_replace<'a>(&'a mut self, caps: &Captures) -> CowString<'a>; -} - -impl<'t> Replacer for NoExpand<'t> { - fn reg_replace<'a>(&'a mut self, _: &Captures) -> CowString<'a> { - let NoExpand(s) = *self; - s.into_cow() - } -} - -impl<'t> Replacer for &'t str { - fn reg_replace<'a>(&'a mut self, caps: &Captures) -> CowString<'a> { - caps.expand(*self).into_cow() - } -} - -impl Replacer for F where F: FnMut(&Captures) -> String { - fn reg_replace<'a>(&'a mut self, caps: &Captures) -> CowString<'a> { - (*self)(caps).into_cow() - } -} - -/// Yields all substrings delimited by a regular expression match. -/// -/// `'r` is the lifetime of the compiled expression and `'t` is the lifetime -/// of the string being split. -#[derive(Clone)] -pub struct RegexSplits<'r, 't> { - finder: FindMatches<'r, 't>, - last: uint, -} - -impl<'r, 't> Iterator for RegexSplits<'r, 't> { - type Item = &'t str; - - fn next(&mut self) -> Option<&'t str> { - let text = self.finder.search; - match self.finder.next() { - None => { - if self.last >= text.len() { - None - } else { - let s = &text[self.last..text.len()]; - self.last = text.len(); - Some(s) - } - } - Some((s, e)) => { - let matched = &text[self.last..s]; - self.last = e; - Some(matched) - } - } - } -} - -/// Yields at most `N` substrings delimited by a regular expression match. -/// -/// The last substring will be whatever remains after splitting. -/// -/// `'r` is the lifetime of the compiled expression and `'t` is the lifetime -/// of the string being split. -#[derive(Clone)] -pub struct RegexSplitsN<'r, 't> { - splits: RegexSplits<'r, 't>, - cur: uint, - limit: uint, -} - -impl<'r, 't> Iterator for RegexSplitsN<'r, 't> { - type Item = &'t str; - - fn next(&mut self) -> Option<&'t str> { - let text = self.splits.finder.search; - if self.cur >= self.limit { - None - } else { - self.cur += 1; - if self.cur >= self.limit { - Some(&text[self.splits.last..text.len()]) - } else { - self.splits.next() - } - } - } -} - -/// Captures represents a group of captured strings for a single match. -/// -/// The 0th capture always corresponds to the entire match. Each subsequent -/// index corresponds to the next capture group in the regex. -/// If a capture group is named, then the matched string is *also* available -/// via the `name` method. (Note that the 0th capture is always unnamed and so -/// must be accessed with the `at` method.) -/// -/// Positions returned from a capture group are always byte indices. -/// -/// `'t` is the lifetime of the matched text. -pub struct Captures<'t> { - text: &'t str, - locs: CaptureLocs, - named: Option>, -} - -impl<'t> Captures<'t> { - fn new(re: &Regex, search: &'t str, locs: CaptureLocs) - -> Option> { - if !has_match(&locs) { - return None - } - - let named = - if re.names_len() == 0 { - None - } else { - let mut named = HashMap::new(); - for (i, name) in re.names_iter().enumerate() { - match name { - None => {}, - Some(name) => { - named.insert(name, i); - } - } - } - Some(named) - }; - Some(Captures { - text: search, - locs: locs, - named: named, - }) - } - - /// Returns the start and end positions of the Nth capture group. - /// Returns `None` if `i` is not a valid capture group or if the capture - /// group did not match anything. - /// The positions returned are *always* byte indices with respect to the - /// original string matched. - pub fn pos(&self, i: uint) -> Option<(uint, uint)> { - let (s, e) = (i * 2, i * 2 + 1); - if e >= self.locs.len() || self.locs[s].is_none() { - // VM guarantees that each pair of locations are both Some or None. - return None - } - Some((self.locs[s].unwrap(), self.locs[e].unwrap())) - } - - /// Returns the matched string for the capture group `i`. If `i` isn't - /// a valid capture group or didn't match anything, then `None` is - /// returned. - pub fn at(&self, i: uint) -> Option<&'t str> { - match self.pos(i) { - None => None, - Some((s, e)) => Some(self.text.slice(s, e)) - } - } - - /// Returns the matched string for the capture group named `name`. If - /// `name` isn't a valid capture group or didn't match anything, then - /// `None` is returned. - pub fn name(&self, name: &str) -> Option<&'t str> { - match self.named { - None => None, - Some(ref h) => { - match h.get(name) { - None => None, - Some(i) => self.at(*i), - } - } - } - } - - /// Creates an iterator of all the capture groups in order of appearance - /// in the regular expression. - pub fn iter(&'t self) -> SubCaptures<'t> { - SubCaptures { idx: 0, caps: self, } - } - - /// Creates an iterator of all the capture group positions in order of - /// appearance in the regular expression. Positions are byte indices - /// in terms of the original string matched. - pub fn iter_pos(&'t self) -> SubCapturesPos<'t> { - SubCapturesPos { idx: 0, caps: self, } - } - - /// Expands all instances of `$name` in `text` to the corresponding capture - /// group `name`. - /// - /// `name` may be an integer corresponding to the index of the - /// capture group (counted by order of opening parenthesis where `0` is the - /// entire match) or it can be a name (consisting of letters, digits or - /// underscores) corresponding to a named capture group. - /// - /// If `name` isn't a valid capture group (whether the name doesn't exist or - /// isn't a valid index), then it is replaced with the empty string. - /// - /// To write a literal `$` use `$$`. - pub fn expand(&self, text: &str) -> String { - // How evil can you get? - // FIXME: Don't use regexes for this. It's completely unnecessary. - let re = Regex::new(r"(^|[^$]|\b)\$(\w+)").unwrap(); - let text = re.replace_all(text, |&mut: refs: &Captures| -> String { - let pre = refs.at(1).unwrap_or(""); - let name = refs.at(2).unwrap_or(""); - format!("{}{}", pre, - match name.parse::() { - None => self.name(name).unwrap_or("").to_string(), - Some(i) => self.at(i).unwrap_or("").to_string(), - }) - }); - let re = Regex::new(r"\$\$").unwrap(); - re.replace_all(&text[], NoExpand("$")) - } - - /// Returns the number of captured groups. - #[inline] - pub fn len(&self) -> uint { self.locs.len() / 2 } - - /// Returns if there are no captured groups. - #[inline] - pub fn is_empty(&self) -> bool { self.len() == 0 } -} - -/// An iterator over capture groups for a particular match of a regular -/// expression. -/// -/// `'t` is the lifetime of the matched text. -#[derive(Clone)] -pub struct SubCaptures<'t> { - idx: uint, - caps: &'t Captures<'t>, -} - -impl<'t> Iterator for SubCaptures<'t> { - type Item = &'t str; - - fn next(&mut self) -> Option<&'t str> { - if self.idx < self.caps.len() { - self.idx += 1; - Some(self.caps.at(self.idx - 1).unwrap_or("")) - } else { - None - } - } -} - -/// An iterator over capture group positions for a particular match of a -/// regular expression. -/// -/// Positions are byte indices in terms of the original string matched. -/// -/// `'t` is the lifetime of the matched text. -#[derive(Clone)] -pub struct SubCapturesPos<'t> { - idx: uint, - caps: &'t Captures<'t>, -} - -impl<'t> Iterator for SubCapturesPos<'t> { - type Item = Option<(uint, uint)>; - - fn next(&mut self) -> Option> { - if self.idx < self.caps.len() { - self.idx += 1; - Some(self.caps.pos(self.idx - 1)) - } else { - None - } - } -} - -/// An iterator that yields all non-overlapping capture groups matching a -/// particular regular expression. -/// -/// The iterator stops when no more matches can be found. -/// -/// `'r` is the lifetime of the compiled expression and `'t` is the lifetime -/// of the matched string. -#[derive(Clone)] -pub struct FindCaptures<'r, 't> { - re: &'r Regex, - search: &'t str, - last_match: Option, - last_end: uint, -} - -impl<'r, 't> Iterator for FindCaptures<'r, 't> { - type Item = Captures<'t>; - - fn next(&mut self) -> Option> { - if self.last_end > self.search.len() { - return None - } - - let caps = exec_slice(self.re, Submatches, self.search, - self.last_end, self.search.len()); - let (s, e) = - if !has_match(&caps) { - return None - } else { - (caps[0].unwrap(), caps[1].unwrap()) - }; - - // Don't accept empty matches immediately following a match. - // i.e., no infinite loops please. - if e == s && Some(self.last_end) == self.last_match { - self.last_end += 1; - return self.next() - } - self.last_end = e; - self.last_match = Some(self.last_end); - Captures::new(self.re, self.search, caps) - } -} - -/// An iterator over all non-overlapping matches for a particular string. -/// -/// The iterator yields a tuple of integers corresponding to the start and end -/// of the match. The indices are byte offsets. The iterator stops when no more -/// matches can be found. -/// -/// `'r` is the lifetime of the compiled expression and `'t` is the lifetime -/// of the matched string. -#[derive(Clone)] -pub struct FindMatches<'r, 't> { - re: &'r Regex, - search: &'t str, - last_match: Option, - last_end: uint, -} - -impl<'r, 't> Iterator for FindMatches<'r, 't> { - type Item = (uint, uint); - - fn next(&mut self) -> Option<(uint, uint)> { - if self.last_end > self.search.len() { - return None - } - - let caps = exec_slice(self.re, Location, self.search, - self.last_end, self.search.len()); - let (s, e) = - if !has_match(&caps) { - return None - } else { - (caps[0].unwrap(), caps[1].unwrap()) - }; - - // Don't accept empty matches immediately following a match. - // i.e., no infinite loops please. - if e == s && Some(self.last_end) == self.last_match { - self.last_end += 1; - return self.next() - } - self.last_end = e; - self.last_match = Some(self.last_end); - Some((s, e)) - } -} - -fn exec(re: &Regex, which: MatchKind, input: &str) -> CaptureLocs { - exec_slice(re, which, input, 0, input.len()) -} - -fn exec_slice(re: &Regex, which: MatchKind, - input: &str, s: uint, e: uint) -> CaptureLocs { - match *re { - Dynamic(ExDynamic { ref prog, .. }) => vm::run(which, prog, input, s, e), - Native(ExNative { ref prog, .. }) => (*prog)(which, input, s, e), - } -} - -#[inline] -fn has_match(caps: &CaptureLocs) -> bool { - caps.len() >= 2 && caps[0].is_some() && caps[1].is_some() -} diff --git a/src/libregex/test/bench.rs b/src/libregex/test/bench.rs deleted file mode 100644 index 17521ff7ea54..000000000000 --- a/src/libregex/test/bench.rs +++ /dev/null @@ -1,183 +0,0 @@ -// 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. -#![allow(non_snake_case)] - -use std::rand::{Rng, thread_rng}; -use stdtest::Bencher; -use std::iter::repeat; - -use regex::{Regex, NoExpand}; - -fn bench_assert_match(b: &mut Bencher, re: Regex, text: &str) { - b.iter(|| if !re.is_match(text) { panic!("no match") }); -} - -#[bench] -fn no_exponential(b: &mut Bencher) { - let n = 100; - let re = Regex::new(format!("{}{}", - repeat("a?").take(n).collect::(), - repeat("a").take(n).collect::()).as_slice()).unwrap(); - let text = repeat("a").take(n).collect::(); - bench_assert_match(b, re, text.as_slice()); -} - -#[bench] -fn literal(b: &mut Bencher) { - let re = regex!("y"); - let text = format!("{}y", repeat("x").take(50).collect::()); - bench_assert_match(b, re, text.as_slice()); -} - -#[bench] -fn not_literal(b: &mut Bencher) { - let re = regex!(".y"); - let text = format!("{}y", repeat("x").take(50).collect::()); - bench_assert_match(b, re, text.as_slice()); -} - -#[bench] -fn match_class(b: &mut Bencher) { - let re = regex!("[abcdw]"); - let text = format!("{}w", repeat("xxxx").take(20).collect::()); - bench_assert_match(b, re, text.as_slice()); -} - -#[bench] -fn match_class_in_range(b: &mut Bencher) { - // 'b' is between 'a' and 'c', so the class range checking doesn't help. - let re = regex!("[ac]"); - let text = format!("{}c", repeat("bbbb").take(20).collect::()); - bench_assert_match(b, re, text.as_slice()); -} - -#[bench] -fn replace_all(b: &mut Bencher) { - let re = regex!("[cjrw]"); - let text = "abcdefghijklmnopqrstuvwxyz"; - // FIXME: This isn't using the $name expand stuff. - // It's possible RE2/Go is using it, but currently, the expand in this - // crate is actually compiling a regex, so it's incredibly slow. - b.iter(|| re.replace_all(text, NoExpand(""))); -} - -#[bench] -fn anchored_literal_short_non_match(b: &mut Bencher) { - let re = regex!("^zbc(d|e)"); - let text = "abcdefghijklmnopqrstuvwxyz"; - b.iter(|| re.is_match(text)); -} - -#[bench] -fn anchored_literal_long_non_match(b: &mut Bencher) { - let re = regex!("^zbc(d|e)"); - let text = repeat("abcdefghijklmnopqrstuvwxyz").take(15).collect::(); - b.iter(|| re.is_match(text.as_slice())); -} - -#[bench] -fn anchored_literal_short_match(b: &mut Bencher) { - let re = regex!("^.bc(d|e)"); - let text = "abcdefghijklmnopqrstuvwxyz"; - b.iter(|| re.is_match(text)); -} - -#[bench] -fn anchored_literal_long_match(b: &mut Bencher) { - let re = regex!("^.bc(d|e)"); - let text = repeat("abcdefghijklmnopqrstuvwxyz").take(15).collect::(); - b.iter(|| re.is_match(text.as_slice())); -} - -#[bench] -fn one_pass_short_a(b: &mut Bencher) { - let re = regex!("^.bc(d|e)*$"); - let text = "abcddddddeeeededd"; - b.iter(|| re.is_match(text)); -} - -#[bench] -fn one_pass_short_a_not(b: &mut Bencher) { - let re = regex!(".bc(d|e)*$"); - let text = "abcddddddeeeededd"; - b.iter(|| re.is_match(text)); -} - -#[bench] -fn one_pass_short_b(b: &mut Bencher) { - let re = regex!("^.bc(?:d|e)*$"); - let text = "abcddddddeeeededd"; - b.iter(|| re.is_match(text)); -} - -#[bench] -fn one_pass_short_b_not(b: &mut Bencher) { - let re = regex!(".bc(?:d|e)*$"); - let text = "abcddddddeeeededd"; - b.iter(|| re.is_match(text)); -} - -#[bench] -fn one_pass_long_prefix(b: &mut Bencher) { - let re = regex!("^abcdefghijklmnopqrstuvwxyz.*$"); - let text = "abcdefghijklmnopqrstuvwxyz"; - b.iter(|| re.is_match(text)); -} - -#[bench] -fn one_pass_long_prefix_not(b: &mut Bencher) { - let re = regex!("^.bcdefghijklmnopqrstuvwxyz.*$"); - let text = "abcdefghijklmnopqrstuvwxyz"; - b.iter(|| re.is_match(text)); -} - -macro_rules! throughput { - ($name:ident, $regex:expr, $size:expr) => ( - #[bench] - fn $name(b: &mut Bencher) { - let text = gen_text($size); - b.bytes = $size; - b.iter(|| if $regex.is_match(text.as_slice()) { panic!("match") }); - } - ); -} - -fn easy0() -> Regex { regex!("ABCDEFGHIJKLMNOPQRSTUVWXYZ$") } -fn easy1() -> Regex { regex!("A[AB]B[BC]C[CD]D[DE]E[EF]F[FG]G[GH]H[HI]I[IJ]J$") } -fn medium() -> Regex { regex!("[XYZ]ABCDEFGHIJKLMNOPQRSTUVWXYZ$") } -fn hard() -> Regex { regex!("[ -~]*ABCDEFGHIJKLMNOPQRSTUVWXYZ$") } - -fn gen_text(n: uint) -> String { - let mut rng = thread_rng(); - let mut bytes = rng.gen_ascii_chars().map(|n| n as u8).take(n) - .collect::>(); - for (i, b) in bytes.iter_mut().enumerate() { - if i % 20 == 0 { - *b = b'\n' - } - } - String::from_utf8(bytes).unwrap() -} - -throughput!{easy0_32, easy0(), 32} -throughput!{easy0_1K, easy0(), 1<<10} -throughput!{easy0_32K, easy0(), 32<<10} - -throughput!{easy1_32, easy1(), 32} -throughput!{easy1_1K, easy1(), 1<<10} -throughput!{easy1_32K, easy1(), 32<<10} - -throughput!{medium_32, medium(), 32} -throughput!{medium_1K, medium(), 1<<10} -throughput!{medium_32K,medium(), 32<<10} - -throughput!{hard_32, hard(), 32} -throughput!{hard_1K, hard(), 1<<10} -throughput!{hard_32K,hard(), 32<<10} diff --git a/src/libregex/test/matches.rs b/src/libregex/test/matches.rs deleted file mode 100644 index 7508f4c50a2c..000000000000 --- a/src/libregex/test/matches.rs +++ /dev/null @@ -1,373 +0,0 @@ -// 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. - -// ignore-tidy-linelength - -// DO NOT EDIT. Automatically generated by 'src/etc/regex-match-tests' -// on 2014-04-23 01:33:36.539280. - -// Tests from basic.dat -mat!{match_basic_3, r"abracadabra$", r"abracadabracadabra", Some((7, 18))} -mat!{match_basic_4, r"a...b", r"abababbb", Some((2, 7))} -mat!{match_basic_5, r"XXXXXX", r"..XXXXXX", Some((2, 8))} -mat!{match_basic_6, r"\)", r"()", Some((1, 2))} -mat!{match_basic_7, r"a]", r"a]a", Some((0, 2))} -mat!{match_basic_9, r"\}", r"}", Some((0, 1))} -mat!{match_basic_10, r"\]", r"]", Some((0, 1))} -mat!{match_basic_12, r"]", r"]", Some((0, 1))} -mat!{match_basic_15, r"^a", r"ax", Some((0, 1))} -mat!{match_basic_16, r"\^a", r"a^a", Some((1, 3))} -mat!{match_basic_17, r"a\^", r"a^", Some((0, 2))} -mat!{match_basic_18, r"a$", r"aa", Some((1, 2))} -mat!{match_basic_19, r"a\$", r"a$", Some((0, 2))} -mat!{match_basic_20, r"^$", r"", Some((0, 0))} -mat!{match_basic_21, r"$^", r"", Some((0, 0))} -mat!{match_basic_22, r"a($)", r"aa", Some((1, 2)), Some((2, 2))} -mat!{match_basic_23, r"a*(^a)", r"aa", Some((0, 1)), Some((0, 1))} -mat!{match_basic_24, r"(..)*(...)*", r"a", Some((0, 0))} -mat!{match_basic_25, r"(..)*(...)*", r"abcd", Some((0, 4)), Some((2, 4))} -mat!{match_basic_26, r"(ab|a)(bc|c)", r"abc", Some((0, 3)), Some((0, 2)), Some((2, 3))} -mat!{match_basic_27, r"(ab)c|abc", r"abc", Some((0, 3)), Some((0, 2))} -mat!{match_basic_28, r"a{0}b", r"ab", Some((1, 2))} -mat!{match_basic_29, r"(a*)(b?)(b+)b{3}", r"aaabbbbbbb", Some((0, 10)), Some((0, 3)), Some((3, 4)), Some((4, 7))} -mat!{match_basic_30, r"(a*)(b{0,1})(b{1,})b{3}", r"aaabbbbbbb", Some((0, 10)), Some((0, 3)), Some((3, 4)), Some((4, 7))} -mat!{match_basic_32, r"((a|a)|a)", r"a", Some((0, 1)), Some((0, 1)), Some((0, 1))} -mat!{match_basic_33, r"(a*)(a|aa)", r"aaaa", Some((0, 4)), Some((0, 3)), Some((3, 4))} -mat!{match_basic_34, r"a*(a.|aa)", r"aaaa", Some((0, 4)), Some((2, 4))} -mat!{match_basic_35, r"a(b)|c(d)|a(e)f", r"aef", Some((0, 3)), None, None, Some((1, 2))} -mat!{match_basic_36, r"(a|b)?.*", r"b", Some((0, 1)), Some((0, 1))} -mat!{match_basic_37, r"(a|b)c|a(b|c)", r"ac", Some((0, 2)), Some((0, 1))} -mat!{match_basic_38, r"(a|b)c|a(b|c)", r"ab", Some((0, 2)), None, Some((1, 2))} -mat!{match_basic_39, r"(a|b)*c|(a|ab)*c", r"abc", Some((0, 3)), Some((1, 2))} -mat!{match_basic_40, r"(a|b)*c|(a|ab)*c", r"xc", Some((1, 2))} -mat!{match_basic_41, r"(.a|.b).*|.*(.a|.b)", r"xa", Some((0, 2)), Some((0, 2))} -mat!{match_basic_42, r"a?(ab|ba)ab", r"abab", Some((0, 4)), Some((0, 2))} -mat!{match_basic_43, r"a?(ac{0}b|ba)ab", r"abab", Some((0, 4)), Some((0, 2))} -mat!{match_basic_44, r"ab|abab", r"abbabab", Some((0, 2))} -mat!{match_basic_45, r"aba|bab|bba", r"baaabbbaba", Some((5, 8))} -mat!{match_basic_46, r"aba|bab", r"baaabbbaba", Some((6, 9))} -mat!{match_basic_47, r"(aa|aaa)*|(a|aaaaa)", r"aa", Some((0, 2)), Some((0, 2))} -mat!{match_basic_48, r"(a.|.a.)*|(a|.a...)", r"aa", Some((0, 2)), Some((0, 2))} -mat!{match_basic_49, r"ab|a", r"xabc", Some((1, 3))} -mat!{match_basic_50, r"ab|a", r"xxabc", Some((2, 4))} -mat!{match_basic_51, r"(?i)(Ab|cD)*", r"aBcD", Some((0, 4)), Some((2, 4))} -mat!{match_basic_52, r"[^-]", r"--a", Some((2, 3))} -mat!{match_basic_53, r"[a-]*", r"--a", Some((0, 3))} -mat!{match_basic_54, r"[a-m-]*", r"--amoma--", Some((0, 4))} -mat!{match_basic_55, r":::1:::0:|:::1:1:0:", r":::0:::1:::1:::0:", Some((8, 17))} -mat!{match_basic_56, r":::1:::0:|:::1:1:1:", r":::0:::1:::1:::0:", Some((8, 17))} -mat!{match_basic_57, r"[[:upper:]]", r"A", Some((0, 1))} -mat!{match_basic_58, r"[[:lower:]]+", r"`az{", Some((1, 3))} -mat!{match_basic_59, r"[[:upper:]]+", r"@AZ[", Some((1, 3))} -mat!{match_basic_65, r" -", r" -", Some((0, 1))} -mat!{match_basic_66, r" -", r" -", Some((0, 1))} -mat!{match_basic_67, r"[^a]", r" -", Some((0, 1))} -mat!{match_basic_68, r" -a", r" -a", Some((0, 2))} -mat!{match_basic_69, r"(a)(b)(c)", r"abc", Some((0, 3)), Some((0, 1)), Some((1, 2)), Some((2, 3))} -mat!{match_basic_70, r"xxx", r"xxx", Some((0, 3))} -mat!{match_basic_71, r"(^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$)", r"feb 6,", Some((0, 6))} -mat!{match_basic_72, r"(^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$)", r"2/7", Some((0, 3))} -mat!{match_basic_73, r"(^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$)", r"feb 1,Feb 6", Some((5, 11))} -mat!{match_basic_74, r"((((((((((((((((((((((((((((((x))))))))))))))))))))))))))))))", r"x", Some((0, 1)), Some((0, 1)), Some((0, 1))} -mat!{match_basic_75, r"((((((((((((((((((((((((((((((x))))))))))))))))))))))))))))))*", r"xx", Some((0, 2)), Some((1, 2)), Some((1, 2))} -mat!{match_basic_76, r"a?(ab|ba)*", r"ababababababababababababababababababababababababababababababababababababababababa", Some((0, 81)), Some((79, 81))} -mat!{match_basic_77, r"abaa|abbaa|abbbaa|abbbbaa", r"ababbabbbabbbabbbbabbbbaa", Some((18, 25))} -mat!{match_basic_78, r"abaa|abbaa|abbbaa|abbbbaa", r"ababbabbbabbbabbbbabaa", Some((18, 22))} -mat!{match_basic_79, r"aaac|aabc|abac|abbc|baac|babc|bbac|bbbc", r"baaabbbabac", Some((7, 11))} -mat!{match_basic_80, r".*", r"", Some((0, 2))} -mat!{match_basic_81, r"aaaa|bbbb|cccc|ddddd|eeeeee|fffffff|gggg|hhhh|iiiii|jjjjj|kkkkk|llll", r"XaaaXbbbXcccXdddXeeeXfffXgggXhhhXiiiXjjjXkkkXlllXcbaXaaaa", Some((53, 57))} -mat!{match_basic_83, r"a*a*a*a*a*b", r"aaaaaaaaab", Some((0, 10))} -mat!{match_basic_84, r"^", r"", Some((0, 0))} -mat!{match_basic_85, r"$", r"", Some((0, 0))} -mat!{match_basic_86, r"^$", r"", Some((0, 0))} -mat!{match_basic_87, r"^a$", r"a", Some((0, 1))} -mat!{match_basic_88, r"abc", r"abc", Some((0, 3))} -mat!{match_basic_89, r"abc", r"xabcy", Some((1, 4))} -mat!{match_basic_90, r"abc", r"ababc", Some((2, 5))} -mat!{match_basic_91, r"ab*c", r"abc", Some((0, 3))} -mat!{match_basic_92, r"ab*bc", r"abc", Some((0, 3))} -mat!{match_basic_93, r"ab*bc", r"abbc", Some((0, 4))} -mat!{match_basic_94, r"ab*bc", r"abbbbc", Some((0, 6))} -mat!{match_basic_95, r"ab+bc", r"abbc", Some((0, 4))} -mat!{match_basic_96, r"ab+bc", r"abbbbc", Some((0, 6))} -mat!{match_basic_97, r"ab?bc", r"abbc", Some((0, 4))} -mat!{match_basic_98, r"ab?bc", r"abc", Some((0, 3))} -mat!{match_basic_99, r"ab?c", r"abc", Some((0, 3))} -mat!{match_basic_100, r"^abc$", r"abc", Some((0, 3))} -mat!{match_basic_101, r"^abc", r"abcc", Some((0, 3))} -mat!{match_basic_102, r"abc$", r"aabc", Some((1, 4))} -mat!{match_basic_103, r"^", r"abc", Some((0, 0))} -mat!{match_basic_104, r"$", r"abc", Some((3, 3))} -mat!{match_basic_105, r"a.c", r"abc", Some((0, 3))} -mat!{match_basic_106, r"a.c", r"axc", Some((0, 3))} -mat!{match_basic_107, r"a.*c", r"axyzc", Some((0, 5))} -mat!{match_basic_108, r"a[bc]d", r"abd", Some((0, 3))} -mat!{match_basic_109, r"a[b-d]e", r"ace", Some((0, 3))} -mat!{match_basic_110, r"a[b-d]", r"aac", Some((1, 3))} -mat!{match_basic_111, r"a[-b]", r"a-", Some((0, 2))} -mat!{match_basic_112, r"a[b-]", r"a-", Some((0, 2))} -mat!{match_basic_113, r"a]", r"a]", Some((0, 2))} -mat!{match_basic_114, r"a[]]b", r"a]b", Some((0, 3))} -mat!{match_basic_115, r"a[^bc]d", r"aed", Some((0, 3))} -mat!{match_basic_116, r"a[^-b]c", r"adc", Some((0, 3))} -mat!{match_basic_117, r"a[^]b]c", r"adc", Some((0, 3))} -mat!{match_basic_118, r"ab|cd", r"abc", Some((0, 2))} -mat!{match_basic_119, r"ab|cd", r"abcd", Some((0, 2))} -mat!{match_basic_120, r"a\(b", r"a(b", Some((0, 3))} -mat!{match_basic_121, r"a\(*b", r"ab", Some((0, 2))} -mat!{match_basic_122, r"a\(*b", r"a((b", Some((0, 4))} -mat!{match_basic_123, r"((a))", r"abc", Some((0, 1)), Some((0, 1)), Some((0, 1))} -mat!{match_basic_124, r"(a)b(c)", r"abc", Some((0, 3)), Some((0, 1)), Some((2, 3))} -mat!{match_basic_125, r"a+b+c", r"aabbabc", Some((4, 7))} -mat!{match_basic_126, r"a*", r"aaa", Some((0, 3))} -mat!{match_basic_128, r"(a*)*", r"-", Some((0, 0)), None} -mat!{match_basic_129, r"(a*)+", r"-", Some((0, 0)), Some((0, 0))} -mat!{match_basic_131, r"(a*|b)*", r"-", Some((0, 0)), None} -mat!{match_basic_132, r"(a+|b)*", r"ab", Some((0, 2)), Some((1, 2))} -mat!{match_basic_133, r"(a+|b)+", r"ab", Some((0, 2)), Some((1, 2))} -mat!{match_basic_134, r"(a+|b)?", r"ab", Some((0, 1)), Some((0, 1))} -mat!{match_basic_135, r"[^ab]*", r"cde", Some((0, 3))} -mat!{match_basic_137, r"(^)*", r"-", Some((0, 0)), None} -mat!{match_basic_138, r"a*", r"", Some((0, 0))} -mat!{match_basic_139, r"([abc])*d", r"abbbcd", Some((0, 6)), Some((4, 5))} -mat!{match_basic_140, r"([abc])*bcd", r"abcd", Some((0, 4)), Some((0, 1))} -mat!{match_basic_141, r"a|b|c|d|e", r"e", Some((0, 1))} -mat!{match_basic_142, r"(a|b|c|d|e)f", r"ef", Some((0, 2)), Some((0, 1))} -mat!{match_basic_144, r"((a*|b))*", r"-", Some((0, 0)), None, None} -mat!{match_basic_145, r"abcd*efg", r"abcdefg", Some((0, 7))} -mat!{match_basic_146, r"ab*", r"xabyabbbz", Some((1, 3))} -mat!{match_basic_147, r"ab*", r"xayabbbz", Some((1, 2))} -mat!{match_basic_148, r"(ab|cd)e", r"abcde", Some((2, 5)), Some((2, 4))} -mat!{match_basic_149, r"[abhgefdc]ij", r"hij", Some((0, 3))} -mat!{match_basic_150, r"(a|b)c*d", r"abcd", Some((1, 4)), Some((1, 2))} -mat!{match_basic_151, r"(ab|ab*)bc", r"abc", Some((0, 3)), Some((0, 1))} -mat!{match_basic_152, r"a([bc]*)c*", r"abc", Some((0, 3)), Some((1, 3))} -mat!{match_basic_153, r"a([bc]*)(c*d)", r"abcd", Some((0, 4)), Some((1, 3)), Some((3, 4))} -mat!{match_basic_154, r"a([bc]+)(c*d)", r"abcd", Some((0, 4)), Some((1, 3)), Some((3, 4))} -mat!{match_basic_155, r"a([bc]*)(c+d)", r"abcd", Some((0, 4)), Some((1, 2)), Some((2, 4))} -mat!{match_basic_156, r"a[bcd]*dcdcde", r"adcdcde", Some((0, 7))} -mat!{match_basic_157, r"(ab|a)b*c", r"abc", Some((0, 3)), Some((0, 2))} -mat!{match_basic_158, r"((a)(b)c)(d)", r"abcd", Some((0, 4)), Some((0, 3)), Some((0, 1)), Some((1, 2)), Some((3, 4))} -mat!{match_basic_159, r"[A-Za-z_][A-Za-z0-9_]*", r"alpha", Some((0, 5))} -mat!{match_basic_160, r"^a(bc+|b[eh])g|.h$", r"abh", Some((1, 3))} -mat!{match_basic_161, r"(bc+d$|ef*g.|h?i(j|k))", r"effgz", Some((0, 5)), Some((0, 5))} -mat!{match_basic_162, r"(bc+d$|ef*g.|h?i(j|k))", r"ij", Some((0, 2)), Some((0, 2)), Some((1, 2))} -mat!{match_basic_163, r"(bc+d$|ef*g.|h?i(j|k))", r"reffgz", Some((1, 6)), Some((1, 6))} -mat!{match_basic_164, r"(((((((((a)))))))))", r"a", Some((0, 1)), Some((0, 1)), Some((0, 1)), Some((0, 1)), Some((0, 1)), Some((0, 1)), Some((0, 1)), Some((0, 1)), Some((0, 1)), Some((0, 1))} -mat!{match_basic_165, r"multiple words", r"multiple words yeah", Some((0, 14))} -mat!{match_basic_166, r"(.*)c(.*)", r"abcde", Some((0, 5)), Some((0, 2)), Some((3, 5))} -mat!{match_basic_167, r"abcd", r"abcd", Some((0, 4))} -mat!{match_basic_168, r"a(bc)d", r"abcd", Some((0, 4)), Some((1, 3))} -mat!{match_basic_169, r"a[-]?c", r"ac", Some((0, 3))} -mat!{match_basic_170, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Muammar Qaddafi", Some((0, 15)), None, Some((10, 12))} -mat!{match_basic_171, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Mo'ammar Gadhafi", Some((0, 16)), None, Some((11, 13))} -mat!{match_basic_172, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Muammar Kaddafi", Some((0, 15)), None, Some((10, 12))} -mat!{match_basic_173, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Muammar Qadhafi", Some((0, 15)), None, Some((10, 12))} -mat!{match_basic_174, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Muammar Gadafi", Some((0, 14)), None, Some((10, 11))} -mat!{match_basic_175, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Mu'ammar Qadafi", Some((0, 15)), None, Some((11, 12))} -mat!{match_basic_176, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Moamar Gaddafi", Some((0, 14)), None, Some((9, 11))} -mat!{match_basic_177, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Mu'ammar Qadhdhafi", Some((0, 18)), None, Some((13, 15))} -mat!{match_basic_178, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Muammar Khaddafi", Some((0, 16)), None, Some((11, 13))} -mat!{match_basic_179, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Muammar Ghaddafy", Some((0, 16)), None, Some((11, 13))} -mat!{match_basic_180, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Muammar Ghadafi", Some((0, 15)), None, Some((11, 12))} -mat!{match_basic_181, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Muammar Ghaddafi", Some((0, 16)), None, Some((11, 13))} -mat!{match_basic_182, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Muamar Kaddafi", Some((0, 14)), None, Some((9, 11))} -mat!{match_basic_183, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Muammar Quathafi", Some((0, 16)), None, Some((11, 13))} -mat!{match_basic_184, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Muammar Gheddafi", Some((0, 16)), None, Some((11, 13))} -mat!{match_basic_185, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Moammar Khadafy", Some((0, 15)), None, Some((11, 12))} -mat!{match_basic_186, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Moammar Qudhafi", Some((0, 15)), None, Some((10, 12))} -mat!{match_basic_187, r"a+(b|c)*d+", r"aabcdd", Some((0, 6)), Some((3, 4))} -mat!{match_basic_188, r"^.+$", r"vivi", Some((0, 4))} -mat!{match_basic_189, r"^(.+)$", r"vivi", Some((0, 4)), Some((0, 4))} -mat!{match_basic_190, r"^([^!.]+).att.com!(.+)$", r"gryphon.att.com!eby", Some((0, 19)), Some((0, 7)), Some((16, 19))} -mat!{match_basic_191, r"^([^!]+!)?([^!]+)$", r"bas", Some((0, 3)), None, Some((0, 3))} -mat!{match_basic_192, r"^([^!]+!)?([^!]+)$", r"bar!bas", Some((0, 7)), Some((0, 4)), Some((4, 7))} -mat!{match_basic_193, r"^([^!]+!)?([^!]+)$", r"foo!bas", Some((0, 7)), Some((0, 4)), Some((4, 7))} -mat!{match_basic_194, r"^.+!([^!]+!)([^!]+)$", r"foo!bar!bas", Some((0, 11)), Some((4, 8)), Some((8, 11))} -mat!{match_basic_195, r"((foo)|(bar))!bas", r"bar!bas", Some((0, 7)), Some((0, 3)), None, Some((0, 3))} -mat!{match_basic_196, r"((foo)|(bar))!bas", r"foo!bar!bas", Some((4, 11)), Some((4, 7)), None, Some((4, 7))} -mat!{match_basic_197, r"((foo)|(bar))!bas", r"foo!bas", Some((0, 7)), Some((0, 3)), Some((0, 3))} -mat!{match_basic_198, r"((foo)|bar)!bas", r"bar!bas", Some((0, 7)), Some((0, 3))} -mat!{match_basic_199, r"((foo)|bar)!bas", r"foo!bar!bas", Some((4, 11)), Some((4, 7))} -mat!{match_basic_200, r"((foo)|bar)!bas", r"foo!bas", Some((0, 7)), Some((0, 3)), Some((0, 3))} -mat!{match_basic_201, r"(foo|(bar))!bas", r"bar!bas", Some((0, 7)), Some((0, 3)), Some((0, 3))} -mat!{match_basic_202, r"(foo|(bar))!bas", r"foo!bar!bas", Some((4, 11)), Some((4, 7)), Some((4, 7))} -mat!{match_basic_203, r"(foo|(bar))!bas", r"foo!bas", Some((0, 7)), Some((0, 3))} -mat!{match_basic_204, r"(foo|bar)!bas", r"bar!bas", Some((0, 7)), Some((0, 3))} -mat!{match_basic_205, r"(foo|bar)!bas", r"foo!bar!bas", Some((4, 11)), Some((4, 7))} -mat!{match_basic_206, r"(foo|bar)!bas", r"foo!bas", Some((0, 7)), Some((0, 3))} -mat!{match_basic_207, r"^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$", r"foo!bar!bas", Some((0, 11)), Some((0, 11)), None, None, Some((4, 8)), Some((8, 11))} -mat!{match_basic_208, r"^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$", r"bas", Some((0, 3)), None, Some((0, 3))} -mat!{match_basic_209, r"^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$", r"bar!bas", Some((0, 7)), Some((0, 4)), Some((4, 7))} -mat!{match_basic_210, r"^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$", r"foo!bar!bas", Some((0, 11)), None, None, Some((4, 8)), Some((8, 11))} -mat!{match_basic_211, r"^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$", r"foo!bas", Some((0, 7)), Some((0, 4)), Some((4, 7))} -mat!{match_basic_212, r"^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$", r"bas", Some((0, 3)), Some((0, 3)), None, Some((0, 3))} -mat!{match_basic_213, r"^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$", r"bar!bas", Some((0, 7)), Some((0, 7)), Some((0, 4)), Some((4, 7))} -mat!{match_basic_214, r"^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$", r"foo!bar!bas", Some((0, 11)), Some((0, 11)), None, None, Some((4, 8)), Some((8, 11))} -mat!{match_basic_215, r"^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$", r"foo!bas", Some((0, 7)), Some((0, 7)), Some((0, 4)), Some((4, 7))} -mat!{match_basic_216, r".*(/XXX).*", r"/XXX", Some((0, 4)), Some((0, 4))} -mat!{match_basic_217, r".*(\\XXX).*", r"\XXX", Some((0, 4)), Some((0, 4))} -mat!{match_basic_218, r"\\XXX", r"\XXX", Some((0, 4))} -mat!{match_basic_219, r".*(/000).*", r"/000", Some((0, 4)), Some((0, 4))} -mat!{match_basic_220, r".*(\\000).*", r"\000", Some((0, 4)), Some((0, 4))} -mat!{match_basic_221, r"\\000", r"\000", Some((0, 4))} - -// Tests from nullsubexpr.dat -mat!{match_nullsubexpr_3, r"(a*)*", r"a", Some((0, 1)), Some((0, 1))} -mat!{match_nullsubexpr_5, r"(a*)*", r"x", Some((0, 0)), None} -mat!{match_nullsubexpr_6, r"(a*)*", r"aaaaaa", Some((0, 6)), Some((0, 6))} -mat!{match_nullsubexpr_7, r"(a*)*", r"aaaaaax", Some((0, 6)), Some((0, 6))} -mat!{match_nullsubexpr_8, r"(a*)+", r"a", Some((0, 1)), Some((0, 1))} -mat!{match_nullsubexpr_9, r"(a*)+", r"x", Some((0, 0)), Some((0, 0))} -mat!{match_nullsubexpr_10, r"(a*)+", r"aaaaaa", Some((0, 6)), Some((0, 6))} -mat!{match_nullsubexpr_11, r"(a*)+", r"aaaaaax", Some((0, 6)), Some((0, 6))} -mat!{match_nullsubexpr_12, r"(a+)*", r"a", Some((0, 1)), Some((0, 1))} -mat!{match_nullsubexpr_13, r"(a+)*", r"x", Some((0, 0))} -mat!{match_nullsubexpr_14, r"(a+)*", r"aaaaaa", Some((0, 6)), Some((0, 6))} -mat!{match_nullsubexpr_15, r"(a+)*", r"aaaaaax", Some((0, 6)), Some((0, 6))} -mat!{match_nullsubexpr_16, r"(a+)+", r"a", Some((0, 1)), Some((0, 1))} -mat!{match_nullsubexpr_17, r"(a+)+", r"x", None} -mat!{match_nullsubexpr_18, r"(a+)+", r"aaaaaa", Some((0, 6)), Some((0, 6))} -mat!{match_nullsubexpr_19, r"(a+)+", r"aaaaaax", Some((0, 6)), Some((0, 6))} -mat!{match_nullsubexpr_21, r"([a]*)*", r"a", Some((0, 1)), Some((0, 1))} -mat!{match_nullsubexpr_23, r"([a]*)*", r"x", Some((0, 0)), None} -mat!{match_nullsubexpr_24, r"([a]*)*", r"aaaaaa", Some((0, 6)), Some((0, 6))} -mat!{match_nullsubexpr_25, r"([a]*)*", r"aaaaaax", Some((0, 6)), Some((0, 6))} -mat!{match_nullsubexpr_26, r"([a]*)+", r"a", Some((0, 1)), Some((0, 1))} -mat!{match_nullsubexpr_27, r"([a]*)+", r"x", Some((0, 0)), Some((0, 0))} -mat!{match_nullsubexpr_28, r"([a]*)+", r"aaaaaa", Some((0, 6)), Some((0, 6))} -mat!{match_nullsubexpr_29, r"([a]*)+", r"aaaaaax", Some((0, 6)), Some((0, 6))} -mat!{match_nullsubexpr_30, r"([^b]*)*", r"a", Some((0, 1)), Some((0, 1))} -mat!{match_nullsubexpr_32, r"([^b]*)*", r"b", Some((0, 0)), None} -mat!{match_nullsubexpr_33, r"([^b]*)*", r"aaaaaa", Some((0, 6)), Some((0, 6))} -mat!{match_nullsubexpr_34, r"([^b]*)*", r"aaaaaab", Some((0, 6)), Some((0, 6))} -mat!{match_nullsubexpr_35, r"([ab]*)*", r"a", Some((0, 1)), Some((0, 1))} -mat!{match_nullsubexpr_36, r"([ab]*)*", r"aaaaaa", Some((0, 6)), Some((0, 6))} -mat!{match_nullsubexpr_37, r"([ab]*)*", r"ababab", Some((0, 6)), Some((0, 6))} -mat!{match_nullsubexpr_38, r"([ab]*)*", r"bababa", Some((0, 6)), Some((0, 6))} -mat!{match_nullsubexpr_39, r"([ab]*)*", r"b", Some((0, 1)), Some((0, 1))} -mat!{match_nullsubexpr_40, r"([ab]*)*", r"bbbbbb", Some((0, 6)), Some((0, 6))} -mat!{match_nullsubexpr_41, r"([ab]*)*", r"aaaabcde", Some((0, 5)), Some((0, 5))} -mat!{match_nullsubexpr_42, r"([^a]*)*", r"b", Some((0, 1)), Some((0, 1))} -mat!{match_nullsubexpr_43, r"([^a]*)*", r"bbbbbb", Some((0, 6)), Some((0, 6))} -mat!{match_nullsubexpr_45, r"([^a]*)*", r"aaaaaa", Some((0, 0)), None} -mat!{match_nullsubexpr_46, r"([^ab]*)*", r"ccccxx", Some((0, 6)), Some((0, 6))} -mat!{match_nullsubexpr_48, r"([^ab]*)*", r"ababab", Some((0, 0)), None} -mat!{match_nullsubexpr_50, r"((z)+|a)*", r"zabcde", Some((0, 2)), Some((1, 2))} -mat!{match_nullsubexpr_69, r"(a*)*(x)", r"x", Some((0, 1)), None, Some((0, 1))} -mat!{match_nullsubexpr_70, r"(a*)*(x)", r"ax", Some((0, 2)), Some((0, 1)), Some((1, 2))} -mat!{match_nullsubexpr_71, r"(a*)*(x)", r"axa", Some((0, 2)), Some((0, 1)), Some((1, 2))} -mat!{match_nullsubexpr_73, r"(a*)+(x)", r"x", Some((0, 1)), Some((0, 0)), Some((0, 1))} -mat!{match_nullsubexpr_74, r"(a*)+(x)", r"ax", Some((0, 2)), Some((0, 1)), Some((1, 2))} -mat!{match_nullsubexpr_75, r"(a*)+(x)", r"axa", Some((0, 2)), Some((0, 1)), Some((1, 2))} -mat!{match_nullsubexpr_77, r"(a*){2}(x)", r"x", Some((0, 1)), Some((0, 0)), Some((0, 1))} -mat!{match_nullsubexpr_78, r"(a*){2}(x)", r"ax", Some((0, 2)), Some((1, 1)), Some((1, 2))} -mat!{match_nullsubexpr_79, r"(a*){2}(x)", r"axa", Some((0, 2)), Some((1, 1)), Some((1, 2))} - -// Tests from repetition.dat -mat!{match_repetition_10, r"((..)|(.))", r"", None} -mat!{match_repetition_11, r"((..)|(.))((..)|(.))", r"", None} -mat!{match_repetition_12, r"((..)|(.))((..)|(.))((..)|(.))", r"", None} -mat!{match_repetition_14, r"((..)|(.)){1}", r"", None} -mat!{match_repetition_15, r"((..)|(.)){2}", r"", None} -mat!{match_repetition_16, r"((..)|(.)){3}", r"", None} -mat!{match_repetition_18, r"((..)|(.))*", r"", Some((0, 0))} -mat!{match_repetition_20, r"((..)|(.))", r"a", Some((0, 1)), Some((0, 1)), None, Some((0, 1))} -mat!{match_repetition_21, r"((..)|(.))((..)|(.))", r"a", None} -mat!{match_repetition_22, r"((..)|(.))((..)|(.))((..)|(.))", r"a", None} -mat!{match_repetition_24, r"((..)|(.)){1}", r"a", Some((0, 1)), Some((0, 1)), None, Some((0, 1))} -mat!{match_repetition_25, r"((..)|(.)){2}", r"a", None} -mat!{match_repetition_26, r"((..)|(.)){3}", r"a", None} -mat!{match_repetition_28, r"((..)|(.))*", r"a", Some((0, 1)), Some((0, 1)), None, Some((0, 1))} -mat!{match_repetition_30, r"((..)|(.))", r"aa", Some((0, 2)), Some((0, 2)), Some((0, 2)), None} -mat!{match_repetition_31, r"((..)|(.))((..)|(.))", r"aa", Some((0, 2)), Some((0, 1)), None, Some((0, 1)), Some((1, 2)), None, Some((1, 2))} -mat!{match_repetition_32, r"((..)|(.))((..)|(.))((..)|(.))", r"aa", None} -mat!{match_repetition_34, r"((..)|(.)){1}", r"aa", Some((0, 2)), Some((0, 2)), Some((0, 2)), None} -mat!{match_repetition_35, r"((..)|(.)){2}", r"aa", Some((0, 2)), Some((1, 2)), None, Some((1, 2))} -mat!{match_repetition_36, r"((..)|(.)){3}", r"aa", None} -mat!{match_repetition_38, r"((..)|(.))*", r"aa", Some((0, 2)), Some((0, 2)), Some((0, 2)), None} -mat!{match_repetition_40, r"((..)|(.))", r"aaa", Some((0, 2)), Some((0, 2)), Some((0, 2)), None} -mat!{match_repetition_41, r"((..)|(.))((..)|(.))", r"aaa", Some((0, 3)), Some((0, 2)), Some((0, 2)), None, Some((2, 3)), None, Some((2, 3))} -mat!{match_repetition_42, r"((..)|(.))((..)|(.))((..)|(.))", r"aaa", Some((0, 3)), Some((0, 1)), None, Some((0, 1)), Some((1, 2)), None, Some((1, 2)), Some((2, 3)), None, Some((2, 3))} -mat!{match_repetition_44, r"((..)|(.)){1}", r"aaa", Some((0, 2)), Some((0, 2)), Some((0, 2)), None} -mat!{match_repetition_46, r"((..)|(.)){2}", r"aaa", Some((0, 3)), Some((2, 3)), Some((0, 2)), Some((2, 3))} -mat!{match_repetition_47, r"((..)|(.)){3}", r"aaa", Some((0, 3)), Some((2, 3)), None, Some((2, 3))} -mat!{match_repetition_50, r"((..)|(.))*", r"aaa", Some((0, 3)), Some((2, 3)), Some((0, 2)), Some((2, 3))} -mat!{match_repetition_52, r"((..)|(.))", r"aaaa", Some((0, 2)), Some((0, 2)), Some((0, 2)), None} -mat!{match_repetition_53, r"((..)|(.))((..)|(.))", r"aaaa", Some((0, 4)), Some((0, 2)), Some((0, 2)), None, Some((2, 4)), Some((2, 4)), None} -mat!{match_repetition_54, r"((..)|(.))((..)|(.))((..)|(.))", r"aaaa", Some((0, 4)), Some((0, 2)), Some((0, 2)), None, Some((2, 3)), None, Some((2, 3)), Some((3, 4)), None, Some((3, 4))} -mat!{match_repetition_56, r"((..)|(.)){1}", r"aaaa", Some((0, 2)), Some((0, 2)), Some((0, 2)), None} -mat!{match_repetition_57, r"((..)|(.)){2}", r"aaaa", Some((0, 4)), Some((2, 4)), Some((2, 4)), None} -mat!{match_repetition_59, r"((..)|(.)){3}", r"aaaa", Some((0, 4)), Some((3, 4)), Some((0, 2)), Some((3, 4))} -mat!{match_repetition_61, r"((..)|(.))*", r"aaaa", Some((0, 4)), Some((2, 4)), Some((2, 4)), None} -mat!{match_repetition_63, r"((..)|(.))", r"aaaaa", Some((0, 2)), Some((0, 2)), Some((0, 2)), None} -mat!{match_repetition_64, r"((..)|(.))((..)|(.))", r"aaaaa", Some((0, 4)), Some((0, 2)), Some((0, 2)), None, Some((2, 4)), Some((2, 4)), None} -mat!{match_repetition_65, r"((..)|(.))((..)|(.))((..)|(.))", r"aaaaa", Some((0, 5)), Some((0, 2)), Some((0, 2)), None, Some((2, 4)), Some((2, 4)), None, Some((4, 5)), None, Some((4, 5))} -mat!{match_repetition_67, r"((..)|(.)){1}", r"aaaaa", Some((0, 2)), Some((0, 2)), Some((0, 2)), None} -mat!{match_repetition_68, r"((..)|(.)){2}", r"aaaaa", Some((0, 4)), Some((2, 4)), Some((2, 4)), None} -mat!{match_repetition_70, r"((..)|(.)){3}", r"aaaaa", Some((0, 5)), Some((4, 5)), Some((2, 4)), Some((4, 5))} -mat!{match_repetition_73, r"((..)|(.))*", r"aaaaa", Some((0, 5)), Some((4, 5)), Some((2, 4)), Some((4, 5))} -mat!{match_repetition_75, r"((..)|(.))", r"aaaaaa", Some((0, 2)), Some((0, 2)), Some((0, 2)), None} -mat!{match_repetition_76, r"((..)|(.))((..)|(.))", r"aaaaaa", Some((0, 4)), Some((0, 2)), Some((0, 2)), None, Some((2, 4)), Some((2, 4)), None} -mat!{match_repetition_77, r"((..)|(.))((..)|(.))((..)|(.))", r"aaaaaa", Some((0, 6)), Some((0, 2)), Some((0, 2)), None, Some((2, 4)), Some((2, 4)), None, Some((4, 6)), Some((4, 6)), None} -mat!{match_repetition_79, r"((..)|(.)){1}", r"aaaaaa", Some((0, 2)), Some((0, 2)), Some((0, 2)), None} -mat!{match_repetition_80, r"((..)|(.)){2}", r"aaaaaa", Some((0, 4)), Some((2, 4)), Some((2, 4)), None} -mat!{match_repetition_81, r"((..)|(.)){3}", r"aaaaaa", Some((0, 6)), Some((4, 6)), Some((4, 6)), None} -mat!{match_repetition_83, r"((..)|(.))*", r"aaaaaa", Some((0, 6)), Some((4, 6)), Some((4, 6)), None} -mat!{match_repetition_90, r"X(.?){0,}Y", r"X1234567Y", Some((0, 9)), Some((7, 8))} -mat!{match_repetition_91, r"X(.?){1,}Y", r"X1234567Y", Some((0, 9)), Some((7, 8))} -mat!{match_repetition_92, r"X(.?){2,}Y", r"X1234567Y", Some((0, 9)), Some((7, 8))} -mat!{match_repetition_93, r"X(.?){3,}Y", r"X1234567Y", Some((0, 9)), Some((7, 8))} -mat!{match_repetition_94, r"X(.?){4,}Y", r"X1234567Y", Some((0, 9)), Some((7, 8))} -mat!{match_repetition_95, r"X(.?){5,}Y", r"X1234567Y", Some((0, 9)), Some((7, 8))} -mat!{match_repetition_96, r"X(.?){6,}Y", r"X1234567Y", Some((0, 9)), Some((7, 8))} -mat!{match_repetition_97, r"X(.?){7,}Y", r"X1234567Y", Some((0, 9)), Some((7, 8))} -mat!{match_repetition_98, r"X(.?){8,}Y", r"X1234567Y", Some((0, 9)), Some((8, 8))} -mat!{match_repetition_100, r"X(.?){0,8}Y", r"X1234567Y", Some((0, 9)), Some((8, 8))} -mat!{match_repetition_102, r"X(.?){1,8}Y", r"X1234567Y", Some((0, 9)), Some((8, 8))} -mat!{match_repetition_104, r"X(.?){2,8}Y", r"X1234567Y", Some((0, 9)), Some((8, 8))} -mat!{match_repetition_106, r"X(.?){3,8}Y", r"X1234567Y", Some((0, 9)), Some((8, 8))} -mat!{match_repetition_108, r"X(.?){4,8}Y", r"X1234567Y", Some((0, 9)), Some((8, 8))} -mat!{match_repetition_110, r"X(.?){5,8}Y", r"X1234567Y", Some((0, 9)), Some((8, 8))} -mat!{match_repetition_112, r"X(.?){6,8}Y", r"X1234567Y", Some((0, 9)), Some((8, 8))} -mat!{match_repetition_114, r"X(.?){7,8}Y", r"X1234567Y", Some((0, 9)), Some((8, 8))} -mat!{match_repetition_115, r"X(.?){8,8}Y", r"X1234567Y", Some((0, 9)), Some((8, 8))} -mat!{match_repetition_126, r"(a|ab|c|bcd){0,}(d*)", r"ababcd", Some((0, 1)), Some((0, 1)), Some((1, 1))} -mat!{match_repetition_127, r"(a|ab|c|bcd){1,}(d*)", r"ababcd", Some((0, 1)), Some((0, 1)), Some((1, 1))} -mat!{match_repetition_128, r"(a|ab|c|bcd){2,}(d*)", r"ababcd", Some((0, 6)), Some((3, 6)), Some((6, 6))} -mat!{match_repetition_129, r"(a|ab|c|bcd){3,}(d*)", r"ababcd", Some((0, 6)), Some((3, 6)), Some((6, 6))} -mat!{match_repetition_130, r"(a|ab|c|bcd){4,}(d*)", r"ababcd", None} -mat!{match_repetition_131, r"(a|ab|c|bcd){0,10}(d*)", r"ababcd", Some((0, 1)), Some((0, 1)), Some((1, 1))} -mat!{match_repetition_132, r"(a|ab|c|bcd){1,10}(d*)", r"ababcd", Some((0, 1)), Some((0, 1)), Some((1, 1))} -mat!{match_repetition_133, r"(a|ab|c|bcd){2,10}(d*)", r"ababcd", Some((0, 6)), Some((3, 6)), Some((6, 6))} -mat!{match_repetition_134, r"(a|ab|c|bcd){3,10}(d*)", r"ababcd", Some((0, 6)), Some((3, 6)), Some((6, 6))} -mat!{match_repetition_135, r"(a|ab|c|bcd){4,10}(d*)", r"ababcd", None} -mat!{match_repetition_136, r"(a|ab|c|bcd)*(d*)", r"ababcd", Some((0, 1)), Some((0, 1)), Some((1, 1))} -mat!{match_repetition_137, r"(a|ab|c|bcd)+(d*)", r"ababcd", Some((0, 1)), Some((0, 1)), Some((1, 1))} -mat!{match_repetition_143, r"(ab|a|c|bcd){0,}(d*)", r"ababcd", Some((0, 6)), Some((4, 5)), Some((5, 6))} -mat!{match_repetition_145, r"(ab|a|c|bcd){1,}(d*)", r"ababcd", Some((0, 6)), Some((4, 5)), Some((5, 6))} -mat!{match_repetition_147, r"(ab|a|c|bcd){2,}(d*)", r"ababcd", Some((0, 6)), Some((4, 5)), Some((5, 6))} -mat!{match_repetition_149, r"(ab|a|c|bcd){3,}(d*)", r"ababcd", Some((0, 6)), Some((4, 5)), Some((5, 6))} -mat!{match_repetition_150, r"(ab|a|c|bcd){4,}(d*)", r"ababcd", None} -mat!{match_repetition_152, r"(ab|a|c|bcd){0,10}(d*)", r"ababcd", Some((0, 6)), Some((4, 5)), Some((5, 6))} -mat!{match_repetition_154, r"(ab|a|c|bcd){1,10}(d*)", r"ababcd", Some((0, 6)), Some((4, 5)), Some((5, 6))} -mat!{match_repetition_156, r"(ab|a|c|bcd){2,10}(d*)", r"ababcd", Some((0, 6)), Some((4, 5)), Some((5, 6))} -mat!{match_repetition_158, r"(ab|a|c|bcd){3,10}(d*)", r"ababcd", Some((0, 6)), Some((4, 5)), Some((5, 6))} -mat!{match_repetition_159, r"(ab|a|c|bcd){4,10}(d*)", r"ababcd", None} -mat!{match_repetition_161, r"(ab|a|c|bcd)*(d*)", r"ababcd", Some((0, 6)), Some((4, 5)), Some((5, 6))} -mat!{match_repetition_163, r"(ab|a|c|bcd)+(d*)", r"ababcd", Some((0, 6)), Some((4, 5)), Some((5, 6))} - diff --git a/src/libregex/test/native_static.rs b/src/libregex/test/native_static.rs deleted file mode 100644 index 62e14731c207..000000000000 --- a/src/libregex/test/native_static.rs +++ /dev/null @@ -1,26 +0,0 @@ -// 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. - -use regex::Regex; -static RE: Regex = regex!(r"\d+"); - -#[test] -fn static_splitn() { - let text = "cauchy123plato456tyler789binx"; - let subs: Vec<&str> = RE.splitn(text, 2).collect(); - assert_eq!(subs, vec!("cauchy", "plato456tyler789binx")); -} - -#[test] -fn static_split() { - let text = "cauchy123plato456tyler789binx"; - let subs: Vec<&str> = RE.split(text).collect(); - assert_eq!(subs, vec!("cauchy", "plato", "tyler", "binx")); -} diff --git a/src/libregex/test/tests.rs b/src/libregex/test/tests.rs deleted file mode 100644 index b69420ac05bd..000000000000 --- a/src/libregex/test/tests.rs +++ /dev/null @@ -1,245 +0,0 @@ -// 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. - -// ignore-tidy-linelength -// ignore-lexer-test FIXME #15679 - -use regex::{Regex, NoExpand}; - -#[test] -fn splitn() { - let re = regex!(r"\d+"); - let text = "cauchy123plato456tyler789binx"; - let subs: Vec<&str> = re.splitn(text, 2).collect(); - assert_eq!(subs, vec!("cauchy", "plato456tyler789binx")); -} - -#[test] -fn split() { - let re = regex!(r"\d+"); - let text = "cauchy123plato456tyler789binx"; - let subs: Vec<&str> = re.split(text).collect(); - assert_eq!(subs, vec!("cauchy", "plato", "tyler", "binx")); -} - -#[test] -fn empty_regex_empty_match() { - let re = regex!(""); - let ms = re.find_iter("").collect::>(); - assert_eq!(ms, vec![(0, 0)]); -} - -#[test] -fn empty_regex_nonempty_match() { - let re = regex!(""); - let ms = re.find_iter("abc").collect::>(); - assert_eq!(ms, vec![(0, 0), (1, 1), (2, 2), (3, 3)]); -} - -#[test] -fn quoted_bracket_set() { - let re = regex!(r"([\x{5b}\x{5d}])"); - let ms = re.find_iter("[]").collect::>(); - assert_eq!(ms, vec![(0, 1), (1, 2)]); - let re = regex!(r"([\[\]])"); - let ms = re.find_iter("[]").collect::>(); - assert_eq!(ms, vec![(0, 1), (1, 2)]); -} - -#[test] -fn first_range_starts_with_left_bracket() { - let re = regex!(r"([[-z])"); - let ms = re.find_iter("[]").collect::>(); - assert_eq!(ms, vec![(0, 1), (1, 2)]); -} - -#[test] -fn range_ends_with_escape() { - let re = regex!(r"([\[-\x{5d}])"); - let ms = re.find_iter("[]").collect::>(); - assert_eq!(ms, vec![(0, 1), (1, 2)]); -} - -macro_rules! replace { - ($name:ident, $which:ident, $re:expr, - $search:expr, $replace:expr, $result:expr) => ( - #[test] - fn $name() { - let re = regex!($re); - assert_eq!(re.$which($search, $replace), String::from_str($result)); - } - ); -} - -replace!{rep_first, replace, r"\d", "age: 26", "Z", "age: Z6"} -replace!{rep_plus, replace, r"\d+", "age: 26", "Z", "age: Z"} -replace!{rep_all, replace_all, r"\d", "age: 26", "Z", "age: ZZ"} -replace!{rep_groups, replace, r"(\S+)\s+(\S+)", "w1 w2", "$2 $1", "w2 w1"} -replace!{rep_double_dollar, replace, - r"(\S+)\s+(\S+)", "w1 w2", "$2 $$1", "w2 $1"} -replace!{rep_no_expand, replace, - r"(\S+)\s+(\S+)", "w1 w2", NoExpand("$2 $1"), "$2 $1"} -replace!{rep_named, replace_all, - r"(?P\S+)\s+(?P\S+)(?P\s*)", - "w1 w2 w3 w4", "$last $first$space", "w2 w1 w4 w3"} -replace!{rep_trim, replace_all, "^[ \t]+|[ \t]+$", " \t trim me\t \t", - "", "trim me"} - -macro_rules! noparse { - ($name:ident, $re:expr) => ( - #[test] - fn $name() { - let re = $re; - match Regex::new(re) { - Err(_) => {}, - Ok(_) => panic!("Regex '{}' should cause a parse error.", re), - } - } - ); -} - -noparse!{fail_double_repeat, "a**"} -noparse!{fail_no_repeat_arg, "*"} -noparse!{fail_no_repeat_arg_begin, "^*"} -noparse!{fail_incomplete_escape, "\\"} -noparse!{fail_class_incomplete, "[A-"} -noparse!{fail_class_not_closed, "[A"} -noparse!{fail_class_no_begin, r"[\A]"} -noparse!{fail_class_no_end, r"[\z]"} -noparse!{fail_class_no_boundary, r"[\b]"} -noparse!{fail_open_paren, "("} -noparse!{fail_close_paren, ")"} -noparse!{fail_invalid_range, "[a-Z]"} -noparse!{fail_empty_capture_name, "(?P<>a)"} -noparse!{fail_empty_capture_exp, "(?P)"} -noparse!{fail_bad_capture_name, "(?P)"} -noparse!{fail_bad_flag, "(?a)a"} -noparse!{fail_empty_alt_before, "|a"} -noparse!{fail_empty_alt_after, "a|"} -noparse!{fail_counted_big_exact, "a{1001}"} -noparse!{fail_counted_big_min, "a{1001,}"} -noparse!{fail_counted_no_close, "a{1001"} -noparse!{fail_unfinished_cap, "(?"} -noparse!{fail_unfinished_escape, "\\"} -noparse!{fail_octal_digit, r"\8"} -noparse!{fail_hex_digit, r"\xG0"} -noparse!{fail_hex_short, r"\xF"} -noparse!{fail_hex_long_digits, r"\x{fffg}"} -noparse!{fail_flag_bad, "(?a)"} -noparse!{fail_flag_empty, "(?)"} -noparse!{fail_double_neg, "(?-i-i)"} -noparse!{fail_neg_empty, "(?i-)"} -noparse!{fail_empty_group, "()"} -noparse!{fail_dupe_named, "(?P.)(?P.)"} -noparse!{fail_range_end_no_class, "[a-[:lower:]]"} -noparse!{fail_range_end_no_begin, r"[a-\A]"} -noparse!{fail_range_end_no_end, r"[a-\z]"} -noparse!{fail_range_end_no_boundary, r"[a-\b]"} -noparse!{fail_repeat_no_expr, r"-|+"} - -macro_rules! mat { - ($name:ident, $re:expr, $text:expr, $($loc:tt)+) => ( - #[test] - fn $name() { - let text = $text; - let expected: Vec> = vec!($($loc)+); - let r = regex!($re); - let got = match r.captures(text) { - Some(c) => c.iter_pos().collect::>>(), - None => vec!(None), - }; - // The test set sometimes leave out capture groups, so truncate - // actual capture groups to match test set. - let mut sgot = got.as_slice(); - if sgot.len() > expected.len() { - sgot = &sgot[..expected.len()] - } - if expected != sgot { - panic!("For RE '{}' against '{}', expected '{:?}' but got '{:?}'", - $re, text, expected, sgot); - } - } - ); -} - -// Some crazy expressions from regular-expressions.info. -mat!{match_ranges, - r"\b(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b", - "num: 255", Some((5, 8))} -mat!{match_ranges_not, - r"\b(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b", - "num: 256", None} -mat!{match_float1, r"[-+]?[0-9]*\.?[0-9]+", "0.1", Some((0, 3))} -mat!{match_float2, r"[-+]?[0-9]*\.?[0-9]+", "0.1.2", Some((0, 3))} -mat!{match_float3, r"[-+]?[0-9]*\.?[0-9]+", "a1.2", Some((1, 4))} -mat!{match_float4, r"^[-+]?[0-9]*\.?[0-9]+$", "1.a", None} -mat!{match_email, r"(?i)\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b", - "mine is jam.slam@gmail.com ", Some((8, 26))} -mat!{match_email_not, r"(?i)\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b", - "mine is jam.slam@gmail ", None} -mat!{match_email_big, r"[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?", - "mine is jam.slam@gmail.com ", Some((8, 26))} -mat!{match_date1, - r"^(19|20)\d\d[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])$", - "1900-01-01", Some((0, 10))} -mat!{match_date2, - r"^(19|20)\d\d[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])$", - "1900-00-01", None} -mat!{match_date3, - r"^(19|20)\d\d[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])$", - "1900-13-01", None} - -// Exercise the flags. -mat!{match_flag_case, "(?i)abc", "ABC", Some((0, 3))} -mat!{match_flag_weird_case, "(?i)a(?-i)bc", "Abc", Some((0, 3))} -mat!{match_flag_weird_case_not, "(?i)a(?-i)bc", "ABC", None} -mat!{match_flag_case_dotnl, "(?is)a.", "A\n", Some((0, 2))} -mat!{match_flag_case_dotnl_toggle, "(?is)a.(?-is)a.", "A\nab", Some((0, 4))} -mat!{match_flag_case_dotnl_toggle_not, "(?is)a.(?-is)a.", "A\na\n", None} -mat!{match_flag_case_dotnl_toggle_ok, "(?is)a.(?-is:a.)?", "A\na\n", Some((0, 2))} -mat!{match_flag_multi, "(?m)(?:^\\d+$\n?)+", "123\n456\n789", Some((0, 11))} -mat!{match_flag_ungreedy, "(?U)a+", "aa", Some((0, 1))} -mat!{match_flag_ungreedy_greedy, "(?U)a+?", "aa", Some((0, 2))} -mat!{match_flag_ungreedy_noop, "(?U)(?-U)a+", "aa", Some((0, 2))} - -// Some Unicode tests. -// A couple of these are commented out because something in the guts of macro expansion is creating -// invalid byte strings. -//mat!{uni_literal, r"Ⅰ", "Ⅰ", Some((0, 3))} -mat!{uni_one, r"\pN", "Ⅰ", Some((0, 3))} -mat!{uni_mixed, r"\pN+", "Ⅰ1Ⅱ2", Some((0, 8))} -mat!{uni_not, r"\PN+", "abⅠ", Some((0, 2))} -mat!{uni_not_class, r"[\PN]+", "abⅠ", Some((0, 2))} -mat!{uni_not_class_neg, r"[^\PN]+", "abⅠ", Some((2, 5))} -mat!{uni_case, r"(?i)Δ", "δ", Some((0, 2))} -//mat!{uni_case_not, r"Δ", "δ", None} -mat!{uni_case_upper, r"\p{Lu}+", "ΛΘΓΔα", Some((0, 8))} -mat!{uni_case_upper_nocase_flag, r"(?i)\p{Lu}+", "ΛΘΓΔα", Some((0, 10))} -mat!{uni_case_upper_nocase, r"\p{L}+", "ΛΘΓΔα", Some((0, 10))} -mat!{uni_case_lower, r"\p{Ll}+", "ΛΘΓΔα", Some((8, 10))} - -// Test the Unicode friendliness of Perl character classes. -mat!{uni_perl_w, r"\w+", "dδd", Some((0, 4))} -mat!{uni_perl_w_not, r"\w+", "⥡", None} -mat!{uni_perl_w_neg, r"\W+", "⥡", Some((0, 3))} -mat!{uni_perl_d, r"\d+", "1२३9", Some((0, 8))} -mat!{uni_perl_d_not, r"\d+", "Ⅱ", None} -mat!{uni_perl_d_neg, r"\D+", "Ⅱ", Some((0, 3))} -mat!{uni_perl_s, r"\s+", " ", Some((0, 3))} -mat!{uni_perl_s_not, r"\s+", "☃", None} -mat!{uni_perl_s_neg, r"\S+", "☃", Some((0, 3))} - -// And do the same for word boundaries. -mat!{uni_boundary_none, r"\d\b", "6δ", None} -mat!{uni_boundary_ogham, r"\d\b", "6 ", Some((0, 1))} - -// A whole mess of tests from Glenn Fowler's regex test suite. -// Generated by the 'src/etc/regex-match-tests' program. -mod matches; diff --git a/src/libregex/testdata/LICENSE b/src/libregex/testdata/LICENSE deleted file mode 100644 index f47dbf4c449b..000000000000 --- a/src/libregex/testdata/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -The following license covers testregex.c and all associated test data. - -Permission is hereby granted, free of charge, to any person obtaining a -copy of THIS SOFTWARE FILE (the "Software"), to deal in the Software -without restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, and/or sell copies of the -Software, and to permit persons to whom the Software is furnished to do -so, subject to the following disclaimer: - -THIS SOFTWARE IS PROVIDED BY AT&T ``AS IS'' AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL AT&T BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/libregex/testdata/README b/src/libregex/testdata/README deleted file mode 100644 index 33b0ba17ed7f..000000000000 --- a/src/libregex/testdata/README +++ /dev/null @@ -1,17 +0,0 @@ -Test data was taken from the Go distribution, which was in turn taken from the -testregex test suite: - - http://www2.research.att.com/~astopen/testregex/testregex.html - -The LICENSE in this directory corresponds to the LICENSE that the data was -released under. - -The tests themselves were modified for RE2/Go. A couple were modified further -by me (Andrew Gallant) (only in repetition.dat) so that RE2/Go would pass them. -(Yes, it seems like RE2/Go includes failing test cases.) This may or may not -have been a bad idea, but I think being consistent with an established Regex -library is worth something. - -Note that these files are read by 'src/etc/regexp-match-tests' and turned into -Rust tests found in 'src/libregexp/tests/matches.rs'. - diff --git a/src/libregex/testdata/basic.dat b/src/libregex/testdata/basic.dat deleted file mode 100644 index e55efaeec062..000000000000 --- a/src/libregex/testdata/basic.dat +++ /dev/null @@ -1,221 +0,0 @@ -NOTE all standard compliant implementations should pass these : 2002-05-31 - -BE abracadabra$ abracadabracadabra (7,18) -BE a...b abababbb (2,7) -BE XXXXXX ..XXXXXX (2,8) -E \) () (1,2) -BE a] a]a (0,2) -B } } (0,1) -E \} } (0,1) -BE \] ] (0,1) -B ] ] (0,1) -E ] ] (0,1) -B { { (0,1) -B } } (0,1) -BE ^a ax (0,1) -BE \^a a^a (1,3) -BE a\^ a^ (0,2) -BE a$ aa (1,2) -BE a\$ a$ (0,2) -BE ^$ NULL (0,0) -E $^ NULL (0,0) -E a($) aa (1,2)(2,2) -E a*(^a) aa (0,1)(0,1) -E (..)*(...)* a (0,0) -E (..)*(...)* abcd (0,4)(2,4) -E (ab|a)(bc|c) abc (0,3)(0,2)(2,3) -E (ab)c|abc abc (0,3)(0,2) -E a{0}b ab (1,2) -E (a*)(b?)(b+)b{3} aaabbbbbbb (0,10)(0,3)(3,4)(4,7) -E (a*)(b{0,1})(b{1,})b{3} aaabbbbbbb (0,10)(0,3)(3,4)(4,7) -E a{9876543210} NULL BADBR -E ((a|a)|a) a (0,1)(0,1)(0,1) -E (a*)(a|aa) aaaa (0,4)(0,3)(3,4) -E a*(a.|aa) aaaa (0,4)(2,4) -E a(b)|c(d)|a(e)f aef (0,3)(?,?)(?,?)(1,2) -E (a|b)?.* b (0,1)(0,1) -E (a|b)c|a(b|c) ac (0,2)(0,1) -E (a|b)c|a(b|c) ab (0,2)(?,?)(1,2) -E (a|b)*c|(a|ab)*c abc (0,3)(1,2) -E (a|b)*c|(a|ab)*c xc (1,2) -E (.a|.b).*|.*(.a|.b) xa (0,2)(0,2) -E a?(ab|ba)ab abab (0,4)(0,2) -E a?(ac{0}b|ba)ab abab (0,4)(0,2) -E ab|abab abbabab (0,2) -E aba|bab|bba baaabbbaba (5,8) -E aba|bab baaabbbaba (6,9) -E (aa|aaa)*|(a|aaaaa) aa (0,2)(0,2) -E (a.|.a.)*|(a|.a...) aa (0,2)(0,2) -E ab|a xabc (1,3) -E ab|a xxabc (2,4) -Ei (Ab|cD)* aBcD (0,4)(2,4) -BE [^-] --a (2,3) -BE [a-]* --a (0,3) -BE [a-m-]* --amoma-- (0,4) -E :::1:::0:|:::1:1:0: :::0:::1:::1:::0: (8,17) -E :::1:::0:|:::1:1:1: :::0:::1:::1:::0: (8,17) -{E [[:upper:]] A (0,1) [[]] not supported -E [[:lower:]]+ `az{ (1,3) -E [[:upper:]]+ @AZ[ (1,3) -# No collation in Go -#BE [[-]] [[-]] (2,4) -#BE [[.NIL.]] NULL ECOLLATE -#BE [[=aleph=]] NULL ECOLLATE -} -BE$ \n \n (0,1) -BEn$ \n \n (0,1) -BE$ [^a] \n (0,1) -BE$ \na \na (0,2) -E (a)(b)(c) abc (0,3)(0,1)(1,2)(2,3) -BE xxx xxx (0,3) -E1 (^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$) feb 6, (0,6) -E1 (^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$) 2/7 (0,3) -E1 (^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$) feb 1,Feb 6 (5,11) -E3 ((((((((((((((((((((((((((((((x)))))))))))))))))))))))))))))) x (0,1)(0,1)(0,1) -E3 ((((((((((((((((((((((((((((((x))))))))))))))))))))))))))))))* xx (0,2)(1,2)(1,2) -E a?(ab|ba)* ababababababababababababababababababababababababababababababababababababababababa (0,81)(79,81) -E abaa|abbaa|abbbaa|abbbbaa ababbabbbabbbabbbbabbbbaa (18,25) -E abaa|abbaa|abbbaa|abbbbaa ababbabbbabbbabbbbabaa (18,22) -E aaac|aabc|abac|abbc|baac|babc|bbac|bbbc baaabbbabac (7,11) -BE$ .* \x01\x7f (0,2) -E aaaa|bbbb|cccc|ddddd|eeeeee|fffffff|gggg|hhhh|iiiii|jjjjj|kkkkk|llll XaaaXbbbXcccXdddXeeeXfffXgggXhhhXiiiXjjjXkkkXlllXcbaXaaaa (53,57) -L aaaa\nbbbb\ncccc\nddddd\neeeeee\nfffffff\ngggg\nhhhh\niiiii\njjjjj\nkkkkk\nllll XaaaXbbbXcccXdddXeeeXfffXgggXhhhXiiiXjjjXkkkXlllXcbaXaaaa NOMATCH -E a*a*a*a*a*b aaaaaaaaab (0,10) -BE ^ NULL (0,0) -BE $ NULL (0,0) -BE ^$ NULL (0,0) -BE ^a$ a (0,1) -BE abc abc (0,3) -BE abc xabcy (1,4) -BE abc ababc (2,5) -BE ab*c abc (0,3) -BE ab*bc abc (0,3) -BE ab*bc abbc (0,4) -BE ab*bc abbbbc (0,6) -E ab+bc abbc (0,4) -E ab+bc abbbbc (0,6) -E ab?bc abbc (0,4) -E ab?bc abc (0,3) -E ab?c abc (0,3) -BE ^abc$ abc (0,3) -BE ^abc abcc (0,3) -BE abc$ aabc (1,4) -BE ^ abc (0,0) -BE $ abc (3,3) -BE a.c abc (0,3) -BE a.c axc (0,3) -BE a.*c axyzc (0,5) -BE a[bc]d abd (0,3) -BE a[b-d]e ace (0,3) -BE a[b-d] aac (1,3) -BE a[-b] a- (0,2) -BE a[b-] a- (0,2) -BE a] a] (0,2) -BE a[]]b a]b (0,3) -BE a[^bc]d aed (0,3) -BE a[^-b]c adc (0,3) -BE a[^]b]c adc (0,3) -E ab|cd abc (0,2) -E ab|cd abcd (0,2) -E a\(b a(b (0,3) -E a\(*b ab (0,2) -E a\(*b a((b (0,4) -E ((a)) abc (0,1)(0,1)(0,1) -E (a)b(c) abc (0,3)(0,1)(2,3) -E a+b+c aabbabc (4,7) -E a* aaa (0,3) -#E (a*)* - (0,0)(0,0) -E (a*)* - (0,0)(?,?) RE2/Go -E (a*)+ - (0,0)(0,0) -#E (a*|b)* - (0,0)(0,0) -E (a*|b)* - (0,0)(?,?) RE2/Go -E (a+|b)* ab (0,2)(1,2) -E (a+|b)+ ab (0,2)(1,2) -E (a+|b)? ab (0,1)(0,1) -BE [^ab]* cde (0,3) -#E (^)* - (0,0)(0,0) -E (^)* - (0,0)(?,?) RE2/Go -BE a* NULL (0,0) -E ([abc])*d abbbcd (0,6)(4,5) -E ([abc])*bcd abcd (0,4)(0,1) -E a|b|c|d|e e (0,1) -E (a|b|c|d|e)f ef (0,2)(0,1) -#E ((a*|b))* - (0,0)(0,0)(0,0) -E ((a*|b))* - (0,0)(?,?)(?,?) RE2/Go -BE abcd*efg abcdefg (0,7) -BE ab* xabyabbbz (1,3) -BE ab* xayabbbz (1,2) -E (ab|cd)e abcde (2,5)(2,4) -BE [abhgefdc]ij hij (0,3) -E (a|b)c*d abcd (1,4)(1,2) -E (ab|ab*)bc abc (0,3)(0,1) -E a([bc]*)c* abc (0,3)(1,3) -E a([bc]*)(c*d) abcd (0,4)(1,3)(3,4) -E a([bc]+)(c*d) abcd (0,4)(1,3)(3,4) -E a([bc]*)(c+d) abcd (0,4)(1,2)(2,4) -E a[bcd]*dcdcde adcdcde (0,7) -E (ab|a)b*c abc (0,3)(0,2) -E ((a)(b)c)(d) abcd (0,4)(0,3)(0,1)(1,2)(3,4) -BE [A-Za-z_][A-Za-z0-9_]* alpha (0,5) -E ^a(bc+|b[eh])g|.h$ abh (1,3) -E (bc+d$|ef*g.|h?i(j|k)) effgz (0,5)(0,5) -E (bc+d$|ef*g.|h?i(j|k)) ij (0,2)(0,2)(1,2) -E (bc+d$|ef*g.|h?i(j|k)) reffgz (1,6)(1,6) -E (((((((((a))))))))) a (0,1)(0,1)(0,1)(0,1)(0,1)(0,1)(0,1)(0,1)(0,1)(0,1) -BE multiple words multiple words yeah (0,14) -E (.*)c(.*) abcde (0,5)(0,2)(3,5) -BE abcd abcd (0,4) -E a(bc)d abcd (0,4)(1,3) -E a[-]?c ac (0,3) -E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Qaddafi (0,15)(?,?)(10,12) -E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Mo'ammar Gadhafi (0,16)(?,?)(11,13) -E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Kaddafi (0,15)(?,?)(10,12) -E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Qadhafi (0,15)(?,?)(10,12) -E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Gadafi (0,14)(?,?)(10,11) -E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Mu'ammar Qadafi (0,15)(?,?)(11,12) -E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Moamar Gaddafi (0,14)(?,?)(9,11) -E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Mu'ammar Qadhdhafi (0,18)(?,?)(13,15) -E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Khaddafi (0,16)(?,?)(11,13) -E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Ghaddafy (0,16)(?,?)(11,13) -E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Ghadafi (0,15)(?,?)(11,12) -E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Ghaddafi (0,16)(?,?)(11,13) -E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muamar Kaddafi (0,14)(?,?)(9,11) -E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Quathafi (0,16)(?,?)(11,13) -E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Gheddafi (0,16)(?,?)(11,13) -E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Moammar Khadafy (0,15)(?,?)(11,12) -E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Moammar Qudhafi (0,15)(?,?)(10,12) -E a+(b|c)*d+ aabcdd (0,6)(3,4) -E ^.+$ vivi (0,4) -E ^(.+)$ vivi (0,4)(0,4) -E ^([^!.]+).att.com!(.+)$ gryphon.att.com!eby (0,19)(0,7)(16,19) -E ^([^!]+!)?([^!]+)$ bas (0,3)(?,?)(0,3) -E ^([^!]+!)?([^!]+)$ bar!bas (0,7)(0,4)(4,7) -E ^([^!]+!)?([^!]+)$ foo!bas (0,7)(0,4)(4,7) -E ^.+!([^!]+!)([^!]+)$ foo!bar!bas (0,11)(4,8)(8,11) -E ((foo)|(bar))!bas bar!bas (0,7)(0,3)(?,?)(0,3) -E ((foo)|(bar))!bas foo!bar!bas (4,11)(4,7)(?,?)(4,7) -E ((foo)|(bar))!bas foo!bas (0,7)(0,3)(0,3) -E ((foo)|bar)!bas bar!bas (0,7)(0,3) -E ((foo)|bar)!bas foo!bar!bas (4,11)(4,7) -E ((foo)|bar)!bas foo!bas (0,7)(0,3)(0,3) -E (foo|(bar))!bas bar!bas (0,7)(0,3)(0,3) -E (foo|(bar))!bas foo!bar!bas (4,11)(4,7)(4,7) -E (foo|(bar))!bas foo!bas (0,7)(0,3) -E (foo|bar)!bas bar!bas (0,7)(0,3) -E (foo|bar)!bas foo!bar!bas (4,11)(4,7) -E (foo|bar)!bas foo!bas (0,7)(0,3) -E ^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$ foo!bar!bas (0,11)(0,11)(?,?)(?,?)(4,8)(8,11) -E ^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$ bas (0,3)(?,?)(0,3) -E ^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$ bar!bas (0,7)(0,4)(4,7) -E ^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$ foo!bar!bas (0,11)(?,?)(?,?)(4,8)(8,11) -E ^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$ foo!bas (0,7)(0,4)(4,7) -E ^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$ bas (0,3)(0,3)(?,?)(0,3) -E ^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$ bar!bas (0,7)(0,7)(0,4)(4,7) -E ^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$ foo!bar!bas (0,11)(0,11)(?,?)(?,?)(4,8)(8,11) -E ^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$ foo!bas (0,7)(0,7)(0,4)(4,7) -E .*(/XXX).* /XXX (0,4)(0,4) -E .*(\\XXX).* \XXX (0,4)(0,4) -E \\XXX \XXX (0,4) -E .*(/000).* /000 (0,4)(0,4) -E .*(\\000).* \000 (0,4)(0,4) -E \\000 \000 (0,4) diff --git a/src/libregex/testdata/nullsubexpr.dat b/src/libregex/testdata/nullsubexpr.dat deleted file mode 100644 index 2e18fbb91707..000000000000 --- a/src/libregex/testdata/nullsubexpr.dat +++ /dev/null @@ -1,79 +0,0 @@ -NOTE null subexpression matches : 2002-06-06 - -E (a*)* a (0,1)(0,1) -#E SAME x (0,0)(0,0) -E SAME x (0,0)(?,?) RE2/Go -E SAME aaaaaa (0,6)(0,6) -E SAME aaaaaax (0,6)(0,6) -E (a*)+ a (0,1)(0,1) -E SAME x (0,0)(0,0) -E SAME aaaaaa (0,6)(0,6) -E SAME aaaaaax (0,6)(0,6) -E (a+)* a (0,1)(0,1) -E SAME x (0,0) -E SAME aaaaaa (0,6)(0,6) -E SAME aaaaaax (0,6)(0,6) -E (a+)+ a (0,1)(0,1) -E SAME x NOMATCH -E SAME aaaaaa (0,6)(0,6) -E SAME aaaaaax (0,6)(0,6) - -E ([a]*)* a (0,1)(0,1) -#E SAME x (0,0)(0,0) -E SAME x (0,0)(?,?) RE2/Go -E SAME aaaaaa (0,6)(0,6) -E SAME aaaaaax (0,6)(0,6) -E ([a]*)+ a (0,1)(0,1) -E SAME x (0,0)(0,0) -E SAME aaaaaa (0,6)(0,6) -E SAME aaaaaax (0,6)(0,6) -E ([^b]*)* a (0,1)(0,1) -#E SAME b (0,0)(0,0) -E SAME b (0,0)(?,?) RE2/Go -E SAME aaaaaa (0,6)(0,6) -E SAME aaaaaab (0,6)(0,6) -E ([ab]*)* a (0,1)(0,1) -E SAME aaaaaa (0,6)(0,6) -E SAME ababab (0,6)(0,6) -E SAME bababa (0,6)(0,6) -E SAME b (0,1)(0,1) -E SAME bbbbbb (0,6)(0,6) -E SAME aaaabcde (0,5)(0,5) -E ([^a]*)* b (0,1)(0,1) -E SAME bbbbbb (0,6)(0,6) -#E SAME aaaaaa (0,0)(0,0) -E SAME aaaaaa (0,0)(?,?) RE2/Go -E ([^ab]*)* ccccxx (0,6)(0,6) -#E SAME ababab (0,0)(0,0) -E SAME ababab (0,0)(?,?) RE2/Go - -E ((z)+|a)* zabcde (0,2)(1,2) - -#{E a+? aaaaaa (0,1) no *? +? mimimal match ops -#E (a) aaa (0,1)(0,1) -#E (a*?) aaa (0,0)(0,0) -#E (a)*? aaa (0,0) -#E (a*?)*? aaa (0,0) -#} - -B \(a*\)*\(x\) x (0,1)(0,0)(0,1) -B \(a*\)*\(x\) ax (0,2)(0,1)(1,2) -B \(a*\)*\(x\) axa (0,2)(0,1)(1,2) -B \(a*\)*\(x\)\(\1\) x (0,1)(0,0)(0,1)(1,1) -B \(a*\)*\(x\)\(\1\) ax (0,2)(1,1)(1,2)(2,2) -B \(a*\)*\(x\)\(\1\) axa (0,3)(0,1)(1,2)(2,3) -B \(a*\)*\(x\)\(\1\)\(x\) axax (0,4)(0,1)(1,2)(2,3)(3,4) -B \(a*\)*\(x\)\(\1\)\(x\) axxa (0,3)(1,1)(1,2)(2,2)(2,3) - -#E (a*)*(x) x (0,1)(0,0)(0,1) -E (a*)*(x) x (0,1)(?,?)(0,1) RE2/Go -E (a*)*(x) ax (0,2)(0,1)(1,2) -E (a*)*(x) axa (0,2)(0,1)(1,2) - -E (a*)+(x) x (0,1)(0,0)(0,1) -E (a*)+(x) ax (0,2)(0,1)(1,2) -E (a*)+(x) axa (0,2)(0,1)(1,2) - -E (a*){2}(x) x (0,1)(0,0)(0,1) -E (a*){2}(x) ax (0,2)(1,1)(1,2) -E (a*){2}(x) axa (0,2)(1,1)(1,2) diff --git a/src/libregex/testdata/repetition.dat b/src/libregex/testdata/repetition.dat deleted file mode 100644 index 3bb212118000..000000000000 --- a/src/libregex/testdata/repetition.dat +++ /dev/null @@ -1,163 +0,0 @@ -NOTE implicit vs. explicit repetitions : 2009-02-02 - -# Glenn Fowler -# conforming matches (column 4) must match one of the following BREs -# NOMATCH -# (0,.)\((\(.\),\(.\))(?,?)(\2,\3)\)* -# (0,.)\((\(.\),\(.\))(\2,\3)(?,?)\)* -# i.e., each 3-tuple has two identical elements and one (?,?) - -E ((..)|(.)) NULL NOMATCH -E ((..)|(.))((..)|(.)) NULL NOMATCH -E ((..)|(.))((..)|(.))((..)|(.)) NULL NOMATCH - -E ((..)|(.)){1} NULL NOMATCH -E ((..)|(.)){2} NULL NOMATCH -E ((..)|(.)){3} NULL NOMATCH - -E ((..)|(.))* NULL (0,0) - -E ((..)|(.)) a (0,1)(0,1)(?,?)(0,1) -E ((..)|(.))((..)|(.)) a NOMATCH -E ((..)|(.))((..)|(.))((..)|(.)) a NOMATCH - -E ((..)|(.)){1} a (0,1)(0,1)(?,?)(0,1) -E ((..)|(.)){2} a NOMATCH -E ((..)|(.)){3} a NOMATCH - -E ((..)|(.))* a (0,1)(0,1)(?,?)(0,1) - -E ((..)|(.)) aa (0,2)(0,2)(0,2)(?,?) -E ((..)|(.))((..)|(.)) aa (0,2)(0,1)(?,?)(0,1)(1,2)(?,?)(1,2) -E ((..)|(.))((..)|(.))((..)|(.)) aa NOMATCH - -E ((..)|(.)){1} aa (0,2)(0,2)(0,2)(?,?) -E ((..)|(.)){2} aa (0,2)(1,2)(?,?)(1,2) -E ((..)|(.)){3} aa NOMATCH - -E ((..)|(.))* aa (0,2)(0,2)(0,2)(?,?) - -E ((..)|(.)) aaa (0,2)(0,2)(0,2)(?,?) -E ((..)|(.))((..)|(.)) aaa (0,3)(0,2)(0,2)(?,?)(2,3)(?,?)(2,3) -E ((..)|(.))((..)|(.))((..)|(.)) aaa (0,3)(0,1)(?,?)(0,1)(1,2)(?,?)(1,2)(2,3)(?,?)(2,3) - -E ((..)|(.)){1} aaa (0,2)(0,2)(0,2)(?,?) -#E ((..)|(.)){2} aaa (0,3)(2,3)(?,?)(2,3) -E ((..)|(.)){2} aaa (0,3)(2,3)(0,2)(2,3) RE2/Go -E ((..)|(.)){3} aaa (0,3)(2,3)(?,?)(2,3) - -#E ((..)|(.))* aaa (0,3)(2,3)(?,?)(2,3) -E ((..)|(.))* aaa (0,3)(2,3)(0,2)(2,3) RE2/Go - -E ((..)|(.)) aaaa (0,2)(0,2)(0,2)(?,?) -E ((..)|(.))((..)|(.)) aaaa (0,4)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?) -E ((..)|(.))((..)|(.))((..)|(.)) aaaa (0,4)(0,2)(0,2)(?,?)(2,3)(?,?)(2,3)(3,4)(?,?)(3,4) - -E ((..)|(.)){1} aaaa (0,2)(0,2)(0,2)(?,?) -E ((..)|(.)){2} aaaa (0,4)(2,4)(2,4)(?,?) -#E ((..)|(.)){3} aaaa (0,4)(3,4)(?,?)(3,4) -E ((..)|(.)){3} aaaa (0,4)(3,4)(0,2)(3,4) RE2/Go - -E ((..)|(.))* aaaa (0,4)(2,4)(2,4)(?,?) - -E ((..)|(.)) aaaaa (0,2)(0,2)(0,2)(?,?) -E ((..)|(.))((..)|(.)) aaaaa (0,4)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?) -E ((..)|(.))((..)|(.))((..)|(.)) aaaaa (0,5)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?)(4,5)(?,?)(4,5) - -E ((..)|(.)){1} aaaaa (0,2)(0,2)(0,2)(?,?) -E ((..)|(.)){2} aaaaa (0,4)(2,4)(2,4)(?,?) -#E ((..)|(.)){3} aaaaa (0,5)(4,5)(?,?)(4,5) -E ((..)|(.)){3} aaaaa (0,5)(4,5)(2,4)(4,5) RE2/Go - -#E ((..)|(.))* aaaaa (0,5)(4,5)(?,?)(4,5) -E ((..)|(.))* aaaaa (0,5)(4,5)(2,4)(4,5) RE2/Go - -E ((..)|(.)) aaaaaa (0,2)(0,2)(0,2)(?,?) -E ((..)|(.))((..)|(.)) aaaaaa (0,4)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?) -E ((..)|(.))((..)|(.))((..)|(.)) aaaaaa (0,6)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?)(4,6)(4,6)(?,?) - -E ((..)|(.)){1} aaaaaa (0,2)(0,2)(0,2)(?,?) -E ((..)|(.)){2} aaaaaa (0,4)(2,4)(2,4)(?,?) -E ((..)|(.)){3} aaaaaa (0,6)(4,6)(4,6)(?,?) - -E ((..)|(.))* aaaaaa (0,6)(4,6)(4,6)(?,?) - -NOTE additional repetition tests graciously provided by Chris Kuklewicz www.haskell.org 2009-02-02 - -# These test a bug in OS X / FreeBSD / NetBSD, and libtree. -# Linux/GLIBC gets the {8,} and {8,8} wrong. - -:HA#100:E X(.?){0,}Y X1234567Y (0,9)(7,8) -:HA#101:E X(.?){1,}Y X1234567Y (0,9)(7,8) -:HA#102:E X(.?){2,}Y X1234567Y (0,9)(7,8) -:HA#103:E X(.?){3,}Y X1234567Y (0,9)(7,8) -:HA#104:E X(.?){4,}Y X1234567Y (0,9)(7,8) -:HA#105:E X(.?){5,}Y X1234567Y (0,9)(7,8) -:HA#106:E X(.?){6,}Y X1234567Y (0,9)(7,8) -:HA#107:E X(.?){7,}Y X1234567Y (0,9)(7,8) -:HA#108:E X(.?){8,}Y X1234567Y (0,9)(8,8) -#:HA#110:E X(.?){0,8}Y X1234567Y (0,9)(7,8) -:HA#110:E X(.?){0,8}Y X1234567Y (0,9)(8,8) RE2/Go -#:HA#111:E X(.?){1,8}Y X1234567Y (0,9)(7,8) -:HA#111:E X(.?){1,8}Y X1234567Y (0,9)(8,8) RE2/Go -#:HA#112:E X(.?){2,8}Y X1234567Y (0,9)(7,8) -:HA#112:E X(.?){2,8}Y X1234567Y (0,9)(8,8) RE2/Go -#:HA#113:E X(.?){3,8}Y X1234567Y (0,9)(7,8) -:HA#113:E X(.?){3,8}Y X1234567Y (0,9)(8,8) RE2/Go -#:HA#114:E X(.?){4,8}Y X1234567Y (0,9)(7,8) -:HA#114:E X(.?){4,8}Y X1234567Y (0,9)(8,8) RE2/Go -#:HA#115:E X(.?){5,8}Y X1234567Y (0,9)(7,8) -:HA#115:E X(.?){5,8}Y X1234567Y (0,9)(8,8) RE2/Go -#:HA#116:E X(.?){6,8}Y X1234567Y (0,9)(7,8) -:HA#116:E X(.?){6,8}Y X1234567Y (0,9)(8,8) RE2/Go -#:HA#117:E X(.?){7,8}Y X1234567Y (0,9)(7,8) -:HA#117:E X(.?){7,8}Y X1234567Y (0,9)(8,8) RE2/Go -:HA#118:E X(.?){8,8}Y X1234567Y (0,9)(8,8) - -# These test a fixed bug in my regex-tdfa that did not keep the expanded -# form properly grouped, so right association did the wrong thing with -# these ambiguous patterns (crafted just to test my code when I became -# suspicious of my implementation). The first subexpression should use -# "ab" then "a" then "bcd". - -# OS X / FreeBSD / NetBSD badly fail many of these, with impossible -# results like (0,6)(4,5)(6,6). - -:HA#260:E (a|ab|c|bcd){0,}(d*) ababcd (0,1)(0,1)(1,1) -:HA#261:E (a|ab|c|bcd){1,}(d*) ababcd (0,1)(0,1)(1,1) -:HA#262:E (a|ab|c|bcd){2,}(d*) ababcd (0,6)(3,6)(6,6) -:HA#263:E (a|ab|c|bcd){3,}(d*) ababcd (0,6)(3,6)(6,6) -:HA#264:E (a|ab|c|bcd){4,}(d*) ababcd NOMATCH -:HA#265:E (a|ab|c|bcd){0,10}(d*) ababcd (0,1)(0,1)(1,1) -:HA#266:E (a|ab|c|bcd){1,10}(d*) ababcd (0,1)(0,1)(1,1) -:HA#267:E (a|ab|c|bcd){2,10}(d*) ababcd (0,6)(3,6)(6,6) -:HA#268:E (a|ab|c|bcd){3,10}(d*) ababcd (0,6)(3,6)(6,6) -:HA#269:E (a|ab|c|bcd){4,10}(d*) ababcd NOMATCH -:HA#270:E (a|ab|c|bcd)*(d*) ababcd (0,1)(0,1)(1,1) -:HA#271:E (a|ab|c|bcd)+(d*) ababcd (0,1)(0,1)(1,1) - -# The above worked on Linux/GLIBC but the following often fail. -# They also trip up OS X / FreeBSD / NetBSD: - -#:HA#280:E (ab|a|c|bcd){0,}(d*) ababcd (0,6)(3,6)(6,6) -:HA#280:E (ab|a|c|bcd){0,}(d*) ababcd (0,6)(4,5)(5,6) RE2/Go -#:HA#281:E (ab|a|c|bcd){1,}(d*) ababcd (0,6)(3,6)(6,6) -:HA#281:E (ab|a|c|bcd){1,}(d*) ababcd (0,6)(4,5)(5,6) RE2/Go -#:HA#282:E (ab|a|c|bcd){2,}(d*) ababcd (0,6)(3,6)(6,6) -:HA#282:E (ab|a|c|bcd){2,}(d*) ababcd (0,6)(4,5)(5,6) RE2/Go -#:HA#283:E (ab|a|c|bcd){3,}(d*) ababcd (0,6)(3,6)(6,6) -:HA#283:E (ab|a|c|bcd){3,}(d*) ababcd (0,6)(4,5)(5,6) RE2/Go -:HA#284:E (ab|a|c|bcd){4,}(d*) ababcd NOMATCH -#:HA#285:E (ab|a|c|bcd){0,10}(d*) ababcd (0,6)(3,6)(6,6) -:HA#285:E (ab|a|c|bcd){0,10}(d*) ababcd (0,6)(4,5)(5,6) RE2/Go -#:HA#286:E (ab|a|c|bcd){1,10}(d*) ababcd (0,6)(3,6)(6,6) -:HA#286:E (ab|a|c|bcd){1,10}(d*) ababcd (0,6)(4,5)(5,6) RE2/Go -#:HA#287:E (ab|a|c|bcd){2,10}(d*) ababcd (0,6)(3,6)(6,6) -:HA#287:E (ab|a|c|bcd){2,10}(d*) ababcd (0,6)(4,5)(5,6) RE2/Go -#:HA#288:E (ab|a|c|bcd){3,10}(d*) ababcd (0,6)(3,6)(6,6) -:HA#288:E (ab|a|c|bcd){3,10}(d*) ababcd (0,6)(4,5)(5,6) RE2/Go -:HA#289:E (ab|a|c|bcd){4,10}(d*) ababcd NOMATCH -#:HA#290:E (ab|a|c|bcd)*(d*) ababcd (0,6)(3,6)(6,6) -:HA#290:E (ab|a|c|bcd)*(d*) ababcd (0,6)(4,5)(5,6) RE2/Go -#:HA#291:E (ab|a|c|bcd)+(d*) ababcd (0,6)(3,6)(6,6) -:HA#291:E (ab|a|c|bcd)+(d*) ababcd (0,6)(4,5)(5,6) RE2/Go diff --git a/src/libregex/vm.rs b/src/libregex/vm.rs deleted file mode 100644 index 9605536a052c..000000000000 --- a/src/libregex/vm.rs +++ /dev/null @@ -1,582 +0,0 @@ -// 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. - -// FIXME: Currently, the VM simulates an NFA. It would be nice to have another -// VM that simulates a DFA. -// -// According to Russ Cox[1], a DFA performs better than an NFA, principally -// because it reuses states previously computed by the machine *and* doesn't -// keep track of capture groups. The drawback of a DFA (aside from its -// complexity) is that it can't accurately return the locations of submatches. -// The NFA *can* do that. (This is my understanding anyway.) -// -// Cox suggests that a DFA ought to be used to answer "does this match" and -// "where does it match" questions. (In the latter, the starting position of -// the match is computed by executing the regex backwards.) Cox also suggests -// that a DFA should be run when asking "where are the submatches", which can -// 1) quickly answer "no" is there's no match and 2) discover the substring -// that matches, which means running the NFA on smaller input. -// -// Currently, the NFA simulation implemented below does some dirty tricks to -// avoid tracking capture groups when they aren't needed (which only works -// for 'is_match', not 'find'). This is a half-measure, but does provide some -// perf improvement. -// -// AFAIK, the DFA/NFA approach is implemented in RE2/C++ but *not* in RE2/Go. -// -// [1] - http://swtch.com/~rsc/regex/regex3.html - -pub use self::MatchKind::*; -pub use self::StepState::*; - -use std::cmp; -use std::cmp::Ordering::{self, Less, Equal, Greater}; -use std::mem; -use std::iter::repeat; -use std::slice::SliceExt; -use compile::{ - Program, - Match, OneChar, CharClass, Any, EmptyBegin, EmptyEnd, EmptyWordBoundary, - Save, Jump, Split, -}; -use parse::{FLAG_NOCASE, FLAG_MULTI, FLAG_DOTNL, FLAG_NEGATED}; -use unicode::regex::PERLW; - -pub type CaptureLocs = Vec>; - -/// Indicates the type of match to be performed by the VM. -#[derive(Copy)] -pub enum MatchKind { - /// Only checks if a match exists or not. Does not return location. - Exists, - /// Returns the start and end indices of the entire match in the input - /// given. - Location, - /// Returns the start and end indices of each submatch in the input given. - Submatches, -} - -/// Runs an NFA simulation on the compiled expression given on the search text -/// `input`. The search begins at byte index `start` and ends at byte index -/// `end`. (The range is specified here so that zero-width assertions will work -/// correctly when searching for successive non-overlapping matches.) -/// -/// The `which` parameter indicates what kind of capture information the caller -/// wants. There are three choices: match existence only, the location of the -/// entire match or the locations of the entire match in addition to the -/// locations of each submatch. -pub fn run<'r, 't>(which: MatchKind, prog: &'r Program, input: &'t str, - start: uint, end: uint) -> CaptureLocs { - Nfa { - which: which, - prog: prog, - input: input, - start: start, - end: end, - ic: 0, - chars: CharReader::new(input), - }.run() -} - -struct Nfa<'r, 't> { - which: MatchKind, - prog: &'r Program, - input: &'t str, - start: uint, - end: uint, - ic: uint, - chars: CharReader<'t>, -} - -/// Indicates the next action to take after a single non-empty instruction -/// is processed. -#[derive(Copy)] -pub enum StepState { - /// This is returned if and only if a Match instruction is reached and - /// we only care about the existence of a match. It instructs the VM to - /// quit early. - StepMatchEarlyReturn, - /// Indicates that a match was found. Thus, the rest of the states in the - /// *current* queue should be dropped (i.e., leftmost-first semantics). - /// States in the "next" queue can still be processed. - StepMatch, - /// No match was found. Continue with the next state in the queue. - StepContinue, -} - -impl<'r, 't> Nfa<'r, 't> { - fn run(&mut self) -> CaptureLocs { - let ncaps = match self.which { - Exists => 0, - Location => 1, - Submatches => self.prog.num_captures(), - }; - let mut matched = false; - let ninsts = self.prog.insts.len(); - let mut clist = &mut Threads::new(self.which, ninsts, ncaps); - let mut nlist = &mut Threads::new(self.which, ninsts, ncaps); - - let mut groups: Vec<_> = repeat(None).take(ncaps * 2).collect(); - - // Determine if the expression starts with a '^' so we can avoid - // simulating .*? - // Make sure multi-line mode isn't enabled for it, otherwise we can't - // drop the initial .*? - let prefix_anchor = - match self.prog.insts[1] { - EmptyBegin(flags) if flags & FLAG_MULTI == 0 => true, - _ => false, - }; - - self.ic = self.start; - let mut next_ic = self.chars.set(self.start); - while self.ic <= self.end { - if clist.size == 0 { - // We have a match and we're done exploring alternatives. - // Time to quit. - if matched { - break - } - - // If there are no threads to try, then we'll have to start - // over at the beginning of the regex. - // BUT, if there's a literal prefix for the program, try to - // jump ahead quickly. If it can't be found, then we can bail - // out early. - if self.prog.prefix.len() > 0 && clist.size == 0 { - let needle = self.prog.prefix.as_bytes(); - let haystack = &self.input.as_bytes()[self.ic..]; - match find_prefix(needle, haystack) { - None => break, - Some(i) => { - self.ic += i; - next_ic = self.chars.set(self.ic); - } - } - } - } - - // This simulates a preceding '.*?' for every regex by adding - // a state starting at the current position in the input for the - // beginning of the program only if we don't already have a match. - if clist.size == 0 || (!prefix_anchor && !matched) { - self.add(clist, 0, groups.as_mut_slice()) - } - - // Now we try to read the next character. - // As a result, the 'step' method will look at the previous - // character. - self.ic = next_ic; - next_ic = self.chars.advance(); - - for i in range(0, clist.size) { - let pc = clist.pc(i); - let step_state = self.step(groups.as_mut_slice(), nlist, - clist.groups(i), pc); - match step_state { - StepMatchEarlyReturn => return vec![Some(0), Some(0)], - StepMatch => { matched = true; break }, - StepContinue => {}, - } - } - mem::swap(&mut clist, &mut nlist); - nlist.empty(); - } - match self.which { - Exists if matched => vec![Some(0), Some(0)], - Exists => vec![None, None], - Location | Submatches => groups, - } - } - - fn step(&self, groups: &mut [Option], nlist: &mut Threads, - caps: &mut [Option], pc: uint) - -> StepState { - match self.prog.insts[pc] { - Match => { - match self.which { - Exists => { - return StepMatchEarlyReturn - } - Location => { - groups[0] = caps[0]; - groups[1] = caps[1]; - return StepMatch - } - Submatches => { - for (slot, val) in groups.iter_mut().zip(caps.iter()) { - *slot = *val; - } - return StepMatch - } - } - } - OneChar(c, flags) => { - if self.char_eq(flags & FLAG_NOCASE > 0, self.chars.prev, c) { - self.add(nlist, pc+1, caps); - } - } - CharClass(ref ranges, flags) => { - if self.chars.prev.is_some() { - let c = self.chars.prev.unwrap(); - let negate = flags & FLAG_NEGATED > 0; - let casei = flags & FLAG_NOCASE > 0; - let found = ranges.as_slice(); - let found = found.binary_search_by(|&rc| class_cmp(casei, c, rc)).is_ok(); - if found ^ negate { - self.add(nlist, pc+1, caps); - } - } - } - Any(flags) => { - if flags & FLAG_DOTNL > 0 - || !self.char_eq(false, self.chars.prev, '\n') { - self.add(nlist, pc+1, caps) - } - } - EmptyBegin(_) | EmptyEnd(_) | EmptyWordBoundary(_) - | Save(_) | Jump(_) | Split(_, _) => {}, - } - StepContinue - } - - fn add(&self, nlist: &mut Threads, pc: uint, groups: &mut [Option]) { - if nlist.contains(pc) { - return - } - // We have to add states to the threads list even if their empty. - // TL;DR - It prevents cycles. - // If we didn't care about cycles, we'd *only* add threads that - // correspond to non-jumping instructions (OneChar, Any, Match, etc.). - // But, it's possible for valid regexs (like '(a*)*') to result in - // a cycle in the instruction list. e.g., We'll keep chasing the Split - // instructions forever. - // So we add these instructions to our thread queue, but in the main - // VM loop, we look for them but simply ignore them. - // Adding them to the queue prevents them from being revisited so we - // can avoid cycles (and the inevitable stack overflow). - // - // We make a minor optimization by indicating that the state is "empty" - // so that its capture groups are not filled in. - match self.prog.insts[pc] { - EmptyBegin(flags) => { - let multi = flags & FLAG_MULTI > 0; - nlist.add(pc, groups, true); - if self.chars.is_begin() - || (multi && self.char_is(self.chars.prev, '\n')) { - self.add(nlist, pc + 1, groups) - } - } - EmptyEnd(flags) => { - let multi = flags & FLAG_MULTI > 0; - nlist.add(pc, groups, true); - if self.chars.is_end() - || (multi && self.char_is(self.chars.cur, '\n')) { - self.add(nlist, pc + 1, groups) - } - } - EmptyWordBoundary(flags) => { - nlist.add(pc, groups, true); - if self.chars.is_word_boundary() == !(flags & FLAG_NEGATED > 0) { - self.add(nlist, pc + 1, groups) - } - } - Save(slot) => { - nlist.add(pc, groups, true); - match self.which { - Location if slot <= 1 => { - let old = groups[slot]; - groups[slot] = Some(self.ic); - self.add(nlist, pc + 1, groups); - groups[slot] = old; - } - Submatches => { - let old = groups[slot]; - groups[slot] = Some(self.ic); - self.add(nlist, pc + 1, groups); - groups[slot] = old; - } - Exists | Location => self.add(nlist, pc + 1, groups), - } - } - Jump(to) => { - nlist.add(pc, groups, true); - self.add(nlist, to, groups) - } - Split(x, y) => { - nlist.add(pc, groups, true); - self.add(nlist, x, groups); - self.add(nlist, y, groups); - } - Match | OneChar(_, _) | CharClass(_, _) | Any(_) => { - nlist.add(pc, groups, false); - } - } - } - - // FIXME: For case insensitive comparisons, it uses the uppercase - // character and tests for equality. IIUC, this does not generalize to - // all of Unicode. I believe we need to check the entire fold for each - // character. This will be easy to add if and when it gets added to Rust's - // standard library. - #[inline] - fn char_eq(&self, casei: bool, textc: Option, regc: char) -> bool { - match textc { - None => false, - Some(textc) => { - regc == textc - || (casei && regc.to_uppercase() == textc.to_uppercase()) - } - } - } - - #[inline] - fn char_is(&self, textc: Option, regc: char) -> bool { - textc == Some(regc) - } -} - -/// CharReader is responsible for maintaining a "previous" and a "current" -/// character. This one-character lookahead is necessary for assertions that -/// look one character before or after the current position. -pub struct CharReader<'t> { - /// The previous character read. It is None only when processing the first - /// character of the input. - pub prev: Option, - /// The current character. - pub cur: Option, - input: &'t str, - next: uint, -} - -impl<'t> CharReader<'t> { - /// Returns a new CharReader that advances through the input given. - /// Note that a CharReader has no knowledge of the range in which to search - /// the input. - pub fn new(input: &'t str) -> CharReader<'t> { - CharReader { - prev: None, - cur: None, - input: input, - next: 0, - } - } - - /// Sets the previous and current character given any arbitrary byte - /// index (at a Unicode codepoint boundary). - #[inline] - pub fn set(&mut self, ic: uint) -> uint { - self.prev = None; - self.cur = None; - self.next = 0; - - if self.input.len() == 0 { - return 1 - } - if ic > 0 { - let i = cmp::min(ic, self.input.len()); - let prev = self.input.char_range_at_reverse(i); - self.prev = Some(prev.ch); - } - if ic < self.input.len() { - let cur = self.input.char_range_at(ic); - self.cur = Some(cur.ch); - self.next = cur.next; - self.next - } else { - self.input.len() + 1 - } - } - - /// Does the same as `set`, except it always advances to the next - /// character in the input (and therefore does half as many UTF8 decodings). - #[inline] - pub fn advance(&mut self) -> uint { - self.prev = self.cur; - if self.next < self.input.len() { - let cur = self.input.char_range_at(self.next); - self.cur = Some(cur.ch); - self.next = cur.next; - } else { - self.cur = None; - self.next = self.input.len() + 1; - } - self.next - } - - /// Returns true if and only if this is the beginning of the input - /// (ignoring the range of the input to search). - #[inline] - pub fn is_begin(&self) -> bool { self.prev.is_none() } - - /// Returns true if and only if this is the end of the input - /// (ignoring the range of the input to search). - #[inline] - pub fn is_end(&self) -> bool { self.cur.is_none() } - - /// Returns true if and only if the current position is a word boundary. - /// (Ignoring the range of the input to search.) - pub fn is_word_boundary(&self) -> bool { - if self.is_begin() { - return is_word(self.cur) - } - if self.is_end() { - return is_word(self.prev) - } - (is_word(self.cur) && !is_word(self.prev)) - || (is_word(self.prev) && !is_word(self.cur)) - } -} - -struct Thread { - pc: uint, - groups: Vec>, -} - -struct Threads { - which: MatchKind, - queue: Vec, - sparse: Vec, - size: uint, -} - -impl Threads { - // This is using a wicked neat trick to provide constant time lookup - // for threads in the queue using a sparse set. A queue of threads is - // allocated once with maximal size when the VM initializes and is reused - // throughout execution. That is, there should be zero allocation during - // the execution of a VM. - // - // See http://research.swtch.com/sparse for the deets. - fn new(which: MatchKind, num_insts: uint, ncaps: uint) -> Threads { - Threads { - which: which, - queue: range(0, num_insts).map(|_| { - Thread { pc: 0, groups: repeat(None).take(ncaps * 2).collect() } - }).collect(), - sparse: repeat(0u).take(num_insts).collect(), - size: 0, - } - } - - fn add(&mut self, pc: uint, groups: &[Option], empty: bool) { - let t = &mut self.queue[self.size]; - t.pc = pc; - match (empty, self.which) { - (_, Exists) | (true, _) => {}, - (false, Location) => { - t.groups[0] = groups[0]; - t.groups[1] = groups[1]; - } - (false, Submatches) => { - for (slot, val) in t.groups.iter_mut().zip(groups.iter()) { - *slot = *val; - } - } - } - self.sparse[pc] = self.size; - self.size += 1; - } - - #[inline] - fn contains(&self, pc: uint) -> bool { - let s = self.sparse[pc]; - s < self.size && self.queue[s].pc == pc - } - - #[inline] - fn empty(&mut self) { - self.size = 0; - } - - #[inline] - fn pc(&self, i: uint) -> uint { - self.queue[i].pc - } - - #[inline] - fn groups<'r>(&'r mut self, i: uint) -> &'r mut [Option] { - let q = &mut self.queue[i]; - q.groups.as_mut_slice() - } -} - -/// Returns true if the character is a word character, according to the -/// (Unicode friendly) Perl character class '\w'. -/// Note that this is only use for testing word boundaries. The actual '\w' -/// is encoded as a CharClass instruction. -pub fn is_word(c: Option) -> bool { - let c = match c { - None => return false, - Some(c) => c, - }; - // Try the common ASCII case before invoking binary search. - match c { - '_' | '0' ... '9' | 'a' ... 'z' | 'A' ... 'Z' => true, - _ => PERLW.binary_search_by(|&(start, end)| { - if c >= start && c <= end { - Equal - } else if start > c { - Greater - } else { - Less - } - }).is_ok() - } -} - -/// Given a character and a single character class range, return an ordering -/// indicating whether the character is less than the start of the range, -/// in the range (inclusive) or greater than the end of the range. -/// -/// If `casei` is `true`, then this ordering is computed case insensitively. -/// -/// This function is meant to be used with a binary search. -#[inline] -fn class_cmp(casei: bool, mut textc: char, - (mut start, mut end): (char, char)) -> Ordering { - if casei { - // FIXME: This is pretty ridiculous. All of this case conversion - // can be moved outside this function: - // 1) textc should be uppercased outside the bsearch. - // 2) the character class itself should be uppercased either in the - // parser or the compiler. - // FIXME: This is too simplistic for correct Unicode support. - // See also: char_eq - textc = textc.to_uppercase(); - start = start.to_uppercase(); - end = end.to_uppercase(); - } - if textc >= start && textc <= end { - Equal - } else if start > textc { - Greater - } else { - Less - } -} - -/// Returns the starting location of `needle` in `haystack`. -/// If `needle` is not in `haystack`, then `None` is returned. -/// -/// Note that this is using a naive substring algorithm. -#[inline] -pub fn find_prefix(needle: &[u8], haystack: &[u8]) -> Option { - let (hlen, nlen) = (haystack.len(), needle.len()); - if nlen > hlen || nlen == 0 { - return None - } - for (offset, window) in haystack.windows(nlen).enumerate() { - if window == needle { - return Some(offset) - } - } - None -} diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 1ea79bdf606d..b48df36a6793 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -10,28 +10,55 @@ #![allow(non_snake_case)] -register_diagnostic! { E0001, r##" +register_long_diagnostics! { + E0001: r##" This error suggests that the expression arm corresponding to the noted pattern will never be reached as for all possible values of the expression being matched, one of the preceeding patterns will match. This means that perhaps some of the preceeding patterns are too general, this one is too specific or the ordering is incorrect. -"## } +"##, + + E0003: r##" + Not-a-Number (NaN) values can not be compared for equality and hence can never match + the input to a match expression. To match against NaN values, you should instead use + the `is_nan` method in a guard, as in: x if x.is_nan() => ... +"##, + + E0004: r##" + This error indicates that the compiler can not guarantee a matching pattern for one + or more possible inputs to a match expression. Guaranteed matches are required in order + to assign values to match expressions, or alternatively, determine the flow of execution. + + If you encounter this error you must alter your patterns so that every possible value of + the input type is matched. For types with a small number of variants (like enums) you + should probably cover all cases explicitly. Alternatively, the underscore `_` wildcard + pattern can be added after all other patterns to match "anything else". +"##, + + // FIXME: Remove duplication here? + E0005: r##" + Patterns used to bind names must be irrefutable, that is, they must guarantee that a + name will be extracted in all cases. If you encounter this error you probably need + to use a `match` or `if let` to deal with the possibility of failure. +"##, + + E0006: r##" + Patterns used to bind names must be irrefutable, that is, they must guarantee that a + name will be extracted in all cases. If you encounter this error you probably need + to use a `match` or `if let` to deal with the possibility of failure. +"## +} register_diagnostics! { E0002, - E0003, - E0004, - E0005, - E0006, E0007, E0008, E0009, E0010, E0011, E0012, - E0013, E0014, E0015, E0016, @@ -49,24 +76,58 @@ register_diagnostics! { E0137, E0138, E0139, - E0140, E0152, - E0153, - E0157, E0158, E0161, E0162, E0165, - E0166, - E0167, - E0168, - E0169, E0170, - E0171, - E0172, - E0173, - E0174, - E0177, - E0178, - E0179 + E0261, // use of undeclared lifetime name + E0262, // illegal lifetime parameter name + E0263, // lifetime name declared twice in same scope + E0264, // unknown external lang item + E0265, // recursive constant + E0266, // expected item + E0267, // thing inside of a closure + E0268, // thing outside of a loop + E0269, // not all control paths return a value + E0270, // computation may converge in a function marked as diverging + E0271, // type mismatch resolving + E0272, // rustc_on_unimplemented attribute refers to non-existent type parameter + E0273, // rustc_on_unimplemented must have named format arguments + E0274, // rustc_on_unimplemented must have a value + E0275, // overflow evaluating requirement + E0276, // requirement appears on impl method but not on corresponding trait method + E0277, // trait is not implemented for type + E0278, // requirement is not satisfied + E0279, // requirement is not satisfied + E0280, // requirement is not satisfied + E0281, // type implements trait but other trait is required + E0282, // unable to infer enough type information about + E0283, // cannot resolve type + E0284, // cannot resolve type + E0285, // overflow evaluation builtin bounds + E0296, // malformed recursion limit attribute + E0297, // refutable pattern in for loop binding + E0298, // mismatched types between arms + E0299, // mismatched types between arms + E0300, // unexpanded macro + E0301, // cannot mutable borrow in a pattern guard + E0302, // cannot assign in a pattern guard + E0303, // pattern bindings are not allowed after an `@` + E0304, // expected signed integer constant + E0305, // expected constant + E0306, // expected positive integer for repeat count + E0307, // expected constant integer for repeat count + E0308, + E0309, // thing may not live long enough + E0310, // thing may not live long enough + E0311, // thing may not live long enough + E0312, // lifetime of reference outlives lifetime of borrowed content + E0313, // lifetime of borrowed pointer outlives lifetime of captured variable + E0314, // closure outlives stack frame + E0315 // cannot invoke closure outside of its lifetime } + +__build_diagnostic_array! { DIAGNOSTICS } + diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index a5ae9e9f40a3..580e55f78a9e 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -40,6 +40,7 @@ #![feature(std_misc)] #![feature(unicode)] #![feature(hash)] +#![cfg_attr(test, feature(test))] extern crate arena; extern crate flate; @@ -47,7 +48,6 @@ extern crate fmt_macros; extern crate getopts; extern crate graphviz; extern crate libc; -extern crate regex; extern crate rustc_llvm; extern crate rustc_back; extern crate serialize; @@ -64,7 +64,9 @@ extern crate test; pub use rustc_llvm as llvm; -mod diagnostics; +// NB: This module needs to be declared first so diagnostics are +// registered before they are used. +pub mod diagnostics; pub mod back { pub use rustc_back::abi; @@ -142,8 +144,6 @@ pub mod lib { pub use llvm; } -__build_diagnostic_array! { DIAGNOSTICS } - // A private module so that macro-expanded idents like // `::rustc::lint::Lint` will also work in `rustc` itself. // diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index e73771649d5b..7f1e8acd5762 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -1199,17 +1199,17 @@ impl LintPass for UnusedImportBraces { lint_array!(UNUSED_IMPORT_BRACES) } - fn check_view_item(&mut self, cx: &Context, view_item: &ast::ViewItem) { - match view_item.node { - ast::ViewItemUse(ref view_path) => { + fn check_item(&mut self, cx: &Context, item: &ast::Item) { + match item.node { + ast::ItemUse(ref view_path) => { match view_path.node { - ast::ViewPathList(_, ref items, _) => { + ast::ViewPathList(_, ref items) => { if items.len() == 1 { match items[0].node { ast::PathListIdent {ref name, ..} => { let m = format!("braces around {} is unnecessary", token::get_ident(*name).get()); - cx.span_lint(UNUSED_IMPORT_BRACES, view_item.span, + cx.span_lint(UNUSED_IMPORT_BRACES, item.span, &m[]); }, _ => () @@ -1326,7 +1326,7 @@ impl UnusedMut { let ident = path1.node; if let ast::BindByValue(ast::MutMutable) = mode { if !token::get_ident(ident).get().starts_with("_") { - match mutables.entry(ident.name.uint()) { + match mutables.entry(ident.name.usize()) { Vacant(entry) => { entry.insert(vec![id]); }, Occupied(mut entry) => { entry.get_mut().push(id); }, } @@ -1663,11 +1663,6 @@ impl LintPass for Stability { lint_array!(DEPRECATED) } - fn check_view_item(&mut self, cx: &Context, item: &ast::ViewItem) { - stability::check_view_item(cx.tcx, item, - &mut |id, sp, stab| self.lint(cx, id, sp, stab)); - } - fn check_item(&mut self, cx: &Context, item: &ast::Item) { stability::check_item(cx.tcx, item, &mut |id, sp, stab| self.lint(cx, id, sp, stab)); diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 2682df8b2ab5..abda815069d9 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -231,30 +231,7 @@ impl LintStore { // We have one lint pass defined in this module. self.register_pass(sess, false, box GatherNodeLevels as LintPassObject); - // Insert temporary renamings for a one-time deprecation (#16545) - self.register_renamed("unnecessary_typecast", "unused_typecasts"); - self.register_renamed("unsigned_negate", "unsigned_negation"); - self.register_renamed("type_limits", "unused_comparisons"); - self.register_renamed("type_overflow", "overflowing_literals"); - self.register_renamed("ctypes", "improper_ctypes"); - self.register_renamed("owned_heap_memory", "box_pointers"); - self.register_renamed("unused_attribute", "unused_attributes"); - self.register_renamed("path_statement", "path_statements"); - self.register_renamed("unused_result", "unused_results"); - self.register_renamed("non_uppercase_statics", "non_upper_case_globals"); - self.register_renamed("unnecessary_parens", "unused_parens"); - self.register_renamed("unnecessary_import_braces", "unused_import_braces"); - self.register_renamed("unsafe_block", "unsafe_blocks"); - self.register_renamed("unnecessary_allocation", "unused_allocation"); - self.register_renamed("missing_doc", "missing_docs"); - self.register_renamed("unused_extern_crate", "unused_extern_crates"); - self.register_renamed("unnecessary_qualification", "unused_qualifications"); - self.register_renamed("unrecognized_lint", "unknown_lints"); - self.register_renamed("unused_variable", "unused_variables"); - self.register_renamed("dead_assignment", "unused_assignments"); - self.register_renamed("unknown_crate_type", "unknown_crate_types"); - self.register_renamed("variant_size_difference", "variant_size_differences"); - self.register_renamed("transmute_fat_ptr", "fat_ptr_transmutes"); + // Insert temporary renamings for a one-time deprecation self.register_renamed("raw_pointer_deriving", "raw_pointer_derive"); self.register_renamed("unknown_features", "unused_features"); @@ -595,14 +572,6 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> { }) } - fn visit_view_item(&mut self, i: &ast::ViewItem) { - self.with_lint_attrs(&i.attrs[], |cx| { - run_lints!(cx, check_view_item, i); - cx.visit_ids(|v| v.visit_view_item(i)); - visit::walk_view_item(cx, i); - }) - } - fn visit_pat(&mut self, p: &ast::Pat) { run_lints!(self, check_pat, p); visit::walk_pat(self, p); diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 826a35e3bb52..a4a3f485af1d 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -128,7 +128,6 @@ pub trait LintPass { fn check_crate(&mut self, _: &Context, _: &ast::Crate) { } fn check_ident(&mut self, _: &Context, _: Span, _: ast::Ident) { } fn check_mod(&mut self, _: &Context, _: &ast::Mod, _: Span, _: ast::NodeId) { } - fn check_view_item(&mut self, _: &Context, _: &ast::ViewItem) { } fn check_foreign_item(&mut self, _: &Context, _: &ast::ForeignItem) { } fn check_item(&mut self, _: &Context, _: &ast::Item) { } fn check_local(&mut self, _: &Context, _: &ast::Local) { } diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs index 5de683f8a4f0..7b71120ba64a 100644 --- a/src/librustc/metadata/creader.rs +++ b/src/librustc/metadata/creader.rs @@ -40,10 +40,6 @@ pub struct CrateReader<'a> { } impl<'a, 'v> visit::Visitor<'v> for CrateReader<'a> { - fn visit_view_item(&mut self, a: &ast::ViewItem) { - self.process_view_item(a); - visit::walk_view_item(self, a); - } fn visit_item(&mut self, a: &ast::Item) { self.process_item(a); visit::walk_item(self, a); @@ -64,9 +60,8 @@ fn dump_crates(cstore: &CStore) { }) } -fn should_link(i: &ast::ViewItem) -> bool { +fn should_link(i: &ast::Item) -> bool { !attr::contains_name(&i.attrs[], "no_link") - } struct CrateInfo { @@ -181,29 +176,10 @@ impl<'a> CrateReader<'a> { } } - fn process_view_item(&mut self, i: &ast::ViewItem) { - if !should_link(i) { - return; - } - - match self.extract_crate_info(i) { - Some(info) => { - let (cnum, _, _) = self.resolve_crate(&None, - &info.ident[], - &info.name[], - None, - i.span, - PathKind::Crate); - self.sess.cstore.add_extern_mod_stmt_cnum(info.id, cnum); - } - None => () - } - } - - fn extract_crate_info(&self, i: &ast::ViewItem) -> Option { + fn extract_crate_info(&self, i: &ast::Item) -> Option { match i.node { - ast::ViewItemExternCrate(ident, ref path_opt, id) => { - let ident = token::get_ident(ident); + ast::ItemExternCrate(ref path_opt) => { + let ident = token::get_ident(i.ident); debug!("resolving extern crate stmt. ident: {} path_opt: {:?}", ident, path_opt); let name = match *path_opt { @@ -218,7 +194,7 @@ impl<'a> CrateReader<'a> { Some(CrateInfo { ident: ident.get().to_string(), name: name, - id: id, + id: i.id, should_link: should_link(i), }) } @@ -226,8 +202,26 @@ impl<'a> CrateReader<'a> { } } - fn process_item(&self, i: &ast::Item) { + fn process_item(&mut self, i: &ast::Item) { match i.node { + ast::ItemExternCrate(_) => { + if !should_link(i) { + return; + } + + match self.extract_crate_info(i) { + Some(info) => { + let (cnum, _, _) = self.resolve_crate(&None, + &info.ident[], + &info.name[], + None, + i.span, + PathKind::Crate); + self.sess.cstore.add_extern_mod_stmt_cnum(info.id, cnum); + } + None => () + } + } ast::ItemForeignMod(ref fm) => { if fm.abi == abi::Rust || fm.abi == abi::RustIntrinsic { return; @@ -533,7 +527,7 @@ impl<'a> CrateReader<'a> { #[derive(Copy)] pub enum CrateOrString<'a> { - Krate(&'a ast::ViewItem), + Krate(&'a ast::Item), Str(&'a str) } diff --git a/src/librustc/metadata/cstore.rs b/src/librustc/metadata/cstore.rs index a928d1c90228..7b7159da4385 100644 --- a/src/librustc/metadata/cstore.rs +++ b/src/librustc/metadata/cstore.rs @@ -242,7 +242,7 @@ impl MetadataBlob { ((slice[2] as u32) << 8) | ((slice[3] as u32) << 0)) as uint; if len + 4 <= slice.len() { - slice.slice(4, len + 4) + &slice[4.. len + 4] } else { &[] // corrupt or old metadata } diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 6bf1798d246a..1197276b9908 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -74,7 +74,7 @@ fn lookup_hash<'a, F>(d: rbml::Doc<'a>, mut eq_fn: F, hash: u64) -> Option { - // macros are encoded separately + ast::ItemExternCrate(_) | ast::ItemUse(_) |ast::ItemMac(..) => { + // these are encoded separately } } } diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs index 70b6ddf23fd8..b1043a4152cf 100644 --- a/src/librustc/metadata/loader.rs +++ b/src/librustc/metadata/loader.rs @@ -392,11 +392,11 @@ impl<'a> Context<'a> { }; let (hash, rlib) = if file.starts_with(&rlib_prefix[]) && file.ends_with(".rlib") { - (file.slice(rlib_prefix.len(), file.len() - ".rlib".len()), + (&file[(rlib_prefix.len()) .. (file.len() - ".rlib".len())], true) } else if file.starts_with(dylib_prefix.as_slice()) && file.ends_with(dypair.1.as_slice()) { - (file.slice(dylib_prefix.len(), file.len() - dypair.1.len()), + (&file[(dylib_prefix.len()) .. (file.len() - dypair.1.len())], false) } else { return FileDoesntMatch diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index 5aacaa04e46d..943be282103a 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -243,19 +243,6 @@ fn parse_size(st: &mut PState) -> Option { } } -fn parse_trait_store_(st: &mut PState, conv: &mut F) -> ty::TraitStore where - F: FnMut(DefIdSource, ast::DefId) -> ast::DefId, -{ - match next(st) { - '~' => ty::UniqTraitStore, - '&' => ty::RegionTraitStore(parse_region_(st, conv), parse_mutability(st)), - c => { - st.tcx.sess.bug(&format!("parse_trait_store(): bad input '{}'", - c)[]) - } - } -} - fn parse_vec_per_param_space<'a, 'tcx, T, F>(st: &mut PState<'a, 'tcx>, mut f: F) -> VecPerParamSpace where @@ -641,14 +628,6 @@ fn parse_abi_set(st: &mut PState) -> abi::Abi { }) } -fn parse_onceness(c: char) -> ast::Onceness { - match c { - 'o' => ast::Once, - 'm' => ast::Many, - _ => panic!("parse_onceness: bad onceness") - } -} - fn parse_closure_ty<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, mut conv: F) -> ty::ClosureTy<'tcx> where F: FnMut(DefIdSource, ast::DefId) -> ast::DefId, @@ -661,16 +640,10 @@ fn parse_closure_ty_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, F: FnMut(DefIdSource, ast::DefId) -> ast::DefId, { let unsafety = parse_unsafety(next(st)); - let onceness = parse_onceness(next(st)); - let store = parse_trait_store_(st, conv); - let bounds = parse_existential_bounds_(st, conv); let sig = parse_sig_(st, conv); let abi = parse_abi_set(st); ty::ClosureTy { unsafety: unsafety, - onceness: onceness, - store: store, - bounds: bounds, sig: sig, abi: abi, } @@ -734,7 +707,7 @@ pub fn parse_def_id(buf: &[u8]) -> ast::DefId { } let crate_part = &buf[0u..colon_idx]; - let def_part = &buf[(colon_idx + 1u)..len]; + let def_part = &buf[colon_idx + 1u..len]; let crate_num = match str::from_utf8(crate_part).ok().and_then(|s| s.parse::()) { Some(cn) => cn as ast::CrateNum, diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index bdd08ad6c495..9aead5bf4e7f 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -305,17 +305,6 @@ pub fn enc_trait_ref<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>, enc_substs(w, cx, s.substs); } -pub fn enc_trait_store(w: &mut SeekableMemWriter, cx: &ctxt, s: ty::TraitStore) { - match s { - ty::UniqTraitStore => mywrite!(w, "~"), - ty::RegionTraitStore(re, m) => { - mywrite!(w, "&"); - enc_region(w, cx, re); - enc_mutability(w, m); - } - } -} - fn enc_unsafety(w: &mut SeekableMemWriter, p: ast::Unsafety) { match p { ast::Unsafety::Normal => mywrite!(w, "n"), @@ -329,13 +318,6 @@ fn enc_abi(w: &mut SeekableMemWriter, abi: Abi) { mywrite!(w, "]") } -fn enc_onceness(w: &mut SeekableMemWriter, o: ast::Onceness) { - match o { - ast::Once => mywrite!(w, "o"), - ast::Many => mywrite!(w, "m") - } -} - pub fn enc_bare_fn_ty<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>, ft: &ty::BareFnTy<'tcx>) { enc_unsafety(w, ft.unsafety); @@ -346,9 +328,6 @@ pub fn enc_bare_fn_ty<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>, pub fn enc_closure_ty<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>, ft: &ty::ClosureTy<'tcx>) { enc_unsafety(w, ft.unsafety); - enc_onceness(w, ft.onceness); - enc_trait_store(w, cx, ft.store); - enc_existential_bounds(w, cx, &ft.bounds); enc_fn_sig(w, cx, &ft.sig); enc_abi(w, ft.abi); } diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index 550c0f34cafe..537a2b3f545a 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -332,8 +332,6 @@ impl Folder for NestedItemsDropper { } }).collect(); let blk_sans_items = P(ast::Block { - view_items: Vec::new(), // I don't know if we need the view_items - // here, but it doesn't break tests! stmts: stmts_sans_items, expr: expr, id: id, @@ -515,17 +513,6 @@ impl tr for ty::BoundRegion { } } -impl tr for ty::TraitStore { - fn tr(&self, dcx: &DecodeContext) -> ty::TraitStore { - match *self { - ty::RegionTraitStore(r, m) => { - ty::RegionTraitStore(r.tr(dcx), m) - } - ty::UniqTraitStore => ty::UniqTraitStore - } - } -} - // ______________________________________________________________________ // Encoding and decoding of freevar information diff --git a/src/librustc/middle/cfg/construct.rs b/src/librustc/middle/cfg/construct.rs index a1ac25a5650e..1a2162b3076e 100644 --- a/src/librustc/middle/cfg/construct.rs +++ b/src/librustc/middle/cfg/construct.rs @@ -424,7 +424,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { } ast::ExprMethodCall(_, _, ref args) => { - self.call(expr, pred, &*args[0], args.slice_from(1).iter().map(|e| &**e)) + self.call(expr, pred, &*args[0], args[1..].iter().map(|e| &**e)) } ast::ExprIndex(ref l, ref r) | diff --git a/src/librustc/middle/check_loop.rs b/src/librustc/middle/check_loop.rs index 1f779acac250..623f3525d4a9 100644 --- a/src/librustc/middle/check_loop.rs +++ b/src/librustc/middle/check_loop.rs @@ -73,12 +73,12 @@ impl<'a> CheckLoopVisitor<'a> { match self.cx { Loop => {} Closure => { - self.sess.span_err(span, - &format!("`{}` inside of a closure", name)[]); + span_err!(self.sess, span, E0267, + "`{}` inside of a closure", name); } Normal => { - self.sess.span_err(span, - &format!("`{}` outside of loop", name)[]); + span_err!(self.sess, span, E0268, + "`{}` outside of loop", name); } } } diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index a1a90395b3b7..aa803d9d8aea 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -57,7 +57,7 @@ struct Matrix<'a>(Vec>); /// ++++++++++++++++++++++++++ /// + _ + [_, _, ..tail] + /// ++++++++++++++++++++++++++ -impl<'a> fmt::Show for Matrix<'a> { +impl<'a> fmt::Debug for Matrix<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { try!(write!(f, "\n")); @@ -226,11 +226,10 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &ast::Expr) { ast::ExprForLoop(ref pat, _, _, _) => { let mut static_inliner = StaticInliner::new(cx.tcx); is_refutable(cx, &*static_inliner.fold_pat((*pat).clone()), |uncovered_pat| { - cx.tcx.sess.span_err( - pat.span, - &format!("refutable pattern in `for` loop binding: \ + span_err!(cx.tcx.sess, pat.span, E0297, + "refutable pattern in `for` loop binding: \ `{}` not covered", - pat_to_string(uncovered_pat))[]); + pat_to_string(uncovered_pat)); }); // Check legality of move bindings. @@ -869,7 +868,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat], Some(true) => Some(vec![]), Some(false) => None, None => { - cx.tcx.sess.span_err(pat_span, "mismatched types between arms"); + span_err!(cx.tcx.sess, pat_span, E0298, "mismatched types between arms"); None } } @@ -882,7 +881,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat], Some(true) => Some(vec![]), Some(false) => None, None => { - cx.tcx.sess.span_err(pat_span, "mismatched types between arms"); + span_err!(cx.tcx.sess, pat_span, E0299, "mismatched types between arms"); None } } @@ -921,13 +920,13 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat], } ast::PatMac(_) => { - cx.tcx.sess.span_err(pat_span, "unexpanded macro"); + span_err!(cx.tcx.sess, pat_span, E0300, "unexpanded macro"); None } }; head.map(|mut head| { head.push_all(&r[..col]); - head.push_all(&r[(col + 1)..]); + head.push_all(&r[col + 1..]); head }) } @@ -1082,11 +1081,8 @@ impl<'a, 'tcx> Delegate<'tcx> for MutationChecker<'a, 'tcx> { _: LoanCause) { match kind { MutBorrow => { - self.cx - .tcx - .sess - .span_err(span, - "cannot mutably borrow in a pattern guard") + span_err!(self.cx.tcx.sess, span, E0301, + "cannot mutably borrow in a pattern guard") } ImmBorrow | UniqueImmBorrow => {} } @@ -1095,10 +1091,7 @@ impl<'a, 'tcx> Delegate<'tcx> for MutationChecker<'a, 'tcx> { fn mutate(&mut self, _: NodeId, span: Span, _: cmt, mode: MutateMode) { match mode { JustWrite | WriteAndRead => { - self.cx - .tcx - .sess - .span_err(span, "cannot assign in a pattern guard") + span_err!(self.cx.tcx.sess, span, E0302, "cannot assign in a pattern guard") } Init => {} } @@ -1120,7 +1113,7 @@ struct AtBindingPatternVisitor<'a, 'b:'a, 'tcx:'b> { impl<'a, 'b, 'tcx, 'v> Visitor<'v> for AtBindingPatternVisitor<'a, 'b, 'tcx> { fn visit_pat(&mut self, pat: &Pat) { if !self.bindings_allowed && pat_is_binding(&self.cx.tcx.def_map, pat) { - self.cx.tcx.sess.span_err(pat.span, + span_err!(self.cx.tcx.sess, pat.span, E0303, "pattern bindings are not allowed \ after an `@`"); } diff --git a/src/librustc/middle/check_static_recursion.rs b/src/librustc/middle/check_static_recursion.rs index 86a58dae45aa..4280b7fe3f09 100644 --- a/src/librustc/middle/check_static_recursion.rs +++ b/src/librustc/middle/check_static_recursion.rs @@ -83,7 +83,7 @@ pub fn check_item_recursion<'a>(sess: &'a Session, impl<'a, 'ast, 'v> Visitor<'v> for CheckItemRecursionVisitor<'a, 'ast> { fn visit_item(&mut self, it: &ast::Item) { if self.idstack.iter().any(|x| x == &(it.id)) { - self.sess.span_err(self.root_it.span, "recursive constant"); + span_err!(self.sess, self.root_it.span, E0265, "recursive constant"); return; } self.idstack.push(it.id); @@ -103,9 +103,9 @@ impl<'a, 'ast, 'v> Visitor<'v> for CheckItemRecursionVisitor<'a, 'ast> { self.visit_item(item), ast_map::NodeForeignItem(_) => {}, _ => { - self.sess.span_err(e.span, - &format!("expected item, found {}", - self.ast_map.node_to_string(def_id.node))[]); + span_err!(self.sess, e.span, E0266, + "expected item, found {}", + self.ast_map.node_to_string(def_id.node)); return; }, } diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs index 2b9bd1cd09fd..a17278698103 100644 --- a/src/librustc/middle/dataflow.rs +++ b/src/librustc/middle/dataflow.rs @@ -118,17 +118,17 @@ impl<'a, 'tcx, O:DataFlowOperator> pprust::PpAnn for DataFlowContext<'a, 'tcx, O assert!(self.bits_per_id > 0); let cfgidx = to_cfgidx_or_die(id, &self.nodeid_to_index); let (start, end) = self.compute_id_range(cfgidx); - let on_entry = self.on_entry.slice(start, end); + let on_entry = &self.on_entry[start.. end]; let entry_str = bits_to_string(on_entry); - let gens = self.gens.slice(start, end); + let gens = &self.gens[start.. end]; let gens_str = if gens.iter().any(|&u| u != 0) { format!(" gen: {}", bits_to_string(gens)) } else { "".to_string() }; - let kills = self.kills.slice(start, end); + let kills = &self.kills[start .. end]; let kills_str = if kills.iter().any(|&u| u != 0) { format!(" kill: {}", bits_to_string(kills)) } else { @@ -232,7 +232,7 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { let cfgidx = to_cfgidx_or_die(id, &self.nodeid_to_index); let (start, end) = self.compute_id_range(cfgidx); - let gens = self.gens.slice_mut(start, end); + let gens = &mut self.gens[start.. end]; set_bit(gens, bit); } @@ -245,7 +245,7 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { let cfgidx = to_cfgidx_or_die(id, &self.nodeid_to_index); let (start, end) = self.compute_id_range(cfgidx); - let kills = self.kills.slice_mut(start, end); + let kills = &mut self.kills[start.. end]; set_bit(kills, bit); } @@ -256,9 +256,9 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { assert!(self.bits_per_id > 0); let (start, end) = self.compute_id_range(cfgidx); - let gens = self.gens.slice(start, end); + let gens = &self.gens[start.. end]; bitwise(bits, gens, &Union); - let kills = self.kills.slice(start, end); + let kills = &self.kills[start.. end]; bitwise(bits, kills, &Subtract); debug!("{} apply_gen_kill(cfgidx={:?}, bits={}) [after]", @@ -304,7 +304,7 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { } let (start, end) = self.compute_id_range(cfgidx); - let on_entry = self.on_entry.slice(start, end); + let on_entry = &self.on_entry[start.. end]; let temp_bits; let slice = match e { Entry => on_entry, @@ -336,7 +336,7 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { let cfgidx = to_cfgidx_or_die(id, &self.nodeid_to_index); let (start, end) = self.compute_id_range(cfgidx); - let gens = self.gens.slice(start, end); + let gens = &self.gens[start.. end]; debug!("{} each_gen_bit(id={}, gens={})", self.analysis_name, id, bits_to_string(gens)); self.each_bit(gens, f) @@ -396,7 +396,7 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { cfg.graph.each_edge(|_edge_index, edge| { let flow_exit = edge.source(); let (start, end) = self.compute_id_range(flow_exit); - let mut orig_kills = self.kills.slice(start, end).to_vec(); + let mut orig_kills = self.kills[start.. end].to_vec(); let mut changed = false; for &node_id in edge.data.exiting_scopes.iter() { @@ -404,7 +404,7 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { match opt_cfg_idx { Some(cfg_idx) => { let (start, end) = self.compute_id_range(cfg_idx); - let kills = self.kills.slice(start, end); + let kills = &self.kills[start.. end]; if bitwise(orig_kills.as_mut_slice(), kills, &Union) { changed = true; } @@ -418,7 +418,7 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { } if changed { - let bits = self.kills.slice_mut(start, end); + let bits = &mut self.kills[start.. end]; debug!("{} add_kills_from_flow_exits flow_exit={:?} bits={} [before]", self.analysis_name, flow_exit, mut_bits_to_string(bits)); bits.clone_from_slice(&orig_kills[]); @@ -487,7 +487,7 @@ impl<'a, 'b, 'tcx, O:DataFlowOperator> PropagationContext<'a, 'b, 'tcx, O> { let (start, end) = self.dfcx.compute_id_range(node_index); // Initialize local bitvector with state on-entry. - in_out.clone_from_slice(self.dfcx.on_entry.slice(start, end)); + in_out.clone_from_slice(&self.dfcx.on_entry[start.. end]); // Compute state on-exit by applying transfer function to // state on-entry. @@ -528,13 +528,13 @@ impl<'a, 'b, 'tcx, O:DataFlowOperator> PropagationContext<'a, 'b, 'tcx, O> { let (start, end) = self.dfcx.compute_id_range(cfgidx); let changed = { // (scoping mutable borrow of self.dfcx.on_entry) - let on_entry = self.dfcx.on_entry.slice_mut(start, end); + let on_entry = &mut self.dfcx.on_entry[start.. end]; bitwise(on_entry, pred_bits, &self.dfcx.oper) }; if changed { debug!("{} changed entry set for {:?} to {}", self.dfcx.analysis_name, cfgidx, - bits_to_string(self.dfcx.on_entry.slice(start, end))); + bits_to_string(&self.dfcx.on_entry[start.. end])); self.changed = true; } } diff --git a/src/librustc/middle/graph.rs b/src/librustc/middle/graph.rs index 30e0ce33018d..affeef330c45 100644 --- a/src/librustc/middle/graph.rs +++ b/src/librustc/middle/graph.rs @@ -32,7 +32,7 @@ #![allow(dead_code)] // still WIP -use std::fmt::{Formatter, Error, Show}; +use std::fmt::{Formatter, Error, Debug}; use std::uint; use std::collections::BitvSet; @@ -53,7 +53,7 @@ pub struct Edge { pub data: E, } -impl Show for Edge { +impl Debug for Edge { fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { write!(f, "Edge {{ next_edge: [{:?}, {:?}], source: {:?}, target: {:?}, data: {:?} }}", self.next_edge[0], self.next_edge[1], self.source, @@ -353,7 +353,7 @@ impl Edge { #[cfg(test)] mod test { use middle::graph::*; - use std::fmt::Show; + use std::fmt::Debug; type TestNode = Node<&'static str>; type TestEdge = Edge<&'static str>; @@ -408,7 +408,7 @@ mod test { }); } - fn test_adjacent_edges(graph: &Graph, + fn test_adjacent_edges(graph: &Graph, start_index: NodeIndex, start_data: N, expected_incoming: &[(E,N)], diff --git a/src/librustc/middle/infer/combine.rs b/src/librustc/middle/infer/combine.rs index 4a4328fa98ba..3280769ff038 100644 --- a/src/librustc/middle/infer/combine.rs +++ b/src/librustc/middle/infer/combine.rs @@ -202,39 +202,6 @@ pub trait Combine<'tcx> : Sized { sig: sig}) } - fn closure_tys(&self, a: &ty::ClosureTy<'tcx>, - b: &ty::ClosureTy<'tcx>) -> cres<'tcx, ty::ClosureTy<'tcx>> { - - let store = match (a.store, b.store) { - (ty::RegionTraitStore(a_r, a_m), - ty::RegionTraitStore(b_r, b_m)) if a_m == b_m => { - let r = try!(self.contraregions(a_r, b_r)); - ty::RegionTraitStore(r, a_m) - } - - _ if a.store == b.store => { - a.store - } - - _ => { - return Err(ty::terr_sigil_mismatch(expected_found(self, a.store, b.store))) - } - }; - let unsafety = try!(self.unsafeties(a.unsafety, b.unsafety)); - let onceness = try!(self.oncenesses(a.onceness, b.onceness)); - let bounds = try!(self.existential_bounds(&a.bounds, &b.bounds)); - let sig = try!(self.binders(&a.sig, &b.sig)); - let abi = try!(self.abi(a.abi, b.abi)); - Ok(ty::ClosureTy { - unsafety: unsafety, - onceness: onceness, - store: store, - bounds: bounds, - sig: sig, - abi: abi, - }) - } - fn fn_sigs(&self, a: &ty::FnSig<'tcx>, b: &ty::FnSig<'tcx>) -> cres<'tcx, ty::FnSig<'tcx>> { if a.variadic != b.variadic { return Err(ty::terr_variadic_mismatch(expected_found(self, a.variadic, b.variadic))); @@ -356,31 +323,6 @@ pub trait Combine<'tcx> : Sized { fn regions(&self, a: ty::Region, b: ty::Region) -> cres<'tcx, ty::Region>; - fn trait_stores(&self, - vk: ty::terr_vstore_kind, - a: ty::TraitStore, - b: ty::TraitStore) - -> cres<'tcx, ty::TraitStore> { - debug!("{}.trait_stores(a={:?}, b={:?})", self.tag(), a, b); - - match (a, b) { - (ty::RegionTraitStore(a_r, a_m), - ty::RegionTraitStore(b_r, b_m)) if a_m == b_m => { - self.contraregions(a_r, b_r).and_then(|r| { - Ok(ty::RegionTraitStore(r, a_m)) - }) - } - - _ if a == b => { - Ok(a) - } - - _ => { - Err(ty::terr_trait_stores_differ(vk, expected_found(self, a, b))) - } - } - } - fn trait_refs(&self, a: &ty::TraitRef<'tcx>, b: &ty::TraitRef<'tcx>) diff --git a/src/librustc/middle/infer/error_reporting.rs b/src/librustc/middle/infer/error_reporting.rs index 1b9d6ec6c33b..18c36f870b5b 100644 --- a/src/librustc/middle/infer/error_reporting.rs +++ b/src/librustc/middle/infer/error_reporting.rs @@ -371,12 +371,11 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { infer::EquatePredicate(_) => "equality predicate not satisfied", }; - self.tcx.sess.span_err( - trace.origin.span(), - &format!("{}: {} ({})", + span_err!(self.tcx.sess, trace.origin.span(), E0308, + "{}: {} ({})", message_root_str, expected_found_str, - ty::type_err_to_str(self.tcx, terr))[]); + ty::type_err_to_str(self.tcx, terr)); match trace.origin { infer::MatchExpressionArm(_, arm_span) => @@ -443,9 +442,8 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { match sub { ty::ReFree(ty::FreeRegion {bound_region: ty::BrNamed(..), ..}) => { // Does the required lifetime have a nice name we can print? - self.tcx.sess.span_err( - origin.span(), - &format!("{} may not live long enough", labeled_user_string)[]); + span_err!(self.tcx.sess, origin.span(), E0309, + "{} may not live long enough", labeled_user_string); self.tcx.sess.span_help( origin.span(), &format!( @@ -456,9 +454,8 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { ty::ReStatic => { // Does the required lifetime have a nice name we can print? - self.tcx.sess.span_err( - origin.span(), - &format!("{} may not live long enough", labeled_user_string)[]); + span_err!(self.tcx.sess, origin.span(), E0310, + "{} may not live long enough", labeled_user_string); self.tcx.sess.span_help( origin.span(), &format!( @@ -468,11 +465,9 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { _ => { // If not, be less specific. - self.tcx.sess.span_err( - origin.span(), - &format!( + span_err!(self.tcx.sess, origin.span(), E0311, "{} may not live long enough", - labeled_user_string)[]); + labeled_user_string); self.tcx.sess.span_help( origin.span(), &format!( @@ -499,8 +494,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { self.report_and_explain_type_error(trace, &terr); } infer::Reborrow(span) => { - self.tcx.sess.span_err( - span, + span_err!(self.tcx.sess, span, E0312, "lifetime of reference outlines \ lifetime of borrowed content..."); note_and_explain_region( @@ -515,14 +509,13 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { ""); } infer::ReborrowUpvar(span, ref upvar_id) => { - self.tcx.sess.span_err( - span, - &format!("lifetime of borrowed pointer outlives \ + span_err!(self.tcx.sess, span, E0313, + "lifetime of borrowed pointer outlives \ lifetime of captured variable `{}`...", ty::local_var_name_str(self.tcx, upvar_id.var_id) .get() - .to_string())[]); + .to_string()); note_and_explain_region( self.tcx, "...the borrowed pointer is valid for ", @@ -539,8 +532,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { ""); } infer::InfStackClosure(span) => { - self.tcx.sess.span_err( - span, + span_err!(self.tcx.sess, span, E0314, "closure outlives stack frame"); note_and_explain_region( self.tcx, @@ -554,8 +546,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { ""); } infer::InvokeClosure(span) => { - self.tcx.sess.span_err( - span, + span_err!(self.tcx.sess, span, E0315, "cannot invoke closure outside of its lifetime"); note_and_explain_region( self.tcx, diff --git a/src/librustc/middle/infer/region_inference/mod.rs b/src/librustc/middle/infer/region_inference/mod.rs index 0f487fffe5cb..9339f435d8fa 100644 --- a/src/librustc/middle/infer/region_inference/mod.rs +++ b/src/librustc/middle/infer/region_inference/mod.rs @@ -609,8 +609,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { pub fn vars_created_since_snapshot(&self, mark: &RegionSnapshot) -> Vec { - self.undo_log.borrow() - .slice_from(mark.length) + self.undo_log.borrow()[mark.length..] .iter() .filter_map(|&elt| match elt { AddVar(vid) => Some(vid), @@ -637,7 +636,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { debug!("result_index={}, r={:?}", result_index, r); for undo_entry in - self.undo_log.borrow().slice_from(mark.length).iter() + self.undo_log.borrow()[mark.length..].iter() { match undo_entry { &AddConstraint(ConstrainVarSubVar(a, b)) => { diff --git a/src/librustc/middle/infer/unify.rs b/src/librustc/middle/infer/unify.rs index 4fa8e07ddd4f..ed11cafdca9b 100644 --- a/src/librustc/middle/infer/unify.rs +++ b/src/librustc/middle/infer/unify.rs @@ -17,7 +17,7 @@ use middle::ty::{self, Ty}; use middle::infer::{uok, ures}; use middle::infer::InferCtxt; use std::cell::RefCell; -use std::fmt::Show; +use std::fmt::Debug; use syntax::ast; use util::ppaux::Repr; use util::snapshot_vec as sv; @@ -32,7 +32,7 @@ use util::snapshot_vec as sv; /// (possibly not yet known) sort of integer. /// /// Implementations of this trait are at the end of this file. -pub trait UnifyKey<'tcx, V> : Clone + Show + PartialEq + Repr<'tcx> { +pub trait UnifyKey<'tcx, V> : Clone + Debug + PartialEq + Repr<'tcx> { fn index(&self) -> uint; fn from_index(u: uint) -> Self; diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index ff79ace99240..2c0de9d16348 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -320,9 +320,7 @@ lets_do_this! { ContravariantLifetimeItem, "contravariant_lifetime", contravariant_lifetime; InvariantLifetimeItem, "invariant_lifetime", invariant_lifetime; - NoSendItem, "no_send_bound", no_send_bound; NoCopyItem, "no_copy_bound", no_copy_bound; - NoSyncItem, "no_sync_bound", no_sync_bound; ManagedItem, "managed_bound", managed_bound; NonZeroItem, "non_zero", non_zero; diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 27a0324a3c41..43989d0aadc8 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -198,13 +198,13 @@ pub fn check_crate(tcx: &ty::ctxt) { tcx.sess.abort_if_errors(); } -impl fmt::Show for LiveNode { +impl fmt::Debug for LiveNode { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "ln({})", self.get()) } } -impl fmt::Show for Variable { +impl fmt::Debug for Variable { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "v({})", self.get()) } @@ -1557,8 +1557,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { }, _ => false }; - self.ir.tcx.sess.span_err( - sp, "not all control paths return a value"); + span_err!(self.ir.tcx.sess, sp, E0269, "not all control paths return a value"); if ends_with_stmt { let last_stmt = body.stmts.first().unwrap(); let original_span = original_sp(self.ir.tcx.sess.codemap(), @@ -1575,7 +1574,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } ty::FnDiverging if self.live_on_entry(entry_ln, self.s.clean_exit_var).is_some() => { - self.ir.tcx.sess.span_err(sp, + span_err!(self.ir.tcx.sess, sp, E0270, "computation may converge in a function marked as diverging"); } diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index d6e652f16c65..b93cde4bf646 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -297,6 +297,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { // These are normal, nothing reachable about these // inherently and their children are already in the // worklist, as determined by the privacy pass + ast::ItemExternCrate(_) | ast::ItemUse(_) | ast::ItemTy(..) | ast::ItemStatic(_, _, _) | ast::ItemMod(..) | ast::ItemForeignMod(..) | ast::ItemImpl(..) | ast::ItemTrait(..) | diff --git a/src/librustc/middle/recursion_limit.rs b/src/librustc/middle/recursion_limit.rs index 017641bd3b71..81cbdf13c518 100644 --- a/src/librustc/middle/recursion_limit.rs +++ b/src/librustc/middle/recursion_limit.rs @@ -33,7 +33,7 @@ pub fn update_recursion_limit(sess: &Session, krate: &ast::Crate) { } } - sess.span_err(attr.span, "malformed recursion limit attribute, \ + span_err!(sess, attr.span, E0296, "malformed recursion limit attribute, \ expected #![recursion_limit=\"N\"]"); } } diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 90ba442ee394..b4b2e1b63e80 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -22,9 +22,6 @@ use util::nodemap::{FnvHashMap, FnvHashSet, NodeMap}; use util::common::can_reach; use std::cell::RefCell; -// NOTE(stage0) remove import after a snapshot -#[cfg(stage0)] -use std::hash::{Hash}; use syntax::codemap::Span; use syntax::{ast, visit}; use syntax::ast::{Block, Item, FnDecl, NodeId, Arm, Pat, Stmt, Expr, Local}; diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index eff0018becc0..030bf26699fb 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -94,6 +94,8 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> { // Fn lifetimes get added in visit_fn below: visit::walk_item(this, item); } + ast::ItemExternCrate(_) | + ast::ItemUse(_) | ast::ItemMod(..) | ast::ItemMac(..) | ast::ItemForeignMod(..) | @@ -396,10 +398,9 @@ impl<'a> LifetimeContext<'a> { } fn unresolved_lifetime_ref(&self, lifetime_ref: &ast::Lifetime) { - self.sess.span_err( - lifetime_ref.span, - &format!("use of undeclared lifetime name `{}`", - token::get_name(lifetime_ref.name))[]); + span_err!(self.sess, lifetime_ref.span, E0261, + "use of undeclared lifetime name `{}`", + token::get_name(lifetime_ref.name)); } fn check_lifetime_defs(&mut self, old_scope: Scope, lifetimes: &Vec) { @@ -409,11 +410,9 @@ impl<'a> LifetimeContext<'a> { let special_idents = [special_idents::static_lifetime]; for lifetime in lifetimes.iter() { if special_idents.iter().any(|&i| i.name == lifetime.lifetime.name) { - self.sess.span_err( - lifetime.lifetime.span, - &format!("illegal lifetime parameter name: `{}`", - token::get_name(lifetime.lifetime.name)) - []); + span_err!(self.sess, lifetime.lifetime.span, E0262, + "illegal lifetime parameter name: `{}`", + token::get_name(lifetime.lifetime.name)); } } @@ -422,12 +421,10 @@ impl<'a> LifetimeContext<'a> { let lifetime_j = &lifetimes[j]; if lifetime_i.lifetime.name == lifetime_j.lifetime.name { - self.sess.span_err( - lifetime_j.lifetime.span, - &format!("lifetime name `{}` declared twice in \ + span_err!(self.sess, lifetime_j.lifetime.span, E0263, + "lifetime name `{}` declared twice in \ the same scope", - token::get_name(lifetime_j.lifetime.name)) - []); + token::get_name(lifetime_j.lifetime.name)); } } @@ -462,11 +459,11 @@ impl<'a> LifetimeContext<'a> { format!("lifetime name `{}` shadows another \ lifetime name that is already in scope", token::get_name(lifetime.name)).as_slice()); - self.sess.span_help( + self.sess.span_note( lifetime_def.span, format!("shadowed lifetime `{}` declared here", token::get_name(lifetime.name)).as_slice()); - self.sess.span_help( + self.sess.span_note( lifetime.span, "shadowed lifetimes are deprecated \ and will become a hard error before 1.0"); @@ -602,7 +599,7 @@ fn early_bound_lifetime_names(generics: &ast::Generics) -> Vec { } } -impl<'a> fmt::Show for ScopeChain<'a> { +impl<'a> fmt::Debug for ScopeChain<'a> { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { match *self { EarlyScope(space, defs, _) => write!(fmt, "EarlyScope({:?}, {:?})", space, defs), diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index c669da9b60dd..714dd7d98cf4 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -244,12 +244,6 @@ impl<'a, 'tcx> Checker<'a, 'tcx> { } impl<'a, 'v, 'tcx> Visitor<'v> for Checker<'a, 'tcx> { - fn visit_view_item(&mut self, item: &ast::ViewItem) { - check_view_item(self.tcx, item, - &mut |id, sp, stab| self.check(id, sp, stab)); - visit::walk_view_item(self, item) - } - fn visit_item(&mut self, item: &ast::Item) { check_item(self.tcx, item, &mut |id, sp, stab| self.check(id, sp, stab)); @@ -264,22 +258,34 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Checker<'a, 'tcx> { } /// Helper for discovering nodes to check for stability -pub fn check_view_item(tcx: &ty::ctxt, item: &ast::ViewItem, - cb: &mut FnMut(ast::DefId, Span, &Option)) { - // compiler-generated `extern crate` statements have a dummy span. - if item.span == DUMMY_SP { return } +pub fn check_item(tcx: &ty::ctxt, item: &ast::Item, + cb: &mut FnMut(ast::DefId, Span, &Option)) { + match item.node { + ast::ItemExternCrate(_) => { + // compiler-generated `extern crate` items have a dummy span. + if item.span == DUMMY_SP { return } - let id = match item.node { - ast::ViewItemExternCrate(_, _, id) => id, - ast::ViewItemUse(..) => return, - }; - let cnum = match tcx.sess.cstore.find_extern_mod_stmt_cnum(id) { - Some(cnum) => cnum, - None => return, - }; - let id = ast::DefId { krate: cnum, node: ast::CRATE_NODE_ID }; - - maybe_do_stability_check(tcx, id, item.span, cb); + let cnum = match tcx.sess.cstore.find_extern_mod_stmt_cnum(item.id) { + Some(cnum) => cnum, + None => return, + }; + let id = ast::DefId { krate: cnum, node: ast::CRATE_NODE_ID }; + maybe_do_stability_check(tcx, id, item.span, cb); + } + ast::ItemTrait(_, _, ref supertraits, _) => { + for t in supertraits.iter() { + if let ast::TraitTyParamBound(ref t, _) = *t { + let id = ty::trait_ref_to_def_id(tcx, &t.trait_ref); + maybe_do_stability_check(tcx, id, t.trait_ref.path.span, cb); + } + } + } + ast::ItemImpl(_, _, _, Some(ref t), _, _) => { + let id = ty::trait_ref_to_def_id(tcx, t); + maybe_do_stability_check(tcx, id, t.path.span, cb); + } + _ => (/* pass */) + } } /// Helper for discovering nodes to check for stability @@ -331,28 +337,6 @@ pub fn check_expr(tcx: &ty::ctxt, e: &ast::Expr, maybe_do_stability_check(tcx, id, span, cb); } -/// Helper for discovering nodes to check for stability -pub fn check_item(tcx: &ty::ctxt, item: &ast::Item, - cb: &mut FnMut(ast::DefId, Span, &Option)) { - if is_internal(tcx, item.span) { return } - - match item.node { - ast::ItemTrait(_, _, ref supertraits, _) => { - for t in supertraits.iter() { - if let ast::TraitTyParamBound(ref t, _) = *t { - let id = ty::trait_ref_to_def_id(tcx, &t.trait_ref); - maybe_do_stability_check(tcx, id, t.trait_ref.path.span, cb); - } - } - } - ast::ItemImpl(_, _, _, Some(ref t), _, _) => { - let id = ty::trait_ref_to_def_id(tcx, t); - maybe_do_stability_check(tcx, id, t.path.span, cb); - } - _ => (/* pass */) - } -} - fn maybe_do_stability_check(tcx: &ty::ctxt, id: ast::DefId, span: Span, cb: &mut FnMut(ast::DefId, Span, &Option)) { if !is_staged_api(tcx, id) { return } diff --git a/src/librustc/middle/subst.rs b/src/librustc/middle/subst.rs index 9ad2dd499cc9..889d8b4052f0 100644 --- a/src/librustc/middle/subst.rs +++ b/src/librustc/middle/subst.rs @@ -238,7 +238,7 @@ pub struct SeparateVecsPerParamSpace { pub fns: Vec, } -impl fmt::Show for VecPerParamSpace { +impl fmt::Debug for VecPerParamSpace { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { try!(write!(fmt, "VecPerParamSpace {{")); for space in ParamSpace::all().iter() { @@ -373,12 +373,12 @@ impl VecPerParamSpace { pub fn get_slice<'a>(&'a self, space: ParamSpace) -> &'a [T] { let (start, limit) = self.limits(space); - self.content.slice(start, limit) + &self.content[start.. limit] } pub fn get_mut_slice<'a>(&'a mut self, space: ParamSpace) -> &'a mut [T] { let (start, limit) = self.limits(space); - self.content.slice_mut(start, limit) + &mut self.content[start.. limit] } pub fn opt_get<'a>(&'a self, diff --git a/src/librustc/middle/traits/error_reporting.rs b/src/librustc/middle/traits/error_reporting.rs index 6d0e60ec495a..7ccb5e6e7116 100644 --- a/src/librustc/middle/traits/error_reporting.rs +++ b/src/librustc/middle/traits/error_reporting.rs @@ -55,12 +55,10 @@ pub fn report_projection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, let predicate = infcx.resolve_type_vars_if_possible(&obligation.predicate); if !predicate.references_error() { - infcx.tcx.sess.span_err( - obligation.cause.span, - format!( + span_err!(infcx.tcx.sess, obligation.cause.span, E0271, "type mismatch resolving `{}`: {}", predicate.user_string(infcx.tcx), - ty::type_err_to_str(infcx.tcx, &error.err)).as_slice()); + ty::type_err_to_str(infcx.tcx, &error.err)); note_obligation_cause(infcx, obligation); } } @@ -97,28 +95,25 @@ fn report_on_unimplemented<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, Position::ArgumentNamed(s) => match generic_map.get(s) { Some(val) => Some(val.as_slice()), None => { - infcx.tcx.sess - .span_err(err_sp, - format!("the #[rustc_on_unimplemented] \ + span_err!(infcx.tcx.sess, err_sp, E0272, + "the #[rustc_on_unimplemented] \ attribute on \ trait definition for {} refers to \ non-existent type parameter {}", - trait_str, s) - .as_slice()); + trait_str, s); errored = true; None } }, _ => { - infcx.tcx.sess - .span_err(err_sp, - format!("the #[rustc_on_unimplemented] \ + span_err!(infcx.tcx.sess, err_sp, E0273, + "the #[rustc_on_unimplemented] \ attribute on \ trait definition for {} must have named \ format arguments, \ eg `#[rustc_on_unimplemented = \ \"foo {{T}}\"]`", - trait_str).as_slice()); + trait_str); errored = true; None } @@ -130,11 +125,11 @@ fn report_on_unimplemented<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, report = Some(err); } } else { - infcx.tcx.sess.span_err(err_sp, - format!("the #[rustc_on_unimplemented] attribute on \ + span_err!(infcx.tcx.sess, err_sp, E0274, + "the #[rustc_on_unimplemented] attribute on \ trait definition for {} must have a value, \ eg `#[rustc_on_unimplemented = \"foo\"]`", - trait_str).as_slice()); + trait_str); } break; } @@ -151,11 +146,9 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, // We could track the stack here more precisely if we wanted, I imagine. let predicate = infcx.resolve_type_vars_if_possible(&obligation.predicate); - infcx.tcx.sess.span_err( - obligation.cause.span, - format!( + span_err!(infcx.tcx.sess, obligation.cause.span, E0275, "overflow evaluating the requirement `{}`", - predicate.user_string(infcx.tcx)).as_slice()); + predicate.user_string(infcx.tcx)); suggest_new_overflow_limit(infcx.tcx, obligation.cause.span); @@ -165,12 +158,10 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, SelectionError::Unimplemented => { match &obligation.cause.code { &ObligationCauseCode::CompareImplMethodObligation => { - infcx.tcx.sess.span_err( - obligation.cause.span, - format!( + span_err!(infcx.tcx.sess, obligation.cause.span, E0276, "the requirement `{}` appears on the impl \ method but not on the corresponding trait method", - obligation.predicate.user_string(infcx.tcx)).as_slice()); + obligation.predicate.user_string(infcx.tcx));; } _ => { match obligation.predicate { @@ -180,12 +171,10 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, if !trait_predicate.references_error() { let trait_ref = trait_predicate.to_poly_trait_ref(); - infcx.tcx.sess.span_err( - obligation.cause.span, - format!( + span_err!(infcx.tcx.sess, obligation.cause.span, E0277, "the trait `{}` is not implemented for the type `{}`", trait_ref.user_string(infcx.tcx), - trait_ref.self_ty().user_string(infcx.tcx)).as_slice()); + trait_ref.self_ty().user_string(infcx.tcx)); // Check if it has a custom "#[rustc_on_unimplemented]" // error message, report with that message if it does let custom_note = report_on_unimplemented(infcx, &*trait_ref.0, @@ -200,35 +189,29 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, ty::Predicate::Equate(ref predicate) => { let predicate = infcx.resolve_type_vars_if_possible(predicate); let err = infcx.equality_predicate(obligation.cause.span, - &predicate).unwrap_err(); - infcx.tcx.sess.span_err( - obligation.cause.span, - format!( + &predicate).err().unwrap(); + span_err!(infcx.tcx.sess, obligation.cause.span, E0278, "the requirement `{}` is not satisfied (`{}`)", predicate.user_string(infcx.tcx), - ty::type_err_to_str(infcx.tcx, &err)).as_slice()); + ty::type_err_to_str(infcx.tcx, &err)); } ty::Predicate::RegionOutlives(ref predicate) => { let predicate = infcx.resolve_type_vars_if_possible(predicate); let err = infcx.region_outlives_predicate(obligation.cause.span, - &predicate).unwrap_err(); - infcx.tcx.sess.span_err( - obligation.cause.span, - format!( + &predicate).err().unwrap(); + span_err!(infcx.tcx.sess, obligation.cause.span, E0279, "the requirement `{}` is not satisfied (`{}`)", predicate.user_string(infcx.tcx), - ty::type_err_to_str(infcx.tcx, &err)).as_slice()); + ty::type_err_to_str(infcx.tcx, &err)); } ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => { let predicate = infcx.resolve_type_vars_if_possible(&obligation.predicate); - infcx.tcx.sess.span_err( - obligation.cause.span, - format!( + span_err!(infcx.tcx.sess, obligation.cause.span, E0280, "the requirement `{}` is not satisfied", - predicate.user_string(infcx.tcx)).as_slice()); + predicate.user_string(infcx.tcx)); } } } @@ -239,15 +222,13 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, let expected_trait_ref = infcx.resolve_type_vars_if_possible(&*expected_trait_ref); let actual_trait_ref = infcx.resolve_type_vars_if_possible(&*actual_trait_ref); if !ty::type_is_error(actual_trait_ref.self_ty()) { - infcx.tcx.sess.span_err( - obligation.cause.span, - format!( + span_err!(infcx.tcx.sess, obligation.cause.span, E0281, "type mismatch: the type `{}` implements the trait `{}`, \ but the trait `{}` is required ({})", expected_trait_ref.self_ty().user_string(infcx.tcx), expected_trait_ref.user_string(infcx.tcx), actual_trait_ref.user_string(infcx.tcx), - ty::type_err_to_str(infcx.tcx, e)).as_slice()); + ty::type_err_to_str(infcx.tcx, e)); note_obligation_cause(infcx, obligation); } } @@ -293,18 +274,14 @@ pub fn maybe_report_ambiguity<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, infcx.tcx.lang_items.sized_trait() .map_or(false, |sized_id| sized_id == trait_ref.def_id()) { - infcx.tcx.sess.span_err( - obligation.cause.span, - format!( + span_err!(infcx.tcx.sess, obligation.cause.span, E0282, "unable to infer enough type information about `{}`; \ type annotations required", - self_ty.user_string(infcx.tcx)).as_slice()); + self_ty.user_string(infcx.tcx)); } else { - infcx.tcx.sess.span_err( - obligation.cause.span, - format!( + span_err!(infcx.tcx.sess, obligation.cause.span, E0283, "type annotations required: cannot resolve `{}`", - predicate.user_string(infcx.tcx)).as_slice()); + predicate.user_string(infcx.tcx));; note_obligation_cause(infcx, obligation); } } @@ -323,11 +300,9 @@ pub fn maybe_report_ambiguity<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, _ => { if !infcx.tcx.sess.has_errors() { - infcx.tcx.sess.span_err( - obligation.cause.span, - format!( + span_err!(infcx.tcx.sess, obligation.cause.span, E0284, "type annotations required: cannot resolve `{}`", - predicate.user_string(infcx.tcx)).as_slice()); + predicate.user_string(infcx.tcx));; note_obligation_cause(infcx, obligation); } } diff --git a/src/librustc/middle/traits/fulfill.rs b/src/librustc/middle/traits/fulfill.rs index 42624555ae47..568286e39d59 100644 --- a/src/librustc/middle/traits/fulfill.rs +++ b/src/librustc/middle/traits/fulfill.rs @@ -84,6 +84,7 @@ pub struct FulfillmentContext<'tcx> { region_obligations: NodeMap>>, } +#[derive(Clone)] pub struct RegionObligation<'tcx> { pub sub_region: ty::Region, pub sup_type: Ty<'tcx>, diff --git a/src/librustc/middle/traits/mod.rs b/src/librustc/middle/traits/mod.rs index 425765edf870..89459f95b879 100644 --- a/src/librustc/middle/traits/mod.rs +++ b/src/librustc/middle/traits/mod.rs @@ -379,11 +379,10 @@ pub fn type_known_to_meet_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>, false } Err(Overflow) => { - infcx.tcx.sess.span_err( - span, - format!("overflow evaluating whether `{}` is `{}`", - ty.user_string(infcx.tcx), - bound.user_string(infcx.tcx)).as_slice()); + span_err!(infcx.tcx.sess, span, E0285, + "overflow evaluating whether `{}` is `{}`", + ty.user_string(infcx.tcx), + bound.user_string(infcx.tcx)); suggest_new_overflow_limit(infcx.tcx, span); false } diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index 62649653a697..e8d82150ade4 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -1554,10 +1554,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let tcx = this.tcx(); match bound { ty::BoundSend => { - if - Some(def_id) == tcx.lang_items.no_send_bound() || - Some(def_id) == tcx.lang_items.managed_bound() - { + if Some(def_id) == tcx.lang_items.managed_bound() { return Err(Unimplemented) } } @@ -1568,7 +1565,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::BoundSync => { if - Some(def_id) == tcx.lang_items.no_sync_bound() || Some(def_id) == tcx.lang_items.managed_bound() || Some(def_id) == tcx.lang_items.unsafe_type() { diff --git a/src/librustc/middle/traits/util.rs b/src/librustc/middle/traits/util.rs index fe8362223e3c..bdf9b16f1396 100644 --- a/src/librustc/middle/traits/util.rs +++ b/src/librustc/middle/traits/util.rs @@ -236,13 +236,13 @@ pub fn fresh_substs_for_impl<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, infcx.fresh_substs_for_generics(span, &impl_generics) } -impl<'tcx, N> fmt::Show for VtableImplData<'tcx, N> { +impl<'tcx, N> fmt::Debug for VtableImplData<'tcx, N> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "VtableImpl({:?})", self.impl_def_id) } } -impl<'tcx> fmt::Show for super::VtableObjectData<'tcx> { +impl<'tcx> fmt::Debug for super::VtableObjectData<'tcx> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "VtableObject(...)") } @@ -449,7 +449,7 @@ impl<'tcx> Repr<'tcx> for super::FulfillmentErrorCode<'tcx> { } } -impl<'tcx> fmt::Show for super::FulfillmentErrorCode<'tcx> { +impl<'tcx> fmt::Debug for super::FulfillmentErrorCode<'tcx> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { super::CodeSelectionError(ref e) => write!(f, "{:?}", e), @@ -465,7 +465,7 @@ impl<'tcx> Repr<'tcx> for super::MismatchedProjectionTypes<'tcx> { } } -impl<'tcx> fmt::Show for super::MismatchedProjectionTypes<'tcx> { +impl<'tcx> fmt::Debug for super::MismatchedProjectionTypes<'tcx> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "MismatchedProjectionTypes(..)") } diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index be6c6b9d34f3..83bbdf14e4a7 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -17,7 +17,6 @@ pub use self::InferTy::*; pub use self::InferRegion::*; pub use self::ImplOrTraitItemId::*; pub use self::UnboxedClosureKind::*; -pub use self::TraitStore::*; pub use self::ast_ty_to_ty_cache_entry::*; pub use self::Variance::*; pub use self::AutoAdjustment::*; @@ -61,7 +60,7 @@ use middle::ty; use middle::ty_fold::{self, TypeFoldable, TypeFolder}; use middle::ty_walk::TypeWalker; use util::ppaux::{note_and_explain_region, bound_region_ptr_to_string}; -use util::ppaux::{trait_store_to_string, ty_to_string}; +use util::ppaux::ty_to_string; use util::ppaux::{Repr, UserString}; use util::common::{memoized, ErrorReported}; use util::nodemap::{NodeMap, NodeSet, DefIdMap, DefIdSet}; @@ -70,7 +69,7 @@ use util::nodemap::{FnvHashMap}; use arena::TypedArena; use std::borrow::{BorrowFrom, Cow}; use std::cell::{Cell, RefCell}; -use std::cmp::{self, Ordering}; +use std::cmp; use std::fmt::{self, Show}; use std::hash::{Hash, Writer, SipHasher, Hasher}; use std::mem; @@ -247,14 +246,6 @@ pub struct mt<'tcx> { pub mutbl: ast::Mutability, } -#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Show)] -pub enum TraitStore { - /// Box - UniqTraitStore, - /// &Trait and &mut Trait - RegionTraitStore(Region, ast::Mutability), -} - #[derive(Clone, Copy, Show)] pub struct field_ty { pub name: Name, @@ -934,7 +925,7 @@ pub struct TyS<'tcx> { region_depth: u32, } -impl fmt::Show for TypeFlags { +impl fmt::Debug for TypeFlags { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.bits) } @@ -1041,11 +1032,8 @@ pub struct BareFnTy<'tcx> { #[derive(Clone, PartialEq, Eq, Hash, Show)] pub struct ClosureTy<'tcx> { pub unsafety: ast::Unsafety, - pub onceness: ast::Onceness, - pub store: TraitStore, - pub bounds: ExistentialBounds<'tcx>, - pub sig: PolyFnSig<'tcx>, pub abi: abi::Abi, + pub sig: PolyFnSig<'tcx>, } #[derive(Clone, Copy, PartialEq, Eq, Hash, Show)] @@ -1545,7 +1533,6 @@ pub enum type_err<'tcx> { terr_onceness_mismatch(expected_found), terr_abi_mismatch(expected_found), terr_mutability, - terr_sigil_mismatch(expected_found), terr_box_mutability, terr_ptr_mutability, terr_ref_mutability, @@ -1559,7 +1546,6 @@ pub enum type_err<'tcx> { terr_regions_no_overlap(Region, Region), terr_regions_insufficiently_polymorphic(BoundRegion, Region), terr_regions_overly_polymorphic(BoundRegion, Region), - terr_trait_stores_differ(terr_vstore_kind, expected_found), terr_sorts(expected_found>), terr_integer_as_char, terr_int_mismatch(expected_found), @@ -1703,37 +1689,37 @@ impl cmp::PartialEq for InferRegion { } } -impl fmt::Show for TyVid { +impl fmt::Debug for TyVid { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result{ write!(f, "_#{}t", self.index) } } -impl fmt::Show for IntVid { +impl fmt::Debug for IntVid { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "_#{}i", self.index) } } -impl fmt::Show for FloatVid { +impl fmt::Debug for FloatVid { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "_#{}f", self.index) } } -impl fmt::Show for RegionVid { +impl fmt::Debug for RegionVid { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "'_#{}r", self.index) } } -impl<'tcx> fmt::Show for FnSig<'tcx> { +impl<'tcx> fmt::Debug for FnSig<'tcx> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "({:?}; variadic: {})->{:?}", self.inputs, self.variadic, self.output) } } -impl fmt::Show for InferTy { +impl fmt::Debug for InferTy { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { TyVar(ref v) => v.fmt(f), @@ -1745,7 +1731,7 @@ impl fmt::Show for InferTy { } } -impl fmt::Show for IntVarValue { +impl fmt::Debug for IntVarValue { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { IntType(ref v) => v.fmt(f), @@ -3319,7 +3305,7 @@ impl ops::Sub for TypeContents { } } -impl fmt::Show for TypeContents { +impl fmt::Debug for TypeContents { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "TypeContents({:b})", self.bits) } @@ -4194,19 +4180,6 @@ pub fn ty_fn_args<'tcx>(fty: Ty<'tcx>) -> ty::Binder>> { ty_fn_sig(fty).inputs() } -pub fn ty_closure_store(fty: Ty) -> TraitStore { - match fty.sty { - ty_unboxed_closure(..) => { - // Close enough for the purposes of all the callers of this - // function (which is soon to be deprecated anyhow). - UniqTraitStore - } - ref s => { - panic!("ty_closure_store() called on non-closure type: {:?}", s) - } - } -} - pub fn ty_fn_ret<'tcx>(fty: Ty<'tcx>) -> Binder> { match fty.sty { ty_bare_fn(_, ref f) => f.sig.output(), @@ -4751,13 +4724,6 @@ impl<'tcx> Repr<'tcx> for ty::type_err<'tcx> { /// afterwards to present additional details, particularly when it comes to lifetime-related /// errors. pub fn type_err_to_str<'tcx>(cx: &ctxt<'tcx>, err: &type_err<'tcx>) -> String { - fn tstore_to_closure(s: &TraitStore) -> String { - match s { - &UniqTraitStore => "proc".to_string(), - &RegionTraitStore(..) => "closure".to_string() - } - } - match *err { terr_cyclic_ty => "cyclic type of infinite size".to_string(), terr_mismatch => "types differ".to_string(), @@ -4776,11 +4742,6 @@ pub fn type_err_to_str<'tcx>(cx: &ctxt<'tcx>, err: &type_err<'tcx>) -> String { values.expected, values.found) } - terr_sigil_mismatch(values) => { - format!("expected {}, found {}", - tstore_to_closure(&values.expected), - tstore_to_closure(&values.found)) - } terr_mutability => "values differ in mutability".to_string(), terr_box_mutability => { "boxed values differ in mutability".to_string() @@ -4828,11 +4789,6 @@ pub fn type_err_to_str<'tcx>(cx: &ctxt<'tcx>, err: &type_err<'tcx>) -> String { found bound lifetime parameter {}", bound_region_ptr_to_string(cx, br)) } - terr_trait_stores_differ(_, ref values) => { - format!("trait storage differs: expected `{}`, found `{}`", - trait_store_to_string(cx, (*values).expected), - trait_store_to_string(cx, (*values).found)) - } terr_sorts(values) => { // A naive approach to making sure that we're not reporting silly errors such as: // (expected closure, found closure). @@ -5089,25 +5045,6 @@ pub fn associated_type_parameter_index(cx: &ctxt, cx.sess.bug("couldn't find associated type parameter index") } -#[derive(Copy, PartialEq, Eq)] -pub struct AssociatedTypeInfo { - pub def_id: ast::DefId, - pub index: uint, - pub name: ast::Name, -} - -impl PartialOrd for AssociatedTypeInfo { - fn partial_cmp(&self, other: &AssociatedTypeInfo) -> Option { - Some(self.index.cmp(&other.index)) - } -} - -impl Ord for AssociatedTypeInfo { - fn cmp(&self, other: &AssociatedTypeInfo) -> Ordering { - self.index.cmp(&other.index) - } -} - pub fn trait_item_def_ids(cx: &ctxt, id: ast::DefId) -> Rc> { lookup_locally_or_in_crate_store("trait_item_def_ids", @@ -5369,15 +5306,13 @@ pub fn enum_variants<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId) discriminant = val as Disr } Ok(_) => { - cx.sess - .span_err(e.span, + span_err!(cx.sess, e.span, E0304, "expected signed integer constant"); } Err(ref err) => { - cx.sess - .span_err(e.span, - &format!("expected constant: {}", - *err)[]); + span_err!(cx.sess, e.span, E0305, + "expected constant: {}", + *err); } }, None => {} @@ -5851,9 +5786,9 @@ pub fn eval_repeat_count(tcx: &ctxt, count_expr: &ast::Expr) -> uint { const_eval::const_binary(_) => "binary array" }; - tcx.sess.span_err(count_expr.span, &format!( + span_err!(tcx.sess, count_expr.span, E0306, "expected positive integer for repeat count, found {}", - found)[]); + found); } Err(_) => { let found = match count_expr.node { @@ -5866,9 +5801,9 @@ pub fn eval_repeat_count(tcx: &ctxt, count_expr: &ast::Expr) -> uint { _ => "non-constant expression" }; - tcx.sess.span_err(count_expr.span, &format!( + span_err!(tcx.sess, count_expr.span, E0307, "expected constant integer for repeat count, found {}", - found)[]); + found); } } 0 @@ -7338,11 +7273,8 @@ impl ReferencesError for Region impl<'tcx> Repr<'tcx> for ClosureTy<'tcx> { fn repr(&self, tcx: &ctxt<'tcx>) -> String { - format!("ClosureTy({},{},{:?},{},{},{})", + format!("ClosureTy({},{},{})", self.unsafety, - self.onceness, - self.store, - self.bounds.repr(tcx), self.sig.repr(tcx), self.abi) } @@ -7373,5 +7305,5 @@ impl<'a, 'tcx> Repr<'tcx> for ParameterEnvironment<'a, 'tcx> { self.free_substs.repr(tcx), self.implicit_region_bound.repr(tcx), self.caller_bounds.repr(tcx)) - } } +} diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs index 37886b4a1e1f..b4e6cff954bc 100644 --- a/src/librustc/middle/ty_fold.rs +++ b/src/librustc/middle/ty_fold.rs @@ -124,10 +124,6 @@ pub trait TypeFolder<'tcx> : Sized { r } - fn fold_trait_store(&mut self, s: ty::TraitStore) -> ty::TraitStore { - super_fold_trait_store(self, s) - } - fn fold_existential_bounds(&mut self, s: &ty::ExistentialBounds<'tcx>) -> ty::ExistentialBounds<'tcx> { super_fold_existential_bounds(self, s) @@ -225,12 +221,6 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for VecPerParamSpace { } } -impl<'tcx> TypeFoldable<'tcx> for ty::TraitStore { - fn fold_with>(&self, folder: &mut F) -> ty::TraitStore { - folder.fold_trait_store(*self) - } -} - impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { fn fold_with>(&self, folder: &mut F) -> Ty<'tcx> { folder.fold_ty(*self) @@ -699,11 +689,8 @@ pub fn super_fold_closure_ty<'tcx, T: TypeFolder<'tcx>>(this: &mut T, -> ty::ClosureTy<'tcx> { ty::ClosureTy { - store: fty.store.fold_with(this), sig: fty.sig.fold_with(this), unsafety: fty.unsafety, - onceness: fty.onceness, - bounds: fty.bounds.fold_with(this), abi: fty.abi, } } @@ -726,17 +713,6 @@ pub fn super_fold_mt<'tcx, T: TypeFolder<'tcx>>(this: &mut T, mutbl: mt.mutbl} } -pub fn super_fold_trait_store<'tcx, T: TypeFolder<'tcx>>(this: &mut T, - trait_store: ty::TraitStore) - -> ty::TraitStore { - match trait_store { - ty::UniqTraitStore => ty::UniqTraitStore, - ty::RegionTraitStore(r, m) => { - ty::RegionTraitStore(r.fold_with(this), m) - } - } -} - pub fn super_fold_existential_bounds<'tcx, T: TypeFolder<'tcx>>( this: &mut T, bounds: &ty::ExistentialBounds<'tcx>) diff --git a/src/librustc/middle/weak_lang_items.rs b/src/librustc/middle/weak_lang_items.rs index 892a8004fec1..25cca98c5fb4 100644 --- a/src/librustc/middle/weak_lang_items.rs +++ b/src/librustc/middle/weak_lang_items.rs @@ -99,9 +99,9 @@ impl<'a> Context<'a> { self.items.missing.push(lang_items::$item); } } else)* { - self.sess.span_err(span, - format!("unknown external lang item: `{}`", - name).as_slice()); + span_err!(self.sess, span, E0264, + "unknown external lang item: `{}`", + name); } } } diff --git a/src/librustc/plugin/load.rs b/src/librustc/plugin/load.rs index ef8a89c40fb5..c420d1f15b43 100644 --- a/src/librustc/plugin/load.rs +++ b/src/librustc/plugin/load.rs @@ -73,8 +73,10 @@ pub fn load_plugins(sess: &Session, krate: &ast::Crate, // We need to error on `#[macro_use] extern crate` when it isn't at the // crate root, because `$crate` won't work properly. Identify these by // spans, because the crate map isn't set up yet. - for vi in krate.module.view_items.iter() { - loader.span_whitelist.insert(vi.span); + for item in krate.module.items.iter() { + if let ast::ItemExternCrate(_) = item.node { + loader.span_whitelist.insert(item.span); + } } visit::walk_crate(&mut loader, krate); @@ -91,18 +93,21 @@ pub fn load_plugins(sess: &Session, krate: &ast::Crate, // note that macros aren't expanded yet, and therefore macros can't add plugins. impl<'a, 'v> Visitor<'v> for PluginLoader<'a> { - fn visit_view_item(&mut self, vi: &ast::ViewItem) { + fn visit_item(&mut self, item: &ast::Item) { // We're only interested in `extern crate`. - match vi.node { - ast::ViewItemExternCrate(..) => (), - _ => return, + match item.node { + ast::ItemExternCrate(_) => {} + _ => { + visit::walk_item(self, item); + return; + } } // Parse the attributes relating to macro / plugin loading. let mut plugin_attr = None; let mut macro_selection = Some(HashSet::new()); // None => load all let mut reexport = HashSet::new(); - for attr in vi.attrs.iter() { + for attr in item.attrs.iter() { let mut used = true; match attr.name().get() { "phase" => { @@ -155,7 +160,10 @@ impl<'a, 'v> Visitor<'v> for PluginLoader<'a> { } } - self.load_plugin(CrateOrString::Krate(vi), plugin_attr, macro_selection, Some(reexport)) + self.load_plugin(CrateOrString::Krate(item), + plugin_attr, + macro_selection, + Some(reexport)) } fn visit_mac(&mut self, _: &ast::Mac) { diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index d9bb1d769bfb..a2bba313cca8 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -249,7 +249,7 @@ pub enum EntryFnType { EntryNone, } -#[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash)] +#[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Show)] pub enum CrateType { CrateTypeExecutable, CrateTypeDylib, @@ -786,7 +786,6 @@ pub fn rustc_optgroups() -> Vec { opt::multi("", "extern", "Specify where an external rust library is \ located", "NAME=PATH"), - opt::opt("", "opt-level", "Optimize with possible levels 0-3", "LEVEL"), opt::opt("", "sysroot", "Override the system root", "PATH"), opt::multi("Z", "", "Set internal debugging options", "FLAG"), opt::opt("", "color", "Configure coloring of output: @@ -794,22 +793,7 @@ pub fn rustc_optgroups() -> Vec { always = always colorize output; never = never colorize output", "auto|always|never"), - // DEPRECATED - opt::flag("", "print-crate-name", "Output the crate name and exit"), - opt::flag("", "print-file-name", "Output the file(s) that would be \ - written if compilation \ - continued and exit"), - opt::opt("", "debuginfo", "Emit DWARF debug info to the objects created: - 0 = no debug info, - 1 = line-tables only (for stacktraces and breakpoints), - 2 = full debug info with variable and type information \ - (same as -g)", "LEVEL"), - opt::flag("", "no-trans", "Run all passes except translation; no output"), - opt::flag("", "no-analysis", "Parse and expand the source, but run no \ - analysis and produce no output"), - opt::flag("", "parse-only", "Parse only; do not compile, assemble, \ - or link"), - opt::flagopt("", "pretty", + opt::flagopt_u("", "pretty", "Pretty-print the input instead of compiling; valid types are: `normal` (un-annotated source), `expanded` (crates expanded), @@ -823,9 +807,6 @@ pub fn rustc_optgroups() -> Vec { `everybody_loops` (all function bodies replaced with `loop {}`).", "TYPE"), opt::opt_u("", "show-span", "Show spans for compiler debugging", "expr|pat|ty"), - opt::flagopt("", "dep-info", - "Output dependency info to after compiling, \ - in a format suitable for use by Makefiles", "FILENAME"), ]); opts } @@ -861,27 +842,9 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { let debugging_opts = build_debugging_options(matches); - let parse_only = if matches.opt_present("parse-only") { - // FIXME(acrichto) remove this eventually - early_warn("--parse-only is deprecated in favor of -Z parse-only"); - true - } else { - debugging_opts.parse_only - }; - let no_trans = if matches.opt_present("no-trans") { - // FIXME(acrichto) remove this eventually - early_warn("--no-trans is deprecated in favor of -Z no-trans"); - true - } else { - debugging_opts.no_trans - }; - let no_analysis = if matches.opt_present("no-analysis") { - // FIXME(acrichto) remove this eventually - early_warn("--no-analysis is deprecated in favor of -Z no-analysis"); - true - } else { - debugging_opts.no_analysis - }; + let parse_only = debugging_opts.parse_only; + let no_trans = debugging_opts.no_trans; + let no_analysis = debugging_opts.no_analysis; if debugging_opts.debug_llvm { unsafe { llvm::LLVMSetDebug(1); } @@ -921,28 +884,10 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { host_triple().to_string()); let opt_level = { if matches.opt_present("O") { - if matches.opt_present("opt-level") { - early_error("-O and --opt-level both provided"); - } if cg.opt_level.is_some() { early_error("-O and -C opt-level both provided"); } Default - } else if matches.opt_present("opt-level") { - // FIXME(acrichto) remove this eventually - early_warn("--opt-level=N is deprecated in favor of -C opt-level=N"); - match matches.opt_str("opt-level").as_ref().map(|s| s.as_slice()) { - None | - Some("0") => No, - Some("1") => Less, - Some("2") => Default, - Some("3") => Aggressive, - Some(arg) => { - early_error(&format!("optimization level needs to be \ - between 0-3 (instead was `{}`)", - arg)[]); - } - } } else { match cg.opt_level { None => No, @@ -960,27 +905,10 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { }; let gc = debugging_opts.gc; let debuginfo = if matches.opt_present("g") { - if matches.opt_present("debuginfo") { - early_error("-g and --debuginfo both provided"); - } if cg.debuginfo.is_some() { early_error("-g and -C debuginfo both provided"); } FullDebugInfo - } else if matches.opt_present("debuginfo") { - // FIXME(acrichto) remove this eventually - early_warn("--debuginfo=N is deprecated in favor of -C debuginfo=N"); - match matches.opt_str("debuginfo").as_ref().map(|s| s.as_slice()) { - Some("0") => NoDebugInfo, - Some("1") => LimitedDebugInfo, - None | - Some("2") => FullDebugInfo, - Some(arg) => { - early_error(&format!("debug info level needs to be between \ - 0-2 (instead was `{}`)", - arg)[]); - } - } } else { match cg.debuginfo { None | Some(0) => NoDebugInfo, @@ -1036,15 +964,9 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { let cfg = parse_cfgspecs(matches.opt_strs("cfg")); let test = matches.opt_present("test"); - let write_dependency_info = if matches.opt_present("dep-info") { - // FIXME(acrichto) remove this eventually - early_warn("--dep-info has been deprecated in favor of --emit"); - (true, matches.opt_str("dep-info").map(|p| Path::new(p))) - } else { - (output_types.contains(&OutputTypeDepInfo), None) - }; + let write_dependency_info = (output_types.contains(&OutputTypeDepInfo), None); - let mut prints = matches.opt_strs("print").into_iter().map(|s| { + let prints = matches.opt_strs("print").into_iter().map(|s| { match s.as_slice() { "crate-name" => PrintRequest::CrateName, "file-names" => PrintRequest::FileNames, @@ -1054,18 +976,6 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { } } }).collect::>(); - if matches.opt_present("print-crate-name") { - // FIXME(acrichto) remove this eventually - early_warn("--print-crate-name has been deprecated in favor of \ - --print crate-name"); - prints.push(PrintRequest::CrateName); - } - if matches.opt_present("print-file-name") { - // FIXME(acrichto) remove this eventually - early_warn("--print-file-name has been deprecated in favor of \ - --print file-names"); - prints.push(PrintRequest::FileNames); - } if !cg.remark.is_empty() && debuginfo == NoDebugInfo { early_warn("-C remark will not show source locations without \ @@ -1159,7 +1069,7 @@ pub fn parse_crate_types_from_list(list_list: Vec) -> Result fmt::Result { match *self { CrateTypeExecutable => "bin".fmt(f), diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 5424b1c8cae5..f90a60c9754a 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -15,8 +15,6 @@ use metadata::filesearch; use session::search_paths::PathKind; use util::nodemap::NodeMap; -use regex::Regex; - use syntax::ast::NodeId; use syntax::codemap::Span; use syntax::diagnostic::{self, Emitter}; @@ -69,65 +67,23 @@ impl Session { pub fn span_fatal(&self, sp: Span, msg: &str) -> ! { self.diagnostic().span_fatal(sp, msg) } + pub fn span_fatal_with_code(&self, sp: Span, msg: &str, code: &str) -> ! { + self.diagnostic().span_fatal_with_code(sp, msg, code) + } pub fn fatal(&self, msg: &str) -> ! { self.diagnostic().handler().fatal(msg) } pub fn span_err(&self, sp: Span, msg: &str) { - // Conditions for enabling multi-line errors: - if !msg.contains("mismatched types") && - !msg.contains("type mismatch resolving") && - !msg.contains("if and else have incompatible types") && - !msg.contains("if may be missing an else clause") && - !msg.contains("match arms have incompatible types") && - !msg.contains("structure constructor specifies a structure of type") { - return self.diagnostic().span_err(sp, msg); + match split_msg_into_multilines(msg) { + Some(msg) => self.diagnostic().span_err(sp, &msg[]), + None => self.diagnostic().span_err(sp, msg) } - - let first = Regex::new(r"[( ]expected").unwrap(); - let second = Regex::new(r" found").unwrap(); - let third = Regex::new( - r"\((values differ|lifetime|cyclic type of infinite size)").unwrap(); - - let mut new_msg = String::new(); - let mut head = 0u; - - // Insert `\n` before expected and found. - for (pos1, pos2) in first.find_iter(msg).zip( - second.find_iter(msg)) { - new_msg = new_msg + - // A `(` may be preceded by a space and it should be trimmed - msg[head..pos1.0].trim_right() + // prefix - "\n" + // insert before first - &msg[pos1.0..pos1.1] + // insert what first matched - &msg[pos1.1..pos2.0] + // between matches - "\n " + // insert before second - // 123 - // `expected` is 3 char longer than `found`. To align the types, `found` gets - // 3 spaces prepended. - &msg[pos2.0..pos2.1]; // insert what second matched - - head = pos2.1; - } - - let mut tail = &msg[head..]; - // Insert `\n` before any remaining messages which match. - for pos in third.find_iter(tail).take(1) { - // The end of the message may just be wrapped in `()` without `expected`/`found`. - // Push this also to a new line and add the final tail after. - new_msg = new_msg + - // `(` is usually preceded by a space and should be trimmed. - tail[..pos.0].trim_right() + // prefix - "\n" + // insert before paren - &tail[pos.0..]; // append the tail - - tail = ""; - } - - new_msg.push_str(tail); - self.diagnostic().span_err(sp, &new_msg[]) } pub fn span_err_with_code(&self, sp: Span, msg: &str, code: &str) { - self.diagnostic().span_err_with_code(sp, msg, code) + match split_msg_into_multilines(msg) { + Some(msg) => self.diagnostic().span_err_with_code(sp, &msg[], code), + None => self.diagnostic().span_err_with_code(sp, msg, code) + } } pub fn err(&self, msg: &str) { self.diagnostic().handler().err(msg) @@ -285,6 +241,66 @@ impl Session { } } +fn split_msg_into_multilines(msg: &str) -> Option { + // Conditions for enabling multi-line errors: + if !msg.contains("mismatched types") && + !msg.contains("type mismatch resolving") && + !msg.contains("if and else have incompatible types") && + !msg.contains("if may be missing an else clause") && + !msg.contains("match arms have incompatible types") && + !msg.contains("structure constructor specifies a structure of type") { + return None + } + let first = msg.match_indices("expected").filter(|s| { + s.0 > 0 && (msg.char_at_reverse(s.0) == ' ' || + msg.char_at_reverse(s.0) == '(') + }).map(|(a, b)| (a - 1, b)); + let second = msg.match_indices("found").filter(|s| { + msg.char_at_reverse(s.0) == ' ' + }).map(|(a, b)| (a - 1, b)); + + let mut new_msg = String::new(); + let mut head = 0u; + + // Insert `\n` before expected and found. + for (pos1, pos2) in first.zip(second) { + new_msg = new_msg + + // A `(` may be preceded by a space and it should be trimmed + msg[head..pos1.0].trim_right() + // prefix + "\n" + // insert before first + &msg[pos1.0..pos1.1] + // insert what first matched + &msg[pos1.1..pos2.0] + // between matches + "\n " + // insert before second + // 123 + // `expected` is 3 char longer than `found`. To align the types, + // `found` gets 3 spaces prepended. + &msg[pos2.0..pos2.1]; // insert what second matched + + head = pos2.1; + } + + let mut tail = &msg[head..]; + let third = tail.find_str("(values differ") + .or(tail.find_str("(lifetime")) + .or(tail.find_str("(cyclic type of infinite size")); + // Insert `\n` before any remaining messages which match. + if let Some(pos) = third { + // The end of the message may just be wrapped in `()` without + // `expected`/`found`. Push this also to a new line and add the + // final tail after. + new_msg = new_msg + + // `(` is usually preceded by a space and should be trimmed. + tail[..pos].trim_right() + // prefix + "\n" + // insert before paren + &tail[pos..]; // append the tail + + tail = ""; + } + + new_msg.push_str(tail); + return Some(new_msg); +} + pub fn build_session(sopts: config::Options, local_crate_source_file: Option, registry: diagnostics::registry::Registry) diff --git a/src/librustc/session/search_paths.rs b/src/librustc/session/search_paths.rs index 0cf04fe0a006..dfc27d3ae684 100644 --- a/src/librustc/session/search_paths.rs +++ b/src/librustc/session/search_paths.rs @@ -36,13 +36,13 @@ impl SearchPaths { pub fn add_path(&mut self, path: &str) { let (kind, path) = if path.starts_with("native=") { - (PathKind::Native, path.slice_from("native=".len())) + (PathKind::Native, &path["native=".len()..]) } else if path.starts_with("crate=") { - (PathKind::Crate, path.slice_from("crate=".len())) + (PathKind::Crate, &path["crate=".len()..]) } else if path.starts_with("dependency=") { - (PathKind::Dependency, path.slice_from("dependency=".len())) + (PathKind::Dependency, &path["dependency=".len()..]) } else if path.starts_with("all=") { - (PathKind::All, path.slice_from("all=".len())) + (PathKind::All, &path["all=".len()..]) } else { (PathKind::All, path) }; diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs index c505e9e31125..8915d55e2063 100644 --- a/src/librustc/util/common.rs +++ b/src/librustc/util/common.rs @@ -12,7 +12,7 @@ use std::cell::{RefCell, Cell}; use std::collections::HashMap; -use std::fmt::Show; +use std::fmt::Debug; use std::hash::{Hash, Hasher}; use std::iter::repeat; use std::time::Duration; @@ -58,7 +58,7 @@ pub fn time(do_it: bool, what: &str, u: U, f: F) -> T where } pub fn indent(op: F) -> R where - R: Show, + R: Debug, F: FnOnce() -> R, { // Use in conjunction with the log post-processor like `src/etc/indenter` diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index fb44d0cadfa6..c5aced4eb86f 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -164,7 +164,7 @@ pub fn explain_region_and_span(cx: &ctxt, region: ty::Region) fn explain_span(cx: &ctxt, heading: &str, span: Span) -> (String, Option) { let lo = cx.sess.codemap().lookup_char_pos_adj(span.lo); - (format!("the {} at {}:{}", heading, lo.line, lo.col.to_uint()), + (format!("the {} at {}:{}", heading, lo.line, lo.col.to_usize()), Some(span)) } } @@ -237,15 +237,6 @@ pub fn mt_to_string<'tcx>(cx: &ctxt<'tcx>, m: &mt<'tcx>) -> String { ty_to_string(cx, m.ty)) } -pub fn trait_store_to_string(cx: &ctxt, s: ty::TraitStore) -> String { - match s { - ty::UniqTraitStore => "Box ".to_string(), - ty::RegionTraitStore(r, m) => { - format!("{}{}", region_ptr_to_string(cx, r), mutability_to_string(m)) - } - } -} - pub fn vec_map_to_string(ts: &[T], f: F) -> String where F: FnMut(&T) -> String, { @@ -285,7 +276,7 @@ pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String { _ => { } } - push_sig_to_string(cx, &mut s, '(', ')', sig, ""); + push_sig_to_string(cx, &mut s, '(', ')', sig); match opt_def_id { Some(def_id) => { @@ -303,13 +294,6 @@ pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String { fn closure_to_string<'tcx>(cx: &ctxt<'tcx>, cty: &ty::ClosureTy<'tcx>) -> String { let mut s = String::new(); - match cty.store { - ty::UniqTraitStore => {} - ty::RegionTraitStore(region, _) => { - s.push_str(®ion_to_string(cx, "", true, region)[]); - } - } - match cty.unsafety { ast::Unsafety::Normal => {} ast::Unsafety::Unsafe => { @@ -318,24 +302,7 @@ pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String { } }; - let bounds_str = cty.bounds.user_string(cx); - - match cty.store { - ty::UniqTraitStore => { - assert_eq!(cty.onceness, ast::Once); - s.push_str("proc"); - push_sig_to_string(cx, &mut s, '(', ')', &cty.sig, - &bounds_str[]); - } - ty::RegionTraitStore(..) => { - match cty.onceness { - ast::Many => {} - ast::Once => s.push_str("once ") - } - push_sig_to_string(cx, &mut s, '|', '|', &cty.sig, - &bounds_str[]); - } - } + push_sig_to_string(cx, &mut s, '|', '|', &cty.sig); s } @@ -344,8 +311,7 @@ pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String { s: &mut String, bra: char, ket: char, - sig: &ty::PolyFnSig<'tcx>, - bounds: &str) { + sig: &ty::PolyFnSig<'tcx>) { s.push(bra); let strs = sig.0.inputs .iter() @@ -357,11 +323,6 @@ pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String { } s.push(ket); - if !bounds.is_empty() { - s.push_str(":"); - s.push_str(bounds); - } - match sig.0.output { ty::FnConverging(t) => { if !ty::type_is_nil(t) { @@ -542,7 +503,7 @@ pub fn parameterized<'tcx>(cx: &ctxt<'tcx>, 0 }; - for t in tps[..(tps.len() - num_defaults)].iter() { + for t in tps[..tps.len() - num_defaults].iter() { strs.push(ty_to_string(cx, *t)) } @@ -550,9 +511,9 @@ pub fn parameterized<'tcx>(cx: &ctxt<'tcx>, format!("{}({}){}", base, if strs[0].starts_with("(") && strs[0].ends_with(",)") { - &strs[0][1 .. (strs[0].len() - 2)] // Remove '(' and ',)' + &strs[0][1 .. strs[0].len() - 2] // Remove '(' and ',)' } else if strs[0].starts_with("(") && strs[0].ends_with(")") { - &strs[0][1 .. (strs[0].len() - 1)] // Remove '(' and ')' + &strs[0][1 .. strs[0].len() - 1] // Remove '(' and ')' } else { &strs[0][] }, @@ -1090,12 +1051,6 @@ impl<'tcx> Repr<'tcx> for ty::MethodObject<'tcx> { } } -impl<'tcx> Repr<'tcx> for ty::TraitStore { - fn repr(&self, tcx: &ctxt) -> String { - trait_store_to_string(tcx, *self) - } -} - impl<'tcx> Repr<'tcx> for ty::BuiltinBound { fn repr(&self, _tcx: &ctxt) -> String { format!("{:?}", *self) diff --git a/src/librustc_back/archive.rs b/src/librustc_back/archive.rs index 7ea192b8d6bc..fa754b4a3018 100644 --- a/src/librustc_back/archive.rs +++ b/src/librustc_back/archive.rs @@ -59,7 +59,7 @@ fn run_ar(handler: &ErrorHandler, maybe_ar_prog: &Option, let mut cmd = Command::new(ar); cmd.arg(args).args(paths); - debug!("{}", cmd); + debug!("{:?}", cmd); match cwd { Some(p) => { @@ -73,9 +73,7 @@ fn run_ar(handler: &ErrorHandler, maybe_ar_prog: &Option, Ok(prog) => { let o = prog.wait_with_output().unwrap(); if !o.status.success() { - handler.err(&format!("{} failed with: {}", - cmd, - o.status)[]); + handler.err(&format!("{:?} failed with: {}", cmd, o.status)[]); handler.note(&format!("stdout ---\n{}", str::from_utf8(&o.output[]).unwrap())[]); handler.note(&format!("stderr ---\n{}", diff --git a/src/librustc_back/sha2.rs b/src/librustc_back/sha2.rs index e376ac50dcdf..0228098b8f83 100644 --- a/src/librustc_back/sha2.rs +++ b/src/librustc_back/sha2.rs @@ -156,7 +156,7 @@ impl FixedBuffer for FixedBuffer64 { // While we have at least a full buffer size chunk's worth of data, process that data // without copying it into the buffer while input.len() - i >= size { - func(&input[i..(i + size)]); + func(&input[i..i + size]); i += size; } diff --git a/src/librustc_back/svh.rs b/src/librustc_back/svh.rs index b71e465b938f..ebeaf3e6e22d 100644 --- a/src/librustc_back/svh.rs +++ b/src/librustc_back/svh.rs @@ -52,7 +52,7 @@ use std::iter::range_step; use syntax::ast; use syntax::visit; -#[derive(Clone, PartialEq)] +#[derive(Clone, PartialEq, Show)] pub struct Svh { hash: String, } @@ -117,13 +117,7 @@ impl Svh { } } -impl fmt::Show for Svh { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "Svh {{ {} }}", self.as_str()) - } -} - -impl fmt::String for Svh { +impl fmt::Display for Svh { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad(self.as_str()) } @@ -188,7 +182,6 @@ mod svh_visitor { SawLifetimeDef(token::InternedString), SawMod, - SawViewItem, SawForeignItem, SawItem, SawDecl, @@ -436,19 +429,6 @@ mod svh_visitor { SawStmt(saw_stmt(&s.node)).hash(self.st); visit::walk_stmt(self, s) } - fn visit_view_item(&mut self, i: &ViewItem) { - // Two kinds of view items can affect the ABI for a crate: - // exported `pub use` view items (since that may expose - // items that downstream crates can call), and `use - // foo::Trait`, since changing that may affect method - // resolution. - // - // The simplest approach to handling both of the above is - // just to adopt the same simple-minded (fine-grained) - // hash that I am deploying elsewhere here. - SawViewItem.hash(self.st); visit::walk_view_item(self, i) - } - fn visit_foreign_item(&mut self, i: &ForeignItem) { // FIXME (#14132) ideally we would incorporate privacy (or // perhaps reachability) somewhere here, so foreign items diff --git a/src/librustc_back/target/aarch64_linux_android.rs b/src/librustc_back/target/aarch64_linux_android.rs new file mode 100644 index 000000000000..313c0dc2a6ea --- /dev/null +++ b/src/librustc_back/target/aarch64_linux_android.rs @@ -0,0 +1,28 @@ +// 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. + +use target::Target; + +pub fn target() -> Target { + let mut base = super::linux_base::opts(); + base.pre_link_args.push("-Wl,--allow-multiple-definition".to_string()); + base.position_independent_executables = true; + Target { + data_layout: "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\ + f32:32:32-f64:64:64-v64:64:64-v128:128:128-a:0:64-\ + n32:64-S128".to_string(), + llvm_target: "aarch64-linux-android".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "64".to_string(), + arch: "aarch64".to_string(), + target_os: "android".to_string(), + options: base, + } +} diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs index f8eabb4375fb..4626f2dc4833 100644 --- a/src/librustc_back/target/mod.rs +++ b/src/librustc_back/target/mod.rs @@ -65,6 +65,7 @@ mod arm_linux_androideabi; mod arm_unknown_linux_gnueabi; mod arm_unknown_linux_gnueabihf; mod aarch64_apple_ios; +mod aarch64_linux_android; mod aarch64_unknown_linux_gnu; mod i686_apple_darwin; mod i686_pc_windows_gnu; @@ -357,6 +358,7 @@ impl Target { i386_apple_ios, x86_64_apple_ios, aarch64_apple_ios, + aarch64_linux_android, armv7_apple_ios, armv7s_apple_ios, diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs index d5ad201eabfa..0ade916f6390 100644 --- a/src/librustc_borrowck/borrowck/check_loans.rs +++ b/src/librustc_borrowck/borrowck/check_loans.rs @@ -370,7 +370,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { for (i, &x) in new_loan_indices.iter().enumerate() { let old_loan = &self.all_loans[x]; - for &y in new_loan_indices.slice_from(i+1).iter() { + for &y in new_loan_indices[(i+1) ..].iter() { let new_loan = &self.all_loans[y]; self.report_error_if_loans_conflict(old_loan, new_loan); } diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs index 889a359b019c..b1cc3a651200 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs @@ -491,7 +491,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for StaticInitializerCtxt<'a, 'tcx> { if let ast::ExprAddrOf(mutbl, ref base) = ex.node { let param_env = ty::empty_parameter_environment(self.bccx.tcx); let mc = mc::MemCategorizationContext::new(¶m_env); - let base_cmt = mc.cat_expr(&**base).unwrap(); + let base_cmt = mc.cat_expr(&**base).ok().unwrap(); let borrow_kind = ty::BorrowKind::from_mutbl(mutbl); // Check that we don't allow borrows of unsafe static items. if check_aliasability(self.bccx, ex.span, euv::AddrOf, diff --git a/src/librustc_borrowck/lib.rs b/src/librustc_borrowck/lib.rs index 0182c90df1c1..d525c22f0ab6 100644 --- a/src/librustc_borrowck/lib.rs +++ b/src/librustc_borrowck/lib.rs @@ -27,6 +27,7 @@ #![feature(collections)] #![feature(core)] #![feature(rustc_private)] +#![feature(hash)] #[macro_use] extern crate log; #[macro_use] extern crate syntax; diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 772d72e59b6b..ffce577899bf 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -70,7 +70,6 @@ use rustc::lint::Lint; use rustc::lint; use rustc::metadata; use rustc::metadata::creader::CrateOrString::Str; -use rustc::DIAGNOSTICS; use rustc::util::common::time; use std::cmp::Ordering::Equal; @@ -107,7 +106,7 @@ fn run_compiler(args: &[String]) { None => return }; - let descriptions = diagnostics::registry::Registry::new(&DIAGNOSTICS); + let descriptions = diagnostics_registry(); match matches.opt_str("explain") { Some(ref code) => { match descriptions.find_description(&code[]) { @@ -163,10 +162,14 @@ fn run_compiler(args: &[String]) { return } - let pretty = matches.opt_default("pretty", "normal").map(|a| { - // stable pretty-print variants only - pretty::parse_pretty(&sess, a.as_slice(), false) - }); + let pretty = if sess.opts.debugging_opts.unstable_options { + matches.opt_default("pretty", "normal").map(|a| { + // stable pretty-print variants only + pretty::parse_pretty(&sess, a.as_slice(), false) + }) + } else { + None + }; let pretty = if pretty.is_none() && sess.unstable_options() { matches.opt_str("xpretty").map(|a| { @@ -668,8 +671,20 @@ pub fn monitor(f: F) { } } +pub fn diagnostics_registry() -> diagnostics::registry::Registry { + use syntax::diagnostics::registry::Registry; + + let all_errors = Vec::new() + + rustc::diagnostics::DIAGNOSTICS.as_slice() + + rustc_typeck::diagnostics::DIAGNOSTICS.as_slice() + + rustc_resolve::diagnostics::DIAGNOSTICS.as_slice(); + + Registry::new(&*all_errors) +} + pub fn main() { let args = std::os::args(); let result = run(args); std::os::set_exit_status(result); } + diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index 279442891bec..582e10323248 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -477,7 +477,7 @@ impl fold::Folder for ReplaceBodyWithLoop { e: Option>) -> P { P(ast::Block { expr: e, - view_items: vec![], stmts: vec![], rules: rules, + stmts: vec![], rules: rules, id: ast::DUMMY_NODE_ID, span: codemap::DUMMY_SP, }) } diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 05ea7094c44c..3543fe072690 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -200,6 +200,7 @@ impl<'a, 'tcx> Env<'a, 'tcx> { } return match it.node { + ast::ItemUse(..) | ast::ItemExternCrate(..) | ast::ItemConst(..) | ast::ItemStatic(..) | ast::ItemFn(..) | ast::ItemForeignMod(..) | ast::ItemTy(..) => { None diff --git a/src/librustc_llvm/diagnostic.rs b/src/librustc_llvm/diagnostic.rs index 464f9f98e7ff..db2a569cdeff 100644 --- a/src/librustc_llvm/diagnostic.rs +++ b/src/librustc_llvm/diagnostic.rs @@ -14,6 +14,7 @@ pub use self::OptimizationDiagnosticKind::*; pub use self::Diagnostic::*; use libc::c_char; +use std::ptr; use {ValueRef, TwineRef, DebugLocRef, DiagnosticInfoRef}; @@ -52,10 +53,10 @@ impl OptimizationDiagnostic { let mut opt = OptimizationDiagnostic { kind: kind, - pass_name: 0 as *const c_char, - function: 0 as ValueRef, - debug_loc: 0 as DebugLocRef, - message: 0 as TwineRef, + pass_name: ptr::null(), + function: ptr::null_mut(), + debug_loc: ptr::null_mut(), + message: ptr::null_mut(), }; super::LLVMUnpackOptimizationDiagnostic(di, diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index 18ed2987c1ce..101a0957290e 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -32,6 +32,7 @@ #![feature(libc)] #![feature(path)] #![feature(std_misc)] +#![feature(hash)] extern crate libc; #[macro_use] #[no_link] extern crate rustc_bitflags; @@ -58,7 +59,7 @@ pub use self::Linkage::*; use std::ffi::CString; use std::cell::RefCell; -use std::{raw, mem}; +use std::{raw, mem, ptr}; use libc::{c_uint, c_ushort, uint64_t, c_int, size_t, c_char}; use libc::{c_longlong, c_ulonglong, c_void}; use debuginfo::{DIBuilderRef, DIDescriptor, @@ -2267,19 +2268,18 @@ pub unsafe fn static_link_hack_this_sucks() { LLVMInitializePowerPCAsmPrinter(); LLVMInitializePowerPCAsmParser(); - LLVMRustSetLLVMOptions(0 as c_int, - 0 as *const _); + LLVMRustSetLLVMOptions(0 as c_int, ptr::null()); - LLVMPassManagerBuilderPopulateModulePassManager(0 as *mut _, 0 as *mut _); - LLVMPassManagerBuilderPopulateLTOPassManager(0 as *mut _, 0 as *mut _, False, False); - LLVMPassManagerBuilderPopulateFunctionPassManager(0 as *mut _, 0 as *mut _); - LLVMPassManagerBuilderSetOptLevel(0 as *mut _, 0 as c_uint); - LLVMPassManagerBuilderUseInlinerWithThreshold(0 as *mut _, 0 as c_uint); - LLVMWriteBitcodeToFile(0 as *mut _, 0 as *const _); + LLVMPassManagerBuilderPopulateModulePassManager(ptr::null_mut(), ptr::null_mut()); + LLVMPassManagerBuilderPopulateLTOPassManager(ptr::null_mut(), ptr::null_mut(), False, False); + LLVMPassManagerBuilderPopulateFunctionPassManager(ptr::null_mut(), ptr::null_mut()); + LLVMPassManagerBuilderSetOptLevel(ptr::null_mut(), 0 as c_uint); + LLVMPassManagerBuilderUseInlinerWithThreshold(ptr::null_mut(), 0 as c_uint); + LLVMWriteBitcodeToFile(ptr::null_mut(), ptr::null()); LLVMPassManagerBuilderCreate(); - LLVMPassManagerBuilderDispose(0 as *mut _); + LLVMPassManagerBuilderDispose(ptr::null_mut()); - LLVMRustLinkInExternalBitcode(0 as *mut _, 0 as *const _, 0 as size_t); + LLVMRustLinkInExternalBitcode(ptr::null_mut(), ptr::null(), 0 as size_t); LLVMLinkInMCJIT(); LLVMLinkInInterpreter(); diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 83ace21721b6..b6bc484bc108 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -833,6 +833,38 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> { impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> { fn visit_item(&mut self, item: &ast::Item) { + match item.node { + ast::ItemUse(ref vpath) => { + match vpath.node { + ast::ViewPathSimple(..) | ast::ViewPathGlob(..) => {} + ast::ViewPathList(ref prefix, ref list) => { + for pid in list.iter() { + match pid.node { + ast::PathListIdent { id, name } => { + debug!("privacy - ident item {}", id); + let seg = ast::PathSegment { + identifier: name, + parameters: ast::PathParameters::none(), + }; + let segs = vec![seg]; + let path = ast::Path { + global: false, + span: pid.span, + segments: segs, + }; + self.check_path(pid.span, id, &path); + } + ast::PathListMod { id } => { + debug!("privacy - mod item {}", id); + self.check_path(pid.span, id, prefix); + } + } + } + } + } + } + _ => {} + } let orig_curitem = replace(&mut self.curitem, item.id); visit::walk_item(self, item); self.curitem = orig_curitem; @@ -929,42 +961,6 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> { visit::walk_expr(self, expr); } - fn visit_view_item(&mut self, a: &ast::ViewItem) { - match a.node { - ast::ViewItemExternCrate(..) => {} - ast::ViewItemUse(ref vpath) => { - match vpath.node { - ast::ViewPathSimple(..) | ast::ViewPathGlob(..) => {} - ast::ViewPathList(ref prefix, ref list, _) => { - for pid in list.iter() { - match pid.node { - ast::PathListIdent { id, name } => { - debug!("privacy - ident item {}", id); - let seg = ast::PathSegment { - identifier: name, - parameters: ast::PathParameters::none(), - }; - let segs = vec![seg]; - let path = ast::Path { - global: false, - span: pid.span, - segments: segs, - }; - self.check_path(pid.span, id, &path); - } - ast::PathListMod { id } => { - debug!("privacy - mod item {}", id); - self.check_path(pid.span, id, prefix); - } - } - } - } - } - } - } - visit::walk_view_item(self, a); - } - fn visit_pat(&mut self, pattern: &ast::Pat) { // Foreign functions do not have their patterns mapped in the def_map, // and there's nothing really relevant there anyway, so don't bother @@ -1072,23 +1068,6 @@ impl<'a, 'tcx, 'v> Visitor<'v> for SanePrivacyVisitor<'a, 'tcx> { visit::walk_fn(self, fk, fd, b, s); self.in_fn = orig_in_fn; } - - fn visit_view_item(&mut self, i: &ast::ViewItem) { - match i.vis { - ast::Inherited => {} - ast::Public => { - if self.in_fn { - self.tcx.sess.span_err(i.span, "unnecessary `pub`, imports \ - in functions are never \ - reachable"); - } else if let ast::ViewItemExternCrate(..) = i.node { - self.tcx.sess.span_err(i.span, "`pub` visibility \ - is not allowed"); - } - } - } - visit::walk_view_item(self, i); - } } impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> { @@ -1165,7 +1144,7 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> { ast::ItemConst(..) | ast::ItemStatic(..) | ast::ItemStruct(..) | ast::ItemFn(..) | ast::ItemMod(..) | ast::ItemTy(..) | - ast::ItemMac(..) => {} + ast::ItemExternCrate(_) | ast::ItemUse(_) | ast::ItemMac(..) => {} } } @@ -1222,6 +1201,7 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> { } } + ast::ItemExternCrate(_) | ast::ItemUse(_) | ast::ItemStatic(..) | ast::ItemConst(..) | ast::ItemFn(..) | ast::ItemMod(..) | ast::ItemTy(..) | ast::ItemMac(..) => {} @@ -1524,11 +1504,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> { // we don't need to introspect into these at all: an - // expression/block context can't possibly contain exported - // things, and neither do view_items. (Making them no-ops stops us - // from traversing the whole AST without having to be super - // careful about our `walk_...` calls above.) - fn visit_view_item(&mut self, _: &ast::ViewItem) {} + // expression/block context can't possibly contain exported things. + // (Making them no-ops stops us from traversing the whole AST without + // having to be super careful about our `walk_...` calls above.) fn visit_block(&mut self, _: &ast::Block) {} fn visit_expr(&mut self, _: &ast::Expr) {} } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 21eec383df46..65bd83d7937f 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -39,9 +39,9 @@ use rustc::middle::subst::FnSpace; use syntax::ast::{Block, Crate}; use syntax::ast::{DeclItem, DefId}; use syntax::ast::{ForeignItem, ForeignItemFn, ForeignItemStatic}; -use syntax::ast::{Item, ItemConst, ItemEnum, ItemFn}; +use syntax::ast::{Item, ItemConst, ItemEnum, ItemExternCrate, ItemFn}; use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic}; -use syntax::ast::{ItemStruct, ItemTrait, ItemTy}; +use syntax::ast::{ItemStruct, ItemTrait, ItemTy, ItemUse}; use syntax::ast::{MethodImplItem, Name, NamedField, NodeId}; use syntax::ast::{PathListIdent, PathListMod}; use syntax::ast::{Public, SelfStatic}; @@ -50,8 +50,7 @@ use syntax::ast::StructVariantKind; use syntax::ast::TupleVariantKind; use syntax::ast::TyObjectSum; use syntax::ast::{TypeImplItem, UnnamedField}; -use syntax::ast::{Variant, ViewItem, ViewItemExternCrate}; -use syntax::ast::{ViewItemUse, ViewPathGlob, ViewPathList, ViewPathSimple}; +use syntax::ast::{Variant, ViewPathGlob, ViewPathList, ViewPathSimple}; use syntax::ast::{Visibility}; use syntax::ast::TyPath; use syntax::ast; @@ -238,11 +237,6 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { } fn block_needs_anonymous_module(&mut self, block: &Block) -> bool { - // If the block has view items, we need an anonymous module. - if block.view_items.len() > 0 { - return true; - } - // Check each statement. for statement in block.stmts.iter() { match statement.node { @@ -262,7 +256,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { } } - // If we found neither view items nor items, we don't need to create + // If we found no items, we don't need to create // an anonymous module. return false; @@ -280,6 +274,133 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE; match item.node { + ItemUse(ref view_path) => { + // Extract and intern the module part of the path. For + // globs and lists, the path is found directly in the AST; + // for simple paths we have to munge the path a little. + let module_path = match view_path.node { + ViewPathSimple(_, ref full_path) => { + full_path.segments + .init() + .iter().map(|ident| ident.identifier.name) + .collect() + } + + ViewPathGlob(ref module_ident_path) | + ViewPathList(ref module_ident_path, _) => { + module_ident_path.segments + .iter().map(|ident| ident.identifier.name).collect() + } + }; + + // Build up the import directives. + let shadowable = item.attrs.iter().any(|attr| { + attr.name() == token::get_name(special_idents::prelude_import.name) + }); + let shadowable = if shadowable { + Shadowable::Always + } else { + Shadowable::Never + }; + + match view_path.node { + ViewPathSimple(binding, ref full_path) => { + let source_name = + full_path.segments.last().unwrap().identifier.name; + if token::get_name(source_name).get() == "mod" || + token::get_name(source_name).get() == "self" { + self.resolve_error(view_path.span, + "`self` imports are only allowed within a { } list"); + } + + let subclass = SingleImport(binding.name, + source_name); + self.build_import_directive(&**parent, + module_path, + subclass, + view_path.span, + item.id, + is_public, + shadowable); + } + ViewPathList(_, ref source_items) => { + // Make sure there's at most one `mod` import in the list. + let mod_spans = source_items.iter().filter_map(|item| match item.node { + PathListMod { .. } => Some(item.span), + _ => None + }).collect::>(); + if mod_spans.len() > 1 { + self.resolve_error(mod_spans[0], + "`self` import can only appear once in the list"); + for other_span in mod_spans.iter().skip(1) { + self.session.span_note(*other_span, + "another `self` import appears here"); + } + } + + for source_item in source_items.iter() { + let (module_path, name) = match source_item.node { + PathListIdent { name, .. } => + (module_path.clone(), name.name), + PathListMod { .. } => { + let name = match module_path.last() { + Some(name) => *name, + None => { + self.resolve_error(source_item.span, + "`self` import can only appear in an import list \ + with a non-empty prefix"); + continue; + } + }; + let module_path = module_path.init(); + (module_path.to_vec(), name) + } + }; + self.build_import_directive( + &**parent, + module_path, + SingleImport(name, name), + source_item.span, + source_item.node.id(), + is_public, + shadowable); + } + } + ViewPathGlob(_) => { + self.build_import_directive(&**parent, + module_path, + GlobImport, + view_path.span, + item.id, + is_public, + shadowable); + } + } + parent.clone() + } + + ItemExternCrate(_) => { + // n.b. we don't need to look at the path option here, because cstore already did + for &crate_id in self.session.cstore + .find_extern_mod_stmt_cnum(item.id).iter() { + let def_id = DefId { krate: crate_id, node: 0 }; + self.external_exports.insert(def_id); + let parent_link = ModuleParentLink(parent.downgrade(), name); + let external_module = Rc::new(Module::new(parent_link, + Some(def_id), + NormalModuleKind, + false, + true)); + debug!("(build reduced graph for item) found extern `{}`", + self.module_to_string(&*external_module)); + self.check_for_conflicts_between_external_crates(&**parent, name, sp); + parent.external_module_children.borrow_mut() + .insert(name, external_module.clone()); + self.build_reduced_graph_for_external_crate(&external_module); + } + parent.clone() + } + ItemMod(..) => { let name_bindings = self.add_child(name, parent, ForbidDuplicateModules, sp); @@ -650,145 +771,6 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { variant.span, PUBLIC | IMPORTABLE); } - /// Constructs the reduced graph for one 'view item'. View items consist - /// of imports and use directives. - fn build_reduced_graph_for_view_item(&mut self, view_item: &ViewItem, parent: &Rc) { - match view_item.node { - ViewItemUse(ref view_path) => { - // Extract and intern the module part of the path. For - // globs and lists, the path is found directly in the AST; - // for simple paths we have to munge the path a little. - let module_path = match view_path.node { - ViewPathSimple(_, ref full_path, _) => { - full_path.segments - .init() - .iter().map(|ident| ident.identifier.name) - .collect() - } - - ViewPathGlob(ref module_ident_path, _) | - ViewPathList(ref module_ident_path, _, _) => { - module_ident_path.segments - .iter().map(|ident| ident.identifier.name).collect() - } - }; - - // Build up the import directives. - let is_public = view_item.vis == ast::Public; - let shadowable = - view_item.attrs - .iter() - .any(|attr| { - attr.name() == token::get_name( - special_idents::prelude_import.name) - }); - let shadowable = if shadowable { - Shadowable::Always - } else { - Shadowable::Never - }; - - match view_path.node { - ViewPathSimple(binding, ref full_path, id) => { - let source_name = - full_path.segments.last().unwrap().identifier.name; - if token::get_name(source_name).get() == "mod" || - token::get_name(source_name).get() == "self" { - self.resolve_error(view_path.span, - "`self` imports are only allowed within a { } list"); - } - - let subclass = SingleImport(binding.name, - source_name); - self.build_import_directive(&**parent, - module_path, - subclass, - view_path.span, - id, - is_public, - shadowable); - } - ViewPathList(_, ref source_items, _) => { - // Make sure there's at most one `mod` import in the list. - let mod_spans = source_items.iter().filter_map(|item| match item.node { - PathListMod { .. } => Some(item.span), - _ => None - }).collect::>(); - if mod_spans.len() > 1 { - self.resolve_error(mod_spans[0], - "`self` import can only appear once in the list"); - for other_span in mod_spans.iter().skip(1) { - self.session.span_note(*other_span, - "another `self` import appears here"); - } - } - - for source_item in source_items.iter() { - let (module_path, name) = match source_item.node { - PathListIdent { name, .. } => - (module_path.clone(), name.name), - PathListMod { .. } => { - let name = match module_path.last() { - Some(name) => *name, - None => { - self.resolve_error(source_item.span, - "`self` import can only appear in an import list \ - with a non-empty prefix"); - continue; - } - }; - let module_path = module_path.init(); - (module_path.to_vec(), name) - } - }; - self.build_import_directive( - &**parent, - module_path, - SingleImport(name, name), - source_item.span, - source_item.node.id(), - is_public, - shadowable); - } - } - ViewPathGlob(_, id) => { - self.build_import_directive(&**parent, - module_path, - GlobImport, - view_path.span, - id, - is_public, - shadowable); - } - } - } - - ViewItemExternCrate(name, _, node_id) => { - // n.b. we don't need to look at the path option here, because cstore already did - for &crate_id in self.session.cstore - .find_extern_mod_stmt_cnum(node_id).iter() { - let def_id = DefId { krate: crate_id, node: 0 }; - self.external_exports.insert(def_id); - let parent_link = ModuleParentLink(parent.downgrade(), name.name); - let external_module = Rc::new(Module::new(parent_link, - Some(def_id), - NormalModuleKind, - false, - true)); - debug!("(build reduced graph for item) found extern `{}`", - self.module_to_string(&*external_module)); - self.check_for_conflicts_between_external_crates( - &**parent, - name.name, - view_item.span); - parent.external_module_children.borrow_mut() - .insert(name.name, external_module.clone()); - self.build_reduced_graph_for_external_crate(&external_module); - } - } - } - } - /// Constructs the reduced graph for one foreign item. fn build_reduced_graph_for_foreign_item(&mut self, foreign_item: &ForeignItem, @@ -1270,10 +1252,6 @@ impl<'a, 'b, 'v, 'tcx> Visitor<'v> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { }) } - fn visit_view_item(&mut self, view_item: &ViewItem) { - self.builder.build_reduced_graph_for_view_item(view_item, &self.parent); - } - fn visit_block(&mut self, block: &Block) { let np = self.builder.build_reduced_graph_for_block(block, &self.parent); let old_parent = replace(&mut self.parent, np); diff --git a/src/librustc_resolve/check_unused.rs b/src/librustc_resolve/check_unused.rs index 18066a7b94bd..97370112ab40 100644 --- a/src/librustc_resolve/check_unused.rs +++ b/src/librustc_resolve/check_unused.rs @@ -25,7 +25,6 @@ use Namespace::{TypeNS, ValueNS}; use rustc::lint; use rustc::middle::privacy::{DependsOn, LastImport, Used, Unused}; use syntax::ast; -use syntax::ast::{ViewItem, ViewItemExternCrate, ViewItemUse}; use syntax::ast::{ViewPathGlob, ViewPathList, ViewPathSimple}; use syntax::codemap::{Span, DUMMY_SP}; use syntax::visit::{self, Visitor}; @@ -109,53 +108,54 @@ impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> { } impl<'a, 'b, 'v, 'tcx> Visitor<'v> for UnusedImportCheckVisitor<'a, 'b, 'tcx> { - fn visit_view_item(&mut self, vi: &ViewItem) { + fn visit_item(&mut self, item: &ast::Item) { // Ignore is_public import statements because there's no way to be sure // whether they're used or not. Also ignore imports with a dummy span // because this means that they were generated in some fashion by the // compiler and we don't need to consider them. - if vi.vis == ast::Public || vi.span == DUMMY_SP { - visit::walk_view_item(self, vi); + if item.vis == ast::Public || item.span == DUMMY_SP { + visit::walk_item(self, item); return; } - match vi.node { - ViewItemExternCrate(_, _, id) => { - if let Some(crate_num) = self.session.cstore.find_extern_mod_stmt_cnum(id) { + match item.node { + ast::ItemExternCrate(_) => { + if let Some(crate_num) = self.session.cstore.find_extern_mod_stmt_cnum(item.id) { if !self.used_crates.contains(&crate_num) { self.session.add_lint(lint::builtin::UNUSED_EXTERN_CRATES, - id, - vi.span, + item.id, + item.span, "unused extern crate".to_string()); } } }, - ViewItemUse(ref p) => { + ast::ItemUse(ref p) => { match p.node { - ViewPathSimple(_, _, id) => { - self.finalize_import(id, p.span) + ViewPathSimple(_, _) => { + self.finalize_import(item.id, p.span) } - ViewPathList(_, ref list, _) => { + ViewPathList(_, ref list) => { for i in list.iter() { self.finalize_import(i.node.id(), i.span); } } - ViewPathGlob(_, id) => { - if !self.used_imports.contains(&(id, TypeNS)) && - !self.used_imports.contains(&(id, ValueNS)) { + ViewPathGlob(_) => { + if !self.used_imports.contains(&(item.id, TypeNS)) && + !self.used_imports.contains(&(item.id, ValueNS)) { self.session .add_lint(lint::builtin::UNUSED_IMPORTS, - id, + item.id, p.span, "unused import".to_string()); } } } } + _ => {} } - visit::walk_view_item(self, vi); + visit::walk_item(self, item); } } diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs new file mode 100644 index 000000000000..dd9ccfbda7ca --- /dev/null +++ b/src/librustc_resolve/diagnostics.rs @@ -0,0 +1,29 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(non_snake_case)] + +register_diagnostics! { + E0154, + E0157, + E0153, + E0251, // a named type or value has already been imported in this module + E0252, // a named type or value has already been imported in this module + E0253, // not directly importable + E0254, // import conflicts with imported crate in this module + E0255, // import conflicts with value in this module + E0256, // import conflicts with type in this module + E0257, // inherent implementations are only allowen on types defined in the current module + E0258, // import conflicts with existing submodule + E0259, // an extern crate has already been imported into this module + E0260 // name conflicts with an external crate that has been imported into this module +} + +__build_diagnostic_array! { DIAGNOSTICS } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index a2e72fa1c557..affd2b541358 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -26,6 +26,7 @@ #![feature(core)] #![feature(rustc_private)] #![feature(std_misc)] +#![feature(hash)] #[macro_use] extern crate log; #[macro_use] extern crate syntax; @@ -70,10 +71,10 @@ use syntax::ast::{DefId, Expr, ExprAgain, ExprBreak, ExprField}; use syntax::ast::{ExprClosure, ExprForLoop, ExprLoop, ExprWhile, ExprMethodCall}; use syntax::ast::{ExprPath, ExprQPath, ExprStruct, FnDecl}; use syntax::ast::{ForeignItemFn, ForeignItemStatic, Generics}; -use syntax::ast::{Ident, ImplItem, Item, ItemConst, ItemEnum, ItemFn}; -use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic}; -use syntax::ast::{ItemStruct, ItemTrait, ItemTy, Local, LOCAL_CRATE}; -use syntax::ast::{MethodImplItem, Mod, Name, NodeId}; +use syntax::ast::{Ident, ImplItem, Item, ItemConst, ItemEnum, ItemExternCrate}; +use syntax::ast::{ItemFn, ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic}; +use syntax::ast::{ItemStruct, ItemTrait, ItemTy, ItemUse}; +use syntax::ast::{Local, MethodImplItem, Mod, Name, NodeId}; use syntax::ast::{Pat, PatEnum, PatIdent, PatLit}; use syntax::ast::{PatRange, PatStruct, Path}; use syntax::ast::{PolyTraitRef, PrimTy, SelfExplicit}; @@ -102,6 +103,10 @@ use std::mem::replace; use std::rc::{Rc, Weak}; use std::uint; +// NB: This module needs to be declared first so diagnostics are +// registered before they are used. +pub mod diagnostics; + mod check_unused; mod record_exports; mod build_reduced_graph; @@ -541,7 +546,7 @@ impl Module { } } -impl fmt::Show for Module { +impl fmt::Debug for Module { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{:?}, kind: {:?}, {}", self.def_id, @@ -1144,7 +1149,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } fn get_trait_name(&self, did: DefId) -> Name { - if did.krate == LOCAL_CRATE { + if did.krate == ast::LOCAL_CRATE { self.ast_map.expect_item(did.node).ident.name } else { csearch::get_trait_name(&self.session.cstore, did) @@ -1723,7 +1728,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { in this module", namespace_name, token::get_name(name).get()); - self.session.span_err(import_directive.span, msg.as_slice()); + span_err!(self.session, import_directive.span, E0251, "{}", msg.as_slice()); } else { let target = Target::new(containing_module.clone(), name_bindings.clone(), @@ -1753,10 +1758,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { import_span: Span, name: Name, namespace: Namespace) { - if self.session.features.borrow().import_shadowing { - return - } - debug!("check_for_conflicting_import: {}; target exists: {}", token::get_name(name).get(), target.is_some()); @@ -1770,7 +1771,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ValueNS => "value", }, token::get_name(name).get()); - self.session.span_err(import_span, &msg[]); + span_err!(self.session, import_span, E0252, "{}", &msg[]); } Some(_) | None => {} } @@ -1785,7 +1786,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if !name_bindings.defined_in_namespace_with(namespace, IMPORTABLE) { let msg = format!("`{}` is not directly importable", token::get_name(name)); - self.session.span_err(import_span, &msg[]); + span_err!(self.session, import_span, E0253, "{}", &msg[]); } } @@ -1796,10 +1797,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &ImportResolution, import_span: Span, name: Name) { - if self.session.features.borrow().import_shadowing { - return - } - // First, check for conflicts between imports and `extern crate`s. if module.external_module_children .borrow() @@ -1810,7 +1807,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { crate in this module \ (maybe you meant `use {0}::*`?)", token::get_name(name).get()); - self.session.span_err(import_span, &msg[]); + span_err!(self.session, import_span, E0254, "{}", &msg[]); } Some(_) | None => {} } @@ -1832,7 +1829,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let msg = format!("import `{}` conflicts with value \ in this module", token::get_name(name).get()); - self.session.span_err(import_span, &msg[]); + span_err!(self.session, import_span, E0255, "{}", &msg[]); if let Some(span) = value.value_span { self.session.span_note(span, "conflicting value here"); @@ -1850,7 +1847,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let msg = format!("import `{}` conflicts with type in \ this module", token::get_name(name).get()); - self.session.span_err(import_span, &msg[]); + span_err!(self.session, import_span, E0256, "{}", &msg[]); if let Some(span) = ty.type_span { self.session.span_note(span, "note conflicting type here") @@ -1863,7 +1860,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let msg = format!("inherent implementations \ are only allowed on types \ defined in the current module"); - self.session.span_err(span, &msg[]); + span_err!(self.session, span, E0257, "{}", &msg[]); self.session.span_note(import_span, "import from other module here") } @@ -1872,7 +1869,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let msg = format!("import `{}` conflicts with existing \ submodule", token::get_name(name).get()); - self.session.span_err(import_span, &msg[]); + span_err!(self.session, import_span, E0258, "{}", &msg[]); if let Some(span) = ty.type_span { self.session.span_note(span, "note conflicting module here") @@ -1893,16 +1890,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { module: &Module, name: Name, span: Span) { - if self.session.features.borrow().import_shadowing { - return - } - if module.external_module_children.borrow().contains_key(&name) { - self.session - .span_err(span, - &format!("an external crate named `{}` has already \ + span_err!(self.session, span, E0259, + "an external crate named `{}` has already \ been imported into this module", - token::get_name(name).get())[]); + token::get_name(name).get()); } } @@ -1911,17 +1903,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { module: &Module, name: Name, span: Span) { - if self.session.features.borrow().import_shadowing { - return - } - if module.external_module_children.borrow().contains_key(&name) { - self.session - .span_err(span, - &format!("the name `{}` conflicts with an external \ + span_err!(self.session, span, E0260, + "the name `{}` conflicts with an external \ crate that has been imported into this \ module", - token::get_name(name).get())[]); + token::get_name(name).get()); } } @@ -1970,7 +1957,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let module_name = self.module_to_string(&*search_module); let mut span = span; let msg = if "???" == &module_name[] { - span.hi = span.lo + Pos::from_uint(segment_name.get().len()); + span.hi = span.lo + Pos::from_usize(segment_name.get().len()); match search_parent_externals(name, &self.current_module) { @@ -2088,8 +2075,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let msg = format!("Could not find `{}` in `{}`", // idx +- 1 to account for the // colons on either side - &mpath[(idx + 1)..], - &mpath[..(idx - 1)]); + &mpath[idx + 1..], + &mpath[..idx - 1]); return Failed(Some((span, msg))); }, None => { @@ -2765,7 +2752,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { for (i, rib) in ribs.iter().enumerate().rev() { match rib.bindings.get(&name).cloned() { Some(def_like) => { - return self.upvarify(&ribs[(i + 1)..], def_like, span); + return self.upvarify(&ribs[i + 1..], def_like, span); } None => { // Continue. @@ -2987,9 +2974,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { }); } - ItemMac(..) => { + ItemExternCrate(_) | ItemUse(_) | ItemMac(..) => { // do nothing, these are just around to be encoded - } + } } } @@ -3530,6 +3517,26 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } + // Check for imports appearing after non-item statements. + let mut found_non_item = false; + for statement in block.stmts.iter() { + if let ast::StmtDecl(ref declaration, _) = statement.node { + if let ast::DeclItem(ref i) = declaration.node { + match i.node { + ItemExternCrate(_) | ItemUse(_) if found_non_item => { + span_err!(self.session, i.span, E0154, + "imports are not allowed after non-item statements"); + } + _ => {} + } + } else { + found_non_item = true + } + } else { + found_non_item = true; + } + } + // Descend into the block. visit::walk_block(self, block); diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index dacf620cbd1d..eedfc9407515 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -178,7 +178,7 @@ pub fn build_link_meta(sess: &Session, krate: &ast::Crate, fn truncated_hash_result(symbol_hasher: &mut Sha256) -> String { let output = symbol_hasher.result_bytes(); // 64 bits should be enough to avoid collisions. - output.slice_to(8).to_hex().to_string() + output[.. 8].to_hex().to_string() } @@ -779,14 +779,14 @@ fn link_natively(sess: &Session, trans: &CrateTranslation, dylib: bool, } if sess.opts.debugging_opts.print_link_args { - println!("{}", &cmd); + println!("{:?}", &cmd); } // May have not found libraries in the right formats. sess.abort_if_errors(); // Invoke the system linker - debug!("{}", &cmd); + debug!("{:?}", &cmd); let prog = time(sess.time_passes(), "running linker", (), |()| cmd.output()); match prog { Ok(prog) => { @@ -794,7 +794,7 @@ fn link_natively(sess: &Session, trans: &CrateTranslation, dylib: bool, sess.err(&format!("linking with `{}` failed: {}", pname, prog.status)[]); - sess.note(&format!("{}", &cmd)[]); + sess.note(&format!("{:?}", &cmd)[]); let mut output = prog.error.clone(); output.push_all(&prog.output[]); sess.note(str::from_utf8(&output[]).unwrap()); @@ -1183,7 +1183,7 @@ fn add_upstream_rust_crates(cmd: &mut Command, sess: &Session, // against the archive. if sess.lto() { let name = cratepath.filename_str().unwrap(); - let name = &name[3..(name.len() - 5)]; // chop off lib/.rlib + let name = &name[3..name.len() - 5]; // chop off lib/.rlib time(sess.time_passes(), &format!("altering {}.rlib", name)[], (), |()| { diff --git a/src/librustc_trans/back/lto.rs b/src/librustc_trans/back/lto.rs index c0b1492a7845..590354ab54e0 100644 --- a/src/librustc_trans/back/lto.rs +++ b/src/librustc_trans/back/lto.rs @@ -60,7 +60,7 @@ pub fn run(sess: &session::Session, llmod: ModuleRef, let archive = ArchiveRO::open(&path).expect("wanted an rlib"); let file = path.filename_str().unwrap(); - let file = &file[3..(file.len() - 5)]; // chop off lib/.rlib + let file = &file[3..file.len() - 5]; // chop off lib/.rlib debug!("reading {}", file); for i in iter::count(0u, 1) { let bc_encoded = time(sess.time_passes(), @@ -201,7 +201,7 @@ fn extract_compressed_bytecode_size_v1(bc: &[u8]) -> u64 { } fn read_from_le_bytes(bytes: &[u8], position_in_bytes: uint) -> T { - let byte_data = &bytes[position_in_bytes..(position_in_bytes + mem::size_of::())]; + let byte_data = &bytes[position_in_bytes..position_in_bytes + mem::size_of::()]; let data = unsafe { *(byte_data.as_ptr() as *const T) }; diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index aa51b0c5ee24..b07c2060e692 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -67,11 +67,11 @@ pub fn write_output_file( output: &Path, file_type: llvm::FileType) { unsafe { - let output = CString::from_slice(output.as_vec()); + let output_c = CString::from_slice(output.as_vec()); let result = llvm::LLVMRustWriteOutputFile( - target, pm, m, output.as_ptr(), file_type); + target, pm, m, output_c.as_ptr(), file_type); if !result { - llvm_err(handler, "could not write output".to_string()); + llvm_err(handler, format!("could not write output to {}", output.display())); } } } @@ -716,7 +716,7 @@ pub fn run_passes(sess: &Session, cmd.args(&sess.target.target.options.post_link_args[]); if sess.opts.debugging_opts.print_link_args { - println!("{}", &cmd); + println!("{:?}", &cmd); } cmd.stdin(::std::io::process::Ignored) @@ -725,7 +725,7 @@ pub fn run_passes(sess: &Session, match cmd.status() { Ok(status) => { if !status.success() { - sess.err(&format!("linking of {} with `{}` failed", + sess.err(&format!("linking of {} with `{:?}` failed", output_path.display(), cmd)[]); sess.abort_if_errors(); } @@ -953,7 +953,7 @@ pub fn run_assembler(sess: &Session, outputs: &OutputFilenames) { cmd.arg("-c").arg("-o").arg(outputs.path(config::OutputTypeObject)) .arg(outputs.temp_path(config::OutputTypeAssembly)); - debug!("{}", &cmd); + debug!("{:?}", &cmd); match cmd.output() { Ok(prog) => { @@ -961,7 +961,7 @@ pub fn run_assembler(sess: &Session, outputs: &OutputFilenames) { sess.err(&format!("linking with `{}` failed: {}", pname, prog.status)[]); - sess.note(&format!("{}", &cmd)[]); + sess.note(&format!("{:?}", &cmd)[]); let mut note = prog.error.clone(); note.push_all(&prog.output[]); sess.note(str::from_utf8(¬e[]).unwrap()); diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs index b12903c814cb..4aec53711ad8 100644 --- a/src/librustc_trans/save/mod.rs +++ b/src/librustc_trans/save/mod.rs @@ -157,7 +157,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { return; } - let sub_paths = sub_paths.slice(0, len-1); + let sub_paths = &sub_paths[.. (len-1)]; for &(ref span, ref qualname) in sub_paths.iter() { self.fmt.sub_mod_ref_str(path.span, *span, @@ -174,7 +174,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { if len <= 1 { return; } - let sub_paths = sub_paths.slice_to(len-1); + let sub_paths = &sub_paths[.. (len-1)]; // write the trait part of the sub-path let (ref span, ref qualname) = sub_paths[len-2]; @@ -186,7 +186,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { if len <= 2 { return; } - let sub_paths = &sub_paths[..(len-2)]; + let sub_paths = &sub_paths[..len-2]; for &(ref span, ref qualname) in sub_paths.iter() { self.fmt.sub_mod_ref_str(path.span, *span, @@ -1037,6 +1037,110 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> { } match item.node { + ast::ItemUse(ref use_item) => { + match use_item.node { + ast::ViewPathSimple(ident, ref path) => { + let sub_span = self.span.span_for_last_ident(path.span); + let mod_id = match self.lookup_type_ref(item.id) { + Some(def_id) => { + match self.lookup_def_kind(item.id, path.span) { + Some(kind) => self.fmt.ref_str(kind, + path.span, + sub_span, + def_id, + self.cur_scope), + None => {}, + } + Some(def_id) + }, + None => None, + }; + + // 'use' always introduces an alias, if there is not an explicit + // one, there is an implicit one. + let sub_span = + match self.span.sub_span_after_keyword(use_item.span, keywords::As) { + Some(sub_span) => Some(sub_span), + None => sub_span, + }; + + self.fmt.use_alias_str(path.span, + sub_span, + item.id, + mod_id, + get_ident(ident).get(), + self.cur_scope); + self.write_sub_paths_truncated(path); + } + ast::ViewPathGlob(ref path) => { + // Make a comma-separated list of names of imported modules. + let mut name_string = String::new(); + let glob_map = &self.analysis.glob_map; + let glob_map = glob_map.as_ref().unwrap(); + if glob_map.contains_key(&item.id) { + for n in glob_map[item.id].iter() { + if name_string.len() > 0 { + name_string.push_str(", "); + } + name_string.push_str(n.as_str()); + } + } + + let sub_span = self.span.sub_span_of_token(path.span, + token::BinOp(token::Star)); + self.fmt.use_glob_str(path.span, + sub_span, + item.id, + name_string.as_slice(), + self.cur_scope); + self.write_sub_paths(path); + } + ast::ViewPathList(ref path, ref list) => { + for plid in list.iter() { + match plid.node { + ast::PathListIdent { id, .. } => { + match self.lookup_type_ref(id) { + Some(def_id) => + match self.lookup_def_kind(id, plid.span) { + Some(kind) => { + self.fmt.ref_str( + kind, plid.span, + Some(plid.span), + def_id, self.cur_scope); + } + None => () + }, + None => () + } + }, + ast::PathListMod { .. } => () + } + } + + self.write_sub_paths(path); + } + } + } + ast::ItemExternCrate(ref s) => { + let name = get_ident(item.ident); + let name = name.get(); + let s = match *s { + Some((ref s, _)) => s.get().to_string(), + None => name.to_string(), + }; + let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Crate); + let cnum = match self.sess.cstore.find_extern_mod_stmt_cnum(item.id) { + Some(cnum) => cnum, + None => 0, + }; + self.fmt.extern_crate_str(item.span, + sub_span, + item.id, + cnum, + name, + &s[], + self.cur_scope); + } ast::ItemFn(ref decl, _, _, ref ty_params, ref body) => self.process_fn(item, &**decl, ty_params, &**body), ast::ItemStatic(ref typ, mt, ref expr) => @@ -1160,119 +1264,6 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> { } } - fn visit_view_item(&mut self, i: &ast::ViewItem) { - if generated_code(i.span) { - return - } - - match i.node { - ast::ViewItemUse(ref item) => { - match item.node { - ast::ViewPathSimple(ident, ref path, id) => { - let sub_span = self.span.span_for_last_ident(path.span); - let mod_id = match self.lookup_type_ref(id) { - Some(def_id) => { - match self.lookup_def_kind(id, path.span) { - Some(kind) => self.fmt.ref_str(kind, - path.span, - sub_span, - def_id, - self.cur_scope), - None => {}, - } - Some(def_id) - }, - None => None, - }; - - // 'use' always introduces an alias, if there is not an explicit - // one, there is an implicit one. - let sub_span = - match self.span.sub_span_after_keyword(item.span, keywords::As) { - Some(sub_span) => Some(sub_span), - None => sub_span, - }; - - self.fmt.use_alias_str(path.span, - sub_span, - id, - mod_id, - get_ident(ident).get(), - self.cur_scope); - self.write_sub_paths_truncated(path); - } - ast::ViewPathGlob(ref path, id) => { - // Make a comma-separated list of names of imported modules. - let mut name_string = String::new(); - let glob_map = &self.analysis.glob_map; - let glob_map = glob_map.as_ref().unwrap(); - if glob_map.contains_key(&id) { - for n in glob_map[id].iter() { - if name_string.len() > 0 { - name_string.push_str(", "); - } - name_string.push_str(n.as_str()); - } - } - - let sub_span = self.span.sub_span_of_token(path.span, - token::BinOp(token::Star)); - self.fmt.use_glob_str(path.span, - sub_span, - id, - name_string.as_slice(), - self.cur_scope); - self.write_sub_paths(path); - } - ast::ViewPathList(ref path, ref list, _) => { - for plid in list.iter() { - match plid.node { - ast::PathListIdent { id, .. } => { - match self.lookup_type_ref(id) { - Some(def_id) => - match self.lookup_def_kind(id, plid.span) { - Some(kind) => { - self.fmt.ref_str( - kind, plid.span, - Some(plid.span), - def_id, self.cur_scope); - } - None => () - }, - None => () - } - }, - ast::PathListMod { .. } => () - } - } - - self.write_sub_paths(path); - } - } - }, - ast::ViewItemExternCrate(ident, ref s, id) => { - let name = get_ident(ident); - let name = name.get(); - let s = match *s { - Some((ref s, _)) => s.get().to_string(), - None => name.to_string(), - }; - let sub_span = self.span.sub_span_after_keyword(i.span, keywords::Crate); - let cnum = match self.sess.cstore.find_extern_mod_stmt_cnum(id) { - Some(cnum) => cnum, - None => 0, - }; - self.fmt.extern_crate_str(i.span, - sub_span, - id, - cnum, - name, - &s[], - self.cur_scope); - }, - } - } - fn visit_ty(&mut self, t: &ast::Ty) { if generated_code(t.span) { return diff --git a/src/librustc_trans/save/span_utils.rs b/src/librustc_trans/save/span_utils.rs index 77343612ac88..97b3cda006bf 100644 --- a/src/librustc_trans/save/span_utils.rs +++ b/src/librustc_trans/save/span_utils.rs @@ -40,8 +40,8 @@ impl<'a> SpanUtils<'a> { format!("file_name,{},file_line,{},file_col,{},extent_start,{},extent_start_bytes,{},\ file_line_end,{},file_col_end,{},extent_end,{},extent_end_bytes,{}", lo_loc.file.name, - lo_loc.line, lo_loc.col.to_uint(), lo_pos.to_uint(), lo_pos_byte.to_uint(), - hi_loc.line, hi_loc.col.to_uint(), hi_pos.to_uint(), hi_pos_byte.to_uint()) + lo_loc.line, lo_loc.col.to_usize(), lo_pos.to_usize(), lo_pos_byte.to_usize(), + hi_loc.line, hi_loc.col.to_usize(), hi_pos.to_usize(), hi_pos_byte.to_usize()) } // sub_span starts at span.lo, so we need to adjust the positions etc. diff --git a/src/librustc_trans/trans/_match.rs b/src/librustc_trans/trans/_match.rs index 9f3c55d4f687..dcb0b0ef4ea3 100644 --- a/src/librustc_trans/trans/_match.rs +++ b/src/librustc_trans/trans/_match.rs @@ -208,10 +208,10 @@ use trans::cleanup::{self, CleanupMethods}; use trans::common::*; use trans::consts; use trans::datum::*; +use trans::debuginfo::{self, DebugLoc, ToDebugLoc}; use trans::expr::{self, Dest}; use trans::tvec; use trans::type_of; -use trans::debuginfo; use middle::ty::{self, Ty}; use session::config::FullDebugInfo; use util::common::indenter; @@ -472,7 +472,7 @@ fn enter_default<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, enter_match(bcx, dm, m, col, val, |pats| { if pat_is_binding_or_wild(dm, &*pats[col]) { let mut r = pats[..col].to_vec(); - r.push_all(&pats[(col + 1)..]); + r.push_all(&pats[col + 1..]); Some(r) } else { None @@ -632,7 +632,7 @@ fn bind_subslice_pat(bcx: Block, let slice_begin = InBoundsGEP(bcx, base, &[C_uint(bcx.ccx(), offset_left)]); let slice_len_offset = C_uint(bcx.ccx(), offset_left + offset_right); - let slice_len = Sub(bcx, len, slice_len_offset); + let slice_len = Sub(bcx, len, slice_len_offset, DebugLoc::None); let slice_ty = ty::mk_slice(bcx.tcx(), bcx.tcx().mk_region(ty::ReStatic), ty::mt {ty: vt.unit_ty, mutbl: ast::MutImmutable}); @@ -656,7 +656,7 @@ fn extract_vec_elems<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, elems.extend(range(0, before).map(|i| GEPi(bcx, base, &[i]))); elems.extend(range(0, after).rev().map(|i| { InBoundsGEP(bcx, base, &[ - Sub(bcx, len, C_uint(bcx.ccx(), i + 1)) + Sub(bcx, len, C_uint(bcx.ccx(), i + 1), DebugLoc::None) ]) })); ExtractedBlock { vals: elems, bcx: bcx } @@ -731,7 +731,7 @@ impl FailureHandler { Infallible => panic!("attempted to panic in a non-panicking panic handler!"), JumpToBasicBlock(basic_block) => - Br(bcx, basic_block), + Br(bcx, basic_block, DebugLoc::None), Unreachable => build::Unreachable(bcx) } @@ -889,7 +889,7 @@ fn compile_guard<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } } - with_cond(bcx, Not(bcx, val), |bcx| { + with_cond(bcx, Not(bcx, val, guard_expr.debug_loc()), |bcx| { // Guard does not match: remove all bindings from the lllocals table for (_, &binding_info) in data.bindings_map.iter() { call_lifetime_end(bcx, binding_info.llmatch); @@ -966,7 +966,7 @@ fn compile_submatch<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } _ => () } - Br(bcx, data.bodycx.llbb); + Br(bcx, data.bodycx.llbb, DebugLoc::None); } } } @@ -983,7 +983,7 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, let dm = &tcx.def_map; let mut vals_left = vals[0u..col].to_vec(); - vals_left.push_all(&vals[(col + 1u)..]); + vals_left.push_all(&vals[col + 1u..]); let ccx = bcx.fcx.ccx; // Find a real id (we're adding placeholder wildcard patterns, but @@ -1096,7 +1096,7 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, if !exhaustive || i + 1 < len { opt_cx = bcx.fcx.new_temp_block("match_case"); match kind { - Single => Br(bcx, opt_cx.llbb), + Single => Br(bcx, opt_cx.llbb, DebugLoc::None), Switch => { match opt.trans(bcx) { SingleResult(r) => { @@ -1131,7 +1131,7 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, compare_scalar_types( bcx, test_val, vend, t, ast::BiLe); - Result::new(bcx, And(bcx, llge, llle)) + Result::new(bcx, And(bcx, llge, llle, DebugLoc::None)) } LowerBound(Result { bcx, val }) => { compare_scalar_types(bcx, test_val, val, t, ast::BiGe) @@ -1149,12 +1149,12 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, if i + 1 < len && (guarded || multi_pats || kind == CompareSliceLength) { branch_chk = Some(JumpToBasicBlock(bcx.llbb)); } - CondBr(after_cx, matches, opt_cx.llbb, bcx.llbb); + CondBr(after_cx, matches, opt_cx.llbb, bcx.llbb, DebugLoc::None); } _ => () } } else if kind == Compare || kind == CompareSliceLength { - Br(bcx, else_cx.llbb); + Br(bcx, else_cx.llbb, DebugLoc::None); } let mut size = 0u; @@ -1194,7 +1194,7 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, // Compile the fall-through case, if any if !exhaustive && kind != Single { if kind == Compare || kind == CompareSliceLength { - Br(bcx, else_cx.llbb); + Br(bcx, else_cx.llbb, DebugLoc::None); } match chk { // If there is only one default arm left, move on to the next diff --git a/src/librustc_trans/trans/adt.rs b/src/librustc_trans/trans/adt.rs index 92883371ec9d..c98515cff685 100644 --- a/src/librustc_trans/trans/adt.rs +++ b/src/librustc_trans/trans/adt.rs @@ -62,6 +62,7 @@ use trans::cleanup; use trans::cleanup::CleanupMethods; use trans::common::*; use trans::datum; +use trans::debuginfo::DebugLoc; use trans::machine; use trans::monomorphize; use trans::type_::Type; @@ -979,7 +980,7 @@ pub fn fold_variants<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, let variant_value = PointerCast(variant_cx, value, real_ty.ptr_to()); variant_cx = f(variant_cx, case, variant_value); - Br(variant_cx, bcx_next.llbb); + Br(variant_cx, bcx_next.llbb, DebugLoc::None); } bcx_next diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index eed61ae59a25..572dfd165eed 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -57,7 +57,7 @@ use trans::closure; use trans::common::{Block, C_bool, C_bytes_in_context, C_i32, C_integral}; use trans::common::{C_null, C_struct_in_context, C_u64, C_u8, C_undef}; use trans::common::{CrateContext, ExternMap, FunctionContext}; -use trans::common::{NodeInfo, Result}; +use trans::common::{Result}; use trans::common::{node_id_type, return_type_is_void}; use trans::common::{tydesc_info, type_is_immediate}; use trans::common::{type_is_zero_size, val_ty}; @@ -66,7 +66,7 @@ use trans::consts; use trans::context::SharedCrateContext; use trans::controlflow; use trans::datum; -use trans::debuginfo; +use trans::debuginfo::{self, DebugLoc}; use trans::expr; use trans::foreign; use trans::glue; @@ -362,18 +362,6 @@ pub fn get_extern_const<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, did: ast::DefId, } } -// Returns a pointer to the body for the box. The box may be an opaque -// box. The result will be casted to the type of body_t, if it is statically -// known. -pub fn at_box_body<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, - body_t: Ty<'tcx>, boxptr: ValueRef) -> ValueRef { - let _icx = push_ctxt("at_box_body"); - let ccx = bcx.ccx(); - let ty = Type::at_box(ccx, type_of(ccx, body_t)); - let boxptr = PointerCast(bcx, boxptr, ty.ptr_to()); - GEPi(bcx, boxptr, &[0u, abi::BOX_FIELD_BODY]) -} - fn require_alloc_fn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, info_ty: Ty<'tcx>, it: LangItem) -> ast::DefId { match bcx.tcx().lang_items.require(it) { @@ -792,7 +780,7 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>, &**variant, substs, &mut f); - Br(variant_cx, next_cx.llbb); + Br(variant_cx, next_cx.llbb, DebugLoc::None); } cx = next_cx; } @@ -957,7 +945,7 @@ pub fn invoke<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, llfn: ValueRef, llargs: &[ValueRef], fn_ty: Ty<'tcx>, - call_info: Option) + debug_loc: DebugLoc) -> (ValueRef, Block<'blk, 'tcx>) { let _icx = push_ctxt("invoke_"); if bcx.unreachable.get() { @@ -983,17 +971,13 @@ pub fn invoke<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let normal_bcx = bcx.fcx.new_temp_block("normal-return"); let landing_pad = bcx.fcx.get_landing_pad(); - match call_info { - Some(info) => debuginfo::set_source_location(bcx.fcx, info.id, info.span), - None => debuginfo::clear_source_location(bcx.fcx) - }; - let llresult = Invoke(bcx, llfn, &llargs[], normal_bcx.llbb, landing_pad, - Some(attributes)); + Some(attributes), + debug_loc); return (llresult, normal_bcx); } else { debug!("calling {} at {:?}", bcx.val_to_string(llfn), bcx.llbb); @@ -1001,12 +985,11 @@ pub fn invoke<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, debug!("arg: {}", bcx.val_to_string(llarg)); } - match call_info { - Some(info) => debuginfo::set_source_location(bcx.fcx, info.id, info.span), - None => debuginfo::clear_source_location(bcx.fcx) - }; - - let llresult = Call(bcx, llfn, &llargs[], Some(attributes)); + let llresult = Call(bcx, + llfn, + &llargs[], + Some(attributes), + debug_loc); return (llresult, bcx); } } @@ -1094,10 +1077,10 @@ pub fn with_cond<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, let fcx = bcx.fcx; let next_cx = fcx.new_temp_block("next"); let cond_cx = fcx.new_temp_block("cond"); - CondBr(bcx, val, cond_cx.llbb, next_cx.llbb); + CondBr(bcx, val, cond_cx.llbb, next_cx.llbb, DebugLoc::None); let after_cx = f(cond_cx); if !after_cx.terminated.get() { - Br(after_cx, next_cx.llbb); + Br(after_cx, next_cx.llbb, DebugLoc::None); } next_cx } @@ -1113,7 +1096,7 @@ pub fn call_lifetime_start(cx: Block, ptr: ValueRef) { let llsize = C_u64(ccx, machine::llsize_of_alloc(ccx, val_ty(ptr).element_type())); let ptr = PointerCast(cx, ptr, Type::i8p(ccx)); let lifetime_start = ccx.get_intrinsic(&"llvm.lifetime.start"); - Call(cx, lifetime_start, &[llsize, ptr], None); + Call(cx, lifetime_start, &[llsize, ptr], None, DebugLoc::None); } pub fn call_lifetime_end(cx: Block, ptr: ValueRef) { @@ -1127,7 +1110,7 @@ pub fn call_lifetime_end(cx: Block, ptr: ValueRef) { let llsize = C_u64(ccx, machine::llsize_of_alloc(ccx, val_ty(ptr).element_type())); let ptr = PointerCast(cx, ptr, Type::i8p(ccx)); let lifetime_end = ccx.get_intrinsic(&"llvm.lifetime.end"); - Call(cx, lifetime_end, &[llsize, ptr], None); + Call(cx, lifetime_end, &[llsize, ptr], None, DebugLoc::None); } pub fn call_memcpy(cx: Block, dst: ValueRef, src: ValueRef, n_bytes: ValueRef, align: u32) { @@ -1144,7 +1127,7 @@ pub fn call_memcpy(cx: Block, dst: ValueRef, src: ValueRef, n_bytes: ValueRef, a let size = IntCast(cx, n_bytes, ccx.int_type()); let align = C_i32(ccx, align as i32); let volatile = C_bool(ccx, false); - Call(cx, memcpy, &[dst_ptr, src_ptr, size, align, volatile], None); + Call(cx, memcpy, &[dst_ptr, src_ptr, size, align, volatile], None, DebugLoc::None); } pub fn memcpy_ty<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, @@ -1697,13 +1680,14 @@ fn copy_unboxed_closure_args_to_allocas<'blk, 'tcx>( // and builds the return block. pub fn finish_fn<'blk, 'tcx>(fcx: &'blk FunctionContext<'blk, 'tcx>, last_bcx: Block<'blk, 'tcx>, - retty: ty::FnOutput<'tcx>) { + retty: ty::FnOutput<'tcx>, + ret_debug_loc: DebugLoc) { let _icx = push_ctxt("finish_fn"); let ret_cx = match fcx.llreturn.get() { Some(llreturn) => { if !last_bcx.terminated.get() { - Br(last_bcx, llreturn); + Br(last_bcx, llreturn, DebugLoc::None); } raw_block(fcx, false, llreturn) } @@ -1713,7 +1697,7 @@ pub fn finish_fn<'blk, 'tcx>(fcx: &'blk FunctionContext<'blk, 'tcx>, // This shouldn't need to recompute the return type, // as new_fn_ctxt did it already. let substd_retty = fcx.monomorphize(&retty); - build_return_block(fcx, ret_cx, substd_retty); + build_return_block(fcx, ret_cx, substd_retty, ret_debug_loc); debuginfo::clear_source_location(fcx); fcx.cleanup(); @@ -1722,10 +1706,11 @@ pub fn finish_fn<'blk, 'tcx>(fcx: &'blk FunctionContext<'blk, 'tcx>, // Builds the return block for a function. pub fn build_return_block<'blk, 'tcx>(fcx: &FunctionContext<'blk, 'tcx>, ret_cx: Block<'blk, 'tcx>, - retty: ty::FnOutput<'tcx>) { + retty: ty::FnOutput<'tcx>, + ret_debug_location: DebugLoc) { if fcx.llretslotptr.get().is_none() || (!fcx.needs_ret_allocas && fcx.caller_expects_out_pointer) { - return RetVoid(ret_cx); + return RetVoid(ret_cx, ret_debug_location); } let retslot = if fcx.needs_ret_allocas { @@ -1755,9 +1740,9 @@ pub fn build_return_block<'blk, 'tcx>(fcx: &FunctionContext<'blk, 'tcx>, if let ty::FnConverging(retty) = retty { store_ty(ret_cx, retval, get_param(fcx.llfn, 0), retty); } - RetVoid(ret_cx) + RetVoid(ret_cx, ret_debug_location) } else { - Ret(ret_cx, retval) + Ret(ret_cx, retval, ret_debug_location) } } // Otherwise, copy the return value to the ret slot @@ -1765,16 +1750,16 @@ pub fn build_return_block<'blk, 'tcx>(fcx: &FunctionContext<'blk, 'tcx>, ty::FnConverging(retty) => { if fcx.caller_expects_out_pointer { memcpy_ty(ret_cx, get_param(fcx.llfn, 0), retslot, retty); - RetVoid(ret_cx) + RetVoid(ret_cx, ret_debug_location) } else { - Ret(ret_cx, load_ty(ret_cx, retslot, retty)) + Ret(ret_cx, load_ty(ret_cx, retslot, retty), ret_debug_location) } } ty::FnDiverging => { if fcx.caller_expects_out_pointer { - RetVoid(ret_cx) + RetVoid(ret_cx, ret_debug_location) } else { - Ret(ret_cx, C_undef(Type::nil(fcx.ccx))) + Ret(ret_cx, C_undef(Type::nil(fcx.ccx)), ret_debug_location) } } } @@ -1832,7 +1817,7 @@ pub fn trans_closure<'a, 'b, 'tcx>(ccx: &CrateContext<'a, 'tcx>, .map(|arg| node_id_type(bcx, arg.id)) .collect::>(); let monomorphized_arg_types = match closure_env.kind { - closure::NotClosure | closure::BoxedClosure(..) => { + closure::NotClosure => { monomorphized_arg_types } @@ -1859,7 +1844,7 @@ pub fn trans_closure<'a, 'b, 'tcx>(ccx: &CrateContext<'a, 'tcx>, }; bcx = match closure_env.kind { - closure::NotClosure | closure::BoxedClosure(..) => { + closure::NotClosure => { copy_args_to_allocas(bcx, arg_scope, &decl.inputs[], @@ -1905,7 +1890,7 @@ pub fn trans_closure<'a, 'b, 'tcx>(ccx: &CrateContext<'a, 'tcx>, match fcx.llreturn.get() { Some(_) => { - Br(bcx, fcx.return_exit_block()); + Br(bcx, fcx.return_exit_block(), DebugLoc::None); fcx.pop_custom_cleanup_scope(arg_scope); } None => { @@ -1924,8 +1909,11 @@ pub fn trans_closure<'a, 'b, 'tcx>(ccx: &CrateContext<'a, 'tcx>, } } + let ret_debug_loc = DebugLoc::At(fn_cleanup_debug_loc.id, + fn_cleanup_debug_loc.span); + // Insert the mandatory first few basic blocks before lltop. - finish_fn(&fcx, bcx, output_type); + finish_fn(&fcx, bcx, output_type, ret_debug_loc); } // trans_fn: creates an LLVM function corresponding to a source language @@ -1977,7 +1965,7 @@ pub fn trans_named_tuple_constructor<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, disr: ty::Disr, args: callee::CallArgs, dest: expr::Dest, - call_info: Option) + debug_loc: DebugLoc) -> Result<'blk, 'tcx> { let ccx = bcx.fcx.ccx; @@ -2016,7 +2004,7 @@ pub fn trans_named_tuple_constructor<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, &fields[], None, expr::SaveIn(llresult), - call_info); + debug_loc); } _ => ccx.sess().bug("expected expr as arguments for variant/struct tuple constructor") } @@ -2027,7 +2015,7 @@ pub fn trans_named_tuple_constructor<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, let bcx = match dest { expr::SaveIn(_) => bcx, expr::Ignore => { - glue::drop_ty(bcx, llresult, result_ty, call_info) + glue::drop_ty(bcx, llresult, result_ty, debug_loc) } }; @@ -2094,7 +2082,7 @@ fn trans_enum_variant_or_tuple_like_struct<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx adt::trans_set_discr(bcx, &*repr, dest, disr); } - finish_fn(&fcx, bcx, result_ty); + finish_fn(&fcx, bcx, result_ty, DebugLoc::None); } fn enum_variant_size_lint(ccx: &CrateContext, enum_def: &ast::EnumDef, sp: Span, id: ast::NodeId) { diff --git a/src/librustc_trans/trans/build.rs b/src/librustc_trans/trans/build.rs index 1f77f625c9db..7acac5a12ebd 100644 --- a/src/librustc_trans/trans/build.rs +++ b/src/librustc_trans/trans/build.rs @@ -20,6 +20,7 @@ use syntax::codemap::Span; use trans::builder::Builder; use trans::type_::Type; +use trans::debuginfo::DebugLoc; use libc::{c_uint, c_char}; @@ -48,41 +49,59 @@ pub fn B<'blk, 'tcx>(cx: Block<'blk, 'tcx>) -> Builder<'blk, 'tcx> { // for (panic/break/return statements, call to diverging functions, etc), and // further instructions to the block should simply be ignored. -pub fn RetVoid(cx: Block) { - if cx.unreachable.get() { return; } +pub fn RetVoid(cx: Block, debug_loc: DebugLoc) { + if cx.unreachable.get() { + return; + } check_not_terminated(cx); terminate(cx, "RetVoid"); + debug_loc.apply(cx.fcx); B(cx).ret_void(); } -pub fn Ret(cx: Block, v: ValueRef) { - if cx.unreachable.get() { return; } +pub fn Ret(cx: Block, v: ValueRef, debug_loc: DebugLoc) { + if cx.unreachable.get() { + return; + } check_not_terminated(cx); terminate(cx, "Ret"); + debug_loc.apply(cx.fcx); B(cx).ret(v); } -pub fn AggregateRet(cx: Block, ret_vals: &[ValueRef]) { - if cx.unreachable.get() { return; } +pub fn AggregateRet(cx: Block, + ret_vals: &[ValueRef], + debug_loc: DebugLoc) { + if cx.unreachable.get() { + return; + } check_not_terminated(cx); terminate(cx, "AggregateRet"); + debug_loc.apply(cx.fcx); B(cx).aggregate_ret(ret_vals); } -pub fn Br(cx: Block, dest: BasicBlockRef) { - if cx.unreachable.get() { return; } +pub fn Br(cx: Block, dest: BasicBlockRef, debug_loc: DebugLoc) { + if cx.unreachable.get() { + return; + } check_not_terminated(cx); terminate(cx, "Br"); + debug_loc.apply(cx.fcx); B(cx).br(dest); } pub fn CondBr(cx: Block, if_: ValueRef, then: BasicBlockRef, - else_: BasicBlockRef) { - if cx.unreachable.get() { return; } + else_: BasicBlockRef, + debug_loc: DebugLoc) { + if cx.unreachable.get() { + return; + } check_not_terminated(cx); terminate(cx, "CondBr"); + debug_loc.apply(cx.fcx); B(cx).cond_br(if_, then, else_); } @@ -101,10 +120,16 @@ pub fn AddCase(s: ValueRef, on_val: ValueRef, dest: BasicBlockRef) { } } -pub fn IndirectBr(cx: Block, addr: ValueRef, num_dests: uint) { - if cx.unreachable.get() { return; } +pub fn IndirectBr(cx: Block, + addr: ValueRef, + num_dests: uint, + debug_loc: DebugLoc) { + if cx.unreachable.get() { + return; + } check_not_terminated(cx); terminate(cx, "IndirectBr"); + debug_loc.apply(cx.fcx); B(cx).indirect_br(addr, num_dests); } @@ -113,7 +138,8 @@ pub fn Invoke(cx: Block, args: &[ValueRef], then: BasicBlockRef, catch: BasicBlockRef, - attributes: Option) + attributes: Option, + debug_loc: DebugLoc) -> ValueRef { if cx.unreachable.get() { return C_null(Type::i8(cx.ccx())); @@ -123,6 +149,7 @@ pub fn Invoke(cx: Block, debug!("Invoke({} with arguments ({}))", cx.val_to_string(fn_), args.iter().map(|a| cx.val_to_string(*a)).collect::>().connect(", ")); + debug_loc.apply(cx.fcx); B(cx).invoke(fn_, args, then, catch, attributes) } @@ -143,176 +170,378 @@ pub fn _Undef(val: ValueRef) -> ValueRef { } /* Arithmetic */ -pub fn Add(cx: Block, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } +pub fn Add(cx: Block, + lhs: ValueRef, + rhs: ValueRef, + debug_loc: DebugLoc) + -> ValueRef { + if cx.unreachable.get() { + return _Undef(lhs); + } + debug_loc.apply(cx.fcx); B(cx).add(lhs, rhs) } -pub fn NSWAdd(cx: Block, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } +pub fn NSWAdd(cx: Block, + lhs: ValueRef, + rhs: ValueRef, + debug_loc: DebugLoc) + -> ValueRef { + if cx.unreachable.get() { + return _Undef(lhs); + } + debug_loc.apply(cx.fcx); B(cx).nswadd(lhs, rhs) } -pub fn NUWAdd(cx: Block, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } +pub fn NUWAdd(cx: Block, + lhs: ValueRef, + rhs: ValueRef, + debug_loc: DebugLoc) + -> ValueRef { + if cx.unreachable.get() { + return _Undef(lhs); + } + debug_loc.apply(cx.fcx); B(cx).nuwadd(lhs, rhs) } -pub fn FAdd(cx: Block, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } +pub fn FAdd(cx: Block, + lhs: ValueRef, + rhs: ValueRef, + debug_loc: DebugLoc) + -> ValueRef { + if cx.unreachable.get() { + return _Undef(lhs); + } + debug_loc.apply(cx.fcx); B(cx).fadd(lhs, rhs) } -pub fn Sub(cx: Block, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } +pub fn Sub(cx: Block, + lhs: ValueRef, + rhs: ValueRef, + debug_loc: DebugLoc) + -> ValueRef { + if cx.unreachable.get() { + return _Undef(lhs); + } + debug_loc.apply(cx.fcx); B(cx).sub(lhs, rhs) } -pub fn NSWSub(cx: Block, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } +pub fn NSWSub(cx: Block, + lhs: ValueRef, + rhs: ValueRef, + debug_loc: DebugLoc) + -> ValueRef { + if cx.unreachable.get() { + return _Undef(lhs); + } + debug_loc.apply(cx.fcx); B(cx).nswsub(lhs, rhs) } -pub fn NUWSub(cx: Block, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } +pub fn NUWSub(cx: Block, + lhs: ValueRef, + rhs: ValueRef, + debug_loc: DebugLoc) + -> ValueRef { + if cx.unreachable.get() { + return _Undef(lhs); + } + debug_loc.apply(cx.fcx); B(cx).nuwsub(lhs, rhs) } -pub fn FSub(cx: Block, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } +pub fn FSub(cx: Block, + lhs: ValueRef, + rhs: ValueRef, + debug_loc: DebugLoc) + -> ValueRef { + if cx.unreachable.get() { + return _Undef(lhs); + } + debug_loc.apply(cx.fcx); B(cx).fsub(lhs, rhs) } -pub fn Mul(cx: Block, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } +pub fn Mul(cx: Block, + lhs: ValueRef, + rhs: ValueRef, + debug_loc: DebugLoc) + -> ValueRef { + if cx.unreachable.get() { + return _Undef(lhs); + } + debug_loc.apply(cx.fcx); B(cx).mul(lhs, rhs) } -pub fn NSWMul(cx: Block, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } +pub fn NSWMul(cx: Block, + lhs: ValueRef, + rhs: ValueRef, + debug_loc: DebugLoc) + -> ValueRef { + if cx.unreachable.get() { + return _Undef(lhs); + } + debug_loc.apply(cx.fcx); B(cx).nswmul(lhs, rhs) } -pub fn NUWMul(cx: Block, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } +pub fn NUWMul(cx: Block, + lhs: ValueRef, + rhs: ValueRef, + debug_loc: DebugLoc) + -> ValueRef { + if cx.unreachable.get() { + return _Undef(lhs); + } + debug_loc.apply(cx.fcx); B(cx).nuwmul(lhs, rhs) } -pub fn FMul(cx: Block, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } +pub fn FMul(cx: Block, + lhs: ValueRef, + rhs: ValueRef, + debug_loc: DebugLoc) + -> ValueRef { + if cx.unreachable.get() { + return _Undef(lhs); + } + debug_loc.apply(cx.fcx); B(cx).fmul(lhs, rhs) } -pub fn UDiv(cx: Block, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } +pub fn UDiv(cx: Block, + lhs: ValueRef, + rhs: ValueRef, + debug_loc: DebugLoc) + -> ValueRef { + if cx.unreachable.get() { + return _Undef(lhs); + } + debug_loc.apply(cx.fcx); B(cx).udiv(lhs, rhs) } -pub fn SDiv(cx: Block, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } +pub fn SDiv(cx: Block, + lhs: ValueRef, + rhs: ValueRef, + debug_loc: DebugLoc) + -> ValueRef { + if cx.unreachable.get() { + return _Undef(lhs); + } + debug_loc.apply(cx.fcx); B(cx).sdiv(lhs, rhs) } -pub fn ExactSDiv(cx: Block, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } +pub fn ExactSDiv(cx: Block, + lhs: ValueRef, + rhs: ValueRef, + debug_loc: DebugLoc) + -> ValueRef { + if cx.unreachable.get() { + return _Undef(lhs); + } + debug_loc.apply(cx.fcx); B(cx).exactsdiv(lhs, rhs) } -pub fn FDiv(cx: Block, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } +pub fn FDiv(cx: Block, + lhs: ValueRef, + rhs: ValueRef, + debug_loc: DebugLoc) + -> ValueRef { + if cx.unreachable.get() { + return _Undef(lhs); + } + debug_loc.apply(cx.fcx); B(cx).fdiv(lhs, rhs) } -pub fn URem(cx: Block, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } +pub fn URem(cx: Block, + lhs: ValueRef, + rhs: ValueRef, + debug_loc: DebugLoc) + -> ValueRef { + if cx.unreachable.get() { + return _Undef(lhs); + } + debug_loc.apply(cx.fcx); B(cx).urem(lhs, rhs) } -pub fn SRem(cx: Block, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } +pub fn SRem(cx: Block, + lhs: ValueRef, + rhs: ValueRef, + debug_loc: DebugLoc) + -> ValueRef { + if cx.unreachable.get() { + return _Undef(lhs); + } + debug_loc.apply(cx.fcx); B(cx).srem(lhs, rhs) } -pub fn FRem(cx: Block, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } +pub fn FRem(cx: Block, + lhs: ValueRef, + rhs: ValueRef, + debug_loc: DebugLoc) + -> ValueRef { + if cx.unreachable.get() { + return _Undef(lhs); + } + debug_loc.apply(cx.fcx); B(cx).frem(lhs, rhs) } -pub fn Shl(cx: Block, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } +pub fn Shl(cx: Block, + lhs: ValueRef, + rhs: ValueRef, + debug_loc: DebugLoc) + -> ValueRef { + if cx.unreachable.get() { + return _Undef(lhs); + } + debug_loc.apply(cx.fcx); B(cx).shl(lhs, rhs) } -pub fn LShr(cx: Block, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } +pub fn LShr(cx: Block, + lhs: ValueRef, + rhs: ValueRef, + debug_loc: DebugLoc) + -> ValueRef { + if cx.unreachable.get() { + return _Undef(lhs); + } + debug_loc.apply(cx.fcx); B(cx).lshr(lhs, rhs) } -pub fn AShr(cx: Block, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } +pub fn AShr(cx: Block, + lhs: ValueRef, + rhs: ValueRef, + debug_loc: DebugLoc) + -> ValueRef { + if cx.unreachable.get() { + return _Undef(lhs); + } + debug_loc.apply(cx.fcx); B(cx).ashr(lhs, rhs) } -pub fn And(cx: Block, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } +pub fn And(cx: Block, + lhs: ValueRef, + rhs: ValueRef, + debug_loc: DebugLoc) + -> ValueRef { + if cx.unreachable.get() { + return _Undef(lhs); + } + debug_loc.apply(cx.fcx); B(cx).and(lhs, rhs) } -pub fn Or(cx: Block, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } +pub fn Or(cx: Block, + lhs: ValueRef, + rhs: ValueRef, + debug_loc: DebugLoc) + -> ValueRef { + if cx.unreachable.get() { + return _Undef(lhs); + } + debug_loc.apply(cx.fcx); B(cx).or(lhs, rhs) } -pub fn Xor(cx: Block, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } +pub fn Xor(cx: Block, + lhs: ValueRef, + rhs: ValueRef, + debug_loc: DebugLoc) + -> ValueRef { + if cx.unreachable.get() { + return _Undef(lhs); + } + debug_loc.apply(cx.fcx); B(cx).xor(lhs, rhs) } -pub fn BinOp(cx: Block, op: Opcode, lhs: ValueRef, rhs: ValueRef) +pub fn BinOp(cx: Block, + op: Opcode, + lhs: ValueRef, + rhs: ValueRef, + debug_loc: DebugLoc) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } + if cx.unreachable.get() { + return _Undef(lhs); + } + debug_loc.apply(cx.fcx); B(cx).binop(op, lhs, rhs) } -pub fn Neg(cx: Block, v: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(v); } +pub fn Neg(cx: Block, v: ValueRef, debug_loc: DebugLoc) -> ValueRef { + if cx.unreachable.get() { + return _Undef(v); + } + debug_loc.apply(cx.fcx); B(cx).neg(v) } -pub fn NSWNeg(cx: Block, v: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(v); } +pub fn NSWNeg(cx: Block, v: ValueRef, debug_loc: DebugLoc) -> ValueRef { + if cx.unreachable.get() { + return _Undef(v); + } + debug_loc.apply(cx.fcx); B(cx).nswneg(v) } -pub fn NUWNeg(cx: Block, v: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(v); } +pub fn NUWNeg(cx: Block, v: ValueRef, debug_loc: DebugLoc) -> ValueRef { + if cx.unreachable.get() { + return _Undef(v); + } + debug_loc.apply(cx.fcx); B(cx).nuwneg(v) } -pub fn FNeg(cx: Block, v: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(v); } +pub fn FNeg(cx: Block, v: ValueRef, debug_loc: DebugLoc) -> ValueRef { + if cx.unreachable.get() { + return _Undef(v); + } + debug_loc.apply(cx.fcx); B(cx).fneg(v) } -pub fn Not(cx: Block, v: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(v); } +pub fn Not(cx: Block, v: ValueRef, debug_loc: DebugLoc) -> ValueRef { + if cx.unreachable.get() { + return _Undef(v); + } + debug_loc.apply(cx.fcx); B(cx).not(v) } /* Memory */ -pub fn Malloc(cx: Block, ty: Type) -> ValueRef { +pub fn Malloc(cx: Block, ty: Type, debug_loc: DebugLoc) -> ValueRef { unsafe { if cx.unreachable.get() { return llvm::LLVMGetUndef(Type::i8p(cx.ccx()).to_ref()); } + debug_loc.apply(cx.fcx); B(cx).malloc(ty) } } -pub fn ArrayMalloc(cx: Block, ty: Type, val: ValueRef) -> ValueRef { +pub fn ArrayMalloc(cx: Block, + ty: Type, + val: ValueRef, + debug_loc: DebugLoc) -> ValueRef { unsafe { if cx.unreachable.get() { return llvm::LLVMGetUndef(Type::i8p(cx.ccx()).to_ref()); } + debug_loc.apply(cx.fcx); B(cx).array_malloc(ty, val) } } @@ -327,6 +556,7 @@ pub fn Alloca(cx: Block, ty: Type, name: &str) -> ValueRef { pub fn AllocaFcx(fcx: &FunctionContext, ty: Type, name: &str) -> ValueRef { let b = fcx.ccx.builder(); b.position_before(fcx.alloca_insert_pt.get().unwrap()); + DebugLoc::None.apply(fcx); b.alloca(ty, name) } @@ -335,6 +565,7 @@ pub fn ArrayAlloca(cx: Block, ty: Type, val: ValueRef) -> ValueRef { if cx.unreachable.get() { return llvm::LLVMGetUndef(ty.ptr_to().to_ref()); } let b = cx.fcx.ccx.builder(); b.position_before(cx.fcx.alloca_insert_pt.get().unwrap()); + DebugLoc::None.apply(cx.fcx); b.array_alloca(ty, val) } } @@ -680,9 +911,16 @@ pub fn InlineAsmCall(cx: Block, asm: *const c_char, cons: *const c_char, B(cx).inline_asm_call(asm, cons, inputs, output, volatile, alignstack, dia) } -pub fn Call(cx: Block, fn_: ValueRef, args: &[ValueRef], - attributes: Option) -> ValueRef { - if cx.unreachable.get() { return _UndefReturn(cx, fn_); } +pub fn Call(cx: Block, + fn_: ValueRef, + args: &[ValueRef], + attributes: Option, + debug_loc: DebugLoc) + -> ValueRef { + if cx.unreachable.get() { + return _UndefReturn(cx, fn_); + } + debug_loc.apply(cx.fcx); B(cx).call(fn_, args, attributes) } diff --git a/src/librustc_trans/trans/cabi_x86_64.rs b/src/librustc_trans/trans/cabi_x86_64.rs index 980a70256e93..3c0530bbb9a6 100644 --- a/src/librustc_trans/trans/cabi_x86_64.rs +++ b/src/librustc_trans/trans/cabi_x86_64.rs @@ -361,7 +361,7 @@ fn llreg_ty(ccx: &CrateContext, cls: &[RegClass]) -> Type { } _ => unreachable!(), }; - let vec_len = llvec_len(&cls[(i + 1u)..]); + let vec_len = llvec_len(&cls[i + 1u..]); let vec_ty = Type::vector(&elt_ty, vec_len as u64 * elts_per_word); tys.push(vec_ty); i += vec_len; diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs index 11006f37531d..7ed4727404e1 100644 --- a/src/librustc_trans/trans/callee.rs +++ b/src/librustc_trans/trans/callee.rs @@ -40,6 +40,7 @@ use trans::common; use trans::common::*; use trans::consts; use trans::datum::*; +use trans::debuginfo::{DebugLoc, ToDebugLoc}; use trans::expr; use trans::glue; use trans::inline; @@ -356,7 +357,7 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>( ArgVals(&llargs[]), dest).bcx; - finish_fn(&fcx, bcx, sig.output); + finish_fn(&fcx, bcx, sig.output, DebugLoc::None); ccx.fn_pointer_shims().borrow_mut().insert(bare_fn_ty, llfn); @@ -646,7 +647,7 @@ pub fn trans_lang_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, /// For non-lang items, `dest` is always Some, and hence the result is written into memory /// somewhere. Nonetheless we return the actual return value of the function. pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, - call_info: Option, + call_info: Option, callee_ty: Ty<'tcx>, get_callee: F, args: CallArgs<'a, 'tcx>, @@ -703,7 +704,7 @@ pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, disr, args, dest.unwrap(), - call_info); + call_info.debug_loc()); } }; @@ -781,7 +782,7 @@ pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, llfn, &llargs[], callee_ty, - call_info); + call_info.debug_loc()); bcx = b; llresult = llret; @@ -828,7 +829,10 @@ pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, match (dest, opt_llretslot, ret_ty) { (Some(expr::Ignore), Some(llretslot), ty::FnConverging(ret_ty)) => { // drop the value if it is not being saved. - bcx = glue::drop_ty(bcx, llretslot, ret_ty, call_info); + bcx = glue::drop_ty(bcx, + llretslot, + ret_ty, + call_info.debug_loc()); call_lifetime_end(bcx, llretslot); } _ => {} diff --git a/src/librustc_trans/trans/cleanup.rs b/src/librustc_trans/trans/cleanup.rs index 5658889aaf36..a25f4f778ab7 100644 --- a/src/librustc_trans/trans/cleanup.rs +++ b/src/librustc_trans/trans/cleanup.rs @@ -21,8 +21,8 @@ use trans::base; use trans::build; use trans::callee; use trans::common; -use trans::common::{Block, FunctionContext, ExprId, NodeInfo}; -use trans::debuginfo; +use trans::common::{Block, FunctionContext, ExprId, NodeIdAndSpan}; +use trans::debuginfo::{DebugLoc, ToDebugLoc}; use trans::glue; use middle::region; use trans::type_::Type; @@ -44,7 +44,7 @@ pub struct CleanupScope<'blk, 'tcx: 'blk> { // The debug location any drop calls generated for this scope will be // associated with. - debug_loc: Option, + debug_loc: DebugLoc, cached_early_exits: Vec, cached_landing_pad: Option, @@ -65,7 +65,7 @@ pub enum CleanupScopeKind<'blk, 'tcx: 'blk> { LoopScopeKind(ast::NodeId, [Block<'blk, 'tcx>; EXIT_MAX]) } -impl<'blk, 'tcx: 'blk> fmt::Show for CleanupScopeKind<'blk, 'tcx> { +impl<'blk, 'tcx: 'blk> fmt::Debug for CleanupScopeKind<'blk, 'tcx> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { CustomScopeKind => write!(f, "CustomScopeKind"), @@ -100,7 +100,7 @@ pub trait Cleanup<'tcx> { fn is_lifetime_end(&self) -> bool; fn trans<'blk>(&self, bcx: Block<'blk, 'tcx>, - debug_loc: Option) + debug_loc: DebugLoc) -> Block<'blk, 'tcx>; } @@ -114,7 +114,7 @@ pub enum ScopeId { impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> { /// Invoked when we start to trans the code contained within a new cleanup scope. - fn push_ast_cleanup_scope(&self, debug_loc: NodeInfo) { + fn push_ast_cleanup_scope(&self, debug_loc: NodeIdAndSpan) { debug!("push_ast_cleanup_scope({})", self.ccx.tcx().map.node_to_string(debug_loc.id)); @@ -139,7 +139,7 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> { } self.push_scope(CleanupScope::new(AstScopeKind(debug_loc.id), - Some(debug_loc))); + debug_loc.debug_loc())); } fn push_loop_cleanup_scope(&self, @@ -168,19 +168,20 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> { .borrow() .last() .map(|opt_scope| opt_scope.debug_loc) - .unwrap_or(None); + .unwrap_or(DebugLoc::None); self.push_scope(CleanupScope::new(CustomScopeKind, debug_loc)); CustomScopeIndex { index: index } } fn push_custom_cleanup_scope_with_debug_loc(&self, - debug_loc: NodeInfo) + debug_loc: NodeIdAndSpan) -> CustomScopeIndex { let index = self.scopes_len(); debug!("push_custom_cleanup_scope(): {}", index); - self.push_scope(CleanupScope::new(CustomScopeKind, Some(debug_loc))); + self.push_scope(CleanupScope::new(CustomScopeKind, + debug_loc.debug_loc())); CustomScopeIndex { index: index } } @@ -664,7 +665,7 @@ impl<'blk, 'tcx> CleanupHelperMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx scope.debug_loc); } } - build::Br(bcx_out, prev_llbb); + build::Br(bcx_out, prev_llbb, DebugLoc::None); prev_llbb = bcx_in.llbb; } else { debug!("no suitable cleanups in {}", @@ -766,7 +767,7 @@ impl<'blk, 'tcx> CleanupHelperMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx // Generate the cleanup block and branch to it. let cleanup_llbb = self.trans_cleanups_to_exit_scope(UnwindExit); - build::Br(pad_bcx, cleanup_llbb); + build::Br(pad_bcx, cleanup_llbb, DebugLoc::None); return pad_bcx.llbb; } @@ -774,7 +775,7 @@ impl<'blk, 'tcx> CleanupHelperMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx impl<'blk, 'tcx> CleanupScope<'blk, 'tcx> { fn new(kind: CleanupScopeKind<'blk, 'tcx>, - debug_loc: Option) + debug_loc: DebugLoc) -> CleanupScope<'blk, 'tcx> { CleanupScope { kind: kind, @@ -896,7 +897,7 @@ impl<'tcx> Cleanup<'tcx> for DropValue<'tcx> { fn trans<'blk>(&self, bcx: Block<'blk, 'tcx>, - debug_loc: Option) + debug_loc: DebugLoc) -> Block<'blk, 'tcx> { let bcx = if self.is_immediate { glue::drop_ty_immediate(bcx, self.val, self.ty, debug_loc) @@ -937,9 +938,9 @@ impl<'tcx> Cleanup<'tcx> for FreeValue<'tcx> { fn trans<'blk>(&self, bcx: Block<'blk, 'tcx>, - debug_loc: Option) + debug_loc: DebugLoc) -> Block<'blk, 'tcx> { - apply_debug_loc(bcx.fcx, debug_loc); + debug_loc.apply(bcx.fcx); match self.heap { HeapExchange => { @@ -972,9 +973,9 @@ impl<'tcx> Cleanup<'tcx> for FreeSlice { fn trans<'blk>(&self, bcx: Block<'blk, 'tcx>, - debug_loc: Option) + debug_loc: DebugLoc) -> Block<'blk, 'tcx> { - apply_debug_loc(bcx.fcx, debug_loc); + debug_loc.apply(bcx.fcx); match self.heap { HeapExchange => { @@ -1004,9 +1005,9 @@ impl<'tcx> Cleanup<'tcx> for LifetimeEnd { fn trans<'blk>(&self, bcx: Block<'blk, 'tcx>, - debug_loc: Option) + debug_loc: DebugLoc) -> Block<'blk, 'tcx> { - apply_debug_loc(bcx.fcx, debug_loc); + debug_loc.apply(bcx.fcx); base::call_lifetime_end(bcx, self.ptr); bcx } @@ -1041,33 +1042,22 @@ fn cleanup_is_suitable_for(c: &Cleanup, !label.is_unwind() || c.clean_on_unwind() } -fn apply_debug_loc(fcx: &FunctionContext, debug_loc: Option) { - match debug_loc { - Some(ref src_loc) => { - debuginfo::set_source_location(fcx, src_loc.id, src_loc.span); - } - None => { - debuginfo::clear_source_location(fcx); - } - } -} - /////////////////////////////////////////////////////////////////////////// // These traits just exist to put the methods into this file. pub trait CleanupMethods<'blk, 'tcx> { - fn push_ast_cleanup_scope(&self, id: NodeInfo); + fn push_ast_cleanup_scope(&self, id: NodeIdAndSpan); fn push_loop_cleanup_scope(&self, id: ast::NodeId, exits: [Block<'blk, 'tcx>; EXIT_MAX]); fn push_custom_cleanup_scope(&self) -> CustomScopeIndex; fn push_custom_cleanup_scope_with_debug_loc(&self, - debug_loc: NodeInfo) + debug_loc: NodeIdAndSpan) -> CustomScopeIndex; fn pop_and_trans_ast_cleanup_scope(&self, - bcx: Block<'blk, 'tcx>, - cleanup_scope: ast::NodeId) - -> Block<'blk, 'tcx>; + bcx: Block<'blk, 'tcx>, + cleanup_scope: ast::NodeId) + -> Block<'blk, 'tcx>; fn pop_loop_cleanup_scope(&self, cleanup_scope: ast::NodeId); fn pop_custom_cleanup_scope(&self, diff --git a/src/librustc_trans/trans/closure.rs b/src/librustc_trans/trans/closure.rs index 8989dfd49323..7a6c0c50dd1f 100644 --- a/src/librustc_trans/trans/closure.rs +++ b/src/librustc_trans/trans/closure.rs @@ -10,270 +10,26 @@ pub use self::ClosureKind::*; -use back::abi; use back::link::mangle_internal_name_by_path_and_seq; -use llvm::ValueRef; use middle::mem_categorization::Typer; use trans::adt; use trans::base::*; use trans::build::*; use trans::cleanup::{CleanupMethods, ScopeId}; use trans::common::*; -use trans::datum::{Datum, Lvalue, rvalue_scratch_datum}; +use trans::datum::{Datum, rvalue_scratch_datum}; use trans::datum::{Rvalue, ByValue}; use trans::debuginfo; use trans::expr; use trans::monomorphize::{self, MonoId}; use trans::type_of::*; -use trans::type_::Type; -use middle::ty::{self, Ty, UnboxedClosureTyper}; +use middle::ty::{self, UnboxedClosureTyper}; use middle::subst::{Substs}; use session::config::FullDebugInfo; -use util::ppaux::ty_to_string; use syntax::ast; use syntax::ast_util; -// ___Good to know (tm)__________________________________________________ -// -// The layout of a closure environment in memory is -// roughly as follows: -// -// struct rust_opaque_box { // see rust_internal.h -// unsigned ref_count; // obsolete (part of @T's header) -// fn(void*) *drop_glue; // destructor (for proc) -// rust_opaque_box *prev; // obsolete (part of @T's header) -// rust_opaque_box *next; // obsolete (part of @T's header) -// struct closure_data { -// upvar1_t upvar1; -// ... -// upvarN_t upvarN; -// } -// }; -// -// Note that the closure is itself a rust_opaque_box. This is true -// even for ~fn and ||, because we wish to keep binary compatibility -// between all kinds of closures. The allocation strategy for this -// closure depends on the closure type. For a sendfn, the closure -// (and the referenced type descriptors) will be allocated in the -// exchange heap. For a fn, the closure is allocated in the task heap -// and is reference counted. For a block, the closure is allocated on -// the stack. -// -// ## Opaque closures and the embedded type descriptor ## -// -// One interesting part of closures is that they encapsulate the data -// that they close over. So when I have a ptr to a closure, I do not -// know how many type descriptors it contains nor what upvars are -// captured within. That means I do not know precisely how big it is -// nor where its fields are located. This is called an "opaque -// closure". -// -// Typically an opaque closure suffices because we only manipulate it -// by ptr. The routine Type::at_box().ptr_to() returns an appropriate -// type for such an opaque closure; it allows access to the box fields, -// but not the closure_data itself. -// -// But sometimes, such as when cloning or freeing a closure, we need -// to know the full information. That is where the type descriptor -// that defines the closure comes in handy. We can use its take and -// drop glue functions to allocate/free data as needed. -// -// ## Subtleties concerning alignment ## -// -// It is important that we be able to locate the closure data *without -// knowing the kind of data that is being bound*. This can be tricky -// because the alignment requirements of the bound data affects the -// alignment requires of the closure_data struct as a whole. However, -// right now this is a non-issue in any case, because the size of the -// rust_opaque_box header is always a multiple of 16-bytes, which is -// the maximum alignment requirement we ever have to worry about. -// -// The only reason alignment matters is that, in order to learn what data -// is bound, we would normally first load the type descriptors: but their -// location is ultimately depend on their content! There is, however, a -// workaround. We can load the tydesc from the rust_opaque_box, which -// describes the closure_data struct and has self-contained derived type -// descriptors, and read the alignment from there. It's just annoying to -// do. Hopefully should this ever become an issue we'll have monomorphized -// and type descriptors will all be a bad dream. -// -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -#[derive(Copy)] -pub struct EnvValue<'tcx> { - action: ast::CaptureClause, - datum: Datum<'tcx, Lvalue> -} - -impl<'tcx> EnvValue<'tcx> { - pub fn to_string<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> String { - format!("{:?}({})", self.action, self.datum.to_string(ccx)) - } -} - -// Given a closure ty, emits a corresponding tuple ty -pub fn mk_closure_tys<'tcx>(tcx: &ty::ctxt<'tcx>, - bound_values: &[EnvValue<'tcx>]) - -> Ty<'tcx> { - // determine the types of the values in the env. Note that this - // is the actual types that will be stored in the map, not the - // logical types as the user sees them, so by-ref upvars must be - // converted to ptrs. - let bound_tys = bound_values.iter().map(|bv| { - match bv.action { - ast::CaptureByValue => bv.datum.ty, - ast::CaptureByRef => ty::mk_mut_ptr(tcx, bv.datum.ty) - } - }).collect(); - let cdata_ty = ty::mk_tup(tcx, bound_tys); - debug!("cdata_ty={}", ty_to_string(tcx, cdata_ty)); - return cdata_ty; -} - -fn tuplify_box_ty<'tcx>(tcx: &ty::ctxt<'tcx>, t: Ty<'tcx>) -> Ty<'tcx> { - let ptr = ty::mk_imm_ptr(tcx, tcx.types.i8); - ty::mk_tup(tcx, vec!(tcx.types.uint, ty::mk_nil_ptr(tcx), ptr, ptr, t)) -} - -pub struct ClosureResult<'blk, 'tcx: 'blk> { - llbox: ValueRef, // llvalue of ptr to closure - cdata_ty: Ty<'tcx>, // type of the closure data - bcx: Block<'blk, 'tcx> // final bcx -} - -// Given a block context and a list of tydescs and values to bind -// construct a closure out of them. If copying is true, it is a -// heap allocated closure that copies the upvars into environment. -// Otherwise, it is stack allocated and copies pointers to the upvars. -pub fn store_environment<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, - bound_values: Vec>) - -> ClosureResult<'blk, 'tcx> { - let _icx = push_ctxt("closure::store_environment"); - let ccx = bcx.ccx(); - let tcx = ccx.tcx(); - - // compute the type of the closure - let cdata_ty = mk_closure_tys(tcx, &bound_values[]); - - // cbox_ty has the form of a tuple: (a, b, c) we want a ptr to a - // tuple. This could be a ptr in uniq or a box or on stack, - // whatever. - let cbox_ty = tuplify_box_ty(tcx, cdata_ty); - let cboxptr_ty = ty::mk_ptr(tcx, ty::mt {ty:cbox_ty, mutbl:ast::MutImmutable}); - let llboxptr_ty = type_of(ccx, cboxptr_ty); - - // If there are no bound values, no point in allocating anything. - if bound_values.is_empty() { - return ClosureResult {llbox: C_null(llboxptr_ty), - cdata_ty: cdata_ty, - bcx: bcx}; - } - - // allocate closure in the heap - let llbox = alloc_ty(bcx, cbox_ty, "__closure"); - - let llbox = PointerCast(bcx, llbox, llboxptr_ty); - debug!("tuplify_box_ty = {}", ty_to_string(tcx, cbox_ty)); - - // Copy expr values into boxed bindings. - let mut bcx = bcx; - for (i, bv) in bound_values.into_iter().enumerate() { - debug!("Copy {} into closure", bv.to_string(ccx)); - - if ccx.sess().asm_comments() { - add_comment(bcx, &format!("Copy {} into closure", - bv.to_string(ccx))[]); - } - - let bound_data = GEPi(bcx, llbox, &[0u, abi::BOX_FIELD_BODY, i]); - - match bv.action { - ast::CaptureByValue => { - bcx = bv.datum.store_to(bcx, bound_data); - } - ast::CaptureByRef => { - Store(bcx, bv.datum.to_llref(), bound_data); - } - } - } - - ClosureResult { llbox: llbox, cdata_ty: cdata_ty, bcx: bcx } -} - -// Given a context and a list of upvars, build a closure. This just -// collects the upvars and packages them up for store_environment. -fn build_closure<'blk, 'tcx>(bcx0: Block<'blk, 'tcx>, - freevar_mode: ast::CaptureClause, - freevars: &Vec) - -> ClosureResult<'blk, 'tcx> { - let _icx = push_ctxt("closure::build_closure"); - - // If we need to, package up the iterator body to call - let bcx = bcx0; - - // Package up the captured upvars - let mut env_vals = Vec::new(); - for freevar in freevars.iter() { - let datum = expr::trans_local_var(bcx, freevar.def); - env_vals.push(EnvValue {action: freevar_mode, datum: datum}); - } - - store_environment(bcx, env_vals) -} - -// Given an enclosing block context, a new function context, a closure type, -// and a list of upvars, generate code to load and populate the environment -// with the upvars and type descriptors. -fn load_environment<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, - cdata_ty: Ty<'tcx>, - freevars: &[ty::Freevar], - store: ty::TraitStore) - -> Block<'blk, 'tcx> { - let _icx = push_ctxt("closure::load_environment"); - - // Load a pointer to the closure data, skipping over the box header: - let llcdata = at_box_body(bcx, cdata_ty, bcx.fcx.llenv.unwrap()); - - // Store the pointer to closure data in an alloca for debug info because that's what the - // llvm.dbg.declare intrinsic expects - let env_pointer_alloca = if bcx.sess().opts.debuginfo == FullDebugInfo { - let alloc = alloc_ty(bcx, ty::mk_mut_ptr(bcx.tcx(), cdata_ty), "__debuginfo_env_ptr"); - Store(bcx, llcdata, alloc); - Some(alloc) - } else { - None - }; - - // Populate the upvars from the environment - let mut i = 0u; - for freevar in freevars.iter() { - let mut upvarptr = GEPi(bcx, llcdata, &[0u, i]); - let captured_by_ref = match store { - ty::RegionTraitStore(..) => { - upvarptr = Load(bcx, upvarptr); - true - } - ty::UniqTraitStore => false - }; - let def_id = freevar.def.def_id(); - - bcx.fcx.llupvars.borrow_mut().insert(def_id.node, upvarptr); - if let Some(env_pointer_alloca) = env_pointer_alloca { - debuginfo::create_captured_var_metadata( - bcx, - def_id.node, - env_pointer_alloca, - i, - captured_by_ref, - freevar.span); - } - - i += 1u; - } - - bcx -} fn load_unboxed_closure_environment<'blk, 'tcx>( bcx: Block<'blk, 'tcx>, @@ -281,7 +37,7 @@ fn load_unboxed_closure_environment<'blk, 'tcx>( freevar_mode: ast::CaptureClause, freevars: &[ty::Freevar]) -> Block<'blk, 'tcx> { - let _icx = push_ctxt("closure::load_environment"); + let _icx = push_ctxt("closure::load_unboxed_closure_environment"); // Special case for small by-value selfs. let closure_id = ast_util::local_def(bcx.fcx.id); @@ -341,17 +97,9 @@ fn load_unboxed_closure_environment<'blk, 'tcx>( bcx } -fn fill_fn_pair(bcx: Block, pair: ValueRef, llfn: ValueRef, llenvptr: ValueRef) { - Store(bcx, llfn, GEPi(bcx, pair, &[0u, abi::FAT_PTR_ADDR])); - let llenvptr = PointerCast(bcx, llenvptr, Type::i8p(bcx.ccx())); - Store(bcx, llenvptr, GEPi(bcx, pair, &[0u, abi::FAT_PTR_EXTRA])); -} - #[derive(PartialEq)] pub enum ClosureKind<'tcx> { NotClosure, - // See load_environment. - BoxedClosure(Ty<'tcx>, ty::TraitStore), // See load_unboxed_closure_environment. UnboxedClosure(ast::CaptureClause) } @@ -379,9 +127,6 @@ impl<'a, 'tcx> ClosureEnv<'a, 'tcx> { match self.kind { NotClosure => bcx, - BoxedClosure(cdata_ty, store) => { - load_environment(bcx, cdata_ty, self.freevars, store) - } UnboxedClosure(freevar_mode) => { load_unboxed_closure_environment(bcx, arg_scope, freevar_mode, self.freevars) } @@ -389,67 +134,6 @@ impl<'a, 'tcx> ClosureEnv<'a, 'tcx> { } } -/// Translates the body of a closure expression. -/// -/// - `store` -/// - `decl` -/// - `body` -/// - `id`: The id of the closure expression. -/// - `cap_clause`: information about captured variables, if any. -/// - `dest`: where to write the closure value, which must be a -/// (fn ptr, env) pair -pub fn trans_expr_fn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, - store: ty::TraitStore, - decl: &ast::FnDecl, - body: &ast::Block, - id: ast::NodeId, - dest: expr::Dest) - -> Block<'blk, 'tcx> { - let _icx = push_ctxt("closure::trans_expr_fn"); - - let dest_addr = match dest { - expr::SaveIn(p) => p, - expr::Ignore => { - return bcx; // closure construction is non-side-effecting - } - }; - - let ccx = bcx.ccx(); - let tcx = bcx.tcx(); - let fty = node_id_type(bcx, id); - let s = tcx.map.with_path(id, |path| { - mangle_internal_name_by_path_and_seq(path, "closure") - }); - let llfn = decl_internal_rust_fn(ccx, fty, &s[]); - - // set an inline hint for all closures - set_inline_hint(llfn); - - let freevar_mode = tcx.capture_mode(id); - let freevars: Vec = - ty::with_freevars(tcx, id, |fv| fv.iter().map(|&fv| fv).collect()); - - let ClosureResult { - llbox, - cdata_ty, - bcx - } = build_closure(bcx, freevar_mode, &freevars); - - trans_closure(ccx, - decl, - body, - llfn, - bcx.fcx.param_substs, - id, - &[], - ty::erase_late_bound_regions(ccx.tcx(), &ty::ty_fn_ret(fty)), - ty::ty_fn_abi(fty), - ClosureEnv::new(&freevars[], - BoxedClosure(cdata_ty, store))); - fill_fn_pair(bcx, dest_addr, llfn, llbox); - bcx -} - /// Returns the LLVM function declaration for an unboxed closure, creating it /// if necessary. If the ID does not correspond to a closure ID, returns None. pub fn get_or_create_declaration_if_unboxed_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs index 312fd33ef1ff..3bc851c55953 100644 --- a/src/librustc_trans/trans/common.rs +++ b/src/librustc_trans/trans/common.rs @@ -30,7 +30,7 @@ use trans::build; use trans::cleanup; use trans::consts; use trans::datum; -use trans::debuginfo; +use trans::debuginfo::{self, DebugLoc}; use trans::machine; use trans::monomorphize; use trans::type_::Type; @@ -275,7 +275,7 @@ pub fn return_type_is_void(ccx: &CrateContext, ty: Ty) -> bool { /// Generates a unique symbol based off the name given. This is used to create /// unique symbols for things like closures. pub fn gensym_name(name: &str) -> PathElem { - let num = token::gensym(name).uint(); + let num = token::gensym(name).usize(); // use one colon which will get translated to a period by the mangler, and // we're guaranteed that `num` is globally unique for this crate. PathName(token::gensym(&format!("{}:{}", name, num)[])) @@ -317,13 +317,13 @@ pub struct tydesc_info<'tcx> { */ #[derive(Copy)] -pub struct NodeInfo { +pub struct NodeIdAndSpan { pub id: ast::NodeId, pub span: Span, } -pub fn expr_info(expr: &ast::Expr) -> NodeInfo { - NodeInfo { id: expr.id, span: expr.span } +pub fn expr_info(expr: &ast::Expr) -> NodeIdAndSpan { + NodeIdAndSpan { id: expr.id, span: expr.span } } pub struct BuilderRef_res { @@ -517,7 +517,7 @@ impl<'a, 'tcx> FunctionContext<'a, 'tcx> { let mut reachable = false; for bcx in in_cxs.iter() { if !bcx.unreachable.get() { - build::Br(*bcx, out.llbb); + build::Br(*bcx, out.llbb, DebugLoc::None); reachable = true; } } @@ -848,7 +848,7 @@ pub fn C_cstr(cx: &CrateContext, s: InternedString, null_terminated: bool) -> Va !null_terminated as Bool); let gsym = token::gensym("str"); - let buf = CString::from_vec(format!("str{}", gsym.uint()).into_bytes()); + let buf = CString::from_vec(format!("str{}", gsym.usize()).into_bytes()); let g = llvm::LLVMAddGlobal(cx.llmod(), val_ty(sc).to_ref(), buf.as_ptr()); llvm::LLVMSetInitializer(g, sc); llvm::LLVMSetGlobalConstant(g, True); @@ -873,7 +873,7 @@ pub fn C_binary_slice(cx: &CrateContext, data: &[u8]) -> ValueRef { let lldata = C_bytes(cx, data); let gsym = token::gensym("binary"); - let name = format!("binary{}", gsym.uint()); + let name = format!("binary{}", gsym.usize()); let name = CString::from_vec(name.into_bytes()); let g = llvm::LLVMAddGlobal(cx.llmod(), val_ty(lldata).to_ref(), name.as_ptr()); diff --git a/src/librustc_trans/trans/controlflow.rs b/src/librustc_trans/trans/controlflow.rs index 5dc939dc2025..bea8a7599715 100644 --- a/src/librustc_trans/trans/controlflow.rs +++ b/src/librustc_trans/trans/controlflow.rs @@ -22,6 +22,7 @@ use trans::common::*; use trans::consts; use trans::datum; use trans::debuginfo; +use trans::debuginfo::{DebugLoc, ToDebugLoc}; use trans::expr; use trans::meth; use trans::type_::Type; @@ -188,6 +189,8 @@ pub fn trans_if<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let then_bcx_out = trans_block(then_bcx_in, &*thn, dest); trans::debuginfo::clear_source_location(bcx.fcx); + let cond_source_loc = cond.debug_loc(); + let next_bcx; match els { Some(elexpr) => { @@ -195,13 +198,13 @@ pub fn trans_if<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let else_bcx_out = expr::trans_into(else_bcx_in, &*elexpr, dest); next_bcx = bcx.fcx.join_blocks(if_id, &[then_bcx_out, else_bcx_out]); - CondBr(bcx, cond_val, then_bcx_in.llbb, else_bcx_in.llbb); + CondBr(bcx, cond_val, then_bcx_in.llbb, else_bcx_in.llbb, cond_source_loc); } None => { next_bcx = bcx.fcx.new_id_block("next-block", if_id); - Br(then_bcx_out, next_bcx.llbb); - CondBr(bcx, cond_val, then_bcx_in.llbb, next_bcx.llbb); + Br(then_bcx_out, next_bcx.llbb, DebugLoc::None); + CondBr(bcx, cond_val, then_bcx_in.llbb, next_bcx.llbb, cond_source_loc); } } @@ -213,7 +216,7 @@ pub fn trans_if<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } pub fn trans_while<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, - loop_id: ast::NodeId, + loop_expr: &ast::Expr, cond: &ast::Expr, body: &ast::Block) -> Block<'blk, 'tcx> { @@ -231,33 +234,34 @@ pub fn trans_while<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, // | body_bcx_out --+ // next_bcx_in - let next_bcx_in = fcx.new_id_block("while_exit", loop_id); + let next_bcx_in = fcx.new_id_block("while_exit", loop_expr.id); let cond_bcx_in = fcx.new_id_block("while_cond", cond.id); let body_bcx_in = fcx.new_id_block("while_body", body.id); - fcx.push_loop_cleanup_scope(loop_id, [next_bcx_in, cond_bcx_in]); + fcx.push_loop_cleanup_scope(loop_expr.id, [next_bcx_in, cond_bcx_in]); - Br(bcx, cond_bcx_in.llbb); + Br(bcx, cond_bcx_in.llbb, loop_expr.debug_loc()); // compile the block where we will handle loop cleanups - let cleanup_llbb = fcx.normal_exit_block(loop_id, cleanup::EXIT_BREAK); + let cleanup_llbb = fcx.normal_exit_block(loop_expr.id, cleanup::EXIT_BREAK); // compile the condition let Result {bcx: cond_bcx_out, val: cond_val} = expr::trans(cond_bcx_in, cond).to_llbool(); - CondBr(cond_bcx_out, cond_val, body_bcx_in.llbb, cleanup_llbb); + + CondBr(cond_bcx_out, cond_val, body_bcx_in.llbb, cleanup_llbb, cond.debug_loc()); // loop body: let body_bcx_out = trans_block(body_bcx_in, body, expr::Ignore); - Br(body_bcx_out, cond_bcx_in.llbb); + Br(body_bcx_out, cond_bcx_in.llbb, DebugLoc::None); - fcx.pop_loop_cleanup_scope(loop_id); + fcx.pop_loop_cleanup_scope(loop_expr.id); return next_bcx_in; } /// Translates a `for` loop. pub fn trans_for<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, - loop_info: NodeInfo, + loop_info: NodeIdAndSpan, pat: &ast::Pat, head: &ast::Expr, body: &ast::Block) @@ -292,7 +296,7 @@ pub fn trans_for<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, let body_bcx_in = bcx.fcx.new_id_block("for_body", body.id); bcx.fcx.push_loop_cleanup_scope(loop_info.id, [next_bcx_in, loopback_bcx_in]); - Br(bcx, loopback_bcx_in.llbb); + Br(bcx, loopback_bcx_in.llbb, DebugLoc::None); let cleanup_llbb = bcx.fcx.normal_exit_block(loop_info.id, cleanup::EXIT_BREAK); @@ -347,7 +351,7 @@ pub fn trans_for<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, None); let i1_type = Type::i1(loopback_bcx_out.ccx()); let llcondition = Trunc(loopback_bcx_out, lldiscriminant, i1_type); - CondBr(loopback_bcx_out, llcondition, body_bcx_in.llbb, cleanup_llbb); + CondBr(loopback_bcx_out, llcondition, body_bcx_in.llbb, cleanup_llbb, DebugLoc::None); // Now we're in the body. Unpack the `Option` value into the programmer- // supplied pattern. @@ -377,7 +381,7 @@ pub fn trans_for<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, body_bcx_out.fcx .pop_and_trans_custom_cleanup_scope(body_bcx_out, option_cleanup_scope); - Br(body_bcx_out, loopback_bcx_in.llbb); + Br(body_bcx_out, loopback_bcx_in.llbb, DebugLoc::None); // Codegen cleanups and leave. next_bcx_in.fcx.pop_loop_cleanup_scope(loop_info.id); @@ -385,7 +389,7 @@ pub fn trans_for<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, } pub fn trans_loop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, - loop_id: ast::NodeId, + loop_expr: &ast::Expr, body: &ast::Block) -> Block<'blk, 'tcx> { let _icx = push_ctxt("trans_loop"); @@ -402,22 +406,22 @@ pub fn trans_loop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, // Links between body_bcx_in and next_bcx are created by // break statements. - let next_bcx_in = bcx.fcx.new_id_block("loop_exit", loop_id); + let next_bcx_in = bcx.fcx.new_id_block("loop_exit", loop_expr.id); let body_bcx_in = bcx.fcx.new_id_block("loop_body", body.id); - fcx.push_loop_cleanup_scope(loop_id, [next_bcx_in, body_bcx_in]); + fcx.push_loop_cleanup_scope(loop_expr.id, [next_bcx_in, body_bcx_in]); - Br(bcx, body_bcx_in.llbb); + Br(bcx, body_bcx_in.llbb, loop_expr.debug_loc()); let body_bcx_out = trans_block(body_bcx_in, body, expr::Ignore); - Br(body_bcx_out, body_bcx_in.llbb); + Br(body_bcx_out, body_bcx_in.llbb, DebugLoc::None); - fcx.pop_loop_cleanup_scope(loop_id); + fcx.pop_loop_cleanup_scope(loop_expr.id); return next_bcx_in; } pub fn trans_break_cont<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, - expr_id: ast::NodeId, + expr: &ast::Expr, opt_label: Option, exit: uint) -> Block<'blk, 'tcx> { @@ -432,7 +436,7 @@ pub fn trans_break_cont<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let loop_id = match opt_label { None => fcx.top_loop_scope(), Some(_) => { - match bcx.tcx().def_map.borrow().get(&expr_id) { + match bcx.tcx().def_map.borrow().get(&expr.id) { Some(&def::DefLabel(loop_id)) => loop_id, ref r => { bcx.tcx().sess.bug(&format!("{:?} in def-map for label", @@ -444,39 +448,40 @@ pub fn trans_break_cont<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, // Generate appropriate cleanup code and branch let cleanup_llbb = fcx.normal_exit_block(loop_id, exit); - Br(bcx, cleanup_llbb); + Br(bcx, cleanup_llbb, expr.debug_loc()); Unreachable(bcx); // anything afterwards should be ignored return bcx; } pub fn trans_break<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, - expr_id: ast::NodeId, + expr: &ast::Expr, label_opt: Option) -> Block<'blk, 'tcx> { - return trans_break_cont(bcx, expr_id, label_opt, cleanup::EXIT_BREAK); + return trans_break_cont(bcx, expr, label_opt, cleanup::EXIT_BREAK); } pub fn trans_cont<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, - expr_id: ast::NodeId, + expr: &ast::Expr, label_opt: Option) -> Block<'blk, 'tcx> { - return trans_break_cont(bcx, expr_id, label_opt, cleanup::EXIT_LOOP); + return trans_break_cont(bcx, expr, label_opt, cleanup::EXIT_LOOP); } pub fn trans_ret<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, - e: Option<&ast::Expr>) + return_expr: &ast::Expr, + retval_expr: Option<&ast::Expr>) -> Block<'blk, 'tcx> { let _icx = push_ctxt("trans_ret"); let fcx = bcx.fcx; let mut bcx = bcx; - let dest = match (fcx.llretslotptr.get(), e) { - (Some(_), Some(e)) => { - let ret_ty = expr_ty(bcx, &*e); + let dest = match (fcx.llretslotptr.get(), retval_expr) { + (Some(_), Some(retval_expr)) => { + let ret_ty = expr_ty(bcx, &*retval_expr); expr::SaveIn(fcx.get_ret_slot(bcx, ty::FnConverging(ret_ty), "ret_slot")) } _ => expr::Ignore, }; - if let Some(x) = e { + if let Some(x) = retval_expr { bcx = expr::trans_into(bcx, &*x, dest); match dest { expr::SaveIn(slot) if fcx.needs_ret_allocas => { @@ -486,7 +491,7 @@ pub fn trans_ret<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } } let cleanup_llbb = fcx.return_exit_block(); - Br(bcx, cleanup_llbb); + Br(bcx, cleanup_llbb, return_expr.debug_loc()); Unreachable(bcx); return bcx; } diff --git a/src/librustc_trans/trans/datum.rs b/src/librustc_trans/trans/datum.rs index 8b52732f4ee9..cba12babb9b1 100644 --- a/src/librustc_trans/trans/datum.rs +++ b/src/librustc_trans/trans/datum.rs @@ -481,7 +481,7 @@ impl<'tcx> Datum<'tcx, Lvalue> { } /// Generic methods applicable to any sort of datum. -impl<'tcx, K: KindOps + fmt::Show> Datum<'tcx, K> { +impl<'tcx, K: KindOps + fmt::Debug> Datum<'tcx, K> { pub fn new(val: ValueRef, ty: Ty<'tcx>, kind: K) -> Datum<'tcx, K> { Datum { val: val, ty: ty, kind: kind } } @@ -591,7 +591,7 @@ impl<'blk, 'tcx, K> DatumBlock<'blk, 'tcx, K> { } } -impl<'blk, 'tcx, K: KindOps + fmt::Show> DatumBlock<'blk, 'tcx, K> { +impl<'blk, 'tcx, K: KindOps + fmt::Debug> DatumBlock<'blk, 'tcx, K> { pub fn to_expr_datumblock(self) -> DatumBlock<'blk, 'tcx, Expr> { DatumBlock::new(self.bcx, self.datum.to_expr_datum()) } diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs index 2f01f0328e28..39413d634824 100644 --- a/src/librustc_trans/trans/debuginfo.rs +++ b/src/librustc_trans/trans/debuginfo.rs @@ -188,7 +188,7 @@ use self::MemberOffset::*; use self::MemberDescriptionFactory::*; use self::RecursiveTypeDescription::*; use self::EnumDiscriminantInfo::*; -use self::DebugLocation::*; +use self::InternalDebugLocation::*; use llvm; use llvm::{ModuleRef, ContextRef, ValueRef}; @@ -196,7 +196,8 @@ use llvm::debuginfo::*; use metadata::csearch; use middle::subst::{self, Substs}; use trans::{self, adt, machine, type_of}; -use trans::common::*; +use trans::common::{self, NodeIdAndSpan, CrateContext, FunctionContext, Block, + C_bytes, C_i32, C_i64, NormalizingUnboxedClosureTyper}; use trans::_match::{BindingInfo, TrByCopy, TrByMove, TrByRef}; use trans::monomorphize; use trans::type_::Type; @@ -551,28 +552,14 @@ impl<'tcx> TypeMap<'tcx> { closure_ty: ty::ClosureTy<'tcx>, unique_type_id: &mut String) { let ty::ClosureTy { unsafety, - onceness, - store, - ref bounds, ref sig, abi: _ } = closure_ty; + if unsafety == ast::Unsafety::Unsafe { unique_type_id.push_str("unsafe "); } - if onceness == ast::Once { - unique_type_id.push_str("once "); - } - - match store { - ty::UniqTraitStore => unique_type_id.push_str("~|"), - ty::RegionTraitStore(_, ast::MutMutable) => { - unique_type_id.push_str("&mut|") - } - ty::RegionTraitStore(_, ast::MutImmutable) => { - unique_type_id.push_str("&|") - } - }; + unique_type_id.push_str("|"); let sig = ty::erase_late_bound_regions(cx.tcx(), sig); @@ -601,18 +588,6 @@ impl<'tcx> TypeMap<'tcx> { unique_type_id.push_str("!"); } } - - unique_type_id.push(':'); - - for bound in bounds.builtin_bounds.iter() { - match bound { - ty::BoundSend => unique_type_id.push_str("Send"), - ty::BoundSized => unique_type_id.push_str("Sized"), - ty::BoundCopy => unique_type_id.push_str("Copy"), - ty::BoundSync => unique_type_id.push_str("Sync"), - }; - unique_type_id.push('+'); - } } // Get the UniqueTypeId for an enum variant. Enum variants are not really @@ -650,7 +625,7 @@ macro_rules! return_if_metadata_created_in_meantime { pub struct CrateDebugContext<'tcx> { llcontext: ContextRef, builder: DIBuilderRef, - current_debug_location: Cell, + current_debug_location: Cell, created_files: RefCell>, created_enum_disr_types: RefCell>, @@ -940,13 +915,14 @@ pub fn create_captured_var_metadata<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } }; - let variable_type = node_id_type(bcx, node_id); + let variable_type = common::node_id_type(bcx, node_id); let scope_metadata = bcx.fcx.debug_context.get_ref(cx, span).fn_metadata; // env_pointer is the alloca containing the pointer to the environment, // so it's type is **EnvironmentType. In order to find out the type of // the environment we have to "dereference" two times. - let llvm_env_data_type = val_ty(env_pointer).element_type().element_type(); + let llvm_env_data_type = common::val_ty(env_pointer).element_type() + .element_type(); let byte_offset_of_var_in_env = machine::llelement_offset(cx, llvm_env_data_type, env_index); @@ -1123,7 +1099,7 @@ pub fn get_cleanup_debug_loc_for_ast_node<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, node_id: ast::NodeId, node_span: Span, is_block: bool) - -> NodeInfo { + -> NodeIdAndSpan { // A debug location needs two things: // (1) A span (of which only the beginning will actually be used) // (2) An AST node-id which will be used to look up the lexical scope @@ -1163,7 +1139,7 @@ pub fn get_cleanup_debug_loc_for_ast_node<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, if let Some(code_snippet) = code_snippet { let bytes = code_snippet.as_bytes(); - if bytes.len() > 0 && &bytes[(bytes.len()-1)..] == b"}" { + if bytes.len() > 0 && &bytes[bytes.len()-1..] == b"}" { cleanup_span = Span { lo: node_span.hi - codemap::BytePos(1), hi: node_span.hi, @@ -1173,12 +1149,56 @@ pub fn get_cleanup_debug_loc_for_ast_node<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, } } - NodeInfo { + NodeIdAndSpan { id: node_id, span: cleanup_span } } +#[derive(Copy, Clone, PartialEq, Eq)] +pub enum DebugLoc { + At(ast::NodeId, Span), + None +} + +impl DebugLoc { + pub fn apply(&self, fcx: &FunctionContext) { + match *self { + DebugLoc::At(node_id, span) => { + set_source_location(fcx, node_id, span); + } + DebugLoc::None => { + clear_source_location(fcx); + } + } + } +} + +pub trait ToDebugLoc { + fn debug_loc(&self) -> DebugLoc; +} + +impl ToDebugLoc for ast::Expr { + fn debug_loc(&self) -> DebugLoc { + DebugLoc::At(self.id, self.span) + } +} + +impl ToDebugLoc for NodeIdAndSpan { + fn debug_loc(&self) -> DebugLoc { + DebugLoc::At(self.id, self.span) + } +} + +impl ToDebugLoc for Option { + fn debug_loc(&self) -> DebugLoc { + match *self { + Some(NodeIdAndSpan { id, span }) => DebugLoc::At(id, span), + None => DebugLoc::None + } + } +} + /// Sets the current debug location at the beginning of the span. /// /// Maps to a call to llvm::LLVMSetCurrentDebugLocation(...). The node_id @@ -1202,9 +1222,9 @@ pub fn set_source_location(fcx: &FunctionContext, let loc = span_start(cx, span); let scope = scope_metadata(fcx, node_id, span); - set_debug_location(cx, DebugLocation::new(scope, - loc.line, - loc.col.to_uint())); + set_debug_location(cx, InternalDebugLocation::new(scope, + loc.line, + loc.col.to_usize())); } else { set_debug_location(cx, UnknownLocation); } @@ -1615,8 +1635,8 @@ fn compile_unit_metadata(cx: &CrateContext) -> DIDescriptor { let prefix: &[u8] = &[dotdot[0], ::std::path::SEP_BYTE]; let mut path_bytes = p.as_vec().to_vec(); - if path_bytes.slice_to(2) != prefix && - path_bytes.slice_to(2) != dotdot { + if &path_bytes[..2] != prefix && + &path_bytes[..2] != dotdot { path_bytes.insert(0, prefix[0]); path_bytes.insert(1, prefix[1]); } @@ -1714,9 +1734,9 @@ fn declare_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ) }; - set_debug_location(cx, DebugLocation::new(scope_metadata, - loc.line, - loc.col.to_uint())); + set_debug_location(cx, InternalDebugLocation::new(scope_metadata, + loc.line, + loc.col.to_usize())); unsafe { let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd( DIB(cx), @@ -1752,7 +1772,7 @@ fn file_metadata(cx: &CrateContext, full_path: &str) -> DIFile { let work_dir = cx.sess().working_dir.as_str().unwrap(); let file_name = if full_path.starts_with(work_dir) { - &full_path[(work_dir.len() + 1u)..full_path.len()] + &full_path[work_dir.len() + 1u..full_path.len()] } else { full_path }; @@ -2068,7 +2088,13 @@ fn prepare_struct_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, unique_type_id, containing_scope); - let fields = ty::struct_fields(cx.tcx(), def_id, substs); + let mut fields = ty::struct_fields(cx.tcx(), def_id, substs); + + // The `Ty` values returned by `ty::struct_fields` can still contain + // `ty_projection` variants, so normalize those away. + for field in fields.iter_mut() { + field.mt.ty = monomorphize::normalize_associated_type(cx.tcx(), &field.mt.ty); + } create_and_register_recursive_type_forward_declaration( cx, @@ -3095,13 +3121,13 @@ impl MetadataCreationResult { } #[derive(Copy, PartialEq)] -enum DebugLocation { +enum InternalDebugLocation { KnownLocation { scope: DIScope, line: uint, col: uint }, UnknownLocation } -impl DebugLocation { - fn new(scope: DIScope, line: uint, col: uint) -> DebugLocation { +impl InternalDebugLocation { + fn new(scope: DIScope, line: uint, col: uint) -> InternalDebugLocation { KnownLocation { scope: scope, line: line, @@ -3110,7 +3136,7 @@ impl DebugLocation { } } -fn set_debug_location(cx: &CrateContext, debug_location: DebugLocation) { +fn set_debug_location(cx: &CrateContext, debug_location: InternalDebugLocation) { if debug_location == debug_context(cx).current_debug_location.get() { return; } @@ -3279,7 +3305,7 @@ fn create_scope_map(cx: &CrateContext, parent_scope, file_metadata, loc.line as c_uint, - loc.col.to_uint() as c_uint) + loc.col.to_usize() as c_uint) }; scope_stack.push(ScopeStackEntry { scope_metadata: scope_metadata, @@ -3401,7 +3427,7 @@ fn create_scope_map(cx: &CrateContext, parent_scope, file_metadata, loc.line as c_uint, - loc.col.to_uint() as c_uint) + loc.col.to_usize() as c_uint) }; scope_stack.push(ScopeStackEntry { @@ -4122,4 +4148,3 @@ fn needs_gdb_debug_scripts_section(ccx: &CrateContext) -> bool { !ccx.sess().target.target.options.is_like_windows && ccx.sess().opts.debuginfo != NoDebugInfo } - diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs index 11d1c7e67968..4ebaf91d1117 100644 --- a/src/librustc_trans/trans/expr.rs +++ b/src/librustc_trans/trans/expr.rs @@ -46,7 +46,7 @@ use trans::build::*; use trans::cleanup::{self, CleanupMethods}; use trans::common::*; use trans::datum::*; -use trans::debuginfo; +use trans::debuginfo::{self, DebugLoc, ToDebugLoc}; use trans::glue; use trans::machine; use trans::meth; @@ -65,7 +65,6 @@ use trans::machine::{llsize_of, llsize_of_alloc}; use trans::type_::Type; use syntax::{ast, ast_util, codemap}; -use syntax::print::pprust::{expr_to_string}; use syntax::ptr::P; use syntax::parse::token; use std::rc::Rc; @@ -779,7 +778,8 @@ fn trans_index<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let expected = Call(bcx, expect, &[bounds_check, C_bool(ccx, false)], - None); + None, + index_expr.debug_loc()); bcx = with_cond(bcx, expected, |bcx| { controlflow::trans_fail_bounds_check(bcx, index_expr.span, @@ -890,10 +890,10 @@ fn trans_rvalue_stmt_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, trans_into(bcx, &**e, Ignore) } ast::ExprBreak(label_opt) => { - controlflow::trans_break(bcx, expr.id, label_opt) + controlflow::trans_break(bcx, expr, label_opt) } ast::ExprAgain(label_opt) => { - controlflow::trans_cont(bcx, expr.id, label_opt) + controlflow::trans_cont(bcx, expr, label_opt) } ast::ExprRet(ref ex) => { // Check to see if the return expression itself is reachable. @@ -905,7 +905,7 @@ fn trans_rvalue_stmt_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, }; if reachable { - controlflow::trans_ret(bcx, ex.as_ref().map(|e| &**e)) + controlflow::trans_ret(bcx, expr, ex.as_ref().map(|e| &**e)) } else { // If it's not reachable, just translate the inner expression // directly. This avoids having to manage a return slot when @@ -921,7 +921,7 @@ fn trans_rvalue_stmt_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } } ast::ExprWhile(ref cond, ref body, _) => { - controlflow::trans_while(bcx, expr.id, &**cond, &**body) + controlflow::trans_while(bcx, expr, &**cond, &**body) } ast::ExprForLoop(ref pat, ref head, ref body, _) => { controlflow::trans_for(bcx, @@ -931,7 +931,7 @@ fn trans_rvalue_stmt_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, &**body) } ast::ExprLoop(ref body, _) => { - controlflow::trans_loop(bcx, expr.id, &**body) + controlflow::trans_loop(bcx, expr, &**body) } ast::ExprAssign(ref dst, ref src) => { let src_datum = unpack_datum!(bcx, trans(bcx, &**src)); @@ -960,7 +960,7 @@ fn trans_rvalue_stmt_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, bcx = glue::drop_ty(bcx, dst_datum.val, dst_datum.ty, - Some(NodeInfo { id: expr.id, span: expr.span })); + expr.debug_loc()); src_datum.store_to(bcx, dst_datum.val) } else { src_datum.store_to(bcx, dst_datum.val) @@ -1078,7 +1078,7 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, &numbered_fields[], None, dest, - Some(NodeInfo { id: expr.id, span: expr.span })) + expr.debug_loc()) } ast::ExprLit(ref lit) => { match lit.node { @@ -1102,17 +1102,7 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, // closure or an older, legacy style closure. Store this // into a variable to ensure the the RefCell-lock is // released before we recurse. - let is_unboxed_closure = - bcx.tcx().unboxed_closures.borrow().contains_key(&ast_util::local_def(expr.id)); - if is_unboxed_closure { - closure::trans_unboxed_closure(bcx, &**decl, &**body, expr.id, dest) - } else { - let expr_ty = expr_ty(bcx, expr); - let store = ty::ty_closure_store(expr_ty); - debug!("translating block function {} with type {}", - expr_to_string(expr), expr_ty.repr(tcx)); - closure::trans_expr_fn(bcx, store, &**decl, &**body, expr.id, dest) - } + closure::trans_unboxed_closure(bcx, &**decl, &**body, expr.id, dest) } ast::ExprCall(ref f, ref args) => { if bcx.tcx().is_method_call(expr.id) { @@ -1417,7 +1407,7 @@ fn trans_struct<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, numbered_fields.as_slice(), optbase, dest, - Some(NodeInfo { id: expr_id, span: expr_span })) + DebugLoc::At(expr_id, expr_span)) }) } @@ -1448,18 +1438,13 @@ pub fn trans_adt<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, fields: &[(uint, &ast::Expr)], optbase: Option>, dest: Dest, - source_location: Option) + debug_location: DebugLoc) -> Block<'blk, 'tcx> { let _icx = push_ctxt("trans_adt"); let fcx = bcx.fcx; let repr = adt::represent_type(bcx.ccx(), ty); - match source_location { - Some(src_loc) => debuginfo::set_source_location(bcx.fcx, - src_loc.id, - src_loc.span), - None => {} - }; + debug_location.apply(bcx.fcx); // If we don't care about the result, just make a // temporary stack slot @@ -1494,12 +1479,7 @@ pub fn trans_adt<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, } } - match source_location { - Some(src_loc) => debuginfo::set_source_location(bcx.fcx, - src_loc.id, - src_loc.span), - None => {} - }; + debug_location.apply(bcx.fcx); if ty::type_is_simd(bcx.tcx(), ty) { // This is the constructor of a SIMD type, such types are @@ -1540,7 +1520,7 @@ pub fn trans_adt<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, match dest { SaveIn(_) => bcx, Ignore => { - bcx = glue::drop_ty(bcx, addr, ty, source_location); + bcx = glue::drop_ty(bcx, addr, ty, debug_location); base::call_lifetime_end(bcx, addr); bcx } @@ -1579,10 +1559,12 @@ fn trans_unary<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let un_ty = expr_ty(bcx, expr); + let debug_loc = expr.debug_loc(); + match op { ast::UnNot => { let datum = unpack_datum!(bcx, trans(bcx, sub_expr)); - let llresult = Not(bcx, datum.to_llscalarish(bcx)); + let llresult = Not(bcx, datum.to_llscalarish(bcx), debug_loc); immediate_rvalue_bcx(bcx, llresult, un_ty).to_expr_datumblock() } ast::UnNeg => { @@ -1590,9 +1572,9 @@ fn trans_unary<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let val = datum.to_llscalarish(bcx); let llneg = { if ty::type_is_fp(un_ty) { - FNeg(bcx, val) + FNeg(bcx, val, debug_loc) } else { - Neg(bcx, val) + Neg(bcx, val, debug_loc) } }; immediate_rvalue_bcx(bcx, llneg, un_ty).to_expr_datumblock() @@ -1691,56 +1673,69 @@ fn trans_eager_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let rhs = base::cast_shift_expr_rhs(bcx, op, lhs, rhs); + let binop_debug_loc = binop_expr.debug_loc(); + let mut bcx = bcx; let val = match op { ast::BiAdd => { - if is_float { FAdd(bcx, lhs, rhs) } - else { Add(bcx, lhs, rhs) } + if is_float { + FAdd(bcx, lhs, rhs, binop_debug_loc) + } else { + Add(bcx, lhs, rhs, binop_debug_loc) + } } ast::BiSub => { - if is_float { FSub(bcx, lhs, rhs) } - else { Sub(bcx, lhs, rhs) } + if is_float { + FSub(bcx, lhs, rhs, binop_debug_loc) + } else { + Sub(bcx, lhs, rhs, binop_debug_loc) + } } ast::BiMul => { - if is_float { FMul(bcx, lhs, rhs) } - else { Mul(bcx, lhs, rhs) } + if is_float { + FMul(bcx, lhs, rhs, binop_debug_loc) + } else { + Mul(bcx, lhs, rhs, binop_debug_loc) + } } ast::BiDiv => { if is_float { - FDiv(bcx, lhs, rhs) + FDiv(bcx, lhs, rhs, binop_debug_loc) } else { // Only zero-check integers; fp /0 is NaN bcx = base::fail_if_zero_or_overflows(bcx, binop_expr.span, op, lhs, rhs, rhs_t); if is_signed { - SDiv(bcx, lhs, rhs) + SDiv(bcx, lhs, rhs, binop_debug_loc) } else { - UDiv(bcx, lhs, rhs) + UDiv(bcx, lhs, rhs, binop_debug_loc) } } } ast::BiRem => { if is_float { - FRem(bcx, lhs, rhs) + FRem(bcx, lhs, rhs, binop_debug_loc) } else { // Only zero-check integers; fp %0 is NaN bcx = base::fail_if_zero_or_overflows(bcx, binop_expr.span, op, lhs, rhs, rhs_t); if is_signed { - SRem(bcx, lhs, rhs) + SRem(bcx, lhs, rhs, binop_debug_loc) } else { - URem(bcx, lhs, rhs) + URem(bcx, lhs, rhs, binop_debug_loc) } } } - ast::BiBitOr => Or(bcx, lhs, rhs), - ast::BiBitAnd => And(bcx, lhs, rhs), - ast::BiBitXor => Xor(bcx, lhs, rhs), - ast::BiShl => Shl(bcx, lhs, rhs), + ast::BiBitOr => Or(bcx, lhs, rhs, binop_debug_loc), + ast::BiBitAnd => And(bcx, lhs, rhs, binop_debug_loc), + ast::BiBitXor => Xor(bcx, lhs, rhs, binop_debug_loc), + ast::BiShl => Shl(bcx, lhs, rhs, binop_debug_loc), ast::BiShr => { if is_signed { - AShr(bcx, lhs, rhs) - } else { LShr(bcx, lhs, rhs) } + AShr(bcx, lhs, rhs, binop_debug_loc) + } else { + LShr(bcx, lhs, rhs, binop_debug_loc) + } } ast::BiEq | ast::BiNe | ast::BiLt | ast::BiGe | ast::BiLe | ast::BiGt => { if ty::type_is_scalar(rhs_t) { @@ -1786,8 +1781,8 @@ fn trans_lazy_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let before_rhs = fcx.new_id_block("before_rhs", b.id); match op { - lazy_and => CondBr(past_lhs, lhs, before_rhs.llbb, join.llbb), - lazy_or => CondBr(past_lhs, lhs, join.llbb, before_rhs.llbb) + lazy_and => CondBr(past_lhs, lhs, before_rhs.llbb, join.llbb, DebugLoc::None), + lazy_or => CondBr(past_lhs, lhs, join.llbb, before_rhs.llbb, DebugLoc::None) } let DatumBlock {bcx: past_rhs, datum: rhs} = trans(before_rhs, b); @@ -1797,7 +1792,7 @@ fn trans_lazy_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, return immediate_rvalue_bcx(join, lhs, binop_ty).to_expr_datumblock(); } - Br(past_rhs, join.llbb); + Br(past_rhs, join.llbb, DebugLoc::None); let phi = Phi(join, Type::i1(bcx.ccx()), &[lhs, rhs], &[past_lhs.llbb, past_rhs.llbb]); diff --git a/src/librustc_trans/trans/glue.rs b/src/librustc_trans/trans/glue.rs index d3f3f34b76bb..fb2ee55940d0 100644 --- a/src/librustc_trans/trans/glue.rs +++ b/src/librustc_trans/trans/glue.rs @@ -29,7 +29,7 @@ use trans::cleanup::CleanupMethods; use trans::consts; use trans::common::*; use trans::datum; -use trans::debuginfo; +use trans::debuginfo::DebugLoc; use trans::expr; use trans::machine::*; use trans::tvec; @@ -106,7 +106,7 @@ pub fn get_drop_glue_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, pub fn drop_ty<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v: ValueRef, t: Ty<'tcx>, - source_location: Option) + debug_loc: DebugLoc) -> Block<'blk, 'tcx> { // NB: v is an *alias* of type t here, not a direct value. debug!("drop_ty(t={})", t.repr(bcx.tcx())); @@ -121,12 +121,7 @@ pub fn drop_ty<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v }; - match source_location { - Some(sl) => debuginfo::set_source_location(bcx.fcx, sl.id, sl.span), - None => debuginfo::clear_source_location(bcx.fcx) - }; - - Call(bcx, glue, &[ptr], None); + Call(bcx, glue, &[ptr], None, debug_loc); } bcx } @@ -134,12 +129,12 @@ pub fn drop_ty<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, pub fn drop_ty_immediate<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v: ValueRef, t: Ty<'tcx>, - source_location: Option) + debug_loc: DebugLoc) -> Block<'blk, 'tcx> { let _icx = push_ctxt("drop_ty_immediate"); let vp = alloca(bcx, type_of(bcx.ccx(), t), ""); store_ty(bcx, v, vp, t); - drop_ty(bcx, vp, t, source_location) + drop_ty(bcx, vp, t, debug_loc) } pub fn get_drop_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> ValueRef { @@ -295,7 +290,7 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, class_did, &[get_drop_glue_type(bcx.ccx(), t)], ty::mk_nil(bcx.tcx())); - let (_, variant_cx) = invoke(variant_cx, dtor_addr, &args[], dtor_ty, None); + let (_, variant_cx) = invoke(variant_cx, dtor_addr, &args[], dtor_ty, DebugLoc::None); variant_cx.fcx.pop_and_trans_custom_cleanup_scope(variant_cx, field_scope); variant_cx @@ -331,7 +326,7 @@ fn size_and_align_of_dst<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t: Ty<'tcx>, info: let (unsized_size, unsized_align) = size_and_align_of_dst(bcx, field_ty, info); // Return the sum of sizes and max of aligns. - let size = Add(bcx, sized_size, unsized_size); + let size = Add(bcx, sized_size, unsized_size, DebugLoc::None); let align = Select(bcx, ICmp(bcx, llvm::IntULT, sized_align, unsized_align), sized_align, @@ -353,7 +348,8 @@ fn size_and_align_of_dst<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t: Ty<'tcx>, info: let llunit_ty = sizing_type_of(bcx.ccx(), unit_ty); let unit_align = llalign_of_min(bcx.ccx(), llunit_ty); let unit_size = llsize_of_alloc(bcx.ccx(), llunit_ty); - (Mul(bcx, info, C_uint(bcx.ccx(), unit_size)), C_uint(bcx.ccx(), unit_align)) + (Mul(bcx, info, C_uint(bcx.ccx(), unit_size), DebugLoc::None), + C_uint(bcx.ccx(), unit_align)) } _ => bcx.sess().bug(&format!("Unexpected unsized type, found {}", bcx.ty_to_string(t))[]) @@ -384,7 +380,8 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, t: Ty<'tcx>) Call(bcx, dtor, &[PointerCast(bcx, lluniquevalue, Type::i8p(bcx.ccx()))], - None); + None, + DebugLoc::None); bcx }) } @@ -393,7 +390,7 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, t: Ty<'tcx>) let llbox = Load(bcx, llval); let not_null = IsNotNull(bcx, llbox); with_cond(bcx, not_null, |bcx| { - let bcx = drop_ty(bcx, v0, content_ty, None); + let bcx = drop_ty(bcx, v0, content_ty, DebugLoc::None); let info = GEPi(bcx, v0, &[0, abi::FAT_PTR_EXTRA]); let info = Load(bcx, info); let (llsize, llalign) = size_and_align_of_dst(bcx, content_ty, info); @@ -406,7 +403,7 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, t: Ty<'tcx>) let llbox = Load(bcx, llval); let not_null = IsNotNull(bcx, llbox); with_cond(bcx, not_null, |bcx| { - let bcx = drop_ty(bcx, llbox, content_ty, None); + let bcx = drop_ty(bcx, llbox, content_ty, DebugLoc::None); trans_exchange_free_ty(bcx, llbox, content_ty) }) } @@ -437,14 +434,16 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, t: Ty<'tcx>) } ty::NoDtor => { // No dtor? Just the default case - iter_structural_ty(bcx, v0, t, |bb, vv, tt| drop_ty(bb, vv, tt, None)) + iter_structural_ty(bcx, v0, t, |bb, vv, tt| drop_ty(bb, vv, tt, DebugLoc::None)) } } } - ty::ty_unboxed_closure(..) => iter_structural_ty(bcx, - v0, - t, - |bb, vv, tt| drop_ty(bb, vv, tt, None)), + ty::ty_unboxed_closure(..) => { + iter_structural_ty(bcx, + v0, + t, + |bb, vv, tt| drop_ty(bb, vv, tt, DebugLoc::None)) + } ty::ty_trait(..) => { // No need to do a null check here (as opposed to the Box(bcx: Block<'blk, 'tcx>, v0: ValueRef, t: Ty<'tcx>) Call(bcx, dtor, &[PointerCast(bcx, Load(bcx, lluniquevalue), Type::i8p(bcx.ccx()))], - None); + None, + DebugLoc::None); bcx }, ty::ty_vec(_, None) | ty::ty_str => { @@ -465,9 +465,11 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, t: Ty<'tcx>) }, _ => { assert!(type_is_sized(bcx.tcx(), t)); - if type_needs_drop(bcx.tcx(), t) && - ty::type_is_structural(t) { - iter_structural_ty(bcx, v0, t, |bb, vv, tt| drop_ty(bb, vv, tt, None)) + if type_needs_drop(bcx.tcx(), t) && ty::type_is_structural(t) { + iter_structural_ty(bcx, + v0, + t, + |bb, vv, tt| drop_ty(bb, vv, tt, DebugLoc::None)) } else { bcx } @@ -559,7 +561,7 @@ fn make_generic_glue<'a, 'tcx, F>(ccx: &CrateContext<'a, 'tcx>, let llrawptr0 = get_param(llfn, fcx.arg_pos(0) as c_uint); let bcx = helper(bcx, llrawptr0, t); - finish_fn(&fcx, bcx, ty::FnConverging(ty::mk_nil(ccx.tcx()))); + finish_fn(&fcx, bcx, ty::FnConverging(ty::mk_nil(ccx.tcx())), DebugLoc::None); llfn } diff --git a/src/librustc_trans/trans/intrinsic.rs b/src/librustc_trans/trans/intrinsic.rs index 771c51d629fb..9bee2c5bbc61 100644 --- a/src/librustc_trans/trans/intrinsic.rs +++ b/src/librustc_trans/trans/intrinsic.rs @@ -21,6 +21,7 @@ use trans::cleanup; use trans::cleanup::CleanupMethods; use trans::common::*; use trans::datum::*; +use trans::debuginfo::DebugLoc; use trans::expr; use trans::glue; use trans::type_of::*; @@ -149,9 +150,8 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, args: callee::CallArgs<'a, 'tcx>, dest: expr::Dest, substs: subst::Substs<'tcx>, - call_info: NodeInfo) - -> Result<'blk, 'tcx> -{ + call_info: NodeIdAndSpan) + -> Result<'blk, 'tcx> { let fcx = bcx.fcx; let ccx = fcx.ccx; let tcx = bcx.tcx(); @@ -270,10 +270,12 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, fcx.pop_custom_cleanup_scope(cleanup_scope); + let call_debug_location = DebugLoc::At(call_info.id, call_info.span); + // These are the only intrinsic functions that diverge. if name.get() == "abort" { let llfn = ccx.get_intrinsic(&("llvm.trap")); - Call(bcx, llfn, &[], None); + Call(bcx, llfn, &[], None, call_debug_location); Unreachable(bcx); return Result::new(bcx, C_undef(Type::nil(ccx).ptr_to())); } else if name.get() == "unreachable" { @@ -304,11 +306,11 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, let simple = get_simple_intrinsic(ccx, &*foreign_item); let llval = match (simple, name.get()) { (Some(llfn), _) => { - Call(bcx, llfn, llargs.as_slice(), None) + Call(bcx, llfn, llargs.as_slice(), None, call_debug_location) } (_, "breakpoint") => { let llfn = ccx.get_intrinsic(&("llvm.debugtrap")); - Call(bcx, llfn, &[], None) + Call(bcx, llfn, &[], None, call_debug_location) } (_, "size_of") => { let tp_ty = *substs.types.get(FnSpace, 0); @@ -384,29 +386,63 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, } (_, "copy_nonoverlapping_memory") => { - copy_intrinsic(bcx, false, false, *substs.types.get(FnSpace, 0), - llargs[0], llargs[1], llargs[2]) + copy_intrinsic(bcx, + false, + false, + *substs.types.get(FnSpace, 0), + llargs[0], + llargs[1], + llargs[2], + call_debug_location) } (_, "copy_memory") => { - copy_intrinsic(bcx, true, false, *substs.types.get(FnSpace, 0), - llargs[0], llargs[1], llargs[2]) + copy_intrinsic(bcx, + true, + false, + *substs.types.get(FnSpace, 0), + llargs[0], + llargs[1], + llargs[2], + call_debug_location) } (_, "set_memory") => { - memset_intrinsic(bcx, false, *substs.types.get(FnSpace, 0), - llargs[0], llargs[1], llargs[2]) + memset_intrinsic(bcx, + false, + *substs.types.get(FnSpace, 0), + llargs[0], + llargs[1], + llargs[2], + call_debug_location) } (_, "volatile_copy_nonoverlapping_memory") => { - copy_intrinsic(bcx, false, true, *substs.types.get(FnSpace, 0), - llargs[0], llargs[1], llargs[2]) + copy_intrinsic(bcx, + false, + true, + *substs.types.get(FnSpace, 0), + llargs[0], + llargs[1], + llargs[2], + call_debug_location) } (_, "volatile_copy_memory") => { - copy_intrinsic(bcx, true, true, *substs.types.get(FnSpace, 0), - llargs[0], llargs[1], llargs[2]) + copy_intrinsic(bcx, + true, + true, + *substs.types.get(FnSpace, 0), + llargs[0], + llargs[1], + llargs[2], + call_debug_location) } (_, "volatile_set_memory") => { - memset_intrinsic(bcx, true, *substs.types.get(FnSpace, 0), - llargs[0], llargs[1], llargs[2]) + memset_intrinsic(bcx, + true, + *substs.types.get(FnSpace, 0), + llargs[0], + llargs[1], + llargs[2], + call_debug_location) } (_, "volatile_load") => { VolatileLoad(bcx, llargs[0]) @@ -416,93 +452,208 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, C_nil(ccx) }, - (_, "ctlz8") => count_zeros_intrinsic(bcx, "llvm.ctlz.i8", llargs[0]), - (_, "ctlz16") => count_zeros_intrinsic(bcx, "llvm.ctlz.i16", llargs[0]), - (_, "ctlz32") => count_zeros_intrinsic(bcx, "llvm.ctlz.i32", llargs[0]), - (_, "ctlz64") => count_zeros_intrinsic(bcx, "llvm.ctlz.i64", llargs[0]), - (_, "cttz8") => count_zeros_intrinsic(bcx, "llvm.cttz.i8", llargs[0]), - (_, "cttz16") => count_zeros_intrinsic(bcx, "llvm.cttz.i16", llargs[0]), - (_, "cttz32") => count_zeros_intrinsic(bcx, "llvm.cttz.i32", llargs[0]), - (_, "cttz64") => count_zeros_intrinsic(bcx, "llvm.cttz.i64", llargs[0]), + (_, "ctlz8") => count_zeros_intrinsic(bcx, + "llvm.ctlz.i8", + llargs[0], + call_debug_location), + (_, "ctlz16") => count_zeros_intrinsic(bcx, + "llvm.ctlz.i16", + llargs[0], + call_debug_location), + (_, "ctlz32") => count_zeros_intrinsic(bcx, + "llvm.ctlz.i32", + llargs[0], + call_debug_location), + (_, "ctlz64") => count_zeros_intrinsic(bcx, + "llvm.ctlz.i64", + llargs[0], + call_debug_location), + (_, "cttz8") => count_zeros_intrinsic(bcx, + "llvm.cttz.i8", + llargs[0], + call_debug_location), + (_, "cttz16") => count_zeros_intrinsic(bcx, + "llvm.cttz.i16", + llargs[0], + call_debug_location), + (_, "cttz32") => count_zeros_intrinsic(bcx, + "llvm.cttz.i32", + llargs[0], + call_debug_location), + (_, "cttz64") => count_zeros_intrinsic(bcx, + "llvm.cttz.i64", + llargs[0], + call_debug_location), (_, "i8_add_with_overflow") => - with_overflow_intrinsic(bcx, "llvm.sadd.with.overflow.i8", ret_ty, - llargs[0], llargs[1]), + with_overflow_intrinsic(bcx, + "llvm.sadd.with.overflow.i8", + ret_ty, + llargs[0], + llargs[1], + call_debug_location), (_, "i16_add_with_overflow") => - with_overflow_intrinsic(bcx, "llvm.sadd.with.overflow.i16", ret_ty, - llargs[0], llargs[1]), + with_overflow_intrinsic(bcx, + "llvm.sadd.with.overflow.i16", + ret_ty, + llargs[0], + llargs[1], + call_debug_location), (_, "i32_add_with_overflow") => - with_overflow_intrinsic(bcx, "llvm.sadd.with.overflow.i32", ret_ty, - llargs[0], llargs[1]), + with_overflow_intrinsic(bcx, + "llvm.sadd.with.overflow.i32", + ret_ty, + llargs[0], + llargs[1], + call_debug_location), (_, "i64_add_with_overflow") => - with_overflow_intrinsic(bcx, "llvm.sadd.with.overflow.i64", ret_ty, - llargs[0], llargs[1]), + with_overflow_intrinsic(bcx, + "llvm.sadd.with.overflow.i64", + ret_ty, + llargs[0], + llargs[1], + call_debug_location), (_, "u8_add_with_overflow") => - with_overflow_intrinsic(bcx, "llvm.uadd.with.overflow.i8", ret_ty, - llargs[0], llargs[1]), + with_overflow_intrinsic(bcx, + "llvm.uadd.with.overflow.i8", + ret_ty, + llargs[0], + llargs[1], + call_debug_location), (_, "u16_add_with_overflow") => - with_overflow_intrinsic(bcx, "llvm.uadd.with.overflow.i16", ret_ty, - llargs[0], llargs[1]), + with_overflow_intrinsic(bcx, + "llvm.uadd.with.overflow.i16", + ret_ty, + llargs[0], + llargs[1], + call_debug_location), (_, "u32_add_with_overflow") => - with_overflow_intrinsic(bcx, "llvm.uadd.with.overflow.i32", ret_ty, - llargs[0], llargs[1]), + with_overflow_intrinsic(bcx, + "llvm.uadd.with.overflow.i32", + ret_ty, + llargs[0], + llargs[1], + call_debug_location), (_, "u64_add_with_overflow") => - with_overflow_intrinsic(bcx, "llvm.uadd.with.overflow.i64", ret_ty, - llargs[0], llargs[1]), - + with_overflow_intrinsic(bcx, + "llvm.uadd.with.overflow.i64", + ret_ty, + llargs[0], + llargs[1], + call_debug_location), (_, "i8_sub_with_overflow") => - with_overflow_intrinsic(bcx, "llvm.ssub.with.overflow.i8", ret_ty, - llargs[0], llargs[1]), + with_overflow_intrinsic(bcx, + "llvm.ssub.with.overflow.i8", + ret_ty, + llargs[0], + llargs[1], + call_debug_location), (_, "i16_sub_with_overflow") => - with_overflow_intrinsic(bcx, "llvm.ssub.with.overflow.i16", ret_ty, - llargs[0], llargs[1]), + with_overflow_intrinsic(bcx, + "llvm.ssub.with.overflow.i16", + ret_ty, + llargs[0], + llargs[1], + call_debug_location), (_, "i32_sub_with_overflow") => - with_overflow_intrinsic(bcx, "llvm.ssub.with.overflow.i32", ret_ty, - llargs[0], llargs[1]), + with_overflow_intrinsic(bcx, + "llvm.ssub.with.overflow.i32", + ret_ty, + llargs[0], + llargs[1], + call_debug_location), (_, "i64_sub_with_overflow") => - with_overflow_intrinsic(bcx, "llvm.ssub.with.overflow.i64", ret_ty, - llargs[0], llargs[1]), - + with_overflow_intrinsic(bcx, + "llvm.ssub.with.overflow.i64", + ret_ty, + llargs[0], + llargs[1], + call_debug_location), (_, "u8_sub_with_overflow") => - with_overflow_intrinsic(bcx, "llvm.usub.with.overflow.i8", ret_ty, - llargs[0], llargs[1]), + with_overflow_intrinsic(bcx, + "llvm.usub.with.overflow.i8", + ret_ty, + llargs[0], + llargs[1], + call_debug_location), (_, "u16_sub_with_overflow") => - with_overflow_intrinsic(bcx, "llvm.usub.with.overflow.i16", ret_ty, - llargs[0], llargs[1]), + with_overflow_intrinsic(bcx, + "llvm.usub.with.overflow.i16", + ret_ty, + llargs[0], + llargs[1], + call_debug_location), (_, "u32_sub_with_overflow") => - with_overflow_intrinsic(bcx, "llvm.usub.with.overflow.i32", ret_ty, - llargs[0], llargs[1]), + with_overflow_intrinsic(bcx, + "llvm.usub.with.overflow.i32", + ret_ty, + llargs[0], + llargs[1], + call_debug_location), (_, "u64_sub_with_overflow") => - with_overflow_intrinsic(bcx, "llvm.usub.with.overflow.i64", ret_ty, - llargs[0], llargs[1]), - + with_overflow_intrinsic(bcx, + "llvm.usub.with.overflow.i64", + ret_ty, + llargs[0], + llargs[1], + call_debug_location), (_, "i8_mul_with_overflow") => - with_overflow_intrinsic(bcx, "llvm.smul.with.overflow.i8", ret_ty, - llargs[0], llargs[1]), + with_overflow_intrinsic(bcx, + "llvm.smul.with.overflow.i8", + ret_ty, + llargs[0], + llargs[1], + call_debug_location), (_, "i16_mul_with_overflow") => - with_overflow_intrinsic(bcx, "llvm.smul.with.overflow.i16", ret_ty, - llargs[0], llargs[1]), + with_overflow_intrinsic(bcx, + "llvm.smul.with.overflow.i16", + ret_ty, + llargs[0], + llargs[1], + call_debug_location), (_, "i32_mul_with_overflow") => - with_overflow_intrinsic(bcx, "llvm.smul.with.overflow.i32", ret_ty, - llargs[0], llargs[1]), + with_overflow_intrinsic(bcx, + "llvm.smul.with.overflow.i32", + ret_ty, + llargs[0], + llargs[1], + call_debug_location), (_, "i64_mul_with_overflow") => - with_overflow_intrinsic(bcx, "llvm.smul.with.overflow.i64", ret_ty, - llargs[0], llargs[1]), - + with_overflow_intrinsic(bcx, + "llvm.smul.with.overflow.i64", + ret_ty, + llargs[0], + llargs[1], + call_debug_location), (_, "u8_mul_with_overflow") => - with_overflow_intrinsic(bcx, "llvm.umul.with.overflow.i8", ret_ty, - llargs[0], llargs[1]), + with_overflow_intrinsic(bcx, + "llvm.umul.with.overflow.i8", + ret_ty, + llargs[0], + llargs[1], + call_debug_location), (_, "u16_mul_with_overflow") => - with_overflow_intrinsic(bcx, "llvm.umul.with.overflow.i16", ret_ty, - llargs[0], llargs[1]), + with_overflow_intrinsic(bcx, + "llvm.umul.with.overflow.i16", + ret_ty, + llargs[0], + llargs[1], + call_debug_location), (_, "u32_mul_with_overflow") => - with_overflow_intrinsic(bcx, "llvm.umul.with.overflow.i32", ret_ty, - llargs[0], llargs[1]), + with_overflow_intrinsic(bcx, + "llvm.umul.with.overflow.i32", + ret_ty, + llargs[0], + llargs[1], + call_debug_location), (_, "u64_mul_with_overflow") => - with_overflow_intrinsic(bcx, "llvm.umul.with.overflow.i64", ret_ty, - llargs[0], llargs[1]), - + with_overflow_intrinsic(bcx, + "llvm.umul.with.overflow.i64", + ret_ty, + llargs[0], + llargs[1], + call_debug_location), (_, "return_address") => { if !fcx.caller_expects_out_pointer { tcx.sess.span_err(call_info.span, @@ -609,7 +760,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, // If we made a temporary stack slot, let's clean it up match dest { expr::Ignore => { - bcx = glue::drop_ty(bcx, llresult, ret_ty, Some(call_info)); + bcx = glue::drop_ty(bcx, llresult, ret_ty, call_debug_location); } expr::SaveIn(_) => {} } @@ -618,8 +769,14 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, } fn copy_intrinsic<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, - allow_overlap: bool, volatile: bool, tp_ty: Ty<'tcx>, - dst: ValueRef, src: ValueRef, count: ValueRef) -> ValueRef { + allow_overlap: bool, + volatile: bool, + tp_ty: Ty<'tcx>, + dst: ValueRef, + src: ValueRef, + count: ValueRef, + call_debug_location: DebugLoc) + -> ValueRef { let ccx = bcx.ccx(); let lltp_ty = type_of::type_of(ccx, tp_ty); let align = C_i32(ccx, type_of::align_of(ccx, tp_ty) as i32); @@ -643,12 +800,25 @@ fn copy_intrinsic<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let src_ptr = PointerCast(bcx, src, Type::i8p(ccx)); let llfn = ccx.get_intrinsic(&name); - Call(bcx, llfn, &[dst_ptr, src_ptr, Mul(bcx, size, count), align, - C_bool(ccx, volatile)], None) + Call(bcx, + llfn, + &[dst_ptr, + src_ptr, + Mul(bcx, size, count, DebugLoc::None), + align, + C_bool(ccx, volatile)], + None, + call_debug_location) } -fn memset_intrinsic<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, volatile: bool, tp_ty: Ty<'tcx>, - dst: ValueRef, val: ValueRef, count: ValueRef) -> ValueRef { +fn memset_intrinsic<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, + volatile: bool, + tp_ty: Ty<'tcx>, + dst: ValueRef, + val: ValueRef, + count: ValueRef, + call_debug_location: DebugLoc) + -> ValueRef { let ccx = bcx.ccx(); let lltp_ty = type_of::type_of(ccx, tp_ty); let align = C_i32(ccx, type_of::align_of(ccx, tp_ty) as i32); @@ -662,22 +832,38 @@ fn memset_intrinsic<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, volatile: bool, tp_ty: T let dst_ptr = PointerCast(bcx, dst, Type::i8p(ccx)); let llfn = ccx.get_intrinsic(&name); - Call(bcx, llfn, &[dst_ptr, val, Mul(bcx, size, count), align, - C_bool(ccx, volatile)], None) + Call(bcx, + llfn, + &[dst_ptr, + val, + Mul(bcx, size, count, DebugLoc::None), + align, + C_bool(ccx, volatile)], + None, + call_debug_location) } -fn count_zeros_intrinsic(bcx: Block, name: &'static str, val: ValueRef) -> ValueRef { +fn count_zeros_intrinsic(bcx: Block, + name: &'static str, + val: ValueRef, + call_debug_location: DebugLoc) + -> ValueRef { let y = C_bool(bcx.ccx(), false); let llfn = bcx.ccx().get_intrinsic(&name); - Call(bcx, llfn, &[val, y], None) + Call(bcx, llfn, &[val, y], None, call_debug_location) } -fn with_overflow_intrinsic<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, name: &'static str, - t: Ty<'tcx>, a: ValueRef, b: ValueRef) -> ValueRef { +fn with_overflow_intrinsic<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, + name: &'static str, + t: Ty<'tcx>, + a: ValueRef, + b: ValueRef, + call_debug_location: DebugLoc) + -> ValueRef { let llfn = bcx.ccx().get_intrinsic(&name); // Convert `i1` to a `bool`, and write it to the out parameter - let val = Call(bcx, llfn, &[a, b], None); + let val = Call(bcx, llfn, &[a, b], None, call_debug_location); let result = ExtractValue(bcx, val, 0); let overflow = ZExt(bcx, ExtractValue(bcx, val, 1), Type::bool(bcx.ccx())); let ret = C_undef(type_of::type_of(bcx.ccx(), t)); diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs index 0fb0dffe930f..c2f19670e4f1 100644 --- a/src/librustc_trans/trans/meth.rs +++ b/src/librustc_trans/trans/meth.rs @@ -24,6 +24,7 @@ use trans::callee; use trans::cleanup; use trans::common::*; use trans::datum::*; +use trans::debuginfo::DebugLoc; use trans::expr::{SaveIn, Ignore}; use trans::expr; use trans::glue; @@ -494,7 +495,7 @@ pub fn trans_trait_callee_from_llval<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ty::ty_bare_fn(_, ref f) if f.abi == Rust || f.abi == RustCall => { let fake_sig = ty::Binder(ty::FnSig { - inputs: f.sig.0.inputs.slice_from(1).to_vec(), + inputs: f.sig.0.inputs[1..].to_vec(), output: f.sig.0.output, variadic: f.sig.0.variadic, }); @@ -634,7 +635,7 @@ pub fn trans_object_shim<'a, 'tcx>( } _ => { // skip the self parameter: - sig.inputs.slice_from(1) + &sig.inputs[1..] } }; @@ -676,7 +677,7 @@ pub fn trans_object_shim<'a, 'tcx>( ArgVals(llargs.as_slice()), dest).bcx; - finish_fn(&fcx, bcx, sig.output); + finish_fn(&fcx, bcx, sig.output, DebugLoc::None); (llfn, method_bare_fn_ty) } @@ -785,7 +786,7 @@ pub fn make_vtable>(ccx: &CrateContext, unsafe { let tbl = C_struct(ccx, &components[], false); let sym = token::gensym("vtable"); - let buf = CString::from_vec(format!("vtable{}", sym.uint()).into_bytes()); + let buf = CString::from_vec(format!("vtable{}", sym.usize()).into_bytes()); let vt_gvar = llvm::LLVMAddGlobal(ccx.llmod(), val_ty(tbl).to_ref(), buf.as_ptr()); llvm::LLVMSetInitializer(vt_gvar, tbl); diff --git a/src/librustc_trans/trans/monomorphize.rs b/src/librustc_trans/trans/monomorphize.rs index f52e7c0ec94c..93076260349a 100644 --- a/src/librustc_trans/trans/monomorphize.rs +++ b/src/librustc_trans/trans/monomorphize.rs @@ -274,7 +274,6 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ast_map::NodeArg(..) | ast_map::NodeBlock(..) | ast_map::NodePat(..) | - ast_map::NodeViewItem(..) | ast_map::NodeLocal(..) => { ccx.sess().bug(&format!("can't monomorphize a {:?}", map_node)[]) diff --git a/src/librustc_trans/trans/tvec.rs b/src/librustc_trans/trans/tvec.rs index f8b01ebf4cca..06bc19f45a47 100644 --- a/src/librustc_trans/trans/tvec.rs +++ b/src/librustc_trans/trans/tvec.rs @@ -21,6 +21,7 @@ use trans::cleanup::CleanupMethods; use trans::common::*; use trans::consts; use trans::datum::*; +use trans::debuginfo::DebugLoc; use trans::expr::{Dest, Ignore, SaveIn}; use trans::expr; use trans::glue; @@ -58,7 +59,11 @@ pub fn make_drop_glue_unboxed<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let dataptr = get_dataptr(bcx, vptr); let bcx = if type_needs_drop(tcx, unit_ty) { let len = get_len(bcx, vptr); - iter_vec_raw(bcx, dataptr, unit_ty, len, |bb, vv, tt| glue::drop_ty(bb, vv, tt, None)) + iter_vec_raw(bcx, + dataptr, + unit_ty, + len, + |bb, vv, tt| glue::drop_ty(bb, vv, tt, DebugLoc::None)) } else { bcx }; @@ -71,7 +76,7 @@ pub fn make_drop_glue_unboxed<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let not_empty = ICmp(bcx, llvm::IntNE, len, C_uint(ccx, 0u)); with_cond(bcx, not_empty, |bcx| { let llalign = C_uint(ccx, machine::llalign_of_min(ccx, llty)); - let size = Mul(bcx, C_uint(ccx, unit_size), len); + let size = Mul(bcx, C_uint(ccx, unit_size), len, DebugLoc::None); glue::trans_exchange_free_dyn(bcx, dataptr, size, llalign) }) } else { @@ -420,14 +425,14 @@ pub fn iter_vec_loop<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, let cond_bcx = fcx.new_temp_block("expr_repeat: loop cond"); let body_bcx = fcx.new_temp_block("expr_repeat: body: set"); let inc_bcx = fcx.new_temp_block("expr_repeat: body: inc"); - Br(bcx, loop_bcx.llbb); + Br(bcx, loop_bcx.llbb, DebugLoc::None); let loop_counter = { // i = 0 let i = alloca(loop_bcx, bcx.ccx().int_type(), "__i"); Store(loop_bcx, C_uint(bcx.ccx(), 0u), i); - Br(loop_bcx, cond_bcx.llbb); + Br(loop_bcx, cond_bcx.llbb, DebugLoc::None); i }; @@ -436,7 +441,7 @@ pub fn iter_vec_loop<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, let rhs = count; let cond_val = ICmp(cond_bcx, llvm::IntULT, lhs, rhs); - CondBr(cond_bcx, cond_val, body_bcx.llbb, next_bcx.llbb); + CondBr(cond_bcx, cond_val, body_bcx.llbb, next_bcx.llbb, DebugLoc::None); } { // loop body @@ -448,15 +453,15 @@ pub fn iter_vec_loop<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, }; let body_bcx = f(body_bcx, lleltptr, vt.unit_ty); - Br(body_bcx, inc_bcx.llbb); + Br(body_bcx, inc_bcx.llbb, DebugLoc::None); } { // i += 1 let i = Load(inc_bcx, loop_counter); - let plusone = Add(inc_bcx, i, C_uint(bcx.ccx(), 1u)); + let plusone = Add(inc_bcx, i, C_uint(bcx.ccx(), 1u), DebugLoc::None); Store(inc_bcx, plusone, loop_counter); - Br(inc_bcx, cond_bcx.llbb); + Br(inc_bcx, cond_bcx.llbb, DebugLoc::None); } next_bcx @@ -484,19 +489,19 @@ pub fn iter_vec_raw<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, // Now perform the iteration. let header_bcx = fcx.new_temp_block("iter_vec_loop_header"); - Br(bcx, header_bcx.llbb); + Br(bcx, header_bcx.llbb, DebugLoc::None); let data_ptr = Phi(header_bcx, val_ty(data_ptr), &[data_ptr], &[bcx.llbb]); let not_yet_at_end = ICmp(header_bcx, llvm::IntULT, data_ptr, data_end_ptr); let body_bcx = fcx.new_temp_block("iter_vec_loop_body"); let next_bcx = fcx.new_temp_block("iter_vec_next"); - CondBr(header_bcx, not_yet_at_end, body_bcx.llbb, next_bcx.llbb); + CondBr(header_bcx, not_yet_at_end, body_bcx.llbb, next_bcx.llbb, DebugLoc::None); let body_bcx = f(body_bcx, data_ptr, vt.unit_ty); AddIncomingToPhi(data_ptr, InBoundsGEP(body_bcx, data_ptr, &[C_int(bcx.ccx(), 1i)]), body_bcx.llbb); - Br(body_bcx, header_bcx.llbb); + Br(body_bcx, header_bcx.llbb, DebugLoc::None); next_bcx } } diff --git a/src/librustc_trans/trans/type_.rs b/src/librustc_trans/trans/type_.rs index 07eb17e6300c..9640443f4f7a 100644 --- a/src/librustc_trans/trans/type_.rs +++ b/src/librustc_trans/trans/type_.rs @@ -21,6 +21,7 @@ use syntax::ast; use std::ffi::CString; use std::mem; +use std::ptr; use std::cell::RefCell; use std::iter::repeat; @@ -227,14 +228,6 @@ impl Type { Type::vec(ccx, &Type::i8(ccx)) } - // The box pointed to by @T. - pub fn at_box(ccx: &CrateContext, ty: Type) -> Type { - Type::struct_(ccx, &[ - ccx.int_type(), Type::glue_fn(ccx, Type::i8p(ccx)).ptr_to(), - Type::i8p(ccx), Type::i8p(ccx), ty - ], false) - } - pub fn vtable_ptr(ccx: &CrateContext) -> Type { Type::glue_fn(ccx, Type::i8p(ccx)).ptr_to().ptr_to() } @@ -303,7 +296,7 @@ impl Type { if n_elts == 0 { return Vec::new(); } - let mut elts: Vec<_> = repeat(Type { rf: 0 as TypeRef }).take(n_elts).collect(); + let mut elts: Vec<_> = repeat(Type { rf: ptr::null_mut() }).take(n_elts).collect(); llvm::LLVMGetStructElementTypes(self.to_ref(), elts.as_mut_ptr() as *mut TypeRef); elts @@ -317,7 +310,7 @@ impl Type { pub fn func_params(&self) -> Vec { unsafe { let n_args = llvm::LLVMCountParamTypes(self.to_ref()) as uint; - let mut args: Vec<_> = repeat(Type { rf: 0 as TypeRef }).take(n_args).collect(); + let mut args: Vec<_> = repeat(Type { rf: ptr::null_mut() }).take(n_args).collect(); llvm::LLVMGetParamTypes(self.to_ref(), args.as_mut_ptr() as *mut TypeRef); args diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 42b12c158664..921ed505fa3a 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -100,8 +100,7 @@ pub trait AstConv<'tcx> { -> Ty<'tcx> { if ty::binds_late_bound_regions(self.tcx(), &poly_trait_ref) { - self.tcx().sess.span_err( - span, + span_err!(self.tcx().sess, span, E0212, "cannot extract an associated type from a higher-ranked trait bound \ in this context"); self.tcx().types.err @@ -119,8 +118,7 @@ pub trait AstConv<'tcx> { _item_name: ast::Name) -> Ty<'tcx> { - self.tcx().sess.span_err( - span, + span_err!(self.tcx().sess, span, E0213, "associated types are not accepted in this context"); self.tcx().types.err @@ -268,8 +266,7 @@ pub fn ast_path_substs_for_ty<'tcx>( convert_angle_bracketed_parameters(this, rscope, data) } ast::ParenthesizedParameters(ref data) => { - tcx.sess.span_err( - path.span, + span_err!(tcx.sess, path.span, E0214, "parenthesized parameters may only be used with a trait"); (Vec::new(), convert_parenthesized_parameters(this, data), Vec::new()) } @@ -342,22 +339,22 @@ fn create_substs_for_ast_path<'tcx>( } else { "expected" }; - this.tcx().sess.span_fatal(span, - &format!("wrong number of type arguments: {} {}, found {}", + span_fatal!(this.tcx().sess, span, E0243, + "wrong number of type arguments: {} {}, found {}", expected, required_ty_param_count, - supplied_ty_param_count)[]); + supplied_ty_param_count); } else if supplied_ty_param_count > formal_ty_param_count { let expected = if required_ty_param_count < formal_ty_param_count { "expected at most" } else { "expected" }; - this.tcx().sess.span_fatal(span, - &format!("wrong number of type arguments: {} {}, found {}", + span_fatal!(this.tcx().sess, span, E0244, + "wrong number of type arguments: {} {}, found {}", expected, formal_ty_param_count, - supplied_ty_param_count)[]); + supplied_ty_param_count); } let mut substs = Substs::new_type(types, regions); @@ -560,10 +557,9 @@ pub fn instantiate_trait_ref<'tcx>( trait_ref } _ => { - this.tcx().sess.span_fatal( - ast_trait_ref.path.span, - &format!("`{}` is not a trait", - ast_trait_ref.path.user_string(this.tcx()))[]); + span_fatal!(this.tcx().sess, ast_trait_ref.path.span, E0245, + "`{}` is not a trait", + ast_trait_ref.path.user_string(this.tcx())); } } } @@ -610,7 +606,7 @@ fn ast_path_to_trait_ref<'a,'tcx>( if !this.tcx().sess.features.borrow().unboxed_closures && this.tcx().lang_items.fn_trait_kind(trait_def_id).is_some() { - this.tcx().sess.span_err(path.span, + span_err!(this.tcx().sess, path.span, E0215, "angle-bracket notation is not stable when \ used with the `Fn` family of traits, use parentheses"); span_help!(this.tcx().sess, path.span, @@ -626,7 +622,7 @@ fn ast_path_to_trait_ref<'a,'tcx>( if !this.tcx().sess.features.borrow().unboxed_closures && this.tcx().lang_items.fn_trait_kind(trait_def_id).is_none() { - this.tcx().sess.span_err(path.span, + span_err!(this.tcx().sess, path.span, E0216, "parenthetical notation is only stable when \ used with the `Fn` family of traits"); span_help!(this.tcx().sess, path.span, @@ -738,32 +734,29 @@ fn ast_type_binding_to_projection_predicate<'tcx>( } if candidates.len() > 1 { - tcx.sess.span_err( - binding.span, - format!("ambiguous associated type: `{}` defined in multiple supertraits `{}`", + span_err!(tcx.sess, binding.span, E0217, + "ambiguous associated type: `{}` defined in multiple supertraits `{}`", token::get_name(binding.item_name), - candidates.user_string(tcx)).as_slice()); + candidates.user_string(tcx)); return Err(ErrorReported); } let candidate = match candidates.pop() { Some(c) => c, None => { - tcx.sess.span_err( - binding.span, - format!("no associated type `{}` defined in `{}`", + span_err!(tcx.sess, binding.span, E0218, + "no associated type `{}` defined in `{}`", token::get_name(binding.item_name), - trait_ref.user_string(tcx)).as_slice()); + trait_ref.user_string(tcx)); return Err(ErrorReported); } }; if ty::binds_late_bound_regions(tcx, &candidate) { - tcx.sess.span_err( - binding.span, - format!("associated type `{}` defined in higher-ranked supertrait `{}`", + span_err!(tcx.sess, binding.span, E0219, + "associated type `{}` defined in higher-ranked supertrait `{}`", token::get_name(binding.item_name), - candidate.user_string(tcx)).as_slice()); + candidate.user_string(tcx)); return Err(ErrorReported); } @@ -893,14 +886,14 @@ fn ast_ty_to_trait_ref<'tcx>(this: &AstConv<'tcx>, pprust::ty_to_string(ty)); match ty.node { ast::TyRptr(None, ref mut_ty) => { - span_note!(this.tcx().sess, ty.span, + span_help!(this.tcx().sess, ty.span, "perhaps you meant `&{}({} +{})`? (per RFC 438)", ppaux::mutability_to_string(mut_ty.mutbl), pprust::ty_to_string(&*mut_ty.ty), pprust::bounds_to_string(bounds)); } ast::TyRptr(Some(ref lt), ref mut_ty) => { - span_note!(this.tcx().sess, ty.span, + span_help!(this.tcx().sess, ty.span, "perhaps you meant `&{} {}({} +{})`? (per RFC 438)", pprust::lifetime_to_string(lt), ppaux::mutability_to_string(mut_ty.mutbl), @@ -909,7 +902,7 @@ fn ast_ty_to_trait_ref<'tcx>(this: &AstConv<'tcx>, } _ => { - span_note!(this.tcx().sess, ty.span, + span_help!(this.tcx().sess, ty.span, "perhaps you forgot parentheses? (per RFC 438)"); } } @@ -964,18 +957,18 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>, } if suitable_bounds.len() == 0 { - tcx.sess.span_err(ast_ty.span, - format!("associated type `{}` not found for type parameter `{}`", + span_err!(tcx.sess, ast_ty.span, E0220, + "associated type `{}` not found for type parameter `{}`", token::get_name(assoc_name), - token::get_name(ty_param_name)).as_slice()); + token::get_name(ty_param_name)); return this.tcx().types.err; } if suitable_bounds.len() > 1 { - tcx.sess.span_err(ast_ty.span, - format!("ambiguous associated type `{}` in bounds of `{}`", + span_err!(tcx.sess, ast_ty.span, E0221, + "ambiguous associated type `{}` in bounds of `{}`", token::get_name(assoc_name), - token::get_name(ty_param_name)).as_slice()); + token::get_name(ty_param_name)); for suitable_bound in suitable_bounds.iter() { span_note!(this.tcx().sess, ast_ty.span, @@ -1042,7 +1035,7 @@ pub fn ast_ty_to_ty<'tcx>( match ast_ty_to_ty_cache.get(&ast_ty.id) { Some(&ty::atttce_resolved(ty)) => return ty, Some(&ty::atttce_unresolved) => { - tcx.sess.span_fatal(ast_ty.span, + span_fatal!(tcx.sess, ast_ty.span, E0246, "illegal recursive type; insert an enum \ or struct in the cycle, if this is \ desired"); @@ -1093,7 +1086,7 @@ pub fn ast_ty_to_ty<'tcx>( ast::TyParen(ref typ) => ast_ty_to_ty(this, rscope, &**typ), ast::TyBareFn(ref bf) => { if bf.decl.variadic && bf.abi != abi::C { - tcx.sess.span_err(ast_ty.span, + span_err!(tcx.sess, ast_ty.span, E0222, "variadic function must have C calling convention"); } let bare_fn = ty_of_bare_fn(this, bf.unsafety, bf.abi, &*bf.decl); @@ -1142,9 +1135,9 @@ pub fn ast_ty_to_ty<'tcx>( ty::mk_self_type(tcx) } def::DefMod(id) => { - tcx.sess.span_fatal(ast_ty.span, - &format!("found module name used as a type: {}", - tcx.map.node_to_string(id.node))[]); + span_fatal!(tcx.sess, ast_ty.span, E0247, + "found module name used as a type: {}", + tcx.map.node_to_string(id.node)); } def::DefPrimTy(_) => { panic!("DefPrimTy arm missed in previous ast_ty_to_prim_ty call"); @@ -1152,8 +1145,8 @@ pub fn ast_ty_to_ty<'tcx>( def::DefAssociatedTy(trait_type_id) => { let path_str = tcx.map.path_to_string( tcx.map.get_parent(trait_type_id.node)); - tcx.sess.span_err(ast_ty.span, - &format!("ambiguous associated \ + span_err!(tcx.sess, ast_ty.span, E0223, + "ambiguous associated \ type; specify the type \ using the syntax `::{}`", @@ -1163,17 +1156,17 @@ pub fn ast_ty_to_ty<'tcx>( .last() .unwrap() .identifier) - .get())[]); + .get()); this.tcx().types.err } def::DefAssociatedPath(provenance, assoc_ident) => { associated_path_def_to_ty(this, ast_ty, provenance, assoc_ident.name) } _ => { - tcx.sess.span_fatal(ast_ty.span, - &format!("found value name used \ + span_fatal!(tcx.sess, ast_ty.span, E0248, + "found value name used \ as a type: {:?}", - a_def)[]); + a_def); } } } @@ -1191,17 +1184,16 @@ pub fn ast_ty_to_ty<'tcx>( ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty), Some(i as uint)), _ => { - tcx.sess.span_fatal( - ast_ty.span, "expected constant expr for array length"); + span_fatal!(tcx.sess, ast_ty.span, E0249, + "expected constant expr for array length"); } } } Err(ref r) => { - tcx.sess.span_fatal( - ast_ty.span, - &format!("expected constant expr for array \ + span_fatal!(tcx.sess, ast_ty.span, E0250, + "expected constant expr for array \ length: {}", - *r)[]); + *r); } } } @@ -1321,7 +1313,7 @@ fn ty_of_method_or_bare_fn<'a, 'tcx>(this: &AstConv<'tcx>, // HACK(eddyb) replace the fake self type in the AST with the actual type. let input_params = if self_ty.is_some() { - decl.inputs.slice_from(1) + &decl.inputs[1..] } else { &decl.inputs[] }; @@ -1339,9 +1331,9 @@ fn ty_of_method_or_bare_fn<'a, 'tcx>(this: &AstConv<'tcx>, let lifetimes_for_params = if implied_output_region.is_none() { let input_tys = if self_ty.is_some() { // Skip the first argument if `self` is present. - self_and_input_tys.slice_from(1) + &self_and_input_tys[1..] } else { - self_and_input_tys.slice_from(0) + &self_and_input_tys[] }; let (ior, lfp) = find_implied_output_region(input_tys, input_pats); @@ -1457,9 +1449,6 @@ fn determine_explicit_self_category<'a, 'tcx>(this: &AstConv<'tcx>, pub fn ty_of_closure<'tcx>( this: &AstConv<'tcx>, unsafety: ast::Unsafety, - onceness: ast::Onceness, - bounds: ty::ExistentialBounds<'tcx>, - store: ty::TraitStore, decl: &ast::FnDecl, abi: abi::Abi, expected_sig: Option>) @@ -1509,9 +1498,6 @@ pub fn ty_of_closure<'tcx>( ty::ClosureTy { unsafety: unsafety, - onceness: onceness, - store: store, - bounds: bounds, abi: abi, sig: ty::Binder(ty::FnSig {inputs: input_tys, output: output_ty, @@ -1557,8 +1543,7 @@ fn conv_ty_poly_trait_ref<'tcx>( None, &mut projection_bounds)) } else { - this.tcx().sess.span_err( - span, + span_err!(this.tcx().sess, span, E0224, "at least one non-builtin trait is required for an object type"); None }; @@ -1593,10 +1578,9 @@ pub fn conv_existential_bounds_from_partitioned_bounds<'tcx>( if !trait_bounds.is_empty() { let b = &trait_bounds[0]; - this.tcx().sess.span_err( - b.trait_ref.path.span, - &format!("only the builtin traits can be used \ - as closure or object bounds")[]); + span_err!(this.tcx().sess, b.trait_ref.path.span, E0225, + "only the builtin traits can be used \ + as closure or object bounds"); } let region_bound = compute_region_bound(this, @@ -1633,9 +1617,8 @@ fn compute_opt_region_bound<'tcx>(tcx: &ty::ctxt<'tcx>, builtin_bounds.repr(tcx)); if explicit_region_bounds.len() > 1 { - tcx.sess.span_err( - explicit_region_bounds[1].span, - format!("only a single explicit lifetime bound is permitted").as_slice()); + span_err!(tcx.sess, explicit_region_bounds[1].span, E0226, + "only a single explicit lifetime bound is permitted"); } if explicit_region_bounds.len() != 0 { @@ -1665,11 +1648,10 @@ fn compute_opt_region_bound<'tcx>(tcx: &ty::ctxt<'tcx>, // of derived region bounds. If so, use that. Otherwise, report an // error. let r = derived_region_bounds[0]; - if derived_region_bounds.slice_from(1).iter().any(|r1| r != *r1) { - tcx.sess.span_err( - span, - &format!("ambiguous lifetime bound, \ - explicit lifetime bound required")[]); + if derived_region_bounds[1..].iter().any(|r1| r != *r1) { + span_err!(tcx.sess, span, E0227, + "ambiguous lifetime bound, \ + explicit lifetime bound required"); } return Some(r); } @@ -1693,9 +1675,8 @@ fn compute_region_bound<'tcx>( match rscope.default_region_bound(span) { Some(r) => { r } None => { - this.tcx().sess.span_err( - span, - &format!("explicit lifetime bound required")[]); + span_err!(this.tcx().sess, span, E0228, + "explicit lifetime bound required"); ty::ReStatic } } @@ -1779,8 +1760,7 @@ fn prohibit_projections<'tcx>(tcx: &ty::ctxt<'tcx>, bindings: &[ConvertedBinding<'tcx>]) { for binding in bindings.iter().take(1) { - tcx.sess.span_err( - binding.span, + span_err!(tcx.sess, binding.span, E0229, "associated type bindings are not allowed here"); } } diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index bfe43086aab1..ffec1421f928 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -50,10 +50,9 @@ pub fn check_expr_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, check_unboxed_closure(fcx, expr, kind, decl, body, None); - fcx.ccx.tcx.sess.span_err( - expr.span, - "can't infer the \"kind\" of the closure, explicitly annotate it. e.g. \ - `|&:| {}`"); + span_err!(fcx.ccx.tcx.sess, expr.span, E0187, + "can't infer the \"kind\" of the closure; explicitly annotate it; e.g. \ + `|&:| {{}}`"); }, Some((sig, kind)) => { check_unboxed_closure(fcx, expr, kind, decl, body, Some(sig)); @@ -89,15 +88,6 @@ fn check_unboxed_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, let mut fn_ty = astconv::ty_of_closure( fcx, ast::Unsafety::Normal, - ast::Many, - - // The `RegionTraitStore` and region_existential_bounds - // are lies, but we ignore them so it doesn't matter. - // - // FIXME(pcwalton): Refactor this API. - ty::region_existential_bound(ty::ReStatic), - ty::RegionTraitStore(ty::ReStatic, ast::MutImmutable), - decl, abi::RustCall, expected_sig); diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 27d4b2055d4c..e3e5d67869fa 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -59,23 +59,21 @@ pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>, (&ty::StaticExplicitSelfCategory, &ty::StaticExplicitSelfCategory) => {} (&ty::StaticExplicitSelfCategory, _) => { - tcx.sess.span_err( - impl_m_span, - format!("method `{}` has a `{}` declaration in the impl, \ + span_err!(tcx.sess, impl_m_span, E0185, + "method `{}` has a `{}` declaration in the impl, \ but not in the trait", token::get_name(trait_m.name), ppaux::explicit_self_category_to_str( - &impl_m.explicit_self)).as_slice()); + &impl_m.explicit_self)); return; } (_, &ty::StaticExplicitSelfCategory) => { - tcx.sess.span_err( - impl_m_span, - format!("method `{}` has a `{}` declaration in the trait, \ + span_err!(tcx.sess, impl_m_span, E0186, + "method `{}` has a `{}` declaration in the trait, \ but not in the impl", token::get_name(trait_m.name), ppaux::explicit_self_category_to_str( - &trait_m.explicit_self)).as_slice()); + &trait_m.explicit_self)); return; } _ => { @@ -400,11 +398,10 @@ pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>, // are zero. Since I don't quite know how to phrase things at // the moment, give a kind of vague error message. if trait_params.len() != impl_params.len() { - tcx.sess.span_err( - span, - &format!("lifetime parameters or bounds on method `{}` do \ + span_err!(tcx.sess, span, E0195, + "lifetime parameters or bounds on method `{}` do \ not match the trait declaration", - token::get_name(impl_m.name))[]); + token::get_name(impl_m.name)); return false; } diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 2a89a1d28bfc..3cf9a1a94566 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -145,6 +145,7 @@ fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, if !valid_out_of_scope_traits.is_empty() { let mut candidates = valid_out_of_scope_traits; candidates.sort(); + candidates.dedup(); let msg = format!( "methods from traits can only be called if the trait is in scope; \ the following {traits_are} implemented but not in scope, \ @@ -172,6 +173,7 @@ fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, if candidates.len() > 0 { // sort from most relevant to least relevant candidates.sort_by(|a, b| a.cmp(b).reverse()); + candidates.dedup(); let msg = format!( "methods from traits can only be called if the trait is implemented and in scope; \ diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index f610456f73cf..5f8ae09b5bd6 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -108,6 +108,7 @@ use lint; use util::common::{block_query, indenter, loop_query}; use util::ppaux::{self, Repr}; use util::nodemap::{DefIdMap, FnvHashMap, NodeMap}; +use util::lev_distance::lev_distance; use std::cell::{Cell, Ref, RefCell}; use std::mem::replace; @@ -801,16 +802,15 @@ fn check_trait_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, }) { Some(_) => (), None => { - ccx.tcx.sess.span_err(attr.span, - format!("there is no type parameter \ + span_err!(ccx.tcx.sess, attr.span, E0230, + "there is no type parameter \ {} on trait {}", - s, item.ident.as_str()) - .as_slice()); + s, item.ident.as_str()); } }, // `{:1}` and `{}` are not to be used Position::ArgumentIs(_) | Position::ArgumentNext => { - ccx.tcx.sess.span_err(attr.span, + span_err!(ccx.tcx.sess, attr.span, E0231, "only named substitution \ parameters are allowed"); } @@ -818,7 +818,7 @@ fn check_trait_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, } } } else { - ccx.tcx.sess.span_err(attr.span, + span_err!(ccx.tcx.sess, attr.span, E0232, "this attribute must have a value, \ eg `#[rustc_on_unimplemented = \"foo\"]`") } @@ -2099,8 +2099,8 @@ fn lookup_method_for_for_loop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, let trait_did = match fcx.tcx().lang_items.require(IteratorItem) { Ok(trait_did) => trait_did, Err(ref err_string) => { - fcx.tcx().sess.span_err(iterator_expr.span, - &err_string[]); + span_err!(fcx.tcx().sess, iterator_expr.span, E0233, + "{}", &err_string[]); return fcx.tcx().types.err } }; @@ -2123,11 +2123,10 @@ fn lookup_method_for_for_loop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, if !ty::type_is_error(true_expr_type) { let ty_string = fcx.infcx().ty_to_string(true_expr_type); - fcx.tcx().sess.span_err(iterator_expr.span, - &format!("`for` loop expression has type `{}` which does \ + span_err!(fcx.tcx().sess, iterator_expr.span, E0234, + "`for` loop expression has type `{}` which does \ not implement the `Iterator` trait; \ - maybe try .iter()", - ty_string)[]); + maybe try .iter()", ty_string); } fcx.tcx().types.err } @@ -2162,11 +2161,10 @@ fn lookup_method_for_for_loop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, fcx.tcx().types.err } _ => { - fcx.tcx().sess.span_err(iterator_expr.span, - &format!("`next` method of the `Iterator` \ + span_err!(fcx.tcx().sess, iterator_expr.span, E0239, + "`next` method of the `Iterator` \ trait has an unexpected type `{}`", - fcx.infcx().ty_to_string(return_type)) - []); + fcx.infcx().ty_to_string(return_type)); fcx.tcx().types.err } } @@ -3074,11 +3072,43 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, actual) }, expr_t, None); + if let Some(t) = ty::ty_to_def_id(expr_t) { + suggest_field_names(t, field, tcx, vec![]); + } } fcx.write_error(expr.id); } + // displays hints about the closest matches in field names + fn suggest_field_names<'tcx>(id : DefId, + field : &ast::SpannedIdent, + tcx : &ty::ctxt<'tcx>, + skip : Vec<&str>) { + let ident = token::get_ident(field.node); + let name = ident.get(); + // only find fits with at least one matching letter + let mut best_dist = name.len(); + let mut best = None; + let fields = ty::lookup_struct_fields(tcx, id); + for elem in fields.iter() { + let n = elem.name.as_str(); + // ignore already set fields + if skip.iter().any(|&x| x == n) { + continue; + } + let dist = lev_distance(n, name); + if dist < best_dist { + best = Some(n); + best_dist = dist; + } + } + if let Some(n) = best { + tcx.sess.span_help(field.span, + format!("did you mean `{}`?", n).as_slice()); + } + } + // Check tuple index expressions fn check_tup_field(fcx: &FnCtxt, expr: &ast::Expr, @@ -3186,6 +3216,13 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, }, struct_ty, None); + // prevent all specified fields from being suggested + let skip_fields = ast_fields.iter().map(|ref x| x.ident.node.name.as_str()); + let actual_id = match enum_id_opt { + Some(_) => class_id, + None => ty::ty_to_def_id(struct_ty).unwrap() + }; + suggest_field_names(actual_id, &field.ident, tcx, skip_fields.collect()); error_happened = true; } Some((_, true)) => { @@ -3880,10 +3917,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, Err(type_error) => { let type_error_description = ty::type_err_to_str(tcx, &type_error); - fcx.tcx() - .sess - .span_err(path.span, - &format!("structure constructor specifies a \ + span_err!(fcx.tcx().sess, path.span, E0235, + "structure constructor specifies a \ structure of type `{}`, but this \ structure has type `{}`: {}", fcx.infcx() @@ -3891,7 +3926,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, fcx.infcx() .ty_to_string( actual_structure_type), - type_error_description)[]); + type_error_description); ty::note_and_explain_type_err(tcx, &type_error); } } @@ -4012,7 +4047,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, ty::mk_struct(tcx, did, tcx.mk_substs(substs)) } else { - tcx.sess.span_err(expr.span, "No lang item for range syntax"); + span_err!(tcx.sess, expr.span, E0236, "no lang item for range syntax"); fcx.tcx().types.err } } @@ -4022,7 +4057,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, let substs = Substs::new_type(vec![], vec![]); ty::mk_struct(tcx, did, tcx.mk_substs(substs)) } else { - tcx.sess.span_err(expr.span, "No lang item for range syntax"); + span_err!(tcx.sess, expr.span, E0237, "no lang item for range syntax"); fcx.tcx().types.err } } @@ -4872,8 +4907,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, } ast::ParenthesizedParameters(ref data) => { - fcx.tcx().sess.span_err( - span, + span_err!(fcx.tcx().sess, span, E0238, "parenthesized parameters may only be used with a trait"); push_explicit_parenthesized_parameters_from_segment_to_substs( fcx, space, span, type_defs, data, substs); @@ -5230,7 +5264,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) { "get_tydesc" => { let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) { Ok(t) => t, - Err(s) => { tcx.sess.span_fatal(it.span, &s[]); } + Err(s) => { span_fatal!(tcx.sess, it.span, E0240, "{}", &s[]); } }; let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt { ty: tydesc_ty, diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 3b5027dbb9e6..56b700663d41 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -297,14 +297,25 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> { fn visit_region_obligations(&mut self, node_id: ast::NodeId) { debug!("visit_region_obligations: node_id={}", node_id); - let fulfillment_cx = self.fcx.inh.fulfillment_cx.borrow(); - for r_o in fulfillment_cx.region_obligations(node_id).iter() { + + // Make a copy of the region obligations vec because we'll need + // to be able to borrow the fulfillment-cx below when projecting. + let region_obligations = + self.fcx.inh.fulfillment_cx.borrow() + .region_obligations(node_id) + .to_vec(); + + for r_o in region_obligations.iter() { debug!("visit_region_obligations: r_o={}", r_o.repr(self.tcx())); let sup_type = self.resolve_type(r_o.sup_type); let origin = infer::RelateRegionParamBound(r_o.cause.span); type_must_outlive(self, origin, sup_type, r_o.sub_region); } + + // Processing the region obligations should not cause the list to grow further: + assert_eq!(region_obligations.len(), + self.fcx.inh.fulfillment_cx.borrow().region_obligations(node_id).len()); } /// This method populates the region map's `free_region_map`. It walks over the transformed @@ -531,7 +542,7 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) { ast::ExprMethodCall(_, _, ref args) => { constrain_call(rcx, expr, Some(&*args[0]), - args.slice_from(1).iter().map(|e| &**e), false); + args[1..].iter().map(|e| &**e), false); visit::walk_expr(rcx, expr); } @@ -1480,6 +1491,15 @@ fn generic_must_outlive<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>, generic.to_ty(rcx.tcx()), param_env.caller_bounds.predicates.as_slice().to_vec()); + // In the case of a projection T::Foo, we may be able to extract bounds from the trait def: + match *generic { + GenericKind::Param(..) => { } + GenericKind::Projection(ref projection_ty) => { + param_bounds.push_all( + &projection_bounds(rcx, origin.span(), projection_ty)[]); + } + } + // Add in the default bound of fn body that applies to all in // scope type parameters: param_bounds.push(param_env.implicit_region_bound); @@ -1511,3 +1531,73 @@ fn generic_must_outlive<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>, region, param_bounds); } + +fn projection_bounds<'a,'tcx>(rcx: &Rcx<'a, 'tcx>, + span: Span, + projection_ty: &ty::ProjectionTy<'tcx>) + -> Vec +{ + let fcx = rcx.fcx; + let tcx = fcx.tcx(); + let infcx = fcx.infcx(); + + debug!("projection_bounds(projection_ty={})", + projection_ty.repr(tcx)); + + let ty = ty::mk_projection(tcx, projection_ty.trait_ref.clone(), projection_ty.item_name); + + // Say we have a projection `>::SomeType`. We are interested + // in looking for a trait definition like: + // + // ``` + // trait SomeTrait<'a> { + // type SomeType : 'a; + // } + // ``` + // + // we can thus deduce that `>::SomeType : 'a`. + let trait_def = ty::lookup_trait_def(tcx, projection_ty.trait_ref.def_id); + let predicates = trait_def.generics.predicates.as_slice().to_vec(); + traits::elaborate_predicates(tcx, predicates) + .filter_map(|predicate| { + // we're only interesting in `T : 'a` style predicates: + let outlives = match predicate { + ty::Predicate::TypeOutlives(data) => data, + _ => { return None; } + }; + + debug!("projection_bounds: outlives={} (1)", + outlives.repr(tcx)); + + // apply the substitutions (and normalize any projected types) + let outlives = fcx.instantiate_type_scheme(span, + projection_ty.trait_ref.substs, + &outlives); + + debug!("projection_bounds: outlives={} (2)", + outlives.repr(tcx)); + + let region_result = infcx.try(|_| { + let (outlives, _) = + infcx.replace_late_bound_regions_with_fresh_var( + span, + infer::AssocTypeProjection(projection_ty.item_name), + &outlives); + + debug!("projection_bounds: outlives={} (3)", + outlives.repr(tcx)); + + // check whether this predicate applies to our current projection + match infer::mk_eqty(infcx, false, infer::Misc(span), ty, outlives.0) { + Ok(()) => { Ok(outlives.1) } + Err(_) => { Err(()) } + } + }); + + debug!("projection_bounds: region_result={}", + region_result.repr(tcx)); + + region_result.ok() + }) + .collect() +} diff --git a/src/librustc_typeck/check/vtable.rs b/src/librustc_typeck/check/vtable.rs index 3940092eb729..41b63830279a 100644 --- a/src/librustc_typeck/check/vtable.rs +++ b/src/librustc_typeck/check/vtable.rs @@ -51,7 +51,7 @@ pub fn check_object_cast<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, { let object_trait = object_trait(&object_trait_ty); if !mutability_allowed(referent_mutbl, target_mutbl) { - fcx.tcx().sess.span_err(source_expr.span, + span_err!(fcx.tcx().sess, source_expr.span, E0188, "types differ in mutability"); } else { // Ensure that if &'a T is cast to &'b Trait, then T : Trait @@ -70,19 +70,17 @@ pub fn check_object_cast<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, } (_, &ty::ty_uniq(..)) => { - fcx.ccx.tcx.sess.span_err( - source_expr.span, - &format!("can only cast an boxed pointer \ + span_err!(fcx.ccx.tcx.sess, source_expr.span, E0189, + "can only cast a boxed pointer \ to a boxed object, not a {}", - ty::ty_sort_string(fcx.tcx(), source_ty))[]); + ty::ty_sort_string(fcx.tcx(), source_ty)); } (_, &ty::ty_rptr(..)) => { - fcx.ccx.tcx.sess.span_err( - source_expr.span, - &format!("can only cast a &-pointer \ + span_err!(fcx.ccx.tcx.sess, source_expr.span, E0190, + "can only cast a &-pointer \ to an &-object, not a {}", - ty::ty_sort_string(fcx.tcx(), source_ty))[]); + ty::ty_sort_string(fcx.tcx(), source_ty)); } _ => { @@ -272,11 +270,10 @@ fn check_object_type_binds_all_associated_types<'tcx>(tcx: &ty::ctxt<'tcx>, } for (trait_def_id, name) in associated_types.into_iter() { - tcx.sess.span_err( - span, - format!("the value of the associated type `{}` (from the trait `{}`) must be specified", + span_err!(tcx.sess, span, E0191, + "the value of the associated type `{}` (from the trait `{}`) must be specified", name.user_string(tcx), - ty::item_path_str(tcx, trait_def_id)).as_slice()); + ty::item_path_str(tcx, trait_def_id)); } } diff --git a/src/librustc_typeck/check/wf.rs b/src/librustc_typeck/check/wf.rs index e6390212c600..60284433ffe4 100644 --- a/src/librustc_typeck/check/wf.rs +++ b/src/librustc_typeck/check/wf.rs @@ -81,10 +81,9 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { match ccx.tcx.lang_items.to_builtin_kind(trait_ref.def_id) { Some(ty::BoundSend) | Some(ty::BoundSync) => {} Some(_) | None => { - ccx.tcx.sess.span_err( - item.span, - format!("negative impls are currently \ - allowed just for `Send` and `Sync`").as_slice()) + span_err!(ccx.tcx.sess, item.span, E0192, + "negative impls are currently \ + allowed just for `Send` and `Sync`") } } } @@ -302,12 +301,11 @@ fn reject_non_type_param_bounds<'tcx>(tcx: &ty::ctxt<'tcx>, fn report_bound_error<'t>(tcx: &ty::ctxt<'t>, span: Span, bounded_ty: ty::Ty<'t>) { - tcx.sess.span_err( - span, - format!("cannot bound type `{}`, where clause \ + span_err!(tcx.sess, span, E0193, + "cannot bound type `{}`, where clause \ bounds may only be attached to types involving \ type parameters", - bounded_ty.repr(tcx)).as_slice()) + bounded_ty.repr(tcx)) } fn is_ty_param(ty: ty::Ty) -> bool { @@ -326,10 +324,9 @@ fn reject_shadowing_type_parameters<'tcx>(tcx: &ty::ctxt<'tcx>, for method_param in generics.types.get_slice(subst::FnSpace).iter() { if impl_params.contains(&method_param.name) { - tcx.sess.span_err( - span, - &*format!("type parameter `{}` shadows another type parameter of the same name", - token::get_name(method_param.name))); + span_err!(tcx.sess, span, E0194, + "type parameter `{}` shadows another type parameter of the same name", + token::get_name(method_param.name)); } } } diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 82da22eab983..52e81585875a 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -416,7 +416,7 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> { ResolvingUnboxedClosure(_) => { let span = self.reason.span(self.tcx); - self.tcx.sess.span_err(span, + span_err!(self.tcx.sess, span, E0196, "cannot determine a type for this \ unboxed closure") } diff --git a/src/librustc_typeck/coherence/impls.rs b/src/librustc_typeck/coherence/impls.rs index 2719a09f4f57..e535b86a7bfd 100644 --- a/src/librustc_typeck/coherence/impls.rs +++ b/src/librustc_typeck/coherence/impls.rs @@ -34,10 +34,9 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for ImplsChecker<'cx, 'tcx> { match trait_ref.self_ty().sty { ty::ty_struct(..) | ty::ty_enum(..) => {} _ => { - self.tcx.sess.span_err( - item.span, - &format!("builtin traits can only be \ - implemented on structs or enums")[]); + span_err!(self.tcx.sess, item.span, E0209, + "builtin traits can only be \ + implemented on structs or enums"); } } } diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 350cee99f6a3..7d59c3f9d3ff 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -490,24 +490,21 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { match ty::can_type_implement_copy(¶m_env, span, self_type) { Ok(()) => {} Err(ty::FieldDoesNotImplementCopy(name)) => { - tcx.sess - .span_err(span, - &format!("the trait `Copy` may not be \ + span_err!(tcx.sess, span, E0204, + "the trait `Copy` may not be \ implemented for this type; field \ `{}` does not implement `Copy`", - token::get_name(name))[]) + token::get_name(name)) } Err(ty::VariantDoesNotImplementCopy(name)) => { - tcx.sess - .span_err(span, - &format!("the trait `Copy` may not be \ + span_err!(tcx.sess, span, E0205, + "the trait `Copy` may not be \ implemented for this type; variant \ `{}` does not implement `Copy`", - token::get_name(name))[]) + token::get_name(name)) } Err(ty::TypeIsStructural) => { - tcx.sess - .span_err(span, + span_err!(tcx.sess, span, E0206, "the trait `Copy` may not be implemented \ for this type; type is not a structure or \ enumeration") diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs index 77d71e740d68..60b1fa5f4cf5 100644 --- a/src/librustc_typeck/coherence/orphan.rs +++ b/src/librustc_typeck/coherence/orphan.rs @@ -89,13 +89,11 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> { } Err(traits::OrphanCheckErr::UncoveredTy(param_ty)) => { if !ty::has_attr(self.tcx, trait_def_id, "old_orphan_check") { - self.tcx.sess.span_err( - item.span, - format!( + span_err!(self.tcx.sess, item.span, E0210, "type parameter `{}` is not constrained by any local type; \ only traits defined in the current crate can be implemented \ for a type parameter", - param_ty.user_string(self.tcx)).as_slice()); + param_ty.user_string(self.tcx)); self.tcx.sess.span_note( item.span, format!("for a limited time, you can add \ diff --git a/src/librustc_typeck/coherence/overlap.rs b/src/librustc_typeck/coherence/overlap.rs index ce7ba9ac11e6..a7bad3dc789a 100644 --- a/src/librustc_typeck/coherence/overlap.rs +++ b/src/librustc_typeck/coherence/overlap.rs @@ -65,7 +65,7 @@ impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> { continue; } - for &impl2_def_id in trait_impls.slice_from(i+1).iter() { + for &impl2_def_id in trait_impls[(i+1)..].iter() { self.check_if_impls_overlap(trait_def_id, impl1_def_id, impl2_def_id); diff --git a/src/librustc_typeck/coherence/unsafety.rs b/src/librustc_typeck/coherence/unsafety.rs index e30d0a29938a..867dea958856 100644 --- a/src/librustc_typeck/coherence/unsafety.rs +++ b/src/librustc_typeck/coherence/unsafety.rs @@ -37,8 +37,7 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for UnsafetyChecker<'cx, 'tcx> { match unsafety { ast::Unsafety::Normal => { /* OK */ } ast::Unsafety::Unsafe => { - self.tcx.sess.span_err( - item.span, + span_err!(self.tcx.sess, item.span, E0197, "inherent impls cannot be declared as unsafe"); } } @@ -49,24 +48,21 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for UnsafetyChecker<'cx, 'tcx> { match (trait_def.unsafety, unsafety, polarity) { (ast::Unsafety::Unsafe, ast::Unsafety::Unsafe, ast::ImplPolarity::Negative) => { - self.tcx.sess.span_err( - item.span, - format!("negative implementations are not unsafe").as_slice()); + span_err!(self.tcx.sess, item.span, E0198, + "negative implementations are not unsafe"); } (ast::Unsafety::Normal, ast::Unsafety::Unsafe, _) => { - self.tcx.sess.span_err( - item.span, - format!("implementing the trait `{}` is not unsafe", - trait_ref.user_string(self.tcx)).as_slice()); + span_err!(self.tcx.sess, item.span, E0199, + "implementing the trait `{}` is not unsafe", + trait_ref.user_string(self.tcx)); } (ast::Unsafety::Unsafe, ast::Unsafety::Normal, ast::ImplPolarity::Positive) => { - self.tcx.sess.span_err( - item.span, - format!("the trait `{}` requires an `unsafe impl` declaration", - trait_ref.user_string(self.tcx)).as_slice()); + span_err!(self.tcx.sess, item.span, E0200, + "the trait `{}` requires an `unsafe impl` declaration", + trait_ref.user_string(self.tcx)); } (ast::Unsafety::Unsafe, diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 80c0a72db838..8158b8da86df 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -452,7 +452,7 @@ fn convert_methods<'a,'tcx,'i,I>(ccx: &CollectCtxt<'a, 'tcx>, let mut seen_methods = FnvHashSet(); for m in ms { if !seen_methods.insert(m.pe_ident().repr(tcx)) { - tcx.sess.span_err(m.span, "duplicate method in trait impl"); + span_err!(tcx.sess, m.span, E0201, "duplicate method in trait impl"); } let m_def_id = local_def(m.id); @@ -555,6 +555,7 @@ fn convert(ccx: &CollectCtxt, it: &ast::Item) { debug!("convert: item {} with id {}", token::get_ident(it.ident), it.id); match it.node { // These don't define types. + ast::ItemExternCrate(_) | ast::ItemUse(_) | ast::ItemForeignMod(_) | ast::ItemMod(_) | ast::ItemMac(_) => {} ast::ItemEnum(ref enum_definition, ref generics) => { let scheme = ty_of_item(ccx, it); @@ -608,7 +609,7 @@ fn convert(ccx: &CollectCtxt, it: &ast::Item) { } ast::TypeImplItem(ref typedef) => { if opt_trait_ref.is_none() { - tcx.sess.span_err(typedef.span, + span_err!(tcx.sess, typedef.span, E0202, "associated items are not allowed in inherent impls"); } @@ -1004,6 +1005,7 @@ fn ty_of_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, it: &ast::Item) tcx.tcache.borrow_mut().insert(local_def(it.id), scheme.clone()); return scheme; } + ast::ItemExternCrate(_) | ast::ItemUse(_) | ast::ItemImpl(..) | ast::ItemMod(_) | ast::ItemForeignMod(_) | ast::ItemMac(_) => panic!(), } @@ -1160,7 +1162,8 @@ fn add_unsized_bound<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>, assert!(ptr.bound_lifetimes.is_empty()); unbound = Some(ptr.trait_ref.clone()); } else { - ccx.tcx.sess.span_err(span, "type parameter has more than one relaxed default \ + span_err!(ccx.tcx.sess, span, E0203, + "type parameter has more than one relaxed default \ bound, only one is supported"); } } @@ -1690,11 +1693,10 @@ fn enforce_impl_ty_params_are_constrained<'tcx>(tcx: &ty::ctxt<'tcx>, impl trait, self type, or predicates", param_ty.user_string(tcx)).as_slice()); } else { - tcx.sess.span_err( - ty_param.span, - format!("the type parameter `{}` is not constrained by the \ + span_err!(tcx.sess, ty_param.span, E0207, + "the type parameter `{}` is not constrained by the \ impl trait, self type, or predicates", - param_ty.user_string(tcx)).as_slice()); + param_ty.user_string(tcx)); tcx.sess.span_help( ty_param.span, format!("you can temporarily opt out of this rule by placing \ diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index c9e15b93ad4c..3627fa411606 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -10,38 +10,7 @@ #![allow(non_snake_case)] -register_diagnostic! { - E0001, -r##" - This error suggests that the expression arm corresponding to the noted pattern - will never be reached as for all possible values of the expression being matched, - one of the preceeding patterns will match. - - This means that perhaps some of the preceeding patterns are too general, this - one is too specific or the ordering is incorrect. -"## } - register_diagnostics! { - E0002, - E0003, - E0004, - E0005, - E0006, - E0007, - E0008, - E0009, - E0010, - E0011, - E0012, - E0013, - E0014, - E0015, - E0016, - E0017, - E0018, - E0019, - E0020, - E0022, E0023, E0024, E0025, @@ -61,12 +30,9 @@ register_diagnostics! { E0046, E0049, E0050, - E0051, - E0052, E0053, E0054, E0055, - E0056, E0057, E0059, E0060, @@ -101,16 +67,12 @@ register_diagnostics! { E0092, E0093, E0094, - E0100, E0101, E0102, E0103, E0104, E0106, E0107, - E0108, - E0109, - E0110, E0116, E0117, E0118, @@ -125,38 +87,92 @@ register_diagnostics! { E0130, E0131, E0132, - E0133, - E0134, - E0135, - E0136, - E0137, - E0138, - E0139, - E0140, E0141, - E0152, - E0153, - E0157, - E0158, E0159, - E0161, - E0162, E0163, E0164, - E0165, E0166, E0167, E0168, - E0169, - E0171, E0172, E0173, // manual implementations of unboxed closure traits are experimental E0174, // explicit use of unboxed closure methods are experimental - E0177, E0178, - E0180, - E0181, E0182, E0183, - E0184 + E0184, + E0185, + E0186, + E0187, // can't infer the kind of the closure + E0188, // types differ in mutability + E0189, // can only cast a boxed pointer to a boxed object + E0190, // can only cast a &-pointer to an &-object + E0191, // value of the associated type must be specified + E0192, // negative imples are allowed just fo `Send` and `Sync` + E0193, // cannot bound type where clause bounds may only be attached to types + // involving type parameters + E0194, + E0195, // lifetime parameters or bounds on method do not match the trait declaration + E0196, // cannot determine a type for this unboxed closure + E0197, // inherent impls cannot be declared as unsafe + E0198, // negative implementations are not unsafe + E0199, // implementing trait is not unsafe + E0200, // trait requires an `unsafe impl` declaration + E0201, // duplicate method in trait impl + E0202, // associated items are not allowed in inherint impls + E0203, // type parameter has more than one relaxed default bound, + // and only one is supported + E0204, // trait `Copy` may not be implemented for this type; field + // does not implement `Copy` + E0205, // trait `Copy` may not be implemented for this type; variant + // does not implement `copy` + E0206, // trait `Copy` may not be implemented for this type; type is + // not a structure or enumeration + E0207, // type parameter is not constrained by the impl trait, self type, or predicate + E0208, + E0209, // builtin traits can only be implemented on structs or enums + E0210, // type parameter is not constrained by any local type + E0211, + E0212, // cannot extract an associated type from a higher-ranked trait bound + E0213, // associated types are not accepted in this context + E0214, // parenthesized parameters may only be used with a trait + E0215, // angle-bracket notation is not stable with `Fn` + E0216, // parenthetical notation is only stable with `Fn` + E0217, // ambiguous associated type, defined in multiple supertraits + E0218, // no associated type defined + E0219, // associated type defined in higher-ranked supertrait + E0220, // associated type not found for type parameter + E0221, // ambiguous associated type in bounds + E0222, // variadic function must have C calling convention + E0223, // ambiguous associated type + E0224, // at least one non-builtin train is required for an object type + E0225, // only the builtin traits can be used as closure or object bounds + E0226, // only a single explicit lifetime bound is permitted + E0227, // ambiguous lifetime bound, explicit lifetime bound required + E0228, // explicit lifetime bound required + E0229, // associated type bindings are not allowed here + E0230, // there is no type parameter on trait + E0231, // only named substitution parameters are allowed + E0232, // this attribute must have a value + E0233, + E0234, // `for` loop expression has type which does not implement the `Iterator` trait + E0235, // structure constructor specifies a structure of type but + E0236, // no lang item for range syntax + E0237, // no lang item for range syntax + E0238, // parenthesized parameters may only be used with a trait + E0239, // `next` method of `Iterator` trait has unexpected type + E0240, + E0241, + E0242, // internal error looking up a definition + E0243, // wrong number of type arguments + E0244, // wrong number of type arguments + E0245, // not a trait + E0246, // illegal recursive type + E0247, // found module name used as a type + E0248, // found value name used as a type + E0249, // expected constant expr for array length + E0250 // expected constant expr for array length } + +__build_diagnostic_array! { DIAGNOSTICS } + diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index ced77ebe8923..31c9f9961260 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -115,6 +115,10 @@ use syntax::ast_util::local_def; use std::cell::RefCell; +// NB: This module needs to be declared first so diagnostics are +// registered before they are used. +pub mod diagnostics; + mod check; mod rscope; mod astconv; @@ -162,7 +166,7 @@ fn lookup_def_tcx(tcx:&ty::ctxt, sp: Span, id: ast::NodeId) -> def::Def { match tcx.def_map.borrow().get(&id) { Some(x) => x.clone(), _ => { - tcx.sess.span_fatal(sp, "internal error looking up a definition") + span_fatal!(tcx.sess, sp, E0242, "internal error looking up a definition") } } } @@ -206,11 +210,11 @@ fn require_same_types<'a, 'tcx, M>(tcx: &ty::ctxt<'tcx>, match result { Ok(_) => true, Err(ref terr) => { - tcx.sess.span_err(span, - &format!("{}: {}", + span_err!(tcx.sess, span, E0211, + "{}: {}", msg(), ty::type_err_to_str(tcx, - terr))[]); + terr)); ty::note_and_explain_type_err(tcx, terr); false } diff --git a/src/librustc_typeck/variance.rs b/src/librustc_typeck/variance.rs index 86447e76a898..6ed18368738e 100644 --- a/src/librustc_typeck/variance.rs +++ b/src/librustc_typeck/variance.rs @@ -240,7 +240,7 @@ enum VarianceTerm<'a> { InferredTerm(InferredIndex), } -impl<'a> fmt::Show for VarianceTerm<'a> { +impl<'a> fmt::Debug for VarianceTerm<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { ConstantTerm(c1) => write!(f, "{:?}", c1), @@ -380,6 +380,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for TermsContext<'a, 'tcx> { visit::walk_item(self, item); } + ast::ItemExternCrate(_) | + ast::ItemUse(_) | ast::ItemImpl(..) | ast::ItemStatic(..) | ast::ItemConst(..) | @@ -532,6 +534,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ConstraintContext<'a, 'tcx> { } } + ast::ItemExternCrate(_) | + ast::ItemUse(_) | ast::ItemStatic(..) | ast::ItemConst(..) | ast::ItemFn(..) | @@ -1055,7 +1059,7 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> { // attribute and report an error with various results if found. if ty::has_attr(tcx, item_def_id, "rustc_variance") { let found = item_variances.repr(tcx); - tcx.sess.span_err(tcx.map.span(item_id), &found[]); + span_err!(tcx.sess, tcx.map.span(item_id), E0208, "{}", &found[]); } let newly_added = tcx.item_variance_map.borrow_mut() diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index ccaefadc1fcd..6e79bd9bebda 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -147,14 +147,22 @@ pub fn record_extern_fqn(cx: &DocContext, did: ast::DefId, kind: clean::TypeKind pub fn build_external_trait(cx: &DocContext, tcx: &ty::ctxt, did: ast::DefId) -> clean::Trait { + use clean::TraitMethod; + let def = ty::lookup_trait_def(tcx, did); let trait_items = ty::trait_items(tcx, did).clean(cx); let provided = ty::provided_trait_methods(tcx, did); let items = trait_items.into_iter().map(|trait_item| { - if provided.iter().any(|a| a.def_id == trait_item.def_id) { - clean::ProvidedMethod(trait_item) - } else { - clean::RequiredMethod(trait_item) + match trait_item.inner { + clean::TyMethodItem(_) => { + if provided.iter().any(|a| a.def_id == trait_item.def_id) { + TraitMethod::ProvidedMethod(trait_item) + } else { + TraitMethod::RequiredMethod(trait_item) + } + }, + clean::AssociatedTypeItem(_) => TraitMethod::TypeTraitItem(trait_item), + _ => unreachable!() } }); let trait_def = ty::lookup_trait_def(tcx, did); @@ -311,12 +319,25 @@ fn build_impl(cx: &DocContext, tcx: &ty::ctxt, }; Some(item) } - ty::TypeTraitItem(_) => { - // FIXME(pcwalton): Implement. - None + ty::TypeTraitItem(ref assoc_ty) => { + let did = assoc_ty.def_id; + let type_scheme = ty::lookup_item_type(tcx, did); + // Not sure the choice of ParamSpace actually matters here, because an + // associated type won't have generics on the LHS + let typedef = (type_scheme, subst::ParamSpace::TypeSpace).clean(cx); + Some(clean::Item { + name: Some(assoc_ty.name.clean(cx)), + inner: clean::TypedefItem(typedef), + source: clean::Span::empty(), + attrs: vec![], + visibility: None, + stability: stability::lookup(tcx, did).clean(cx), + def_id: did + }) } } }).collect(); + let polarity = csearch::get_impl_polarity(tcx, did); return Some(clean::Item { inner: clean::ImplItem(clean::Impl { derived: clean::detect_derived(attrs.as_slice()), @@ -329,6 +350,7 @@ fn build_impl(cx: &DocContext, tcx: &ty::ctxt, for_: ty.ty.clean(cx), generics: (&ty.generics, subst::TypeSpace).clean(cx), items: trait_items, + polarity: polarity.map(|p| { p.clean(cx) }), }), source: clean::Span::empty(), name: None, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index abe227537583..07b5586e691f 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -18,8 +18,7 @@ pub use self::TypeKind::*; pub use self::StructField::*; pub use self::VariantKind::*; pub use self::Mutability::*; -pub use self::ViewItemInner::*; -pub use self::ViewPath::*; +pub use self::Import::*; pub use self::ItemEnum::*; pub use self::Attribute::*; pub use self::TyParamBound::*; @@ -46,7 +45,6 @@ use rustc::middle::def; use rustc::middle::subst::{self, ParamSpace, VecPerParamSpace}; use rustc::middle::ty; use rustc::middle::stability; -use rustc::session::config; use std::rc::Rc; use std::u32; @@ -117,7 +115,7 @@ impl, U> Clean> for syntax::owned_slice::OwnedSlice { } } -#[derive(Clone, RustcEncodable, RustcDecodable)] +#[derive(Clone, RustcEncodable, RustcDecodable, Show)] pub struct Crate { pub name: String, pub src: FsPath, @@ -128,6 +126,8 @@ pub struct Crate { impl<'a, 'tcx> Clean for visit_ast::RustdocVisitor<'a, 'tcx> { fn clean(&self, cx: &DocContext) -> Crate { + use rustc::session::config::Input; + let mut externs = Vec::new(); cx.sess().cstore.iter_crate_data(|n, meta| { externs.push((n, meta.clean(cx))); @@ -135,8 +135,8 @@ impl<'a, 'tcx> Clean for visit_ast::RustdocVisitor<'a, 'tcx> { externs.sort_by(|&(a, _), &(b, _)| a.cmp(&b)); // Figure out the name of this crate - let input = config::Input::File(cx.src.clone()); - let name = link::find_crate_name(None, self.attrs.as_slice(), &input); + let input = &cx.input; + let name = link::find_crate_name(None, self.attrs.as_slice(), input); // Clean the crate, translating the entire libsyntax AST to one that is // understood by rustdoc. @@ -189,9 +189,14 @@ impl<'a, 'tcx> Clean for visit_ast::RustdocVisitor<'a, 'tcx> { m.items.extend(tmp.into_iter()); } + let src = match cx.input { + Input::File(ref path) => path.clone(), + Input::Str(_) => FsPath::new("") // FIXME: this is wrong + }; + Crate { name: name.to_string(), - src: cx.src.clone(), + src: src, module: Some(module), externs: externs, primitives: primitives, @@ -199,7 +204,7 @@ impl<'a, 'tcx> Clean for visit_ast::RustdocVisitor<'a, 'tcx> { } } -#[derive(Clone, RustcEncodable, RustcDecodable)] +#[derive(Clone, RustcEncodable, RustcDecodable, Show)] pub struct ExternalCrate { pub name: String, pub attrs: Vec, @@ -232,7 +237,7 @@ impl Clean for cstore::crate_metadata { /// Anything with a source location and set of attributes and, optionally, a /// name. That is, anything that can be documented. This doesn't correspond /// directly to the AST's concept of an item; it's a strict superset. -#[derive(Clone, RustcEncodable, RustcDecodable)] +#[derive(Clone, RustcEncodable, RustcDecodable, Show)] pub struct Item { /// Stringified span pub source: Span, @@ -308,8 +313,10 @@ impl Item { } } -#[derive(Clone, RustcEncodable, RustcDecodable)] +#[derive(Clone, RustcEncodable, RustcDecodable, Show)] pub enum ItemEnum { + ExternCrateItem(String, Option), + ImportItem(Import), StructItem(Struct), EnumItem(Enum), FunctionItem(Function), @@ -319,8 +326,6 @@ pub enum ItemEnum { ConstantItem(Constant), TraitItem(Trait), ImplItem(Impl), - /// `use` and `extern crate` - ViewItemItem(ViewItem), /// A method signature only. Used for required methods in traits (ie, /// non-default-methods). TyMethodItem(TyMethod), @@ -337,7 +342,7 @@ pub enum ItemEnum { AssociatedTypeItem(TyParam), } -#[derive(Clone, RustcEncodable, RustcDecodable)] +#[derive(Clone, RustcEncodable, RustcDecodable, Show)] pub struct Module { pub items: Vec, pub is_crate: bool, @@ -350,27 +355,21 @@ impl Clean for doctree::Module { } else { "".to_string() }; - let mut foreigns = Vec::new(); - for subforeigns in self.foreigns.clean(cx).into_iter() { - for foreign in subforeigns.into_iter() { - foreigns.push(foreign) - } - } - let items: Vec > = vec!( - self.structs.clean(cx), - self.enums.clean(cx), - self.fns.clean(cx), - foreigns, - self.mods.clean(cx), - self.typedefs.clean(cx), - self.statics.clean(cx), - self.constants.clean(cx), - self.traits.clean(cx), - self.impls.clean(cx), - self.view_items.clean(cx).into_iter() - .flat_map(|s| s.into_iter()).collect(), - self.macros.clean(cx), - ); + let items: Vec = + self.extern_crates.iter().map(|x| x.clean(cx)) + .chain(self.imports.iter().flat_map(|x| x.clean(cx).into_iter())) + .chain(self.structs.iter().map(|x| x.clean(cx))) + .chain(self.enums.iter().map(|x| x.clean(cx))) + .chain(self.fns.iter().map(|x| x.clean(cx))) + .chain(self.foreigns.iter().flat_map(|x| x.clean(cx).into_iter())) + .chain(self.mods.iter().map(|x| x.clean(cx))) + .chain(self.typedefs.iter().map(|x| x.clean(cx))) + .chain(self.statics.iter().map(|x| x.clean(cx))) + .chain(self.constants.iter().map(|x| x.clean(cx))) + .chain(self.traits.iter().map(|x| x.clean(cx))) + .chain(self.impls.iter().map(|x| x.clean(cx))) + .chain(self.macros.iter().map(|x| x.clean(cx))) + .collect(); // determine if we should display the inner contents or // the outer `mod` item for the source code. @@ -396,9 +395,7 @@ impl Clean for doctree::Module { def_id: ast_util::local_def(self.id), inner: ModuleItem(Module { is_crate: self.is_crate, - items: items.iter() - .flat_map(|x| x.iter().map(|x| (*x).clone())) - .collect(), + items: items }) } } @@ -941,7 +938,7 @@ impl<'a, 'tcx> Clean for (&'a ty::Generics<'tcx>, subst::ParamSpace) { } } -#[derive(Clone, RustcEncodable, RustcDecodable)] +#[derive(Clone, RustcEncodable, RustcDecodable, Show)] pub struct Method { pub generics: Generics, pub self_: SelfTy, @@ -980,7 +977,7 @@ impl Clean for ast::Method { } } -#[derive(Clone, RustcEncodable, RustcDecodable)] +#[derive(Clone, RustcEncodable, RustcDecodable, Show)] pub struct TyMethod { pub unsafety: ast::Unsafety, pub decl: FnDecl, @@ -1018,7 +1015,7 @@ impl Clean for ast::TypeMethod { } } -#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq)] +#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Show)] pub enum SelfTy { SelfStatic, SelfValue, @@ -1039,7 +1036,7 @@ impl Clean for ast::ExplicitSelf_ { } } -#[derive(Clone, RustcEncodable, RustcDecodable)] +#[derive(Clone, RustcEncodable, RustcDecodable, Show)] pub struct Function { pub decl: FnDecl, pub generics: Generics, @@ -1158,7 +1155,7 @@ impl Clean for ast::FunctionRetTy { } } -#[derive(Clone, RustcEncodable, RustcDecodable)] +#[derive(Clone, RustcEncodable, RustcDecodable, Show)] pub struct Trait { pub unsafety: ast::Unsafety, pub items: Vec, @@ -1202,11 +1199,11 @@ impl Clean for ast::PolyTraitRef { /// An item belonging to a trait, whether a method or associated. Could be named /// TraitItem except that's already taken by an exported enum variant. -#[derive(Clone, RustcEncodable, RustcDecodable)] +#[derive(Clone, RustcEncodable, RustcDecodable, Show)] pub enum TraitMethod { RequiredMethod(Item), ProvidedMethod(Item), - TypeTraitItem(Item), + TypeTraitItem(Item), // an associated type } impl TraitMethod { @@ -1247,7 +1244,7 @@ impl Clean for ast::TraitItem { } } -#[derive(Clone, RustcEncodable, RustcDecodable)] +#[derive(Clone, RustcEncodable, RustcDecodable, Show)] pub enum ImplMethod { MethodImplItem(Item), TypeImplItem(Item), @@ -1383,7 +1380,7 @@ pub enum PrimitiveType { PrimitiveTuple, } -#[derive(Clone, RustcEncodable, RustcDecodable, Copy)] +#[derive(Clone, RustcEncodable, RustcDecodable, Copy, Show)] pub enum TypeKind { TypeEnum, TypeFunction, @@ -1626,7 +1623,7 @@ impl Clean for ast::QPath { } } -#[derive(Clone, RustcEncodable, RustcDecodable)] +#[derive(Clone, RustcEncodable, RustcDecodable, Show)] pub enum StructField { HiddenStructField, // inserted later by strip passes TypedStructField(Type), @@ -1685,7 +1682,7 @@ impl Clean> for ast::Visibility { } } -#[derive(Clone, RustcEncodable, RustcDecodable)] +#[derive(Clone, RustcEncodable, RustcDecodable, Show)] pub struct Struct { pub struct_type: doctree::StructType, pub generics: Generics, @@ -1715,7 +1712,7 @@ impl Clean for doctree::Struct { /// This is a more limited form of the standard Struct, different in that /// it lacks the things most items have (name, id, parameterization). Found /// only as a variant in an enum. -#[derive(Clone, RustcEncodable, RustcDecodable)] +#[derive(Clone, RustcEncodable, RustcDecodable, Show)] pub struct VariantStruct { pub struct_type: doctree::StructType, pub fields: Vec, @@ -1732,7 +1729,7 @@ impl Clean for syntax::ast::StructDef { } } -#[derive(Clone, RustcEncodable, RustcDecodable)] +#[derive(Clone, RustcEncodable, RustcDecodable, Show)] pub struct Enum { pub variants: Vec, pub generics: Generics, @@ -1757,7 +1754,7 @@ impl Clean for doctree::Enum { } } -#[derive(Clone, RustcEncodable, RustcDecodable)] +#[derive(Clone, RustcEncodable, RustcDecodable, Show)] pub struct Variant { pub kind: VariantKind, } @@ -1825,7 +1822,7 @@ impl<'tcx> Clean for ty::VariantInfo<'tcx> { } } -#[derive(Clone, RustcEncodable, RustcDecodable)] +#[derive(Clone, RustcEncodable, RustcDecodable, Show)] pub enum VariantKind { CLikeVariant, TupleVariant(Vec), @@ -1875,9 +1872,9 @@ impl Clean for syntax::codemap::Span { Span { filename: filename.to_string(), loline: lo.line, - locol: lo.col.to_uint(), + locol: lo.col.to_usize(), hiline: hi.line, - hicol: hi.col.to_uint(), + hicol: hi.col.to_usize(), } } } @@ -1972,7 +1969,7 @@ impl Clean for ast::Name { } } -#[derive(Clone, RustcEncodable, RustcDecodable)] +#[derive(Clone, RustcEncodable, RustcDecodable, Show)] pub struct Typedef { pub type_: Type, pub generics: Generics, @@ -2085,13 +2082,29 @@ impl Clean for ast::Mutability { } } -#[derive(Clone, RustcEncodable, RustcDecodable)] +#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Copy, Show)] +pub enum ImplPolarity { + Positive, + Negative, +} + +impl Clean for ast::ImplPolarity { + fn clean(&self, _: &DocContext) -> ImplPolarity { + match self { + &ast::ImplPolarity::Positive => ImplPolarity::Positive, + &ast::ImplPolarity::Negative => ImplPolarity::Negative, + } + } +} + +#[derive(Clone, RustcEncodable, RustcDecodable, Show)] pub struct Impl { pub generics: Generics, pub trait_: Option, pub for_: Type, pub items: Vec, pub derived: bool, + pub polarity: Option, } fn detect_derived(attrs: &[M]) -> bool { @@ -2118,17 +2131,27 @@ impl Clean for doctree::Impl { } }).collect(), derived: detect_derived(self.attrs.as_slice()), + polarity: Some(self.polarity.clean(cx)), }), } } } -#[derive(Clone, RustcEncodable, RustcDecodable)] -pub struct ViewItem { - pub inner: ViewItemInner, +impl Clean for doctree::ExternCrate { + fn clean(&self, cx: &DocContext) -> Item { + Item { + name: None, + attrs: self.attrs.clean(cx), + source: self.whence.clean(cx), + def_id: ast_util::local_def(0), + visibility: self.vis.clean(cx), + stability: None, + inner: ExternCrateItem(self.name.clean(cx), self.path.clone()) + } + } } -impl Clean> for ast::ViewItem { +impl Clean> for doctree::Import { fn clean(&self, cx: &DocContext) -> Vec { // We consider inlining the documentation of `pub use` statements, but we // forcefully don't inline if this is not public or if the @@ -2139,81 +2162,63 @@ impl Clean> for ast::ViewItem { None => false, } }); - let convert = |&: node: &ast::ViewItem_| { - Item { - name: None, - attrs: self.attrs.clean(cx), - source: self.span.clean(cx), - def_id: ast_util::local_def(0), - visibility: self.vis.clean(cx), - stability: None, - inner: ViewItemItem(ViewItem { inner: node.clean(cx) }), + let (mut ret, inner) = match self.node { + ast::ViewPathGlob(ref p) => { + (vec![], GlobImport(resolve_use_source(cx, p.clean(cx), self.id))) } - }; - let mut ret = Vec::new(); - match self.node { - ast::ViewItemUse(ref path) if !denied => { - match path.node { - ast::ViewPathGlob(..) => ret.push(convert(&self.node)), - ast::ViewPathList(ref a, ref list, ref b) => { - // Attempt to inline all reexported items, but be sure - // to keep any non-inlineable reexports so they can be - // listed in the documentation. - let remaining = list.iter().filter(|path| { - match inline::try_inline(cx, path.node.id(), None) { - Some(items) => { - ret.extend(items.into_iter()); false - } - None => true, + ast::ViewPathList(ref p, ref list) => { + // Attempt to inline all reexported items, but be sure + // to keep any non-inlineable reexports so they can be + // listed in the documentation. + let mut ret = vec![]; + let remaining = if !denied { + let mut remaining = vec![]; + for path in list.iter() { + match inline::try_inline(cx, path.node.id(), None) { + Some(items) => { + ret.extend(items.into_iter()); + } + None => { + remaining.push(path.clean(cx)); } - }).map(|a| a.clone()).collect::>(); - if remaining.len() > 0 { - let path = ast::ViewPathList(a.clone(), - remaining, - b.clone()); - let path = syntax::codemap::dummy_spanned(path); - ret.push(convert(&ast::ViewItemUse(P(path)))); } } - ast::ViewPathSimple(ident, _, id) => { - match inline::try_inline(cx, id, Some(ident)) { - Some(items) => ret.extend(items.into_iter()), - None => ret.push(convert(&self.node)), - } + remaining + } else { + list.clean(cx) + }; + if remaining.is_empty() { + return ret; + } + (ret, ImportList(resolve_use_source(cx, p.clean(cx), self.id), + remaining)) + } + ast::ViewPathSimple(i, ref p) => { + if !denied { + match inline::try_inline(cx, self.id, Some(i)) { + Some(items) => return items, + None => {} } } + (vec![], SimpleImport(i.clean(cx), + resolve_use_source(cx, p.clean(cx), self.id))) } - ref n => ret.push(convert(n)), - } - return ret; + }; + ret.push(Item { + name: None, + attrs: self.attrs.clean(cx), + source: self.whence.clean(cx), + def_id: ast_util::local_def(0), + visibility: self.vis.clean(cx), + stability: None, + inner: ImportItem(inner) + }); + ret } } -#[derive(Clone, RustcEncodable, RustcDecodable)] -pub enum ViewItemInner { - ExternCrate(String, Option, ast::NodeId), - Import(ViewPath) -} - -impl Clean for ast::ViewItem_ { - fn clean(&self, cx: &DocContext) -> ViewItemInner { - match self { - &ast::ViewItemExternCrate(ref i, ref p, ref id) => { - let string = match *p { - None => None, - Some((ref x, _)) => Some(x.get().to_string()), - }; - ExternCrate(i.clean(cx), string, *id) - } - &ast::ViewItemUse(ref vp) => { - Import(vp.clean(cx)) - } - } - } -} - -#[derive(Clone, RustcEncodable, RustcDecodable)] -pub enum ViewPath { +#[derive(Clone, RustcEncodable, RustcDecodable, Show)] +pub enum Import { // use source as str; SimpleImport(String, ImportSource), // use source::*; @@ -2222,28 +2227,13 @@ pub enum ViewPath { ImportList(ImportSource, Vec), } -#[derive(Clone, RustcEncodable, RustcDecodable)] +#[derive(Clone, RustcEncodable, RustcDecodable, Show)] pub struct ImportSource { pub path: Path, pub did: Option, } -impl Clean for ast::ViewPath { - fn clean(&self, cx: &DocContext) -> ViewPath { - match self.node { - ast::ViewPathSimple(ref i, ref p, id) => - SimpleImport(i.clean(cx), resolve_use_source(cx, p.clean(cx), id)), - ast::ViewPathGlob(ref p, id) => - GlobImport(resolve_use_source(cx, p.clean(cx), id)), - ast::ViewPathList(ref p, ref pl, id) => { - ImportList(resolve_use_source(cx, p.clean(cx), id), - pl.clean(cx)) - } - } - } -} - -#[derive(Clone, RustcEncodable, RustcDecodable)] +#[derive(Clone, RustcEncodable, RustcDecodable, Show)] pub struct ViewListIdent { pub name: String, pub source: Option, @@ -2462,7 +2452,7 @@ fn resolve_def(cx: &DocContext, id: ast::NodeId) -> Option { }) } -#[derive(Clone, RustcEncodable, RustcDecodable)] +#[derive(Clone, RustcEncodable, RustcDecodable, Show)] pub struct Macro { pub source: String, } @@ -2483,7 +2473,7 @@ impl Clean for doctree::Macro { } } -#[derive(Clone, RustcEncodable, RustcDecodable)] +#[derive(Clone, RustcEncodable, RustcDecodable, Show)] pub struct Stability { pub level: attr::StabilityLevel, pub feature: String, @@ -2524,14 +2514,14 @@ impl Clean for ty::AssociatedType { source: DUMMY_SP.clean(cx), name: Some(self.name.clean(cx)), attrs: Vec::new(), - // FIXME(#18048): this is wrong, but cross-crate associated types are broken - // anyway, for the time being. inner: AssociatedTypeItem(TyParam { name: self.name.clean(cx), did: ast::DefId { krate: 0, node: ast::DUMMY_NODE_ID }, + // FIXME(#20727): bounds are missing and need to be filled in from the + // predicates on the trait itself bounds: vec![], default: None, }), @@ -2563,6 +2553,16 @@ impl Clean for ast::Typedef { } } +impl<'a> Clean for (ty::TypeScheme<'a>, ParamSpace) { + fn clean(&self, cx: &DocContext) -> Typedef { + let (ref ty_scheme, ps) = *self; + Typedef { + type_: ty_scheme.ty.clean(cx), + generics: (&ty_scheme.generics, ps).clean(cx) + } + } +} + fn lang_struct(cx: &DocContext, did: Option, t: ty::Ty, name: &str, fallback: fn(Box) -> Type) -> Type { diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 5bef0195874b..04947e41663e 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -12,7 +12,6 @@ pub use self::MaybeTyped::*; use rustc_driver::driver; use rustc::session::{self, config}; use rustc::session::config::UnstableFeatures; -use rustc::session::search_paths::SearchPaths; use rustc::middle::{privacy, ty}; use rustc::lint; use rustc_trans::back::link; @@ -27,6 +26,9 @@ use visit_ast::RustdocVisitor; use clean; use clean::Clean; +pub use rustc::session::config::Input; +pub use rustc::session::search_paths::SearchPaths; + /// Are we generating documentation (`Typed`) or tests (`NotTyped`)? pub enum MaybeTyped<'tcx> { Typed(ty::ctxt<'tcx>), @@ -39,7 +41,7 @@ pub type ExternalPaths = RefCell { pub krate: &'tcx ast::Crate, pub maybe_typed: MaybeTyped<'tcx>, - pub src: Path, + pub input: Input, pub external_paths: ExternalPaths, pub external_traits: RefCell>>, pub external_typarams: RefCell>>, @@ -80,12 +82,15 @@ pub struct CrateAnalysis { pub type Externs = HashMap>; pub fn run_core(search_paths: SearchPaths, cfgs: Vec, externs: Externs, - cpath: &Path, triple: Option) + input: Input, triple: Option) -> (clean::Crate, CrateAnalysis) { // Parse, resolve, and typecheck the given crate. - let input = config::Input::File(cpath.clone()); + let cpath = match input { + Input::File(ref p) => Some(p.clone()), + _ => None + }; let warning_lint = lint::builtin::WARNINGS.name_lower(); @@ -107,8 +112,7 @@ pub fn run_core(search_paths: SearchPaths, cfgs: Vec, externs: Externs, let span_diagnostic_handler = diagnostic::mk_span_handler(diagnostic_handler, codemap); - let sess = session::build_session_(sessopts, - Some(cpath.clone()), + let sess = session::build_session_(sessopts, cpath, span_diagnostic_handler); let cfg = config::build_configuration(&sess); @@ -136,7 +140,7 @@ pub fn run_core(search_paths: SearchPaths, cfgs: Vec, externs: Externs, let ctxt = DocContext { krate: ty_cx.map.krate(), maybe_typed: Typed(ty_cx), - src: cpath.clone(), + input: input, external_traits: RefCell::new(Some(HashMap::new())), external_typarams: RefCell::new(Some(HashMap::new())), external_paths: RefCell::new(Some(HashMap::new())), diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index 99afef4173fd..0e8ab594c20c 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -25,6 +25,8 @@ pub struct Module { pub attrs: Vec, pub where_outer: Span, pub where_inner: Span, + pub extern_crates: Vec, + pub imports: Vec, pub structs: Vec, pub enums: Vec, pub fns: Vec, @@ -38,7 +40,6 @@ pub struct Module { pub stab: Option, pub impls: Vec, pub foreigns: Vec, - pub view_items: Vec, pub macros: Vec, pub is_crate: bool, } @@ -53,6 +54,8 @@ impl Module { where_outer: syntax::codemap::DUMMY_SP, where_inner: syntax::codemap::DUMMY_SP, attrs : Vec::new(), + extern_crates: Vec::new(), + imports : Vec::new(), structs : Vec::new(), enums : Vec::new(), fns : Vec::new(), @@ -62,7 +65,6 @@ impl Module { constants : Vec::new(), traits : Vec::new(), impls : Vec::new(), - view_items : Vec::new(), foreigns : Vec::new(), macros : Vec::new(), is_crate : false, @@ -202,6 +204,22 @@ pub struct Macro { pub stab: Option, } +pub struct ExternCrate { + pub name: Ident, + pub path: Option, + pub vis: ast::Visibility, + pub attrs: Vec, + pub whence: Span, +} + +pub struct Import { + pub id: NodeId, + pub vis: ast::Visibility, + pub attrs: Vec, + pub node: ast::ViewPath_, + pub whence: Span, +} + pub fn struct_type_from_def(sd: &ast::StructDef) -> StructType { if sd.ctor_id.is_some() { // We are in a tuple-struct diff --git a/src/librustdoc/html/escape.rs b/src/librustdoc/html/escape.rs index 6fb78d9a8334..fe8ac3fde5fc 100644 --- a/src/librustdoc/html/escape.rs +++ b/src/librustdoc/html/escape.rs @@ -19,7 +19,7 @@ use std::fmt; /// string when passed to a format string. pub struct Escape<'a>(pub &'a str); -impl<'a> fmt::String for Escape<'a> { +impl<'a> fmt::Display for Escape<'a> { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { // Because the internet is always right, turns out there's not that many // characters to escape: http://stackoverflow.com/questions/7381974 @@ -29,7 +29,7 @@ impl<'a> fmt::String for Escape<'a> { for (i, ch) in s.bytes().enumerate() { match ch as char { '<' | '>' | '&' | '\'' | '"' => { - try!(fmt.write_str(pile_o_bits.slice(last, i))); + try!(fmt.write_str(&pile_o_bits[last.. i])); let s = match ch as char { '>' => ">", '<' => "<", @@ -46,7 +46,7 @@ impl<'a> fmt::String for Escape<'a> { } if last < s.len() { - try!(fmt.write_str(pile_o_bits.slice_from(last))); + try!(fmt.write_str(&pile_o_bits[last..])); } Ok(()) } diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 255ce03c586f..b6db3222f305 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -66,7 +66,7 @@ impl UnsafetySpace { } } -impl<'a, T: fmt::String> fmt::String for CommaSep<'a, T> { +impl<'a, T: fmt::Display> fmt::Display for CommaSep<'a, T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { for (i, item) in self.0.iter().enumerate() { if i != 0 { try!(write!(f, ", ")); } @@ -76,7 +76,7 @@ impl<'a, T: fmt::String> fmt::String for CommaSep<'a, T> { } } -impl<'a> fmt::String for TyParamBounds<'a> { +impl<'a> fmt::Display for TyParamBounds<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let &TyParamBounds(bounds) = self; for (i, bound) in bounds.iter().enumerate() { @@ -89,7 +89,7 @@ impl<'a> fmt::String for TyParamBounds<'a> { } } -impl fmt::String for clean::Generics { +impl fmt::Display for clean::Generics { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { if self.lifetimes.len() == 0 && self.type_params.len() == 0 { return Ok(()) } try!(f.write_str("<")); @@ -126,7 +126,7 @@ impl fmt::String for clean::Generics { } } -impl<'a> fmt::String for WhereClause<'a> { +impl<'a> fmt::Display for WhereClause<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let &WhereClause(gens) = self; if gens.where_predicates.len() == 0 { @@ -163,14 +163,14 @@ impl<'a> fmt::String for WhereClause<'a> { } } -impl fmt::String for clean::Lifetime { +impl fmt::Display for clean::Lifetime { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { try!(f.write_str(self.get_ref())); Ok(()) } } -impl fmt::String for clean::PolyTrait { +impl fmt::Display for clean::PolyTrait { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { if self.lifetimes.len() > 0 { try!(f.write_str("for<")); @@ -186,7 +186,7 @@ impl fmt::String for clean::PolyTrait { } } -impl fmt::String for clean::TyParamBound { +impl fmt::Display for clean::TyParamBound { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { clean::RegionBound(ref lt) => { @@ -203,7 +203,7 @@ impl fmt::String for clean::TyParamBound { } } -impl fmt::String for clean::PathParameters { +impl fmt::Display for clean::PathParameters { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { clean::PathParameters::AngleBracketed { @@ -257,14 +257,14 @@ impl fmt::String for clean::PathParameters { } } -impl fmt::String for clean::PathSegment { +impl fmt::Display for clean::PathSegment { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { try!(f.write_str(self.name.as_slice())); write!(f, "{}", self.params) } } -impl fmt::String for clean::Path { +impl fmt::Display for clean::Path { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { if self.global { try!(f.write_str("::")) @@ -358,7 +358,7 @@ fn path(w: &mut fmt::Formatter, // This is a documented path, link to it! Some((ref fqp, shortty)) if abs_root.is_some() => { let mut url = String::from_str(abs_root.unwrap().as_slice()); - let to_link = &fqp[..(fqp.len() - 1)]; + let to_link = &fqp[..fqp.len() - 1]; for component in to_link.iter() { url.push_str(component.as_slice()); url.push_str("/"); @@ -450,7 +450,7 @@ fn tybounds(w: &mut fmt::Formatter, } } -impl fmt::String for clean::Type { +impl fmt::Display for clean::Type { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { clean::TyParamBinder(id) => { @@ -539,7 +539,7 @@ impl fmt::String for clean::Type { } } -impl fmt::String for clean::Arguments { +impl fmt::Display for clean::Arguments { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { for (i, input) in self.values.iter().enumerate() { if i > 0 { try!(write!(f, ", ")); } @@ -552,7 +552,7 @@ impl fmt::String for clean::Arguments { } } -impl fmt::String for clean::FunctionRetTy { +impl fmt::Display for clean::FunctionRetTy { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { clean::Return(clean::Tuple(ref tys)) if tys.is_empty() => Ok(()), @@ -563,13 +563,13 @@ impl fmt::String for clean::FunctionRetTy { } } -impl fmt::String for clean::FnDecl { +impl fmt::Display for clean::FnDecl { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "({args}){arrow}", args = self.inputs, arrow = self.output) } } -impl<'a> fmt::String for Method<'a> { +impl<'a> fmt::Display for Method<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let Method(selfty, d) = *self; let mut args = String::new(); @@ -599,7 +599,7 @@ impl<'a> fmt::String for Method<'a> { } } -impl fmt::String for VisSpace { +impl fmt::Display for VisSpace { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.get() { Some(ast::Public) => write!(f, "pub "), @@ -608,7 +608,7 @@ impl fmt::String for VisSpace { } } -impl fmt::String for UnsafetySpace { +impl fmt::Display for UnsafetySpace { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.get() { ast::Unsafety::Unsafe => write!(f, "unsafe "), @@ -617,7 +617,7 @@ impl fmt::String for UnsafetySpace { } } -impl fmt::String for clean::ViewPath { +impl fmt::Display for clean::Import { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { clean::SimpleImport(ref name, ref src) => { @@ -644,7 +644,7 @@ impl fmt::String for clean::ViewPath { } } -impl fmt::String for clean::ImportSource { +impl fmt::Display for clean::ImportSource { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.did { Some(did) => resolved_path(f, did, &self.path, true), @@ -661,7 +661,7 @@ impl fmt::String for clean::ImportSource { } } -impl fmt::String for clean::ViewListIdent { +impl fmt::Display for clean::ViewListIdent { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.source { Some(did) => { @@ -683,13 +683,13 @@ impl fmt::String for clean::ViewListIdent { } } -impl fmt::String for clean::TypeBinding { +impl fmt::Display for clean::TypeBinding { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}={}", self.name, self.ty) } } -impl fmt::String for MutableSpace { +impl fmt::Display for MutableSpace { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { MutableSpace(clean::Immutable) => Ok(()), @@ -698,7 +698,7 @@ impl fmt::String for MutableSpace { } } -impl fmt::String for RawMutableSpace { +impl fmt::Display for RawMutableSpace { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { RawMutableSpace(clean::Immutable) => write!(f, "const "), @@ -707,7 +707,7 @@ impl fmt::String for RawMutableSpace { } } -impl<'a> fmt::String for Stability<'a> { +impl<'a> fmt::Display for Stability<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let Stability(stab) = *self; match *stab { @@ -721,7 +721,7 @@ impl<'a> fmt::String for Stability<'a> { } } -impl<'a> fmt::String for ConciseStability<'a> { +impl<'a> fmt::Display for ConciseStability<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let ConciseStability(stab) = *self; match *stab { @@ -738,7 +738,7 @@ impl<'a> fmt::String for ConciseStability<'a> { } } -impl fmt::String for ModuleSummary { +impl fmt::Display for ModuleSummary { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt_inner<'a>(f: &mut fmt::Formatter, context: &mut Vec<&'a str>, diff --git a/src/librustdoc/html/item_type.rs b/src/librustdoc/html/item_type.rs index db3319eb7659..356be2ffeb04 100644 --- a/src/librustdoc/html/item_type.rs +++ b/src/librustdoc/html/item_type.rs @@ -22,29 +22,31 @@ use clean; #[derive(Copy, PartialEq, Clone)] pub enum ItemType { Module = 0, - Struct = 1, - Enum = 2, - Function = 3, - Typedef = 4, - Static = 5, - Trait = 6, - Impl = 7, - ViewItem = 8, - TyMethod = 9, - Method = 10, - StructField = 11, - Variant = 12, - // we used to have ForeignFunction and ForeignStatic. they are retired now. - Macro = 15, - Primitive = 16, - AssociatedType = 17, - Constant = 18, + ExternCrate = 1, + Import = 2, + Struct = 3, + Enum = 4, + Function = 5, + Typedef = 6, + Static = 7, + Trait = 8, + Impl = 9, + TyMethod = 10, + Method = 11, + StructField = 12, + Variant = 13, + Macro = 14, + Primitive = 15, + AssociatedType = 16, + Constant = 17, } impl ItemType { pub fn from_item(item: &clean::Item) -> ItemType { match item.inner { clean::ModuleItem(..) => ItemType::Module, + clean::ExternCrateItem(..) => ItemType::ExternCrate, + clean::ImportItem(..) => ItemType::Import, clean::StructItem(..) => ItemType::Struct, clean::EnumItem(..) => ItemType::Enum, clean::FunctionItem(..) => ItemType::Function, @@ -53,7 +55,6 @@ impl ItemType { clean::ConstantItem(..) => ItemType::Constant, clean::TraitItem(..) => ItemType::Trait, clean::ImplItem(..) => ItemType::Impl, - clean::ViewItemItem(..) => ItemType::ViewItem, clean::TyMethodItem(..) => ItemType::TyMethod, clean::MethodItem(..) => ItemType::Method, clean::StructFieldItem(..) => ItemType::StructField, @@ -83,6 +84,8 @@ impl ItemType { pub fn to_static_str(&self) -> &'static str { match *self { ItemType::Module => "mod", + ItemType::ExternCrate => "externcrate", + ItemType::Import => "import", ItemType::Struct => "struct", ItemType::Enum => "enum", ItemType::Function => "fn", @@ -90,7 +93,6 @@ impl ItemType { ItemType::Static => "static", ItemType::Trait => "trait", ItemType::Impl => "impl", - ItemType::ViewItem => "viewitem", ItemType::TyMethod => "tymethod", ItemType::Method => "method", ItemType::StructField => "structfield", @@ -103,7 +105,7 @@ impl ItemType { } } -impl fmt::String for ItemType { +impl fmt::Display for ItemType { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.to_static_str().fmt(f) } diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index f75ab3f431c2..e3bd2b4e27f0 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -30,7 +30,7 @@ pub struct Page<'a> { pub keywords: &'a str } -pub fn render( +pub fn render( dst: &mut io::Writer, layout: &Layout, page: &Page, sidebar: &S, t: &T) -> io::IoResult<()> { diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 0dbd13b4616b..00182a80ab3d 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -72,16 +72,40 @@ type blockcodefn = extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer, type headerfn = extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer, libc::c_int, *mut libc::c_void); +type linkfn = extern "C" fn (*mut hoedown_buffer, *const hoedown_buffer, + *const hoedown_buffer, *const hoedown_buffer, + *mut libc::c_void) -> libc::c_int; + +type normaltextfn = extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer, + *mut libc::c_void); + #[repr(C)] struct hoedown_renderer { - opaque: *mut hoedown_html_renderer_state, + opaque: *mut libc::c_void, + blockcode: Option, blockquote: Option, blockhtml: Option, header: Option, - other: [libc::size_t; 28], + + other_block_level_callbacks: [libc::size_t; 9], + + /* span level callbacks - NULL or return 0 prints the span verbatim */ + other_span_level_callbacks_1: [libc::size_t; 9], + link: Option, + other_span_level_callbacks_2: [libc::size_t; 5], + // hoedown will add `math` callback here, but we use an old version of it. + + /* low level callbacks - NULL copies input directly into the output */ + entity: Option, + normal_text: Option, + + /* header and footer */ + doc_header: Option, + doc_footer: Option, } #[repr(C)] @@ -134,6 +158,8 @@ extern { fn hoedown_document_free(md: *mut hoedown_document); fn hoedown_buffer_new(unit: libc::size_t) -> *mut hoedown_buffer; + fn hoedown_buffer_put(b: *mut hoedown_buffer, c: *const libc::c_char, + n: libc::size_t); fn hoedown_buffer_puts(b: *mut hoedown_buffer, c: *const libc::c_char); fn hoedown_buffer_free(b: *mut hoedown_buffer); @@ -146,7 +172,7 @@ extern { fn stripped_filtered_line<'a>(s: &'a str) -> Option<&'a str> { let trimmed = s.trim(); if trimmed.starts_with("# ") { - Some(trimmed.slice_from(2)) + Some(&trimmed[2..]) } else { None } @@ -279,7 +305,8 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result { dfltblk: (*renderer).blockcode.unwrap(), toc_builder: if print_toc {Some(TocBuilder::new())} else {None} }; - (*(*renderer).opaque).opaque = &mut opaque as *mut _ as *mut libc::c_void; + (*((*renderer).opaque as *mut hoedown_html_renderer_state)).opaque + = &mut opaque as *mut _ as *mut libc::c_void; (*renderer).blockcode = Some(block as blockcodefn); (*renderer).header = Some(header as headerfn); @@ -355,7 +382,8 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector) { let renderer = hoedown_html_renderer_new(0, 0); (*renderer).blockcode = Some(block as blockcodefn); (*renderer).header = Some(header as headerfn); - (*(*renderer).opaque).opaque = tests as *mut _ as *mut libc::c_void; + (*((*renderer).opaque as *mut hoedown_html_renderer_state)).opaque + = tests as *mut _ as *mut libc::c_void; let document = hoedown_document_new(renderer, HOEDOWN_EXTENSIONS, 16); hoedown_document_render(document, ob, doc.as_ptr(), @@ -426,7 +454,7 @@ pub fn reset_headers() { USED_HEADER_MAP.with(|s| s.borrow_mut().clear()); } -impl<'a> fmt::String for Markdown<'a> { +impl<'a> fmt::Display for Markdown<'a> { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let Markdown(md) = *self; // This is actually common enough to special-case @@ -435,16 +463,67 @@ impl<'a> fmt::String for Markdown<'a> { } } -impl<'a> fmt::String for MarkdownWithToc<'a> { +impl<'a> fmt::Display for MarkdownWithToc<'a> { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let MarkdownWithToc(md) = *self; render(fmt, md.as_slice(), true) } } +pub fn plain_summary_line(md: &str) -> String { + extern fn link(_ob: *mut hoedown_buffer, + _link: *const hoedown_buffer, + _title: *const hoedown_buffer, + content: *const hoedown_buffer, + opaque: *mut libc::c_void) -> libc::c_int + { + unsafe { + if !content.is_null() && (*content).size > 0 { + let ob = opaque as *mut hoedown_buffer; + hoedown_buffer_put(ob, (*content).data as *const libc::c_char, + (*content).size); + } + } + 1 + } + + extern fn normal_text(_ob: *mut hoedown_buffer, + text: *const hoedown_buffer, + opaque: *mut libc::c_void) + { + unsafe { + let ob = opaque as *mut hoedown_buffer; + hoedown_buffer_put(ob, (*text).data as *const libc::c_char, + (*text).size); + } + } + + unsafe { + let ob = hoedown_buffer_new(DEF_OUNIT); + let mut plain_renderer: hoedown_renderer = ::std::mem::zeroed(); + let renderer = &mut plain_renderer as *mut hoedown_renderer; + (*renderer).opaque = ob as *mut libc::c_void; + (*renderer).link = Some(link as linkfn); + (*renderer).normal_text = Some(normal_text as normaltextfn); + + let document = hoedown_document_new(renderer, HOEDOWN_EXTENSIONS, 16); + hoedown_document_render(document, ob, md.as_ptr(), + md.len() as libc::size_t); + hoedown_document_free(document); + let plain_slice = slice::from_raw_buf(&(*ob).data, (*ob).size as uint); + let plain = match str::from_utf8(plain_slice) { + Ok(s) => s.to_string(), + Err(_) => "".to_string(), + }; + hoedown_buffer_free(ob); + plain + } +} + #[cfg(test)] mod tests { use super::{LangString, Markdown}; + use super::plain_summary_line; #[test] fn test_lang_string_parse() { @@ -478,4 +557,18 @@ mod tests { let markdown = "# title"; format!("{}", Markdown(markdown.as_slice())); } + + #[test] + fn test_plain_summary_line() { + fn t(input: &str, expect: &str) { + let output = plain_summary_line(input); + assert_eq!(output, expect); + } + + t("hello [Rust](http://rust-lang.org) :)", "hello Rust :)"); + t("code `let x = i32;` ...", "code `let x = i32;` ..."); + t("type `Type<'static>` ...", "type `Type<'static>` ..."); + t("# top header", "top header"); + t("## header", "header"); + } } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index ab9700d966aa..9a25993d28a6 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -35,7 +35,7 @@ pub use self::ExternalLocation::*; use std::cell::RefCell; -use std::cmp::Ordering::{self, Less, Greater, Equal}; +use std::cmp::Ordering; use std::collections::{HashMap, HashSet}; use std::default::Default; use std::fmt; @@ -64,8 +64,13 @@ use html::item_type::ItemType; use html::layout; use html::markdown::Markdown; use html::markdown; +use html::escape::Escape; use stability_summary; +/// A pair of name and its optional document. +#[derive(Clone, Eq, Ord, PartialEq, PartialOrd)] +pub struct NameDoc(String, Option); + /// Major driving force in all rustdoc rendering. This contains information /// about where in the tree-like hierarchy rendering is occurring and controls /// how the current page is being rendered. @@ -95,7 +100,7 @@ pub struct Context { /// functions), and the value is the list of containers belonging to this /// header. This map will change depending on the surrounding context of the /// page. - pub sidebar: HashMap>, + pub sidebar: HashMap>, /// This flag indicates whether [src] links should be generated or not. If /// the source files are present in the html rendering, then this will be /// `true`. @@ -404,7 +409,7 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> io::IoResult search_index.push(IndexItem { ty: shortty(item), name: item.name.clone().unwrap(), - path: fqp[..(fqp.len() - 1)].connect("::"), + path: fqp[..fqp.len() - 1].connect("::"), desc: shorter(item.doc_value()).to_string(), parent: Some(did), }); @@ -559,7 +564,7 @@ fn write_shared(cx: &Context, }; let mut mydst = dst.clone(); - for part in remote_path[..(remote_path.len() - 1)].iter() { + for part in remote_path[..remote_path.len() - 1].iter() { mydst.push(part.as_slice()); try!(mkdir(&mydst)); } @@ -749,7 +754,7 @@ impl<'a> SourceCollector<'a> { // Remove the utf-8 BOM if any let contents = if contents.starts_with("\u{feff}") { - contents.slice_from(3) + &contents[3..] } else { contents }; @@ -842,7 +847,7 @@ impl DocFolder for Cache { clean::StructFieldItem(..) | clean::VariantItem(..) => { ((Some(*self.parent_stack.last().unwrap()), - Some(&self.stack[..(self.stack.len() - 1)])), + Some(&self.stack[..self.stack.len() - 1])), false) } clean::MethodItem(..) => { @@ -853,13 +858,13 @@ impl DocFolder for Cache { let did = *last; let path = match self.paths.get(&did) { Some(&(_, ItemType::Trait)) => - Some(&self.stack[..(self.stack.len() - 1)]), + Some(&self.stack[..self.stack.len() - 1]), // The current stack not necessarily has correlation for // where the type was defined. On the other hand, // `paths` always has the right information if present. Some(&(ref fqp, ItemType::Struct)) | Some(&(ref fqp, ItemType::Enum)) => - Some(&fqp[..(fqp.len() - 1)]), + Some(&fqp[..fqp.len() - 1]), Some(..) => Some(self.stack.as_slice()), None => None }; @@ -1185,7 +1190,7 @@ impl Context { .collect::(); match cache().paths.get(&it.def_id) { Some(&(ref names, _)) => { - for name in (&names[..(names.len() - 1)]).iter() { + for name in (&names[..names.len() - 1]).iter() { url.push_str(name.as_slice()); url.push_str("/"); } @@ -1245,7 +1250,7 @@ impl Context { } } - fn build_sidebar(&self, m: &clean::Module) -> HashMap> { + fn build_sidebar(&self, m: &clean::Module) -> HashMap> { let mut map = HashMap::new(); for item in m.items.iter() { if self.ignore_private_item(item) { continue } @@ -1262,7 +1267,7 @@ impl Context { let short = short.to_string(); let v = map.entry(short).get().unwrap_or_else( |vacant_entry| vacant_entry.insert(Vec::with_capacity(1))); - v.push(myname); + v.push(NameDoc(myname, Some(shorter_line(item.doc_value())))); } for (_, items) in map.iter_mut() { @@ -1351,7 +1356,7 @@ impl<'a> Item<'a> { } -impl<'a> fmt::String for Item<'a> { +impl<'a> fmt::Display for Item<'a> { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { // Write the breadcrumb trail header for the top try!(write!(fmt, "\n

")); @@ -1469,13 +1474,18 @@ fn full_path(cx: &Context, item: &clean::Item) -> String { fn shorter<'a>(s: Option<&'a str>) -> &'a str { match s { Some(s) => match s.find_str("\n\n") { - Some(pos) => s.slice_to(pos), + Some(pos) => &s[..pos], None => s, }, None => "" } } +#[inline] +fn shorter_line(s: Option<&str>) -> String { + shorter(s).replace("\n", " ") +} + fn document(w: &mut fmt::Formatter, item: &clean::Item) -> fmt::Result { match item.doc_value() { Some(s) => { @@ -1497,18 +1507,19 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context, // the order of item types in the listing fn reorder(ty: ItemType) -> u8 { match ty { - ItemType::ViewItem => 0, - ItemType::Primitive => 1, - ItemType::Module => 2, - ItemType::Macro => 3, - ItemType::Struct => 4, - ItemType::Enum => 5, - ItemType::Constant => 6, - ItemType::Static => 7, - ItemType::Trait => 8, - ItemType::Function => 9, - ItemType::Typedef => 10, - _ => 11 + ty as u8, + ItemType::ExternCrate => 0, + ItemType::Import => 1, + ItemType::Primitive => 2, + ItemType::Module => 3, + ItemType::Macro => 4, + ItemType::Struct => 5, + ItemType::Enum => 6, + ItemType::Constant => 7, + ItemType::Static => 8, + ItemType::Trait => 9, + ItemType::Function => 10, + ItemType::Typedef => 12, + _ => 13 + ty as u8, } } @@ -1518,25 +1529,7 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context, if ty1 == ty2 { return i1.name.cmp(&i2.name); } - - let tycmp = reorder(ty1).cmp(&reorder(ty2)); - if let Equal = tycmp { - // for reexports, `extern crate` takes precedence. - match (&i1.inner, &i2.inner) { - (&clean::ViewItemItem(ref a), &clean::ViewItemItem(ref b)) => { - match (&a.inner, &b.inner) { - (&clean::ExternCrate(..), _) => return Less, - (_, &clean::ExternCrate(..)) => return Greater, - _ => {} - } - } - (_, _) => {} - } - - idx1.cmp(&idx2) - } else { - tycmp - } + (reorder(ty1), idx1).cmp(&(reorder(ty2), idx2)) } indices.sort_by(|&i1, &i2| cmp(&items[i1], &items[i2], i1, i2)); @@ -1547,12 +1540,17 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context, let myitem = &items[idx]; let myty = Some(shortty(myitem)); - if myty != curty { + if curty == Some(ItemType::ExternCrate) && myty == Some(ItemType::Import) { + // Put `extern crate` and `use` re-exports in the same section. + curty = myty; + } else if myty != curty { if curty.is_some() { try!(write!(w, "")); } curty = myty; let (short, name) = match myty.unwrap() { + ItemType::ExternCrate | + ItemType::Import => ("reexports", "Reexports"), ItemType::Module => ("modules", "Modules"), ItemType::Struct => ("structs", "Structs"), ItemType::Enum => ("enums", "Enums"), @@ -1562,7 +1560,6 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context, ItemType::Constant => ("constants", "Constants"), ItemType::Trait => ("traits", "Traits"), ItemType::Impl => ("impls", "Implementations"), - ItemType::ViewItem => ("reexports", "Reexports"), ItemType::TyMethod => ("tymethods", "Type Methods"), ItemType::Method => ("methods", "Methods"), ItemType::StructField => ("fields", "Struct Fields"), @@ -1578,28 +1575,25 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context, } match myitem.inner { - clean::ViewItemItem(ref item) => { - match item.inner { - clean::ExternCrate(ref name, ref src, _) => { - match *src { - Some(ref src) => - try!(write!(w, "extern crate \"{}\" as {}", - src.as_slice(), - name.as_slice())), - None => - try!(write!(w, "extern crate {}", - name.as_slice())), - } - try!(write!(w, ";")); + clean::ExternCrateItem(ref name, ref src) => { + match *src { + Some(ref src) => { + try!(write!(w, "{}extern crate \"{}\" as {};", + VisSpace(myitem.visibility), + src.as_slice(), + name.as_slice())) } - - clean::Import(ref import) => { - try!(write!(w, "{}{}", - VisSpace(myitem.visibility), - *import)); + None => { + try!(write!(w, "{}extern crate {};", + VisSpace(myitem.visibility), name.as_slice())) } } + try!(write!(w, "")); + } + clean::ImportItem(ref import) => { + try!(write!(w, "{}{}", + VisSpace(myitem.visibility), *import)); } _ => { @@ -1626,7 +1620,7 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context, struct Initializer<'a>(&'a str); -impl<'a> fmt::String for Initializer<'a> { +impl<'a> fmt::Display for Initializer<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let Initializer(s) = *self; if s.len() == 0 { return Ok(()); } @@ -2085,6 +2079,10 @@ fn render_impl(w: &mut fmt::Formatter, i: &Impl) -> fmt::Result { try!(write!(w, "

{}impl{} ", ConciseStability(&i.stability), i.impl_.generics)); + match i.impl_.polarity { + Some(clean::ImplPolarity::Negative) => try!(write!(w, "!")), + _ => {} + } match i.impl_.trait_ { Some(ref ty) => try!(write!(w, "{} for ", *ty)), None => {} @@ -2188,7 +2186,7 @@ fn item_typedef(w: &mut fmt::Formatter, it: &clean::Item, document(w, it) } -impl<'a> fmt::String for Sidebar<'a> { +impl<'a> fmt::Display for Sidebar<'a> { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let cx = self.cx; let it = self.item; @@ -2213,21 +2211,22 @@ impl<'a> fmt::String for Sidebar<'a> { None => return Ok(()) }; try!(write!(w, "

{}

", short, longty)); - for item in items.iter() { + for &NameDoc(ref name, ref doc) in items.iter() { let curty = shortty(cur).to_static_str(); - let class = if cur.name.as_ref().unwrap() == item && + let class = if cur.name.as_ref().unwrap() == name && short == curty { "current" } else { "" }; - try!(write!(w, "
\ - {name}", + try!(write!(w, "{name}", ty = short, class = class, href = if curty == "mod" {"../"} else {""}, path = if short == "mod" { - format!("{}/index.html", item.as_slice()) + format!("{}/index.html", name.as_slice()) } else { - format!("{}.{}.html", short, item.as_slice()) + format!("{}.{}.html", short, name.as_slice()) }, - name = item.as_slice())); + title = Escape(doc.as_ref().unwrap().as_slice()), + name = name.as_slice())); } try!(write!(w, "
")); Ok(()) @@ -2243,7 +2242,7 @@ impl<'a> fmt::String for Sidebar<'a> { } } -impl<'a> fmt::String for Source<'a> { +impl<'a> fmt::Display for Source<'a> { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let Source(s) = *self; let lines = s.lines().count(); diff --git a/src/librustdoc/html/static/main.css b/src/librustdoc/html/static/main.css index 5951ac2bae71..0914f93efd80 100644 --- a/src/librustdoc/html/static/main.css +++ b/src/librustdoc/html/static/main.css @@ -245,7 +245,6 @@ nav.sub { .content .highlighted.method { background-color: #c6afb3; } .content .highlighted.tymethod { background-color: #c6afb3; } .content .highlighted.type { background-color: #c6afb3; } -.content .highlighted.ffi { background-color: #c6afb3; } .docblock.short.nowrap { display: block; @@ -365,7 +364,6 @@ p a:hover { text-decoration: underline; } .content span.fn, .content a.fn, .block a.current.fn { color: #8c6067; } .content span.method, .content a.method, .block a.current.method { color: #8c6067; } .content span.tymethod, .content a.tymethod, .block a.current.tymethod { color: #8c6067; } -.content span.ffi, .content a.ffi, .block a.current.ffi { color: #8c6067; } .content .fnname { color: #8c6067; } .search-input { diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index f27f0cd70f4e..aac3985f0cc9 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -555,6 +555,8 @@ // This mapping table should match the discriminants of // `rustdoc::html::item_type::ItemType` type in Rust. var itemTypes = ["mod", + "externcrate", + "import", "struct", "enum", "fn", @@ -562,13 +564,10 @@ "static", "trait", "impl", - "viewitem", "tymethod", "method", "structfield", "variant", - "ffi", // retained for backward compatibility - "ffs", // retained for backward compatibility "macro", "primitive", "associatedtype", @@ -669,6 +668,15 @@ search(); } + function plainSummaryLine(markdown) { + var str = markdown.replace(/\n/g, ' ') + str = str.replace(/'/g, "\'") + str = str.replace(/^#+? (.+?)/, "$1") + str = str.replace(/\[(.*?)\]\(.*?\)/g, "$1") + str = str.replace(/\[(.*?)\]\[.*?\]/g, "$1") + return str; + } + index = buildIndex(rawSearchIndex); startSearch(); @@ -689,8 +697,10 @@ if (crates[i] == window.currentCrate) { klass += ' current'; } + var desc = rawSearchIndex[crates[i]].items[0][3]; div.append($('', {'href': '../' + crates[i] + '/index.html', - 'class': klass}).text(crates[i])); + 'title': plainSummaryLine(desc), + 'class': klass}).text(crates[i])); } sidebar.append(div); } diff --git a/src/librustdoc/html/toc.rs b/src/librustdoc/html/toc.rs index 8d94e1857c41..aca6e5bb10ed 100644 --- a/src/librustdoc/html/toc.rs +++ b/src/librustdoc/html/toc.rs @@ -176,13 +176,13 @@ impl TocBuilder { } } -impl fmt::Show for Toc { +impl fmt::Debug for Toc { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::String::fmt(self, f) + fmt::Display::fmt(self, f) } } -impl fmt::String for Toc { +impl fmt::Display for Toc { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { try!(write!(fmt, "
    ")); for entry in self.entries.iter() { diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 1f5d15383028..b3b0a1fb373e 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -31,6 +31,7 @@ #![feature(std_misc)] #![feature(test)] #![feature(unicode)] +#![feature(hash)] extern crate arena; extern crate getopts; @@ -121,7 +122,7 @@ pub fn main() { let res = std::thread::Builder::new().stack_size(STACK_SIZE).scoped(move || { main_args(std::os::args().as_slice()) }).join(); - std::os::set_exit_status(res.map_err(|_| ()).unwrap()); + std::os::set_exit_status(res.ok().unwrap()); } pub fn opts() -> Vec { @@ -361,8 +362,10 @@ fn rust_input(cratefile: &str, externs: core::Externs, matches: &getopts::Matche info!("starting to run rustc"); let (mut krate, analysis) = std::thread::Thread::scoped(move |:| { + use rustc::session::config::Input; + let cr = cr; - core::run_core(paths, cfgs, externs, &cr, triple) + core::run_core(paths, cfgs, externs, Input::File(cr), triple) }).join().map_err(|_| "rustc failed").unwrap(); info!("finished with rustc"); let mut analysis = Some(analysis); diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index dc98a56eb1a4..594cf3dcd439 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -28,10 +28,10 @@ fn extract_leading_metadata<'a>(s: &'a str) -> (Vec<&'a str>, &'a str) { for line in s.lines() { if line.starts_with("%") { // remove % - metadata.push(line.slice_from(1).trim_left()) + metadata.push(line[1..].trim_left()) } else { let line_start_byte = s.subslice_offset(line); - return (metadata, s.slice_from(line_start_byte)); + return (metadata, &s[line_start_byte..]); } } // if we're here, then all lines were metadata % lines. diff --git a/src/librustdoc/passes.rs b/src/librustdoc/passes.rs index 9a67b479106e..30b2ad810f1d 100644 --- a/src/librustdoc/passes.rs +++ b/src/librustdoc/passes.rs @@ -149,7 +149,7 @@ impl<'a> fold::DocFolder for Stripper<'a> { } } - clean::ViewItemItem(..) => { + clean::ExternCrateItem(..) | clean::ImportItem(_) => { if i.visibility != Some(ast::Public) { return None } @@ -357,7 +357,7 @@ pub fn unindent(s: &str) -> String { line.to_string() } else { assert!(line.len() >= min_indent); - line.slice_from(min_indent).to_string() + line[min_indent..].to_string() } }).collect::>().as_slice()); unindented.connect("\n") diff --git a/src/librustdoc/stability_summary.rs b/src/librustdoc/stability_summary.rs index 9e6986d78464..f1d9aef7f7ce 100644 --- a/src/librustdoc/stability_summary.rs +++ b/src/librustdoc/stability_summary.rs @@ -21,7 +21,7 @@ use syntax::ast::Public; use clean::{Crate, Item, ModuleItem, Module, EnumItem, Enum}; use clean::{ImplItem, Impl, Trait, TraitItem, TraitMethod, ProvidedMethod, RequiredMethod}; -use clean::{TypeTraitItem, ViewItemItem, PrimitiveItem, Stability}; +use clean::{TypeTraitItem, ExternCrateItem, ImportItem, PrimitiveItem, Stability}; use html::render::cache; @@ -182,7 +182,8 @@ fn summarize_item(item: &Item) -> (Counts, Option) { })) } // no stability information for the following items: - ViewItemItem(_) | PrimitiveItem(_) => (Counts::zero(), None), + ExternCrateItem(..) | ImportItem(_) | + PrimitiveItem(_) => (Counts::zero(), None), _ => (item_counts, None) } } diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 9b8d220acc39..7f1bd9e6d596 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -79,7 +79,7 @@ pub fn run(input: &str, let ctx = core::DocContext { krate: &krate, maybe_typed: core::NotTyped(sess), - src: input_path, + input: input, external_paths: RefCell::new(Some(HashMap::new())), external_traits: RefCell::new(None), external_typarams: RefCell::new(None), diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 428b4e92a681..848205f589ed 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -20,7 +20,6 @@ use syntax::ast_map; use syntax::attr; use syntax::attr::AttrMetaMethods; use syntax::codemap::Span; -use syntax::ptr::P; use rustc::middle::stability; @@ -142,9 +141,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { m: &ast::Mod, name: Option) -> Module { let mut om = Module::new(name); - for item in m.view_items.iter() { - self.visit_view_item(item, &mut om); - } om.where_outer = span; om.where_inner = m.inner; om.attrs = attrs; @@ -157,68 +153,41 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { om } - pub fn visit_view_item(&mut self, item: &ast::ViewItem, om: &mut Module) { - if item.vis != ast::Public { - return om.view_items.push(item.clone()); - } - let please_inline = item.attrs.iter().any(|item| { - match item.meta_item_list() { - Some(list) => { - list.iter().any(|i| i.name().get() == "inline") - } - None => false, - } - }); - let item = match item.node { - ast::ViewItemUse(ref vpath) => { - match self.visit_view_path(&**vpath, om, please_inline) { - None => return, - Some(path) => { - ast::ViewItem { - node: ast::ViewItemUse(path), - .. item.clone() - } - } - } - } - ast::ViewItemExternCrate(..) => item.clone() - }; - om.view_items.push(item); - } - - fn visit_view_path(&mut self, path: &ast::ViewPath, + fn visit_view_path(&mut self, path: ast::ViewPath_, om: &mut Module, - please_inline: bool) -> Option> { - match path.node { - ast::ViewPathSimple(dst, _, id) => { + id: ast::NodeId, + please_inline: bool) -> Option { + match path { + ast::ViewPathSimple(dst, base) => { if self.resolve_id(id, Some(dst), false, om, please_inline) { - return None + None + } else { + Some(ast::ViewPathSimple(dst, base)) } } - ast::ViewPathList(ref p, ref paths, ref b) => { - let mut mine = Vec::new(); - for path in paths.iter() { - if !self.resolve_id(path.node.id(), None, false, om, - please_inline) { - mine.push(path.clone()); - } - } + ast::ViewPathList(p, paths) => { + let mine = paths.into_iter().filter(|path| { + !self.resolve_id(path.node.id(), None, false, om, + please_inline) + }).collect::>(); - if mine.len() == 0 { return None } - return Some(P(::syntax::codemap::Spanned { - node: ast::ViewPathList(p.clone(), mine, b.clone()), - span: path.span, - })) + if mine.len() == 0 { + None + } else { + Some(ast::ViewPathList(p, mine)) + } } // these are feature gated anyway - ast::ViewPathGlob(_, id) => { + ast::ViewPathGlob(base) => { if self.resolve_id(id, None, true, om, please_inline) { - return None + None + } else { + Some(ast::ViewPathGlob(base)) } } } - Some(P(path.clone())) + } fn resolve_id(&mut self, id: ast::NodeId, renamed: Option, @@ -242,9 +211,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { if glob { match it.node { ast::ItemMod(ref m) => { - for vi in m.view_items.iter() { - self.visit_view_item(vi, om); - } for i in m.items.iter() { self.visit_item(&**i, None, om); } @@ -268,6 +234,45 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { debug!("Visiting item {:?}", item); let name = renamed.unwrap_or(item.ident); match item.node { + ast::ItemExternCrate(ref p) => { + let path = match *p { + None => None, + Some((ref x, _)) => Some(x.get().to_string()), + }; + om.extern_crates.push(ExternCrate { + name: name, + path: path, + vis: item.vis, + attrs: item.attrs.clone(), + whence: item.span, + }) + } + ast::ItemUse(ref vpath) => { + let node = vpath.node.clone(); + let node = if item.vis == ast::Public { + let please_inline = item.attrs.iter().any(|item| { + match item.meta_item_list() { + Some(list) => { + list.iter().any(|i| i.name().get() == "inline") + } + None => false, + } + }); + match self.visit_view_path(node, om, item.id, please_inline) { + None => return, + Some(p) => p + } + } else { + node + }; + om.imports.push(Import { + id: item.id, + vis: item.vis, + attrs: item.attrs.clone(), + node: node, + whence: item.span, + }); + } ast::ItemMod(ref m) => { om.mods.push(self.visit_mod_contents(item.span, item.attrs.clone(), diff --git a/src/libserialize/base64.rs b/src/libserialize/base64.rs deleted file mode 100644 index d13d110320e1..000000000000 --- a/src/libserialize/base64.rs +++ /dev/null @@ -1,428 +0,0 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. -// -// ignore-lexer-test FIXME #15679 - -//! Base64 binary-to-text encoding - -pub use self::FromBase64Error::*; -pub use self::CharacterSet::*; - -use std::fmt; -use std::error; - -/// Available encoding character sets -#[derive(Copy)] -pub enum CharacterSet { - /// The standard character set (uses `+` and `/`) - Standard, - /// The URL safe character set (uses `-` and `_`) - UrlSafe -} - -/// Available newline types -#[derive(Copy)] -pub enum Newline { - /// A linefeed (i.e. Unix-style newline) - LF, - /// A carriage return and a linefeed (i.e. Windows-style newline) - CRLF -} - -/// Contains configuration parameters for `to_base64`. -#[derive(Copy)] -pub struct Config { - /// Character set to use - pub char_set: CharacterSet, - /// Newline to use - pub newline: Newline, - /// True to pad output with `=` characters - pub pad: bool, - /// `Some(len)` to wrap lines at `len`, `None` to disable line wrapping - pub line_length: Option -} - -/// Configuration for RFC 4648 standard base64 encoding -pub static STANDARD: Config = - Config {char_set: Standard, newline: Newline::CRLF, pad: true, line_length: None}; - -/// Configuration for RFC 4648 base64url encoding -pub static URL_SAFE: Config = - Config {char_set: UrlSafe, newline: Newline::CRLF, pad: false, line_length: None}; - -/// Configuration for RFC 2045 MIME base64 encoding -pub static MIME: Config = - Config {char_set: Standard, newline: Newline::CRLF, pad: true, line_length: Some(76)}; - -static STANDARD_CHARS: &'static[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\ - abcdefghijklmnopqrstuvwxyz\ - 0123456789+/"; - -static URLSAFE_CHARS: &'static[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\ - abcdefghijklmnopqrstuvwxyz\ - 0123456789-_"; - -/// A trait for converting a value to base64 encoding. -pub trait ToBase64 { - /// Converts the value of `self` to a base64 value following the specified - /// format configuration, returning the owned string. - fn to_base64(&self, config: Config) -> String; -} - -impl ToBase64 for [u8] { - /// Turn a vector of `u8` bytes into a base64 string. - /// - /// # Example - /// - /// ```rust - /// extern crate serialize; - /// use serialize::base64::{ToBase64, STANDARD}; - /// - /// fn main () { - /// let str = [52,32].to_base64(STANDARD); - /// println!("base 64 output: {}", str); - /// } - /// ``` - fn to_base64(&self, config: Config) -> String { - let bytes = match config.char_set { - Standard => STANDARD_CHARS, - UrlSafe => URLSAFE_CHARS - }; - - // In general, this Vec only needs (4/3) * self.len() memory, but - // addition is faster than multiplication and division. - let mut v = Vec::with_capacity(self.len() + self.len()); - let mut i = 0; - let mut cur_length = 0; - let len = self.len(); - let mod_len = len % 3; - let cond_len = len - mod_len; - let newline = match config.newline { - Newline::LF => b"\n", - Newline::CRLF => b"\r\n" - }; - while i < cond_len { - let (first, second, third) = (self[i], self[i + 1], self[i + 2]); - if let Some(line_length) = config.line_length { - if cur_length >= line_length { - v.push_all(newline); - cur_length = 0; - } - } - - let n = (first as u32) << 16 | - (second as u32) << 8 | - (third as u32); - - // This 24-bit number gets separated into four 6-bit numbers. - v.push(bytes[((n >> 18) & 63) as uint]); - v.push(bytes[((n >> 12) & 63) as uint]); - v.push(bytes[((n >> 6 ) & 63) as uint]); - v.push(bytes[(n & 63) as uint]); - - cur_length += 4; - i += 3; - } - - if mod_len != 0 { - if let Some(line_length) = config.line_length { - if cur_length >= line_length { - v.push_all(newline); - } - } - } - - // Heh, would be cool if we knew this was exhaustive - // (the dream of bounded integer types) - match mod_len { - 0 => (), - 1 => { - let n = (self[i] as u32) << 16; - v.push(bytes[((n >> 18) & 63) as uint]); - v.push(bytes[((n >> 12) & 63) as uint]); - if config.pad { - v.push(b'='); - v.push(b'='); - } - } - 2 => { - let n = (self[i] as u32) << 16 | - (self[i + 1u] as u32) << 8; - v.push(bytes[((n >> 18) & 63) as uint]); - v.push(bytes[((n >> 12) & 63) as uint]); - v.push(bytes[((n >> 6 ) & 63) as uint]); - if config.pad { - v.push(b'='); - } - } - _ => panic!("Algebra is broken, please alert the math police") - } - - unsafe { String::from_utf8_unchecked(v) } - } -} - -/// A trait for converting from base64 encoded values. -pub trait FromBase64 { - /// Converts the value of `self`, interpreted as base64 encoded data, into - /// an owned vector of bytes, returning the vector. - fn from_base64(&self) -> Result, FromBase64Error>; -} - -/// Errors that can occur when decoding a base64 encoded string -#[derive(Copy)] -pub enum FromBase64Error { - /// The input contained a character not part of the base64 format - InvalidBase64Byte(u8, uint), - /// The input had an invalid length - InvalidBase64Length, -} - -impl fmt::Show for FromBase64Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - InvalidBase64Byte(ch, idx) => - write!(f, "Invalid character '{}' at position {}", ch, idx), - InvalidBase64Length => write!(f, "Invalid length"), - } - } -} - -impl error::Error for FromBase64Error { - fn description(&self) -> &str { - match *self { - InvalidBase64Byte(_, _) => "invalid character", - InvalidBase64Length => "invalid length", - } - } - - fn detail(&self) -> Option { - Some(format!("{:?}", self)) - } -} - -impl FromBase64 for str { - /// Convert any base64 encoded string (literal, `@`, `&`, or `~`) - /// to the byte values it encodes. - /// - /// You can use the `String::from_utf8` function to turn a `Vec` into a - /// string with characters corresponding to those values. - /// - /// # Example - /// - /// This converts a string literal to base64 and back. - /// - /// ```rust - /// extern crate serialize; - /// use serialize::base64::{ToBase64, FromBase64, STANDARD}; - /// - /// fn main () { - /// let hello_str = b"Hello, World".to_base64(STANDARD); - /// println!("base64 output: {}", hello_str); - /// let res = hello_str.as_slice().from_base64(); - /// if res.is_ok() { - /// let opt_bytes = String::from_utf8(res.unwrap()); - /// if opt_bytes.is_ok() { - /// println!("decoded from base64: {}", opt_bytes.unwrap()); - /// } - /// } - /// } - /// ``` - #[inline] - fn from_base64(&self) -> Result, FromBase64Error> { - self.as_bytes().from_base64() - } -} - -impl FromBase64 for [u8] { - fn from_base64(&self) -> Result, FromBase64Error> { - let mut r = Vec::with_capacity(self.len()); - let mut buf: u32 = 0; - let mut modulus = 0i; - - let mut it = self.iter().enumerate(); - for (idx, &byte) in it { - let val = byte as u32; - - match byte { - b'A'...b'Z' => buf |= val - 0x41, - b'a'...b'z' => buf |= val - 0x47, - b'0'...b'9' => buf |= val + 0x04, - b'+' | b'-' => buf |= 0x3E, - b'/' | b'_' => buf |= 0x3F, - b'\r' | b'\n' => continue, - b'=' => break, - _ => return Err(InvalidBase64Byte(self[idx], idx)), - } - - buf <<= 6; - modulus += 1; - if modulus == 4 { - modulus = 0; - r.push((buf >> 22) as u8); - r.push((buf >> 14) as u8); - r.push((buf >> 6 ) as u8); - } - } - - for (idx, &byte) in it { - match byte { - b'=' | b'\r' | b'\n' => continue, - _ => return Err(InvalidBase64Byte(self[idx], idx)), - } - } - - match modulus { - 2 => { - r.push((buf >> 10) as u8); - } - 3 => { - r.push((buf >> 16) as u8); - r.push((buf >> 8 ) as u8); - } - 0 => (), - _ => return Err(InvalidBase64Length), - } - - Ok(r) - } -} - -#[cfg(test)] -mod tests { - extern crate test; - use self::test::Bencher; - use base64::{Config, Newline, FromBase64, ToBase64, STANDARD, URL_SAFE}; - - #[test] - fn test_to_base64_basic() { - assert_eq!("".as_bytes().to_base64(STANDARD), ""); - assert_eq!("f".as_bytes().to_base64(STANDARD), "Zg=="); - assert_eq!("fo".as_bytes().to_base64(STANDARD), "Zm8="); - assert_eq!("foo".as_bytes().to_base64(STANDARD), "Zm9v"); - assert_eq!("foob".as_bytes().to_base64(STANDARD), "Zm9vYg=="); - assert_eq!("fooba".as_bytes().to_base64(STANDARD), "Zm9vYmE="); - assert_eq!("foobar".as_bytes().to_base64(STANDARD), "Zm9vYmFy"); - } - - #[test] - fn test_to_base64_crlf_line_break() { - assert!(![0u8; 1000].to_base64(Config {line_length: None, ..STANDARD}) - .contains("\r\n")); - assert_eq!(b"foobar".to_base64(Config {line_length: Some(4), - ..STANDARD}), - "Zm9v\r\nYmFy"); - } - - #[test] - fn test_to_base64_lf_line_break() { - assert!(![0u8; 1000].to_base64(Config {line_length: None, - newline: Newline::LF, - ..STANDARD}) - .as_slice() - .contains("\n")); - assert_eq!(b"foobar".to_base64(Config {line_length: Some(4), - newline: Newline::LF, - ..STANDARD}), - "Zm9v\nYmFy"); - } - - #[test] - fn test_to_base64_padding() { - assert_eq!("f".as_bytes().to_base64(Config {pad: false, ..STANDARD}), "Zg"); - assert_eq!("fo".as_bytes().to_base64(Config {pad: false, ..STANDARD}), "Zm8"); - } - - #[test] - fn test_to_base64_url_safe() { - assert_eq!([251, 255].to_base64(URL_SAFE), "-_8"); - assert_eq!([251, 255].to_base64(STANDARD), "+/8="); - } - - #[test] - fn test_from_base64_basic() { - assert_eq!("".from_base64().unwrap(), b""); - assert_eq!("Zg==".from_base64().unwrap(), b"f"); - assert_eq!("Zm8=".from_base64().unwrap(), b"fo"); - assert_eq!("Zm9v".from_base64().unwrap(), b"foo"); - assert_eq!("Zm9vYg==".from_base64().unwrap(), b"foob"); - assert_eq!("Zm9vYmE=".from_base64().unwrap(), b"fooba"); - assert_eq!("Zm9vYmFy".from_base64().unwrap(), b"foobar"); - } - - #[test] - fn test_from_base64_bytes() { - assert_eq!(b"Zm9vYmFy".from_base64().unwrap(), b"foobar"); - } - - #[test] - fn test_from_base64_newlines() { - assert_eq!("Zm9v\r\nYmFy".from_base64().unwrap(), - b"foobar"); - assert_eq!("Zm9vYg==\r\n".from_base64().unwrap(), - b"foob"); - assert_eq!("Zm9v\nYmFy".from_base64().unwrap(), - b"foobar"); - assert_eq!("Zm9vYg==\n".from_base64().unwrap(), - b"foob"); - } - - #[test] - fn test_from_base64_urlsafe() { - assert_eq!("-_8".from_base64().unwrap(), "+/8=".from_base64().unwrap()); - } - - #[test] - fn test_from_base64_invalid_char() { - assert!("Zm$=".from_base64().is_err()); - assert!("Zg==$".from_base64().is_err()); - } - - #[test] - fn test_from_base64_invalid_padding() { - assert!("Z===".from_base64().is_err()); - } - - #[test] - fn test_base64_random() { - use std::rand::{thread_rng, random, Rng}; - - for _ in range(0u, 1000) { - let times = thread_rng().gen_range(1u, 100); - let v = thread_rng().gen_iter::().take(times).collect::>(); - assert_eq!(v.to_base64(STANDARD) - .from_base64() - .unwrap(), - v); - } - } - - #[bench] - pub fn bench_to_base64(b: &mut Bencher) { - let s = "イロハニホヘト チリヌルヲ ワカヨタレソ ツネナラム \ - ウヰノオクヤマ ケフコエテ アサキユメミシ ヱヒモセスン"; - b.iter(|| { - s.as_bytes().to_base64(STANDARD); - }); - b.bytes = s.len() as u64; - } - - #[bench] - pub fn bench_from_base64(b: &mut Bencher) { - let s = "イロハニホヘト チリヌルヲ ワカヨタレソ ツネナラム \ - ウヰノオクヤマ ケフコエテ アサキユメミシ ヱヒモセスン"; - let sb = s.as_bytes().to_base64(STANDARD); - b.iter(|| { - sb.from_base64().unwrap(); - }); - b.bytes = sb.len() as u64; - } - -} diff --git a/src/libserialize/hex.rs b/src/libserialize/hex.rs index a11eb3f78987..e477f4418a52 100644 --- a/src/libserialize/hex.rs +++ b/src/libserialize/hex.rs @@ -61,7 +61,7 @@ pub trait FromHex { } /// Errors that can occur when decoding a hex encoded string -#[derive(Copy)] +#[derive(Copy, Show)] pub enum FromHexError { /// The input contained a character not part of the hex format InvalidHexCharacter(char, uint), @@ -69,7 +69,7 @@ pub enum FromHexError { InvalidHexLength, } -impl fmt::Show for FromHexError { +impl fmt::Display for FromHexError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { InvalidHexCharacter(ch, idx) => @@ -86,10 +86,6 @@ impl error::Error for FromHexError { InvalidHexLength => "invalid length", } } - - fn detail(&self) -> Option { - Some(format!("{:?}", self)) - } } diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs index a876ca3cb119..5f4ba8ef9fcc 100644 --- a/src/libserialize/json.rs +++ b/src/libserialize/json.rs @@ -235,7 +235,7 @@ pub struct AsJson<'a, T: 'a> { inner: &'a T } pub struct AsPrettyJson<'a, T: 'a> { inner: &'a T, indent: Option } /// The errors that can arise while parsing a JSON stream. -#[derive(Clone, Copy, PartialEq)] +#[derive(Clone, Copy, PartialEq, Show)] pub enum ErrorCode { InvalidSyntax, InvalidNumber, @@ -325,7 +325,7 @@ pub fn encode(object: &T) -> string::String { s } -impl fmt::Show for ErrorCode { +impl fmt::Display for ErrorCode { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { error_str(*self).fmt(f) } @@ -335,14 +335,33 @@ fn io_error_to_error(io: io::IoError) -> ParserError { IoError(io.kind, io.desc) } +impl fmt::Display for ParserError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + // FIXME this should be a nicer error + fmt::Debug::fmt(self, f) + } +} + +impl fmt::Display for DecoderError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + // FIXME this should be a nicer error + fmt::Debug::fmt(self, f) + } +} + impl std::error::Error for DecoderError { fn description(&self) -> &str { "decoder error" } - fn detail(&self) -> Option { Some(format!("{:?}", self)) } +} + +impl fmt::Display for EncoderError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + // FIXME this should be a nicer error + fmt::Debug::fmt(self, f) + } } impl std::error::Error for EncoderError { fn description(&self) -> &str { "encoder error" } - fn detail(&self) -> Option { Some(format!("{:?}", self)) } } impl std::error::FromError for EncoderError { @@ -1298,7 +1317,7 @@ impl Stack { InternalIndex(i) => StackElement::Index(i), InternalKey(start, size) => { StackElement::Key(str::from_utf8( - &self.str_buffer[(start as uint) .. (start as uint + size as uint)]) + &self.str_buffer[start as uint .. start as uint + size as uint]) .unwrap()) } } @@ -1341,7 +1360,7 @@ impl Stack { Some(&InternalIndex(i)) => Some(StackElement::Index(i)), Some(&InternalKey(start, size)) => { Some(StackElement::Key(str::from_utf8( - &self.str_buffer[(start as uint) .. (start+size) as uint] + &self.str_buffer[start as uint .. (start+size) as uint] ).unwrap())) } } @@ -2519,7 +2538,7 @@ impl<'a, 'b> fmt::Writer for FormatShim<'a, 'b> { } } -impl fmt::String for Json { +impl fmt::Display for Json { /// Encodes a json value into a string fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut shim = FormatShim { inner: f }; @@ -2531,7 +2550,7 @@ impl fmt::String for Json { } } -impl<'a> fmt::String for PrettyJson<'a> { +impl<'a> fmt::Display for PrettyJson<'a> { /// Encodes a json value into a string fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut shim = FormatShim { inner: f }; @@ -2543,7 +2562,7 @@ impl<'a> fmt::String for PrettyJson<'a> { } } -impl<'a, T: Encodable> fmt::String for AsJson<'a, T> { +impl<'a, T: Encodable> fmt::Display for AsJson<'a, T> { /// Encodes a json value into a string fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut shim = FormatShim { inner: f }; @@ -2563,7 +2582,7 @@ impl<'a, T> AsPrettyJson<'a, T> { } } -impl<'a, T: Encodable> fmt::String for AsPrettyJson<'a, T> { +impl<'a, T: Encodable> fmt::Display for AsPrettyJson<'a, T> { /// Encodes a json value into a string fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut shim = FormatShim { inner: f }; @@ -3920,7 +3939,7 @@ mod tests { let mut mem_buf = Vec::new(); let mut encoder = Encoder::new(&mut mem_buf as &mut fmt::Writer); let result = hm.encode(&mut encoder); - match result.unwrap_err() { + match result.err().unwrap() { EncoderError::BadHashmapKey => (), _ => panic!("expected bad hash map key") } diff --git a/src/libserialize/lib.rs b/src/libserialize/lib.rs index c3e9815f2287..d51bb3af6272 100644 --- a/src/libserialize/lib.rs +++ b/src/libserialize/lib.rs @@ -52,7 +52,6 @@ pub use self::serialize::{Decoder, Encoder, Decodable, Encodable, mod serialize; mod collection_impls; -pub mod base64; pub mod hex; pub mod json; diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 4ce9639bedbc..ae295c3e8e44 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -1,4 +1,4 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -18,7 +18,7 @@ use borrow::BorrowFrom; use clone::Clone; use cmp::{max, Eq, PartialEq}; use default::Default; -use fmt::{self, Show}; +use fmt::{self, Debug}; use hash::{self, Hash, SipHasher}; use iter::{self, Iterator, ExactSizeIterator, IteratorExt, FromIterator, Extend, Map}; use marker::Sized; @@ -76,7 +76,7 @@ impl DefaultResizePolicy { // min_capacity(size) must be smaller than the internal capacity, // so that the map is not resized: // `min_capacity(usable_capacity(x)) <= x`. - // The lef-hand side can only be smaller due to flooring by integer + // The left-hand side can only be smaller due to flooring by integer // division. // // This doesn't have to be checked for overflow since allocation size @@ -270,7 +270,7 @@ fn test_resize_policy() { /// ``` /// use std::collections::HashMap; /// -/// #[derive(Hash, Eq, PartialEq, Show)] +/// #[derive(Hash, Eq, PartialEq, Debug)] /// struct Viking { /// name: String, /// country: String, @@ -838,8 +838,8 @@ impl HashMap /// map.insert("b", 2); /// map.insert("c", 3); /// - /// for key in map.values() { - /// println!("{}", key); + /// for val in map.values() { + /// println!("{}", val); /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] @@ -939,7 +939,7 @@ impl HashMap search_entry_hashed(&mut self.table, hash, key) } - /// Return the number of elements in the map. + /// Returns the number of elements in the map. /// /// # Example /// @@ -954,7 +954,7 @@ impl HashMap #[stable(feature = "rust1", since = "1.0.0")] pub fn len(&self) -> uint { self.table.size() } - /// Return true if the map contains no elements. + /// Returns true if the map contains no elements. /// /// # Example /// @@ -1218,8 +1218,8 @@ impl Eq for HashMap {} #[stable(feature = "rust1", since = "1.0.0")] -impl Show for HashMap - where K: Eq + Hash + Show, V: Show, +impl Debug for HashMap + where K: Eq + Hash + Debug, V: Debug, S: HashState, H: hash::Hasher { @@ -1276,7 +1276,7 @@ impl IndexMut for HashMap } } -/// HashMap iterator +/// HashMap iterator. #[stable(feature = "rust1", since = "1.0.0")] pub struct Iter<'a, K: 'a, V: 'a> { inner: table::Iter<'a, K, V> @@ -1291,13 +1291,13 @@ impl<'a, K, V> Clone for Iter<'a, K, V> { } } -/// HashMap mutable values iterator +/// HashMap mutable values iterator. #[stable(feature = "rust1", since = "1.0.0")] pub struct IterMut<'a, K: 'a, V: 'a> { inner: table::IterMut<'a, K, V> } -/// HashMap move iterator +/// HashMap move iterator. #[stable(feature = "rust1", since = "1.0.0")] pub struct IntoIter { inner: iter::Map< @@ -1308,7 +1308,7 @@ pub struct IntoIter { > } -/// HashMap keys iterator +/// HashMap keys iterator. #[stable(feature = "rust1", since = "1.0.0")] pub struct Keys<'a, K: 'a, V: 'a> { inner: Map<(&'a K, &'a V), &'a K, Iter<'a, K, V>, fn((&'a K, &'a V)) -> &'a K> @@ -1323,7 +1323,7 @@ impl<'a, K, V> Clone for Keys<'a, K, V> { } } -/// HashMap values iterator +/// HashMap values iterator. #[stable(feature = "rust1", since = "1.0.0")] pub struct Values<'a, K: 'a, V: 'a> { inner: Map<(&'a K, &'a V), &'a V, Iter<'a, K, V>, fn((&'a K, &'a V)) -> &'a V> @@ -1338,7 +1338,7 @@ impl<'a, K, V> Clone for Values<'a, K, V> { } } -/// HashMap drain iterator +/// HashMap drain iterator. #[unstable(feature = "std_misc", reason = "matches collection reform specification, waiting for dust to settle")] pub struct Drain<'a, K: 'a, V: 'a> { @@ -1350,14 +1350,14 @@ pub struct Drain<'a, K: 'a, V: 'a> { > } -/// A view into a single occupied location in a HashMap +/// A view into a single occupied location in a HashMap. #[unstable(feature = "std_misc", reason = "precise API still being fleshed out")] pub struct OccupiedEntry<'a, K: 'a, V: 'a> { elem: FullBucket>, } -/// A view into a single empty location in a HashMap +/// A view into a single empty location in a HashMap. #[unstable(feature = "std_misc", reason = "precise API still being fleshed out")] pub struct VacantEntry<'a, K: 'a, V: 'a> { @@ -1366,22 +1366,22 @@ pub struct VacantEntry<'a, K: 'a, V: 'a> { elem: VacantEntryState>, } -/// A view into a single location in a map, which may be vacant or occupied +/// A view into a single location in a map, which may be vacant or occupied. #[unstable(feature = "std_misc", reason = "precise API still being fleshed out")] pub enum Entry<'a, K: 'a, V: 'a> { - /// An occupied Entry + /// An occupied Entry. Occupied(OccupiedEntry<'a, K, V>), - /// A vacant Entry + /// A vacant Entry. Vacant(VacantEntry<'a, K, V>), } -/// Possible states of a VacantEntry +/// Possible states of a VacantEntry. enum VacantEntryState { /// The index is occupied, but the key to insert has precedence, - /// and will kick the current one out on insertion + /// and will kick the current one out on insertion. NeqElem(FullBucket, uint), - /// The index is genuinely vacant + /// The index is genuinely vacant. NoElem(EmptyBucket), } @@ -1460,7 +1460,7 @@ impl<'a, K, V> ExactSizeIterator for Drain<'a, K, V> { #[unstable(feature = "std_misc", reason = "matches collection reform v2 specification, waiting for dust to settle")] impl<'a, K, V> Entry<'a, K, V> { - /// Returns a mutable reference to the entry if occupied, or the VacantEntry if vacant + /// Returns a mutable reference to the entry if occupied, or the VacantEntry if vacant. pub fn get(self) -> Result<&'a mut V, VacantEntry<'a, K, V>> { match self { Occupied(entry) => Ok(entry.into_mut()), @@ -1472,12 +1472,12 @@ impl<'a, K, V> Entry<'a, K, V> { #[unstable(feature = "std_misc", reason = "matches collection reform v2 specification, waiting for dust to settle")] impl<'a, K, V> OccupiedEntry<'a, K, V> { - /// Gets a reference to the value in the entry + /// Gets a reference to the value in the entry. pub fn get(&self) -> &V { self.elem.read().1 } - /// Gets a mutable reference to the value in the entry + /// Gets a mutable reference to the value in the entry. pub fn get_mut(&mut self) -> &mut V { self.elem.read_mut().1 } @@ -2009,8 +2009,8 @@ mod test_map { let map_str = format!("{:?}", map); - assert!(map_str == "HashMap {1i: 2i, 3i: 4i}" || - map_str == "HashMap {3i: 4i, 1i: 2i}"); + assert!(map_str == "HashMap {1: 2, 3: 4}" || + map_str == "HashMap {3: 4, 1: 2}"); assert_eq!(format!("{:?}", empty), "HashMap {}"); } diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index a6ebc402adea..84f01f70c3e8 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -15,7 +15,7 @@ use clone::Clone; use cmp::{Eq, PartialEq}; use core::marker::Sized; use default::Default; -use fmt::Show; +use fmt::Debug; use fmt; use hash::{self, Hash}; use iter::{Iterator, ExactSizeIterator, IteratorExt, FromIterator, Map, Chain, Extend}; @@ -71,7 +71,7 @@ use super::state::HashState; /// /// ``` /// use std::collections::HashSet; -/// #[derive(Hash, Eq, PartialEq, Show)] +/// #[derive(Hash, Eq, PartialEq, Debug)] /// struct Viking<'a> { /// name: &'a str, /// power: uint, @@ -597,8 +597,8 @@ impl Eq for HashSet {} #[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Show for HashSet - where T: Eq + Hash + fmt::Show, +impl fmt::Debug for HashSet + where T: Eq + Hash + fmt::Debug, S: HashState, H: hash::Hasher { @@ -1180,7 +1180,7 @@ mod test_set { let set_str = format!("{:?}", set); - assert!(set_str == "HashSet {1i, 2i}" || set_str == "HashSet {2i, 1i}"); + assert!(set_str == "HashSet {1, 2}" || set_str == "HashSet {2, 1}"); assert_eq!(format!("{:?}", empty), "HashSet {}"); } diff --git a/src/libstd/collections/mod.rs b/src/libstd/collections/mod.rs index 1b8780120b15..0c55850b32a2 100644 --- a/src/libstd/collections/mod.rs +++ b/src/libstd/collections/mod.rs @@ -49,8 +49,8 @@ //! * You want a double-ended queue (deque). //! //! ### Use a `DList` when: -//! * You want a `Vec` or `RingBuf` of unknown size, and can't tolerate inconsistent -//! performance during insertions. +//! * You want a `Vec` or `RingBuf` of unknown size, and can't tolerate amortization. +//! * You want to efficiently split and append lists. //! * You are *absolutely* certain you *really*, *truly*, want a doubly linked list. //! //! ### Use a `HashMap` when: @@ -85,6 +85,56 @@ //! or "most important" one at any given time. //! * You want a priority queue. //! +//! # Performance +//! +//! Choosing the right collection for the job requires an understanding of what each collection +//! is good at. Here we briefly summarize the performance of different collections for certain +//! important operations. For further details, see each type's documentation. +//! +//! Throughout the documentation, we will follow a few conventions. For all operations, +//! the collection's size is denoted by n. If another collection is involved in the operation, it +//! contains m elements. Operations which have an *amortized* cost are suffixed with a `*`. +//! Operations with an *expected* cost are suffixed with a `~`. +//! +//! All amortized costs are for the potential need to resize when capacity is exhausted. +//! If a resize occurs it will take O(n) time. Our collections never automatically shrink, +//! so removal operations aren't amortized. Over a sufficiently large series of +//! operations, the average cost per operation will deterministically equal the given cost. +//! +//! Only HashMap has expected costs, due to the probabilistic nature of hashing. It is +//! theoretically possible, though very unlikely, for HashMap to experience worse performance. +//! +//! ## Sequences +//! +//! | | get(i) | insert(i) | remove(i) | append | split_off(i) | +//! |---------|----------------|-----------------|----------------|--------|----------------| +//! | Vec | O(1) | O(n-i)* | O(n-i) | O(m)* | O(n-i) | +//! | RingBuf | O(1) | O(min(i, n-i))* | O(min(i, n-i)) | O(m)* | O(min(i, n-i)) | +//! | DList | O(min(i, n-i)) | O(min(i, n-i)) | O(min(i, n-i)) | O(1) | O(min(i, n-i)) | +//! | Bitv | O(1) | O(n-i)* | O(n-i) | O(m)* | O(n-i) | +//! +//! Note that where ties occur, Vec is generally going to be faster than RingBuf, and RingBuf +//! is generally going to be faster than DList. Bitv is not a general purpose collection, and +//! therefore cannot reasonably be compared. +//! +//! ## Maps +//! +//! For Sets, all operations have the cost of the equivalent Map operation. For BitvSet, +//! refer to VecMap. +//! +//! | | get | insert | remove | predecessor | +//! |----------|-----------|----------|----------|-------------| +//! | HashMap | O(1)~ | O(1)~* | O(1)~ | N/A | +//! | BTreeMap | O(log n) | O(log n) | O(log n) | O(log n) | +//! | VecMap | O(1) | O(1)? | O(1) | O(n) | +//! +//! Note that VecMap is *incredibly* inefficient in terms of space. The O(1) insertion time +//! assumes space for the element is already allocated. Otherwise, a large key may require a +//! massive reallocation, with no direct relation to the number of elements in the collection. +//! VecMap should only be seriously considered for small keys. +//! +//! Note also that BTreeMap's precise preformance depends on the value of B. +//! //! # Correct and Efficient Usage of Collections //! //! Of course, knowing which collection is the right one for the job doesn't instantly diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index d7f8eb2e4158..fdd7aa216d3c 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -115,11 +115,12 @@ impl Deref for CString { type Target = [libc::c_char]; fn deref(&self) -> &[libc::c_char] { - self.inner.slice_to(self.inner.len() - 1) + &self.inner[..(self.inner.len() - 1)] } } -impl fmt::Show for CString { +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for CString { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { String::from_utf8_lossy(self.as_bytes()).fmt(f) } @@ -215,4 +216,10 @@ mod tests { assert_eq!(s.as_bytes(), b"\0"); } } + + #[test] + fn formatted() { + let s = CString::from_slice(b"12"); + assert_eq!(format!("{:?}", s), "\"12\""); + } } diff --git a/src/libstd/fmt.rs b/src/libstd/fmt.rs index 57b57bdfe95e..6f2e011d5954 100644 --- a/src/libstd/fmt.rs +++ b/src/libstd/fmt.rs @@ -123,8 +123,8 @@ //! This allows multiple actual types to be formatted via `{:x}` (like `i8` as //! well as `int`). The current mapping of types to traits is: //! -//! * *nothing* ⇒ `String` -//! * `?` ⇒ `Show` +//! * *nothing* ⇒ `Display` +//! * `?` ⇒ `Debug` //! * `o` ⇒ `Octal` //! * `x` ⇒ `LowerHex` //! * `X` ⇒ `UpperHex` @@ -137,7 +137,7 @@ //! `std::fmt::Binary` trait can then be formatted with `{:b}`. Implementations //! are provided for these traits for a number of primitive types by the //! standard library as well. If no format is specified (as in `{}` or `{:6}`), -//! then the format trait used is the `String` trait. +//! then the format trait used is the `Display` trait. //! //! When implementing a format trait for your own type, you will have to //! implement a method of the signature: @@ -145,7 +145,7 @@ //! ```rust //! # use std::fmt; //! # struct Foo; // our custom type -//! # impl fmt::Show for Foo { +//! # impl fmt::Display for Foo { //! fn fmt(&self, f: &mut std::fmt::Formatter) -> fmt::Result { //! # write!(f, "testing, testing") //! # } } @@ -171,13 +171,13 @@ //! use std::f64; //! use std::num::Float; //! -//! #[derive(Show)] +//! #[derive(Debug)] //! struct Vector2D { //! x: int, //! y: int, //! } //! -//! impl fmt::String for Vector2D { +//! impl fmt::Display for Vector2D { //! fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { //! // The `f` value implements the `Writer` trait, which is what the //! // write! macro is expecting. Note that this formatting ignores the @@ -211,22 +211,22 @@ //! } //! ``` //! -//! #### fmt::String vs fmt::Show +//! #### fmt::Display vs fmt::Debug //! //! These two formatting traits have distinct purposes: //! -//! - `fmt::String` implementations assert that the type can be faithfully +//! - `fmt::Display` implementations assert that the type can be faithfully //! represented as a UTF-8 string at all times. It is **not** expected that -//! all types implement the `String` trait. -//! - `fmt::Show` implementations should be implemented for **all** public types. +//! all types implement the `Display` trait. +//! - `fmt::Debug` implementations should be implemented for **all** public types. //! Output will typically represent the internal state as faithfully as possible. -//! The purpose of the `Show` trait is to facilitate debugging Rust code. In -//! most cases, using `#[derive(Show)]` is sufficient and recommended. +//! The purpose of the `Debug` trait is to facilitate debugging Rust code. In +//! most cases, using `#[derive(Debug)]` is sufficient and recommended. //! //! Some examples of the output from both traits: //! //! ``` -//! assert_eq!(format!("{} {:?}", 3i32, 4i32), "3 4i32"); +//! assert_eq!(format!("{} {:?}", 3i32, 4i32), "3 4"); //! assert_eq!(format!("{} {:?}", 'a', 'b'), "a 'b'"); //! assert_eq!(format!("{} {:?}", "foo\n", "bar\n"), "foo\n \"bar\\n\""); //! ``` @@ -409,6 +409,7 @@ use string; pub use core::fmt::{Formatter, Result, Writer, rt}; pub use core::fmt::{Show, String, Octal, Binary}; +pub use core::fmt::{Display, Debug}; pub use core::fmt::{LowerHex, UpperHex, Pointer}; pub use core::fmt::{LowerExp, UpperExp}; pub use core::fmt::Error; diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index 8c38bc009cc6..1c1c73cddd18 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -52,7 +52,8 @@ pub struct BufferedReader { cap: uint, } -impl fmt::Show for BufferedReader where R: fmt::Show { +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for BufferedReader where R: fmt::Debug { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { write!(fmt, "BufferedReader {{ reader: {:?}, buffer: {}/{} }}", self.inner, self.cap - self.pos, self.buf.len()) @@ -150,7 +151,8 @@ pub struct BufferedWriter { pos: uint } -impl fmt::Show for BufferedWriter where W: fmt::Show { +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for BufferedWriter where W: fmt::Debug { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { write!(fmt, "BufferedWriter {{ writer: {:?}, buffer: {}/{} }}", self.inner.as_ref().unwrap(), self.pos, self.buf.len()) @@ -219,7 +221,7 @@ impl Writer for BufferedWriter { if buf.len() > self.buf.len() { self.inner.as_mut().unwrap().write(buf) } else { - let dst = self.buf.slice_from_mut(self.pos); + let dst = &mut self.buf[self.pos..]; slice::bytes::copy_memory(dst, buf); self.pos += buf.len(); Ok(()) @@ -249,7 +251,8 @@ pub struct LineBufferedWriter { inner: BufferedWriter, } -impl fmt::Show for LineBufferedWriter where W: fmt::Show { +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for LineBufferedWriter where W: fmt::Debug { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { write!(fmt, "LineBufferedWriter {{ writer: {:?}, buffer: {}/{} }}", self.inner.inner, self.inner.pos, self.inner.buf.len()) @@ -281,9 +284,9 @@ impl Writer for LineBufferedWriter { fn write(&mut self, buf: &[u8]) -> IoResult<()> { match buf.iter().rposition(|&b| b == b'\n') { Some(i) => { - try!(self.inner.write(&buf[..(i + 1)])); + try!(self.inner.write(&buf[..i + 1])); try!(self.inner.flush()); - try!(self.inner.write(&buf[(i + 1)..])); + try!(self.inner.write(&buf[i + 1..])); Ok(()) } None => self.inner.write(buf), @@ -339,7 +342,8 @@ pub struct BufferedStream { inner: BufferedReader> } -impl fmt::Show for BufferedStream where S: fmt::Show { +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for BufferedStream where S: fmt::Debug { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let reader = &self.inner; let writer = &self.inner.inner.0; diff --git a/src/libstd/io/comm_adapters.rs b/src/libstd/io/comm_adapters.rs index 20901d9c50e2..d3d49d41a679 100644 --- a/src/libstd/io/comm_adapters.rs +++ b/src/libstd/io/comm_adapters.rs @@ -72,7 +72,7 @@ impl Buffer for ChanReader { if self.closed { Err(io::standard_error(io::EndOfFile)) } else { - Ok(self.buf.slice_from(self.pos)) + Ok(&self.buf[self.pos..]) } } @@ -88,7 +88,7 @@ impl Reader for ChanReader { loop { let count = match self.fill_buf().ok() { Some(src) => { - let dst = buf.slice_from_mut(num_read); + let dst = &mut buf[num_read..]; let count = cmp::min(src.len(), dst.len()); bytes::copy_memory(dst, &src[..count]); count diff --git a/src/libstd/io/fs.rs b/src/libstd/io/fs.rs index 64406d88253a..cc36c5640d0a 100644 --- a/src/libstd/io/fs.rs +++ b/src/libstd/io/fs.rs @@ -156,7 +156,7 @@ impl File { }) } }).update_err("couldn't open path as file", |e| { - format!("{}; path={:?}; mode={}; access={}", e, path.display(), + format!("{}; path={}; mode={}; access={}", e, path.display(), mode_string(mode), access_string(access)) }) } @@ -211,7 +211,7 @@ impl File { pub fn fsync(&mut self) -> IoResult<()> { self.fd.fsync() .update_err("couldn't fsync file", - |e| format!("{}; path={:?}", e, self.path.display())) + |e| format!("{}; path={}", e, self.path.display())) } /// This function is similar to `fsync`, except that it may not synchronize @@ -221,7 +221,7 @@ impl File { pub fn datasync(&mut self) -> IoResult<()> { self.fd.datasync() .update_err("couldn't datasync file", - |e| format!("{}; path={:?}", e, self.path.display())) + |e| format!("{}; path={}", e, self.path.display())) } /// Either truncates or extends the underlying file, updating the size of @@ -235,7 +235,7 @@ impl File { pub fn truncate(&mut self, size: i64) -> IoResult<()> { self.fd.truncate(size) .update_err("couldn't truncate file", |e| - format!("{}; path={:?}; size={:?}", e, self.path.display(), size)) + format!("{}; path={}; size={}", e, self.path.display(), size)) } /// Returns true if the stream has reached the end of the file. @@ -255,7 +255,7 @@ impl File { pub fn stat(&self) -> IoResult { self.fd.fstat() .update_err("couldn't fstat file", |e| - format!("{}; path={:?}", e, self.path.display())) + format!("{}; path={}", e, self.path.display())) } } @@ -283,7 +283,7 @@ impl File { pub fn unlink(path: &Path) -> IoResult<()> { fs_imp::unlink(path) .update_err("couldn't unlink path", |e| - format!("{}; path={:?}", e, path.display())) + format!("{}; path={}", e, path.display())) } /// Given a path, query the file system to get information about a file, @@ -310,7 +310,7 @@ pub fn unlink(path: &Path) -> IoResult<()> { pub fn stat(path: &Path) -> IoResult { fs_imp::stat(path) .update_err("couldn't stat path", |e| - format!("{}; path={:?}", e, path.display())) + format!("{}; path={}", e, path.display())) } /// Perform the same operation as the `stat` function, except that this @@ -324,7 +324,7 @@ pub fn stat(path: &Path) -> IoResult { pub fn lstat(path: &Path) -> IoResult { fs_imp::lstat(path) .update_err("couldn't lstat path", |e| - format!("{}; path={:?}", e, path.display())) + format!("{}; path={}", e, path.display())) } /// Rename a file or directory to a new name. @@ -424,14 +424,14 @@ pub fn copy(from: &Path, to: &Path) -> IoResult<()> { pub fn chmod(path: &Path, mode: io::FilePermission) -> IoResult<()> { fs_imp::chmod(path, mode.bits() as uint) .update_err("couldn't chmod path", |e| - format!("{}; path={:?}; mode={:?}", e, path.display(), mode)) + format!("{}; path={}; mode={:?}", e, path.display(), mode)) } /// Change the user and group owners of a file at the specified path. pub fn chown(path: &Path, uid: int, gid: int) -> IoResult<()> { fs_imp::chown(path, uid, gid) .update_err("couldn't chown path", |e| - format!("{}; path={:?}; uid={}; gid={}", e, path.display(), uid, gid)) + format!("{}; path={}; uid={}; gid={}", e, path.display(), uid, gid)) } /// Creates a new hard link on the filesystem. The `dst` path will be a @@ -460,7 +460,7 @@ pub fn symlink(src: &Path, dst: &Path) -> IoResult<()> { pub fn readlink(path: &Path) -> IoResult { fs_imp::readlink(path) .update_err("couldn't resolve symlink for path", |e| - format!("{}; path={:?}", e, path.display())) + format!("{}; path={}", e, path.display())) } /// Create a new, empty directory at the provided path @@ -483,7 +483,7 @@ pub fn readlink(path: &Path) -> IoResult { pub fn mkdir(path: &Path, mode: FilePermission) -> IoResult<()> { fs_imp::mkdir(path, mode.bits() as uint) .update_err("couldn't create directory", |e| - format!("{}; path={:?}; mode={:?}", e, path.display(), mode)) + format!("{}; path={}; mode={}", e, path.display(), mode)) } /// Remove an existing, empty directory @@ -505,7 +505,7 @@ pub fn mkdir(path: &Path, mode: FilePermission) -> IoResult<()> { pub fn rmdir(path: &Path) -> IoResult<()> { fs_imp::rmdir(path) .update_err("couldn't remove directory", |e| - format!("{}; path={:?}", e, path.display())) + format!("{}; path={}", e, path.display())) } /// Retrieve a vector containing all entries within a provided directory @@ -545,7 +545,7 @@ pub fn rmdir(path: &Path) -> IoResult<()> { pub fn readdir(path: &Path) -> IoResult> { fs_imp::readdir(path) .update_err("couldn't read directory", - |e| format!("{}; path={:?}", e, path.display())) + |e| format!("{}; path={}", e, path.display())) } /// Returns an iterator that will recursively walk the directory structure @@ -555,7 +555,7 @@ pub fn readdir(path: &Path) -> IoResult> { pub fn walk_dir(path: &Path) -> IoResult { Ok(Directories { stack: try!(readdir(path).update_err("couldn't walk directory", - |e| format!("{}; path={:?}", e, path.display()))) + |e| format!("{}; path={}", e, path.display()))) }) } @@ -605,7 +605,7 @@ pub fn mkdir_recursive(path: &Path, mode: FilePermission) -> IoResult<()> { let result = mkdir(&curpath, mode) .update_err("couldn't recursively mkdir", - |e| format!("{}; path={:?}", e, path.display())); + |e| format!("{}; path={}", e, path.display())); match result { Err(mkdir_err) => { @@ -632,7 +632,7 @@ pub fn rmdir_recursive(path: &Path) -> IoResult<()> { rm_stack.push(path.clone()); fn rmdir_failed(err: &IoError, path: &Path) -> String { - format!("rmdir_recursive failed; path={:?}; cause={}", + format!("rmdir_recursive failed; path={}; cause={}", path.display(), err) } @@ -692,14 +692,14 @@ pub fn rmdir_recursive(path: &Path) -> IoResult<()> { pub fn change_file_times(path: &Path, atime: u64, mtime: u64) -> IoResult<()> { fs_imp::utime(path, atime, mtime) .update_err("couldn't change_file_times", |e| - format!("{}; path={:?}", e, path.display())) + format!("{}; path={}", e, path.display())) } impl Reader for File { fn read(&mut self, buf: &mut [u8]) -> IoResult { fn update_err(result: IoResult, file: &File) -> IoResult { result.update_err("couldn't read file", - |e| format!("{}; path={:?}", + |e| format!("{}; path={}", e, file.path.display())) } @@ -722,7 +722,7 @@ impl Writer for File { fn write(&mut self, buf: &[u8]) -> IoResult<()> { self.fd.write(buf) .update_err("couldn't write to file", - |e| format!("{}; path={:?}", e, self.path.display())) + |e| format!("{}; path={}", e, self.path.display())) } } @@ -730,7 +730,7 @@ impl Seek for File { fn tell(&self) -> IoResult { self.fd.tell() .update_err("couldn't retrieve file cursor (`tell`)", - |e| format!("{}; path={:?}", e, self.path.display())) + |e| format!("{}; path={}", e, self.path.display())) } fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()> { @@ -743,7 +743,7 @@ impl Seek for File { Err(e) => Err(e), }; err.update_err("couldn't seek in file", - |e| format!("{}; path={:?}", e, self.path.display())) + |e| format!("{}; path={}", e, self.path.display())) } } @@ -906,7 +906,7 @@ mod test { if cfg!(unix) { error!(result, "no such file or directory"); } - error!(result, format!("path={:?}; mode=open; access=read", filename.display())); + error!(result, format!("path={}; mode=open; access=read", filename.display())); } #[test] @@ -920,7 +920,7 @@ mod test { if cfg!(unix) { error!(result, "no such file or directory"); } - error!(result, format!("path={:?}", filename.display())); + error!(result, format!("path={}", filename.display())); } #[test] @@ -1188,7 +1188,7 @@ mod test { error!(result, "couldn't recursively mkdir"); error!(result, "couldn't create directory"); error!(result, "mode=0700"); - error!(result, format!("path={:?}", file.display())); + error!(result, format!("path={}", file.display())); } #[test] diff --git a/src/libstd/io/mem.rs b/src/libstd/io/mem.rs index bbc3f80dd86c..8c0de7819948 100644 --- a/src/libstd/io/mem.rs +++ b/src/libstd/io/mem.rs @@ -161,8 +161,8 @@ impl Reader for MemReader { let write_len = min(buf.len(), self.buf.len() - self.pos); { - let input = &self.buf[self.pos.. (self.pos + write_len)]; - let output = buf.slice_to_mut(write_len); + let input = &self.buf[self.pos.. self.pos + write_len]; + let output = &mut buf[..write_len]; assert_eq!(input.len(), output.len()); slice::bytes::copy_memory(output, input); } @@ -207,11 +207,11 @@ impl<'a> Reader for &'a [u8] { let write_len = min(buf.len(), self.len()); { let input = &self[..write_len]; - let output = buf.slice_to_mut(write_len); + let output = &mut buf[.. write_len]; slice::bytes::copy_memory(output, input); } - *self = self.slice_from(write_len); + *self = &self[write_len..]; Ok(write_len) } @@ -272,7 +272,7 @@ impl<'a> BufWriter<'a> { impl<'a> Writer for BufWriter<'a> { #[inline] fn write(&mut self, src: &[u8]) -> IoResult<()> { - let dst = self.buf.slice_from_mut(self.pos); + let dst = &mut self.buf[self.pos..]; let dst_len = dst.len(); if dst_len == 0 { @@ -351,8 +351,8 @@ impl<'a> Reader for BufReader<'a> { let write_len = min(buf.len(), self.buf.len() - self.pos); { - let input = &self.buf[self.pos.. (self.pos + write_len)]; - let output = buf.slice_to_mut(write_len); + let input = &self.buf[self.pos.. self.pos + write_len]; + let output = &mut buf[..write_len]; assert_eq!(input.len(), output.len()); slice::bytes::copy_memory(output, input); } @@ -434,8 +434,8 @@ mod test { writer.write(&[]).unwrap(); assert_eq!(writer.tell(), Ok(8)); - assert_eq!(writer.write(&[8, 9]).unwrap_err().kind, io::ShortWrite(1)); - assert_eq!(writer.write(&[10]).unwrap_err().kind, io::EndOfFile); + assert_eq!(writer.write(&[8, 9]).err().unwrap().kind, io::ShortWrite(1)); + assert_eq!(writer.write(&[10]).err().unwrap().kind, io::EndOfFile); } let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8]; assert_eq!(buf, b); diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 0046a323d076..cc7f9f5b8927 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -228,13 +228,12 @@ pub use self::FileAccess::*; pub use self::IoErrorKind::*; use char::CharExt; -use clone::Clone; use default::Default; -use error::{FromError, Error}; +use error::Error; use fmt; use int; use iter::{Iterator, IteratorExt}; -use marker::{Sized, Send}; +use marker::Sized; use mem::transmute; use ops::FnOnce; use option::Option; @@ -340,7 +339,8 @@ impl IoError { } } -impl fmt::String for IoError { +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for IoError { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { match *self { IoError { kind: OtherIoError, desc: "unknown error", detail: Some(ref detail) } => @@ -354,19 +354,7 @@ impl fmt::String for IoError { } impl Error for IoError { - fn description(&self) -> &str { - self.desc - } - - fn detail(&self) -> Option { - self.detail.clone() - } -} - -impl FromError for Box { - fn from_error(err: IoError) -> Box { - box err - } + fn description(&self) -> &str { self.desc } } /// A list specifying general categories of I/O error. @@ -516,7 +504,7 @@ pub trait Reader { while read < min { let mut zeroes = 0; loop { - match self.read(buf.slice_from_mut(read)) { + match self.read(&mut buf[read..]) { Ok(0) => { zeroes += 1; if zeroes >= NO_PROGRESS_LIMIT { @@ -1436,33 +1424,31 @@ pub trait Buffer: Reader { fn read_until(&mut self, byte: u8) -> IoResult> { let mut res = Vec::new(); - let mut used; loop { - { + let (done, used) = { let available = match self.fill_buf() { Ok(n) => n, Err(ref e) if res.len() > 0 && e.kind == EndOfFile => { - used = 0; - break + return Ok(res); } Err(e) => return Err(e) }; match available.iter().position(|&b| b == byte) { Some(i) => { - res.push_all(&available[..(i + 1)]); - used = i + 1; - break + res.push_all(&available[..i + 1]); + (true, i + 1) } None => { res.push_all(available); - used = available.len(); + (false, available.len()) } } - } + }; self.consume(used); + if done { + return Ok(res); + } } - self.consume(used); - Ok(res) } /// Reads the next utf8-encoded character from the underlying stream. @@ -1481,7 +1467,7 @@ pub trait Buffer: Reader { { let mut start = 1; while start < width { - match try!(self.read(buf.slice_mut(start, width))) { + match try!(self.read(&mut buf[start .. width])) { n if n == width - start => break, n if n < width - start => { start += n; } _ => return Err(standard_error(InvalidInput)), @@ -1780,6 +1766,7 @@ pub struct UnstableFileStat { bitflags! { /// A set of permissions for a file or directory is represented by a set of /// flags which are or'd together. + #[derive(Show)] flags FilePermission: u32 { const USER_READ = 0o400, const USER_WRITE = 0o200, @@ -1821,13 +1808,8 @@ impl Default for FilePermission { fn default() -> FilePermission { FilePermission::empty() } } -impl fmt::Show for FilePermission { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::String::fmt(self, f) - } -} - -impl fmt::String for FilePermission { +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for FilePermission { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{:04o}", self.bits) } diff --git a/src/libstd/io/net/ip.rs b/src/libstd/io/net/ip.rs index adc122ff4474..7e7603c826eb 100644 --- a/src/libstd/io/net/ip.rs +++ b/src/libstd/io/net/ip.rs @@ -38,7 +38,8 @@ pub enum IpAddr { Ipv6Addr(u16, u16, u16, u16, u16, u16, u16, u16) } -impl fmt::String for IpAddr { +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for IpAddr { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { match *self { Ipv4Addr(a, b, c, d) => @@ -69,7 +70,8 @@ pub struct SocketAddr { pub port: Port, } -impl fmt::String for SocketAddr { +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for SocketAddr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.ip { Ipv4Addr(..) => write!(f, "{}:{}", self.ip, self.port), @@ -251,7 +253,7 @@ impl<'a> Parser<'a> { assert!(head.len() + tail.len() <= 8); let mut gs = [0u16; 8]; gs.clone_from_slice(head); - gs.slice_mut(8 - tail.len(), 8).clone_from_slice(tail); + gs[(8 - tail.len()) .. 8].clone_from_slice(tail); Ipv6Addr(gs[0], gs[1], gs[2], gs[3], gs[4], gs[5], gs[6], gs[7]) } diff --git a/src/libstd/io/process.rs b/src/libstd/io/process.rs index 6b09ac9a58ff..a406d3c27885 100644 --- a/src/libstd/io/process.rs +++ b/src/libstd/io/process.rs @@ -20,9 +20,6 @@ use prelude::v1::*; use collections::HashMap; use ffi::CString; use fmt; -// NOTE(stage0) remove import after a snapshot -#[cfg(stage0)] -use hash::Hash; use io::pipe::{PipeStream, PipePair}; use io::{IoResult, IoError}; use io; @@ -396,7 +393,7 @@ impl Command { } } -impl fmt::String for Command { +impl fmt::Debug for Command { /// Format the program and arguments of a Command for display. Any /// non-utf8 data is lossily converted using the utf8 replacement /// character. @@ -495,7 +492,7 @@ pub enum StdioContainer { /// Describes the result of a process after it has terminated. /// Note that Windows have no signals, so the result is usually ExitStatus. -#[derive(PartialEq, Eq, Clone, Copy)] +#[derive(PartialEq, Eq, Clone, Copy, Show)] pub enum ProcessExit { /// Normal termination with an exit status. ExitStatus(int), @@ -504,15 +501,8 @@ pub enum ProcessExit { ExitSignal(int), } -impl fmt::Show for ProcessExit { - /// Format a ProcessExit enum, to nicely present the information. - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::String::fmt(self, f) - } -} - - -impl fmt::String for ProcessExit { +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for ProcessExit { /// Format a ProcessExit enum, to nicely present the information. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index 9ee2f5705b82..a5664b9f0137 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -40,6 +40,7 @@ use mem; use option::Option; use option::Option::{Some, None}; use ops::{Deref, DerefMut, FnOnce}; +use ptr; use result::Result::{Ok, Err}; use rt; use slice::SliceExt; @@ -238,7 +239,7 @@ pub fn stdin() -> StdinReader { // Make sure to free it at exit rt::at_exit(|| { mem::transmute::<_, Box>(STDIN); - STDIN = 0 as *const _; + STDIN = ptr::null(); }); }); diff --git a/src/libstd/io/timer.rs b/src/libstd/io/timer.rs index 844a97dea2d5..68ae7d0ff208 100644 --- a/src/libstd/io/timer.rs +++ b/src/libstd/io/timer.rs @@ -227,6 +227,12 @@ mod test { use thread::Thread; use time::Duration; + #[test] + fn test_timer_send() { + let mut timer = Timer::new().unwrap(); + Thread::spawn(move || timer.sleep(Duration::milliseconds(1))); + } + #[test] fn test_io_timer_sleep_simple() { let mut timer = Timer::new().unwrap(); diff --git a/src/libstd/io/util.rs b/src/libstd/io/util.rs index adfd88644cce..e4bf38a9ef5d 100644 --- a/src/libstd/io/util.rs +++ b/src/libstd/io/util.rs @@ -48,7 +48,7 @@ impl Reader for LimitReader { } let len = cmp::min(self.limit, buf.len()); - let res = self.inner.read(buf.slice_to_mut(len)); + let res = self.inner.read(&mut buf[..len]); match res { Ok(len) => self.limit -= len, _ => {} diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index d708f4df2a58..4827bc2b3c86 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -176,6 +176,7 @@ pub use core::raw; pub use core::simd; pub use core::result; pub use core::option; +pub use core::error; #[cfg(not(test))] pub use alloc::boxed; pub use alloc::rc; @@ -236,7 +237,6 @@ pub mod thunk; /* Common traits */ -pub mod error; pub mod num; /* Runtime and platform support */ diff --git a/src/libstd/num/mod.rs b/src/libstd/num/mod.rs index c81dfad63d7f..dad8b70ceacd 100644 --- a/src/libstd/num/mod.rs +++ b/src/libstd/num/mod.rs @@ -16,7 +16,7 @@ #![stable(feature = "rust1", since = "1.0.0")] #![allow(missing_docs)] -#[cfg(test)] use fmt::Show; +#[cfg(test)] use fmt::Debug; use ops::{Add, Sub, Mul, Div, Rem, Neg}; use marker::Copy; @@ -353,7 +353,7 @@ pub fn test_num(ten: T, two: T) where T: PartialEq + NumCast + Add + Sub + Mul + Div - + Rem + Show + + Rem + Debug + Copy { assert_eq!(ten.add(two), cast(12i).unwrap()); diff --git a/src/libstd/num/strconv.rs b/src/libstd/num/strconv.rs index 67fe599ecd6b..1d3bf484edb9 100644 --- a/src/libstd/num/strconv.rs +++ b/src/libstd/num/strconv.rs @@ -379,14 +379,14 @@ pub fn float_to_str_bytes_common( // only resize buf if we actually remove digits if i < buf_max_i { - buf = buf.slice(0, i + 1).to_vec(); + buf = buf[.. (i + 1)].to_vec(); } } } // If exact and trailing '.', just cut that else { let max_i = buf.len() - 1; if buf[max_i] == b'.' { - buf = buf.slice(0, max_i).to_vec(); + buf = buf[.. max_i].to_vec(); } } diff --git a/src/libstd/os.rs b/src/libstd/os.rs index efd571be9e2a..d81e2b3aa4b7 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -855,7 +855,7 @@ pub enum MapOption { impl Copy for MapOption {} /// Possible errors when creating a map. -#[derive(Copy)] +#[derive(Copy, Show)] pub enum MapError { /// # The following are POSIX-specific /// @@ -900,7 +900,8 @@ pub enum MapError { ErrMapViewOfFile(uint) } -impl fmt::Show for MapError { +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for MapError { fn fmt(&self, out: &mut fmt::Formatter) -> fmt::Result { let str = match *self { ErrFdNotAvail => "fd not available for reading or writing", @@ -934,13 +935,6 @@ impl fmt::Show for MapError { impl Error for MapError { fn description(&self) -> &str { "memory map error" } - fn detail(&self) -> Option { Some(format!("{:?}", self)) } -} - -impl FromError for Box { - fn from_error(err: MapError) -> Box { - box err - } } // Round up `from` to be divisible by `to` diff --git a/src/libstd/path/mod.rs b/src/libstd/path/mod.rs index 7a34a1d8c380..e4a662f8463d 100644 --- a/src/libstd/path/mod.rs +++ b/src/libstd/path/mod.rs @@ -399,7 +399,7 @@ pub trait GenericPath: Clone + GenericPathUnsafe { match name.rposition_elem(&dot) { None | Some(0) => None, Some(1) if name == b".." => None, - Some(pos) => Some(&name[(pos+1)..]) + Some(pos) => Some(&name[pos+1..]) } } } @@ -823,13 +823,15 @@ pub struct Display<'a, P:'a> { filename: bool } -impl<'a, P: GenericPath> fmt::Show for Display<'a, P> { +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, P: GenericPath> fmt::Debug for Display<'a, P> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::String::fmt(self, f) + fmt::Debug::fmt(&self.as_cow(), f) } } -impl<'a, P: GenericPath> fmt::String for Display<'a, P> { +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, P: GenericPath> fmt::Display for Display<'a, P> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.as_cow().fmt(f) } diff --git a/src/libstd/path/posix.rs b/src/libstd/path/posix.rs index aab64639ab59..07fdd1a830f5 100644 --- a/src/libstd/path/posix.rs +++ b/src/libstd/path/posix.rs @@ -57,9 +57,10 @@ pub fn is_sep(c: char) -> bool { c == SEP } -impl fmt::Show for Path { +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for Path { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Show::fmt(&self.display(), f) + fmt::Debug::fmt(&self.display(), f) } } @@ -126,7 +127,7 @@ impl GenericPathUnsafe for Path { None => { self.repr = Path::normalize(filename); } - Some(idx) if &self.repr[(idx+1)..] == b".." => { + Some(idx) if &self.repr[idx+1..] == b".." => { let mut v = Vec::with_capacity(self.repr.len() + 1 + filename.len()); v.push_all(self.repr.as_slice()); v.push(SEP_BYTE); @@ -136,7 +137,7 @@ impl GenericPathUnsafe for Path { } Some(idx) => { let mut v = Vec::with_capacity(idx + 1 + filename.len()); - v.push_all(&self.repr[..(idx+1)]); + v.push_all(&self.repr[..idx+1]); v.push_all(filename); // FIXME: this is slow self.repr = Path::normalize(v.as_slice()); @@ -178,7 +179,7 @@ impl GenericPath for Path { None if b".." == self.repr => self.repr.as_slice(), None => dot_static, Some(0) => &self.repr[..1], - Some(idx) if &self.repr[(idx+1)..] == b".." => self.repr.as_slice(), + Some(idx) if &self.repr[idx+1..] == b".." => self.repr.as_slice(), Some(idx) => &self.repr[..idx] } } @@ -188,9 +189,9 @@ impl GenericPath for Path { None if b"." == self.repr || b".." == self.repr => None, None => Some(self.repr.as_slice()), - Some(idx) if &self.repr[(idx+1)..] == b".." => None, + Some(idx) if &self.repr[idx+1..] == b".." => None, Some(0) if self.repr[1..].is_empty() => None, - Some(idx) => Some(&self.repr[(idx+1)..]) + Some(idx) => Some(&self.repr[idx+1..]) } } diff --git a/src/libstd/path/windows.rs b/src/libstd/path/windows.rs index 3cff1c67be36..ebded1f0855d 100644 --- a/src/libstd/path/windows.rs +++ b/src/libstd/path/windows.rs @@ -85,9 +85,10 @@ pub struct Path { sepidx: Option // index of the final separator in the non-prefix portion of repr } -impl fmt::Show for Path { +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for Path { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Show::fmt(&self.display(), f) + fmt::Debug::fmt(&self.display(), f) } } @@ -428,10 +429,10 @@ impl GenericPath for Path { if self.prefix.is_some() { Some(Path::new(match self.prefix { Some(DiskPrefix) if self.is_absolute() => { - &self.repr[..(self.prefix_len()+1)] + &self.repr[..self.prefix_len()+1] } Some(VerbatimDiskPrefix) => { - &self.repr[..(self.prefix_len()+1)] + &self.repr[..self.prefix_len()+1] } _ => &self.repr[..self.prefix_len()] })) @@ -635,7 +636,7 @@ impl Path { Some(_) => { let plen = self.prefix_len(); if repr.len() > plen && repr.as_bytes()[plen] == SEP_BYTE { - &repr[(plen+1)..] + &repr[plen+1..] } else { &repr[plen..] } } None if repr.as_bytes()[0] == SEP_BYTE => &repr[1..], @@ -786,9 +787,9 @@ impl Path { } Some(UNCPrefix(a,b)) => { s.push_str("\\\\"); - s.push_str(&prefix_[2..(a+2)]); + s.push_str(&prefix_[2..a+2]); s.push(SEP); - s.push_str(&prefix_[(3+a)..(3+a+b)]); + s.push_str(&prefix_[3+a..3+a+b]); } Some(_) => s.push_str(prefix_), None => () @@ -813,7 +814,7 @@ impl Path { fn update_sepidx(&mut self) { let s = if self.has_nonsemantic_trailing_slash() { - &self.repr[..(self.repr.len()-1)] + &self.repr[..self.repr.len()-1] } else { &self.repr[] }; let sep_test: fn(char) -> bool = if !prefix_is_verbatim(self.prefix) { is_sep @@ -1029,7 +1030,7 @@ fn parse_prefix<'a>(mut path: &'a str) -> Option { None => return None, Some(x) => x }; - path = &path[(idx_a+1)..]; + path = &path[idx_a+1..]; let idx_b = path.find(f).unwrap_or(path.len()); Some((idx_a, idx_b)) } diff --git a/src/libstd/rand/os.rs b/src/libstd/rand/os.rs index 68ba7e1dd29e..bafbde2511de 100644 --- a/src/libstd/rand/os.rs +++ b/src/libstd/rand/os.rs @@ -65,7 +65,7 @@ mod imp { let mut read = 0; let len = v.len(); while read < len { - let result = getrandom(v.slice_from_mut(read)); + let result = getrandom(&mut v[read..]); if result == -1 { let err = errno() as libc::c_int; if err == libc::EINTR { diff --git a/src/libstd/rt/unwind.rs b/src/libstd/rt/unwind.rs index 7d886f9936fc..18298f1c7f4f 100644 --- a/src/libstd/rt/unwind.rs +++ b/src/libstd/rt/unwind.rs @@ -152,7 +152,7 @@ pub unsafe fn try(f: F) -> Result<(), Box> { } } -/// Test if the current thread is currently panicking. +/// Determines whether the current thread is unwinding because of panic. pub fn panicking() -> bool { PANICKING.with(|s| s.get()) } diff --git a/src/libstd/rt/util.rs b/src/libstd/rt/util.rs index 235cedcda524..4023a0a4c100 100644 --- a/src/libstd/rt/util.rs +++ b/src/libstd/rt/util.rs @@ -130,7 +130,7 @@ pub fn abort(args: fmt::Arguments) -> ! { } impl<'a> fmt::Writer for BufWriter<'a> { fn write_str(&mut self, bytes: &str) -> fmt::Result { - let left = self.buf.slice_from_mut(self.pos); + let left = &mut self.buf[self.pos..]; let to_write = &bytes.as_bytes()[..cmp::min(bytes.len(), left.len())]; slice::bytes::copy_memory(left, to_write); self.pos += to_write.len(); diff --git a/src/libstd/sync/mpsc/blocking.rs b/src/libstd/sync/mpsc/blocking.rs index 17e690e95409..61ffb532d36a 100644 --- a/src/libstd/sync/mpsc/blocking.rs +++ b/src/libstd/sync/mpsc/blocking.rs @@ -14,8 +14,6 @@ use thread::Thread; use sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering}; use sync::Arc; use marker::{Sync, Send}; -#[cfg(stage0)] // NOTE remove use after next snapshot -use marker::{NoSend, NoSync}; use mem; use clone::Clone; @@ -32,42 +30,14 @@ pub struct SignalToken { inner: Arc, } -#[cfg(stage0)] // NOTE remove impl after next snapshot -pub struct WaitToken { - inner: Arc, - no_send: NoSend, - no_sync: NoSync, -} - -#[cfg(not(stage0))] // NOTE remove cfg after next snapshot pub struct WaitToken { inner: Arc, } -#[cfg(not(stage0))] // NOTE remove cfg after next snapshot impl !Send for WaitToken {} -#[cfg(not(stage0))] // NOTE remove cfg after next snapshot impl !Sync for WaitToken {} -#[cfg(stage0)] // NOTE remove impl after next snapshot -pub fn tokens() -> (WaitToken, SignalToken) { - let inner = Arc::new(Inner { - thread: Thread::current(), - woken: ATOMIC_BOOL_INIT, - }); - let wait_token = WaitToken { - inner: inner.clone(), - no_send: NoSend, - no_sync: NoSync, - }; - let signal_token = SignalToken { - inner: inner - }; - (wait_token, signal_token) -} - -#[cfg(not(stage0))] // NOTE remove cfg after next snapshot pub fn tokens() -> (WaitToken, SignalToken) { let inner = Arc::new(Inner { thread: Thread::current(), diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs index 8fce8cbabccd..101af8d5e9a4 100644 --- a/src/libstd/sync/mpsc/mod.rs +++ b/src/libstd/sync/mpsc/mod.rs @@ -319,7 +319,6 @@ use prelude::v1::*; use sync::Arc; use fmt; -use marker; use mem; use cell::UnsafeCell; @@ -369,31 +368,21 @@ unsafe impl Send for Sender { } /// The sending-half of Rust's synchronous channel type. This half can only be /// owned by one task, but it can be cloned to send to other tasks. -#[cfg(stage0)] // NOTE remove impl after next snapshot #[stable(feature = "rust1", since = "1.0.0")] pub struct SyncSender { - inner: Arc>>, - // can't share in an arc - _marker: marker::NoSync, + inner: Arc>>, } -/// The sending-half of Rust's synchronous channel type. This half can only be -/// owned by one task, but it can be cloned to send to other tasks. -#[stable(feature = "rust1", since = "1.0.0")] -#[cfg(not(stage0))] // NOTE remove cfg after next snapshot -pub struct SyncSender { - inner: Arc>>, -} +unsafe impl Send for SyncSender {} -#[cfg(not(stage0))] // NOTE remove cfg after next snapshot -impl !marker::Sync for SyncSender {} +impl !Sync for SyncSender {} /// An error returned from the `send` function on channels. /// /// A `send` operation can only fail if the receiving end of a channel is /// disconnected, implying that the data could never be received. The error /// contains the data being sent as a payload so it can be recovered. -#[derive(PartialEq, Eq)] +#[derive(PartialEq, Eq, Show)] #[stable(feature = "rust1", since = "1.0.0")] pub struct SendError(pub T); @@ -401,13 +390,13 @@ pub struct SendError(pub T); /// /// The `recv` operation can only fail if the sending half of a channel is /// disconnected, implying that no further messages will ever be received. -#[derive(PartialEq, Eq, Clone, Copy)] +#[derive(PartialEq, Eq, Clone, Copy, Show)] #[stable(feature = "rust1", since = "1.0.0")] pub struct RecvError; /// This enumeration is the list of the possible reasons that try_recv could not /// return data when called. -#[derive(PartialEq, Clone, Copy)] +#[derive(PartialEq, Clone, Copy, Show)] #[stable(feature = "rust1", since = "1.0.0")] pub enum TryRecvError { /// This channel is currently empty, but the sender(s) have not yet @@ -423,7 +412,7 @@ pub enum TryRecvError { /// This enumeration is the list of the possible error outcomes for the /// `SyncSender::try_send` method. -#[derive(PartialEq, Clone)] +#[derive(PartialEq, Clone, Show)] #[stable(feature = "rust1", since = "1.0.0")] pub enum TrySendError { /// The data could not be sent on the channel because it would require that @@ -442,10 +431,10 @@ pub enum TrySendError { } enum Flavor { - Oneshot(Arc>>), - Stream(Arc>>), - Shared(Arc>>), - Sync(Arc>>), + Oneshot(Arc>>), + Stream(Arc>>), + Shared(Arc>>), + Sync(Arc>>), } #[doc(hidden)] @@ -497,7 +486,7 @@ impl UnsafeFlavor for Receiver { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn channel() -> (Sender, Receiver) { - let a = Arc::new(RacyCell::new(oneshot::Packet::new())); + let a = Arc::new(UnsafeCell::new(oneshot::Packet::new())); (Sender::new(Flavor::Oneshot(a.clone())), Receiver::new(Flavor::Oneshot(a))) } @@ -537,7 +526,7 @@ pub fn channel() -> (Sender, Receiver) { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn sync_channel(bound: uint) -> (SyncSender, Receiver) { - let a = Arc::new(RacyCell::new(sync::Packet::new(bound))); + let a = Arc::new(UnsafeCell::new(sync::Packet::new(bound))); (SyncSender::new(a.clone()), Receiver::new(Flavor::Sync(a))) } @@ -589,7 +578,7 @@ impl Sender { return (*p).send(t).map_err(SendError); } else { let a = - Arc::new(RacyCell::new(stream::Packet::new())); + Arc::new(UnsafeCell::new(stream::Packet::new())); let rx = Receiver::new(Flavor::Stream(a.clone())); match (*p).upgrade(rx) { oneshot::UpSuccess => { @@ -631,7 +620,7 @@ impl Clone for Sender { fn clone(&self) -> Sender { let (packet, sleeper, guard) = match *unsafe { self.inner() } { Flavor::Oneshot(ref p) => { - let a = Arc::new(RacyCell::new(shared::Packet::new())); + let a = Arc::new(UnsafeCell::new(shared::Packet::new())); unsafe { let guard = (*a.get()).postinit_lock(); let rx = Receiver::new(Flavor::Shared(a.clone())); @@ -643,7 +632,7 @@ impl Clone for Sender { } } Flavor::Stream(ref p) => { - let a = Arc::new(RacyCell::new(shared::Packet::new())); + let a = Arc::new(UnsafeCell::new(shared::Packet::new())); unsafe { let guard = (*a.get()).postinit_lock(); let rx = Receiver::new(Flavor::Shared(a.clone())); @@ -689,13 +678,7 @@ impl Drop for Sender { //////////////////////////////////////////////////////////////////////////////// impl SyncSender { - #[cfg(stage0)] // NOTE remove impl after next snapshot - fn new(inner: Arc>>) -> SyncSender { - SyncSender { inner: inner, _marker: marker::NoSync } - } - - #[cfg(not(stage0))] // NOTE remove cfg after next snapshot - fn new(inner: Arc>>) -> SyncSender { + fn new(inner: Arc>>) -> SyncSender { SyncSender { inner: inner } } @@ -978,33 +961,15 @@ impl Drop for Receiver { } } -/// A version of `UnsafeCell` intended for use in concurrent data -/// structures (for example, you might put it in an `Arc`). -struct RacyCell(pub UnsafeCell); - -impl RacyCell { - - fn new(value: T) -> RacyCell { - RacyCell(UnsafeCell { value: value }) - } - - unsafe fn get(&self) -> *mut T { - self.0.get() - } - -} - -unsafe impl Send for RacyCell { } - -unsafe impl Sync for RacyCell { } // Oh dear - -impl fmt::Show for SendError { +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for SendError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { "sending on a closed channel".fmt(f) } } -impl fmt::Show for TrySendError { +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for TrySendError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { TrySendError::Full(..) => { @@ -1017,13 +982,15 @@ impl fmt::Show for TrySendError { } } -impl fmt::Show for RecvError { +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for RecvError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { "receiving on a closed channel".fmt(f) } } -impl fmt::Show for TryRecvError { +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for TryRecvError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { TryRecvError::Empty => { diff --git a/src/libstd/sync/mpsc/mpsc_queue.rs b/src/libstd/sync/mpsc/mpsc_queue.rs index 92aec5cde07e..c222c313ba68 100644 --- a/src/libstd/sync/mpsc/mpsc_queue.rs +++ b/src/libstd/sync/mpsc/mpsc_queue.rs @@ -46,6 +46,7 @@ use core::prelude::*; use alloc::boxed::Box; use core::mem; +use core::ptr; use core::cell::UnsafeCell; use sync::atomic::{AtomicPtr, Ordering}; @@ -82,7 +83,7 @@ unsafe impl Sync for Queue { } impl Node { unsafe fn new(v: Option) -> *mut Node { mem::transmute(box Node { - next: AtomicPtr::new(0 as *mut Node), + next: AtomicPtr::new(ptr::null_mut()), value: v, }) } diff --git a/src/libstd/sync/mpsc/select.rs b/src/libstd/sync/mpsc/select.rs index ee4d3a554818..e97c82a5b1b0 100644 --- a/src/libstd/sync/mpsc/select.rs +++ b/src/libstd/sync/mpsc/select.rs @@ -60,6 +60,7 @@ use core::prelude::*; use core::cell::Cell; use core::marker; use core::mem; +use core::ptr; use core::uint; use sync::mpsc::{Receiver, RecvError}; @@ -67,24 +68,12 @@ use sync::mpsc::blocking::{self, SignalToken}; /// The "receiver set" of the select interface. This structure is used to manage /// a set of receivers which are being selected over. -#[cfg(stage0)] // NOTE remove impl after next snapshot -pub struct Select { - head: *mut Handle<'static, ()>, - tail: *mut Handle<'static, ()>, - next_id: Cell, - marker1: marker::NoSend, -} - -/// The "receiver set" of the select interface. This structure is used to manage -/// a set of receivers which are being selected over. -#[cfg(not(stage0))] // NOTE remove cfg after next snapshot pub struct Select { head: *mut Handle<'static, ()>, tail: *mut Handle<'static, ()>, next_id: Cell, } -#[cfg(not(stage0))] // NOTE remove cfg after next snapshot impl !marker::Send for Select {} /// A handle to a receiver which is currently a member of a `Select` set of @@ -127,26 +116,10 @@ impl Select { /// /// Usage of this struct directly can sometimes be burdensome, and usage is /// rather much easier through the `select!` macro. - #[cfg(stage0)] // NOTE remove impl after next snapshot pub fn new() -> Select { Select { - marker1: marker::NoSend, - head: 0 as *mut Handle<'static, ()>, - tail: 0 as *mut Handle<'static, ()>, - next_id: Cell::new(1), - } - } - - /// Creates a new selection structure. This set is initially empty and - /// `wait` will panic!() if called. - /// - /// Usage of this struct directly can sometimes be burdensome, and usage is - /// rather much easier through the `select!` macro. - #[cfg(not(stage0))] // NOTE remove cfg after next snapshot - pub fn new() -> Select { - Select { - head: 0 as *mut Handle<'static, ()>, - tail: 0 as *mut Handle<'static, ()>, + head: ptr::null_mut(), + tail: ptr::null_mut(), next_id: Cell::new(1), } } @@ -160,8 +133,8 @@ impl Select { Handle { id: id, selector: self, - next: 0 as *mut Handle<'static, ()>, - prev: 0 as *mut Handle<'static, ()>, + next: ptr::null_mut(), + prev: ptr::null_mut(), added: false, rx: rx, packet: rx, @@ -326,8 +299,8 @@ impl<'rx, T: Send> Handle<'rx, T> { (*self.next).prev = self.prev; } - self.next = 0 as *mut Handle<'static, ()>; - self.prev = 0 as *mut Handle<'static, ()>; + self.next = ptr::null_mut(); + self.prev = ptr::null_mut(); self.added = false; } diff --git a/src/libstd/sync/mpsc/spsc_queue.rs b/src/libstd/sync/mpsc/spsc_queue.rs index 893260415ebd..c1983fcab194 100644 --- a/src/libstd/sync/mpsc/spsc_queue.rs +++ b/src/libstd/sync/mpsc/spsc_queue.rs @@ -39,6 +39,7 @@ use core::prelude::*; use alloc::boxed::Box; use core::mem; +use core::ptr; use core::cell::UnsafeCell; use sync::atomic::{AtomicPtr, AtomicUsize, Ordering}; @@ -82,7 +83,7 @@ impl Node { unsafe { mem::transmute(box Node { value: None, - next: AtomicPtr::new(0 as *mut Node), + next: AtomicPtr::new(ptr::null_mut::>()), }) } } @@ -131,7 +132,7 @@ impl Queue { let n = self.alloc(); assert!((*n).value.is_none()); (*n).value = Some(t); - (*n).next.store(0 as *mut Node, Ordering::Relaxed); + (*n).next.store(ptr::null_mut(), Ordering::Relaxed); (**self.head.get()).next.store(n, Ordering::Release); *self.head.get() = n; } diff --git a/src/libstd/sync/mpsc/sync.rs b/src/libstd/sync/mpsc/sync.rs index 30304dffb75a..d38f14a91302 100644 --- a/src/libstd/sync/mpsc/sync.rs +++ b/src/libstd/sync/mpsc/sync.rs @@ -40,6 +40,7 @@ use self::Blocker::*; use vec::Vec; use core::mem; +use core::ptr; use sync::atomic::{Ordering, AtomicUsize}; use sync::mpsc::blocking::{self, WaitToken, SignalToken}; @@ -145,8 +146,8 @@ impl Packet { cap: cap, canceled: None, queue: Queue { - head: 0 as *mut Node, - tail: 0 as *mut Node, + head: ptr::null_mut(), + tail: ptr::null_mut(), }, buf: Buffer { buf: range(0, cap + if cap == 0 {1} else {0}).map(|_| None).collect(), @@ -160,7 +161,7 @@ impl Packet { // wait until a send slot is available, returning locked access to // the channel state. fn acquire_send_slot(&self) -> MutexGuard> { - let mut node = Node { token: None, next: 0 as *mut Node }; + let mut node = Node { token: None, next: ptr::null_mut() }; loop { let mut guard = self.lock.lock().unwrap(); // are we ready to go? @@ -343,8 +344,8 @@ impl Packet { Vec::new() }; let mut queue = mem::replace(&mut guard.queue, Queue { - head: 0 as *mut Node, - tail: 0 as *mut Node, + head: ptr::null_mut(), + tail: ptr::null_mut(), }); let waiter = match mem::replace(&mut guard.blocker, NoneBlocked) { @@ -453,7 +454,7 @@ impl Queue { fn enqueue(&mut self, node: &mut Node) -> WaitToken { let (wait_token, signal_token) = blocking::tokens(); node.token = Some(signal_token); - node.next = 0 as *mut Node; + node.next = ptr::null_mut(); if self.tail.is_null() { self.head = node as *mut Node; @@ -475,10 +476,10 @@ impl Queue { let node = self.head; self.head = unsafe { (*node).next }; if self.head.is_null() { - self.tail = 0 as *mut Node; + self.tail = ptr::null_mut(); } unsafe { - (*node).next = 0 as *mut Node; + (*node).next = ptr::null_mut(); Some((*node).token.take().unwrap()) } } diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs index d74e030a018c..f7fdd60eb8cb 100644 --- a/src/libstd/sync/mutex.rs +++ b/src/libstd/sync/mutex.rs @@ -160,25 +160,7 @@ unsafe impl Sync for StaticMutex {} /// The data protected by the mutex can be access through this guard via its /// Deref and DerefMut implementations #[must_use] -#[cfg(stage0)] // NOTE remove impl after next snapshot #[stable(feature = "rust1", since = "1.0.0")] -pub struct MutexGuard<'a, T: 'a> { - // funny underscores due to how Deref/DerefMut currently work (they - // disregard field privacy). - __lock: &'a StaticMutex, - __data: &'a UnsafeCell, - __poison: poison::Guard, - __marker: marker::NoSend, -} - -/// An RAII implementation of a "scoped lock" of a mutex. When this structure is -/// dropped (falls out of scope), the lock will be unlocked. -/// -/// The data protected by the mutex can be access through this guard via its -/// Deref and DerefMut implementations -#[must_use] -#[stable(feature = "rust1", since = "1.0.0")] -#[cfg(not(stage0))] // NOTE remove cfg after next snapshot pub struct MutexGuard<'a, T: 'a> { // funny underscores due to how Deref/DerefMut currently work (they // disregard field privacy). @@ -187,7 +169,6 @@ pub struct MutexGuard<'a, T: 'a> { __poison: poison::Guard, } -#[cfg(not(stage0))] // NOTE remove cfg after next snapshot impl<'a, T> !marker::Send for MutexGuard<'a, T> {} /// Static initialization of a mutex. This constant can be used to initialize @@ -304,20 +285,7 @@ impl StaticMutex { } impl<'mutex, T> MutexGuard<'mutex, T> { - #[cfg(stage0)] // NOTE remove afte next snapshot - fn new(lock: &'mutex StaticMutex, data: &'mutex UnsafeCell) - -> LockResult> { - poison::map_result(lock.poison.borrow(), |guard| { - MutexGuard { - __lock: lock, - __data: data, - __poison: guard, - __marker: marker::NoSend, - } - }) - } - #[cfg(not(stage0))] // NOTE remove cfg afte next snapshot fn new(lock: &'mutex StaticMutex, data: &'mutex UnsafeCell) -> LockResult> { poison::map_result(lock.poison.borrow(), |guard| { diff --git a/src/libstd/sync/poison.rs b/src/libstd/sync/poison.rs index 6c5cb302ab11..b04c2310fc0b 100644 --- a/src/libstd/sync/poison.rs +++ b/src/libstd/sync/poison.rs @@ -53,6 +53,7 @@ pub struct Guard { /// is held. The precise semantics for when a lock is poisoned is documented on /// each lock, but once a lock is poisoned then all future acquisitions will /// return this error. +#[derive(Show)] #[stable(feature = "rust1", since = "1.0.0")] pub struct PoisonError { guard: T, @@ -60,6 +61,7 @@ pub struct PoisonError { /// An enumeration of possible errors which can occur while calling the /// `try_lock` method. +#[derive(Show)] #[stable(feature = "rust1", since = "1.0.0")] pub enum TryLockError { /// The lock could not be acquired because another task failed while holding @@ -90,7 +92,8 @@ pub type LockResult = Result>; #[stable(feature = "rust1", since = "1.0.0")] pub type TryLockResult = Result>; -impl fmt::Show for PoisonError { +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for PoisonError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.description().fmt(f) } @@ -131,7 +134,8 @@ impl FromError> for TryLockError { } } -impl fmt::Show for TryLockError { +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for TryLockError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.description().fmt(f) } diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs index 01389047df60..12befbf72e37 100644 --- a/src/libstd/sync/rwlock.rs +++ b/src/libstd/sync/rwlock.rs @@ -112,54 +112,35 @@ pub const RW_LOCK_INIT: StaticRwLock = StaticRwLock { /// dropped. #[must_use] #[stable(feature = "rust1", since = "1.0.0")] -#[cfg(stage0)] // NOTE remove impl after next snapshot -pub struct RwLockReadGuard<'a, T: 'a> { - __lock: &'a StaticRwLock, - __data: &'a UnsafeCell, - __marker: marker::NoSend, -} - -/// RAII structure used to release the shared read access of a lock when -/// dropped. -#[must_use] -#[cfg(not(stage0))] // NOTE remove cfg after next snapshot -#[stable(feature = "rust1", since = "1.0.0")] pub struct RwLockReadGuard<'a, T: 'a> { __lock: &'a StaticRwLock, __data: &'a UnsafeCell, } -#[cfg(not(stage0))] // NOTE remove cfg after next snapshot impl<'a, T> !marker::Send for RwLockReadGuard<'a, T> {} /// RAII structure used to release the exclusive write access of a lock when /// dropped. #[must_use] -#[cfg(stage0)] // NOTE remove impl after next snapshot #[stable(feature = "rust1", since = "1.0.0")] -pub struct RwLockWriteGuard<'a, T: 'a> { - __lock: &'a StaticRwLock, - __data: &'a UnsafeCell, - __poison: poison::Guard, - __marker: marker::NoSend, -} - -/// RAII structure used to release the exclusive write access of a lock when -/// dropped. -#[must_use] -#[stable(feature = "rust1", since = "1.0.0")] -#[cfg(not(stage0))] // NOTE remove cfg after next snapshot pub struct RwLockWriteGuard<'a, T: 'a> { __lock: &'a StaticRwLock, __data: &'a UnsafeCell, __poison: poison::Guard, } -#[cfg(not(stage0))] // NOTE remove cfg after next snapshot impl<'a, T> !marker::Send for RwLockWriteGuard<'a, T> {} impl RwLock { - /// Creates a new instance of an RwLock which is unlocked and read to go. + /// Creates a new instance of an `RwLock` which is unlocked. + /// + /// # Examples + /// + /// ``` + /// use std::sync::RwLock; + /// + /// let lock = RwLock::new(5); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn new(t: T) -> RwLock { RwLock { inner: box RW_LOCK_INIT, data: UnsafeCell::new(t) } @@ -339,19 +320,7 @@ impl StaticRwLock { } impl<'rwlock, T> RwLockReadGuard<'rwlock, T> { - #[cfg(stage0)] // NOTE remove impl after next snapshot - fn new(lock: &'rwlock StaticRwLock, data: &'rwlock UnsafeCell) - -> LockResult> { - poison::map_result(lock.poison.borrow(), |_| { - RwLockReadGuard { - __lock: lock, - __data: data, - __marker: marker::NoSend, - } - }) - } - #[cfg(not(stage0))] // NOTE remove cfg after next snapshot fn new(lock: &'rwlock StaticRwLock, data: &'rwlock UnsafeCell) -> LockResult> { poison::map_result(lock.poison.borrow(), |_| { @@ -363,20 +332,7 @@ impl<'rwlock, T> RwLockReadGuard<'rwlock, T> { } } impl<'rwlock, T> RwLockWriteGuard<'rwlock, T> { - #[cfg(stage0)] // NOTE remove impl after next snapshot - fn new(lock: &'rwlock StaticRwLock, data: &'rwlock UnsafeCell) - -> LockResult> { - poison::map_result(lock.poison.borrow(), |guard| { - RwLockWriteGuard { - __lock: lock, - __data: data, - __poison: guard, - __marker: marker::NoSend, - } - }) - } - #[cfg(not(stage0))] // NOTE remove cfg after next snapshot fn new(lock: &'rwlock StaticRwLock, data: &'rwlock UnsafeCell) -> LockResult> { poison::map_result(lock.poison.borrow(), |guard| { diff --git a/src/libstd/sys/common/backtrace.rs b/src/libstd/sys/common/backtrace.rs index d8b859872360..d069d9ee3b8b 100644 --- a/src/libstd/sys/common/backtrace.rs +++ b/src/libstd/sys/common/backtrace.rs @@ -42,10 +42,10 @@ pub fn demangle(writer: &mut Writer, s: &str) -> IoResult<()> { let mut valid = true; let mut inner = s; if s.len() > 4 && s.starts_with("_ZN") && s.ends_with("E") { - inner = s.slice(3, s.len() - 1); + inner = &s[3 .. s.len() - 1]; // On Windows, dbghelp strips leading underscores, so we accept "ZN...E" form too. } else if s.len() > 3 && s.starts_with("ZN") && s.ends_with("E") { - inner = s.slice(2, s.len() - 1); + inner = &s[2 .. s.len() - 1]; } else { valid = false; } @@ -83,11 +83,11 @@ pub fn demangle(writer: &mut Writer, s: &str) -> IoResult<()> { } let mut rest = inner; while rest.char_at(0).is_numeric() { - rest = rest.slice_from(1); + rest = &rest[1..]; } - let i: uint = inner.slice_to(inner.len() - rest.len()).parse().unwrap(); - inner = rest.slice_from(i); - rest = rest.slice_to(i); + let i: uint = inner[.. (inner.len() - rest.len())].parse().unwrap(); + inner = &rest[i..]; + rest = &rest[..i]; while rest.len() > 0 { if rest.starts_with("$") { macro_rules! demangle { @@ -128,8 +128,8 @@ pub fn demangle(writer: &mut Writer, s: &str) -> IoResult<()> { None => rest.len(), Some(i) => i, }; - try!(writer.write_str(rest.slice_to(idx))); - rest = rest.slice_from(idx); + try!(writer.write_str(&rest[..idx])); + rest = &rest[idx..]; } } } diff --git a/src/libstd/sys/common/helper_thread.rs b/src/libstd/sys/common/helper_thread.rs index f940b6ed3682..6f6179a436e9 100644 --- a/src/libstd/sys/common/helper_thread.rs +++ b/src/libstd/sys/common/helper_thread.rs @@ -24,6 +24,7 @@ use prelude::v1::*; use cell::UnsafeCell; use mem; +use ptr; use rt; use sync::{StaticMutex, StaticCondvar}; use sync::mpsc::{channel, Sender, Receiver}; @@ -132,7 +133,7 @@ impl Helper { // Close the channel by destroying it let chan: Box> = mem::transmute(*self.chan.get()); - *self.chan.get() = 0 as *mut Sender; + *self.chan.get() = ptr::null_mut(); drop(chan); helper_signal::signal(*self.signal.get() as helper_signal::signal); diff --git a/src/libstd/sys/unix/backtrace.rs b/src/libstd/sys/unix/backtrace.rs index 70b9c012b008..cb2edf50ebd3 100644 --- a/src/libstd/sys/unix/backtrace.rs +++ b/src/libstd/sys/unix/backtrace.rs @@ -353,7 +353,7 @@ fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void) -> IoResult<()> { if state.is_null() { return output(w, idx, addr, None) } - let mut data = 0 as *const libc::c_char; + let mut data = ptr::null(); let data_addr = &mut data as *mut *const libc::c_char; let ret = unsafe { backtrace_syminfo(state, addr as libc::uintptr_t, @@ -418,7 +418,7 @@ mod uw { trace_argument: *mut libc::c_void) -> _Unwind_Reason_Code; - #[cfg(all(not(target_os = "android"), + #[cfg(all(not(all(target_os = "android", target_arch = "arm")), not(all(target_os = "linux", target_arch = "arm"))))] pub fn _Unwind_GetIP(ctx: *mut _Unwind_Context) -> libc::uintptr_t; @@ -431,7 +431,7 @@ mod uw { // On android, the function _Unwind_GetIP is a macro, and this is the // expansion of the macro. This is all copy/pasted directly from the // header file with the definition of _Unwind_GetIP. - #[cfg(any(target_os = "android", + #[cfg(any(all(target_os = "android", target_arch = "arm"), all(target_os = "linux", target_arch = "arm")))] pub unsafe fn _Unwind_GetIP(ctx: *mut _Unwind_Context) -> libc::uintptr_t { #[repr(C)] diff --git a/src/libstd/sys/unix/condvar.rs b/src/libstd/sys/unix/condvar.rs index 85a65bbef508..3bc414731526 100644 --- a/src/libstd/sys/unix/condvar.rs +++ b/src/libstd/sys/unix/condvar.rs @@ -10,6 +10,7 @@ use cell::UnsafeCell; use libc; +use ptr; use std::option::Option::{Some, None}; use sys::mutex::{self, Mutex}; use sys::time; @@ -62,7 +63,7 @@ impl Condvar { // time. let mut sys_now = libc::timeval { tv_sec: 0, tv_usec: 0 }; let stable_now = time::SteadyTime::now(); - let r = ffi::gettimeofday(&mut sys_now, 0 as *mut _); + let r = ffi::gettimeofday(&mut sys_now, ptr::null_mut()); debug_assert_eq!(r, 0); let seconds = NumCast::from(dur.num_seconds()); diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index c53f9d22790d..dd478347f819 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -19,6 +19,7 @@ use io::{Read, Truncate, SeekCur, SeekSet, ReadWrite, SeekEnd, Append}; use io; use libc::{self, c_int, c_void}; use mem; +use ptr; use sys::retry; use sys_common::{keep_going, eof, mkerr_libc}; @@ -207,7 +208,7 @@ pub fn readdir(p: &Path) -> IoResult> { if dir_ptr as uint != 0 { let mut paths = vec!(); - let mut entry_ptr = 0 as *mut dirent_t; + let mut entry_ptr = ptr::null_mut(); while unsafe { readdir_r(dir_ptr, ptr, &mut entry_ptr) == 0 } { if entry_ptr.is_null() { break } paths.push(unsafe { diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs index 175c4e2e353f..2c25af055ee1 100644 --- a/src/libstd/sys/unix/os.rs +++ b/src/libstd/sys/unix/os.rs @@ -143,7 +143,7 @@ pub unsafe fn get_env_pairs() -> Vec> { os::last_os_error()); } let mut result = Vec::new(); - while *environ != 0 as *const _ { + while *environ != ptr::null() { let env_pair = ffi::c_str_to_bytes(&*environ).to_vec(); result.push(env_pair); environ = environ.offset(1); diff --git a/src/libstd/sys/unix/process.rs b/src/libstd/sys/unix/process.rs index 36bf696dba55..2b4d168d881f 100644 --- a/src/libstd/sys/unix/process.rs +++ b/src/libstd/sys/unix/process.rs @@ -125,9 +125,9 @@ impl Process { let mut bytes = [0; 8]; return match input.read(&mut bytes) { Ok(8) => { - assert!(combine(CLOEXEC_MSG_FOOTER) == combine(bytes.slice(4, 8)), + assert!(combine(CLOEXEC_MSG_FOOTER) == combine(&bytes[4.. 8]), "Validation on the CLOEXEC pipe failed: {:?}", bytes); - let errno = combine(bytes.slice(0, 4)); + let errno = combine(&bytes[0.. 4]); assert!(p.wait(0).is_ok(), "wait(0) should either return Ok or panic"); Err(super::decode_error(errno)) } @@ -251,7 +251,7 @@ impl Process { fn setgroups(ngroups: libc::c_int, ptr: *const libc::c_void) -> libc::c_int; } - let _ = setgroups(0, 0 as *const libc::c_void); + let _ = setgroups(0, ptr::null()); if libc::setuid(u as libc::uid_t) != 0 { fail(&mut output); diff --git a/src/libstd/sys/windows/backtrace.rs b/src/libstd/sys/windows/backtrace.rs index ee2dd14955b6..cba7d81937ac 100644 --- a/src/libstd/sys/windows/backtrace.rs +++ b/src/libstd/sys/windows/backtrace.rs @@ -31,6 +31,7 @@ use mem; use ops::Drop; use option::Option::{Some, None}; use path::Path; +use ptr; use result::Result::{Ok, Err}; use slice::SliceExt; use str::{self, StrExt}; @@ -327,7 +328,7 @@ pub fn write(w: &mut Writer) -> IoResult<()> { let image = arch::init_frame(&mut frame, &context); // Initialize this process's symbols - let ret = SymInitialize(process, 0 as *mut libc::c_void, libc::TRUE); + let ret = SymInitialize(process, ptr::null_mut(), libc::TRUE); if ret != libc::TRUE { return Ok(()) } let _c = Cleanup { handle: process, SymCleanup: SymCleanup }; @@ -335,10 +336,10 @@ pub fn write(w: &mut Writer) -> IoResult<()> { let mut i = 0i; try!(write!(w, "stack backtrace:\n")); while StackWalk64(image, process, thread, &mut frame, &mut context, - 0 as *mut libc::c_void, - 0 as *mut libc::c_void, - 0 as *mut libc::c_void, - 0 as *mut libc::c_void) == libc::TRUE{ + ptr::null_mut(), + ptr::null_mut(), + ptr::null_mut(), + ptr::null_mut()) == libc::TRUE{ let addr = frame.AddrPC.Offset; if addr == frame.AddrReturn.Offset || addr == 0 || frame.AddrReturn.Offset == 0 { break } @@ -362,7 +363,7 @@ pub fn write(w: &mut Writer) -> IoResult<()> { let bytes = unsafe { ffi::c_str_to_bytes(&ptr) }; match str::from_utf8(bytes) { Ok(s) => try!(demangle(w, s)), - Err(..) => try!(w.write(&bytes[..(bytes.len()-1)])), + Err(..) => try!(w.write(&bytes[..bytes.len()-1])), } } try!(w.write(&['\n' as u8])); diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index a7330f7c67c9..cb8ef7eb66bc 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -376,7 +376,7 @@ pub fn readlink(p: &Path) -> IoResult { }); let ret = match ret { Some(ref s) if s.starts_with(r"\\?\") => { // " - Ok(Path::new(s.slice_from(4))) + Ok(Path::new(&s[4..])) } Some(s) => Ok(Path::new(s)), None => Err(super::last_error()), diff --git a/src/libstd/sys/windows/os.rs b/src/libstd/sys/windows/os.rs index e9490dc95c94..36dc9b2afe49 100644 --- a/src/libstd/sys/windows/os.rs +++ b/src/libstd/sys/windows/os.rs @@ -146,7 +146,7 @@ pub fn fill_utf16_buf_and_decode(mut f: F) -> Option where done = true; } if k != 0 && done { - let sub = buf.slice(0, k as uint); + let sub = &buf[.. (k as uint)]; // We want to explicitly catch the case when the // closure returned invalid UTF-16, rather than // set `res` to None and continue. diff --git a/src/libstd/sys/windows/thread_local.rs b/src/libstd/sys/windows/thread_local.rs index d371023f2188..d148f82184bd 100644 --- a/src/libstd/sys/windows/thread_local.rs +++ b/src/libstd/sys/windows/thread_local.rs @@ -13,6 +13,7 @@ use prelude::v1::*; use libc::types::os::arch::extra::{DWORD, LPVOID, BOOL}; use mem; +use ptr; use rt; use sys_common::mutex::{MUTEX_INIT, Mutex}; @@ -137,7 +138,7 @@ unsafe fn init_dtors() { rt::at_exit(move|| { DTOR_LOCK.lock(); let dtors = DTORS; - DTORS = 0 as *mut _; + DTORS = ptr::null_mut(); mem::transmute::<_, Box>>(dtors); assert!(DTORS.is_null()); // can't re-init after destructing DTOR_LOCK.unlock(); @@ -250,7 +251,7 @@ unsafe fn run_dtors() { for &(key, dtor) in dtors.iter() { let ptr = TlsGetValue(key); if !ptr.is_null() { - TlsSetValue(key, 0 as *mut _); + TlsSetValue(key, ptr::null_mut()); dtor(ptr as *mut _); any_run = true; } diff --git a/src/libstd/sys/windows/timer.rs b/src/libstd/sys/windows/timer.rs index 1ae3979cd9ac..12b4e56bf520 100644 --- a/src/libstd/sys/windows/timer.rs +++ b/src/libstd/sys/windows/timer.rs @@ -48,9 +48,9 @@ pub enum Req { RemoveTimer(libc::HANDLE, Sender<()>), } +unsafe impl Send for Timer {} unsafe impl Send for Req {} - fn helper(input: libc::HANDLE, messages: Receiver, _: ()) { let mut objs = vec![input]; let mut chans = vec![]; diff --git a/src/libstd/thread.rs b/src/libstd/thread.rs index ec2718bef692..09f50059936a 100644 --- a/src/libstd/thread.rs +++ b/src/libstd/thread.rs @@ -388,7 +388,7 @@ impl Thread { unsafe { imp::yield_now() } } - /// Determines whether the current thread is panicking. + /// Determines whether the current thread is unwinding because of panic. #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn panicking() -> bool { @@ -527,14 +527,14 @@ mod test { fn test_unnamed_thread() { Thread::scoped(move|| { assert!(Thread::current().name().is_none()); - }).join().map_err(|_| ()).unwrap(); + }).join().ok().unwrap(); } #[test] fn test_named_thread() { Builder::new().name("ada lovelace".to_string()).scoped(move|| { assert!(Thread::current().name().unwrap() == "ada lovelace".to_string()); - }).join().map_err(|_| ()).unwrap(); + }).join().ok().unwrap(); } #[test] @@ -670,7 +670,7 @@ mod test { Err(e) => { type T = &'static str; assert!(e.is::()); - assert_eq!(*e.downcast::().unwrap(), "static string"); + assert_eq!(*e.downcast::().ok().unwrap(), "static string"); } Ok(()) => panic!() } @@ -684,7 +684,7 @@ mod test { Err(e) => { type T = String; assert!(e.is::()); - assert_eq!(*e.downcast::().unwrap(), "owned string".to_string()); + assert_eq!(*e.downcast::().ok().unwrap(), "owned string".to_string()); } Ok(()) => panic!() } @@ -698,9 +698,9 @@ mod test { Err(e) => { type T = Box; assert!(e.is::()); - let any = e.downcast::().unwrap(); + let any = e.downcast::().ok().unwrap(); assert!(any.is::()); - assert_eq!(*any.downcast::().unwrap(), 413u16); + assert_eq!(*any.downcast::().ok().unwrap(), 413u16); } Ok(()) => panic!() } diff --git a/src/libstd/thread_local/mod.rs b/src/libstd/thread_local/mod.rs index f7be63212aba..2a9bf452329c 100644 --- a/src/libstd/thread_local/mod.rs +++ b/src/libstd/thread_local/mod.rs @@ -429,7 +429,7 @@ mod imp { dtor(ptr); } ptr = DTORS.get(); - DTORS.set(0 as *mut _); + DTORS.set(ptr::null_mut()); } } } @@ -463,6 +463,7 @@ mod imp { use cell::UnsafeCell; use mem; + use ptr; use sys_common::thread_local::StaticKey as OsStaticKey; #[doc(hidden)] @@ -526,7 +527,7 @@ mod imp { let key = ptr.key; key.os.set(1 as *mut u8); drop(ptr); - key.os.set(0 as *mut u8); + key.os.set(ptr::null_mut()); } } diff --git a/src/libstd/time/duration.rs b/src/libstd/time/duration.rs index 1bf3454eaa14..fdd9cbdccf51 100644 --- a/src/libstd/time/duration.rs +++ b/src/libstd/time/duration.rs @@ -334,7 +334,8 @@ impl Div for Duration { } } -impl fmt::String for Duration { +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for Duration { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { // technically speaking, negative duration is not valid ISO 8601, // but we need to print it anyway. diff --git a/src/libsyntax/abi.rs b/src/libsyntax/abi.rs index 09235ee209c4..5f593ac7081c 100644 --- a/src/libsyntax/abi.rs +++ b/src/libsyntax/abi.rs @@ -15,7 +15,7 @@ pub use self::AbiArchitecture::*; use std::fmt; -#[derive(Copy, PartialEq)] +#[derive(Copy, PartialEq, Eq, Show)] pub enum Os { OsWindows, OsMacos, @@ -26,7 +26,7 @@ pub enum Os { OsDragonfly, } -#[derive(PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Clone, Copy)] +#[derive(PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Clone, Copy, Show)] pub enum Abi { // NB: This ordering MUST match the AbiDatas array below. // (This is ensured by the test indices_are_correct().) @@ -105,8 +105,8 @@ pub fn all_names() -> Vec<&'static str> { impl Abi { #[inline] - pub fn index(&self) -> uint { - *self as uint + pub fn index(&self) -> usize { + *self as usize } #[inline] @@ -119,25 +119,13 @@ impl Abi { } } -impl fmt::Show for Abi { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::String::fmt(self, f) - } -} - -impl fmt::String for Abi { +impl fmt::Display for Abi { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "\"{}\"", self.name()) } } -impl fmt::Show for Os { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::String::fmt(self, f) - } -} - -impl fmt::String for Os { +impl fmt::Display for Os { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { OsLinux => "linux".fmt(f), diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index fcf80410da24..7111fe3af1fa 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -53,7 +53,6 @@ pub use self::UnboxedClosureKind::*; pub use self::UnOp::*; pub use self::UnsafeSource::*; pub use self::VariantKind::*; -pub use self::ViewItem_::*; pub use self::ViewPath_::*; pub use self::Visibility::*; pub use self::PathParameters::*; @@ -95,33 +94,33 @@ impl Ident { pub fn encode_with_hygiene(&self) -> String { format!("\x00name_{},ctxt_{}\x00", - self.name.uint(), + self.name.usize(), self.ctxt) } } -impl fmt::Show for Ident { +impl fmt::Debug for Ident { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}#{}", self.name, self.ctxt) } } -impl fmt::String for Ident { +impl fmt::Display for Ident { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::String::fmt(&self.name, f) + fmt::Display::fmt(&self.name, f) } } -impl fmt::Show for Name { +impl fmt::Debug for Name { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let Name(nm) = *self; write!(f, "{:?}({})", token::get_name(*self).get(), nm) } } -impl fmt::String for Name { +impl fmt::Display for Name { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::String::fmt(token::get_name(*self).get(), f) + fmt::Display::fmt(token::get_name(*self).get(), f) } } @@ -152,7 +151,7 @@ impl PartialEq for Ident { /// A SyntaxContext represents a chain of macro-expandings /// and renamings. Each macro expansion corresponds to -/// a fresh uint +/// a fresh usize // I'm representing this syntax context as an index into // a table, in order to work around a compiler bug @@ -181,9 +180,9 @@ impl Name { } } - pub fn uint(&self) -> uint { + pub fn usize(&self) -> usize { let Name(nm) = *self; - nm as uint + nm as usize } pub fn ident(&self) -> Ident { @@ -511,7 +510,6 @@ impl PartialEq for MetaItem_ { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub struct Block { - pub view_items: Vec, pub stmts: Vec>, pub expr: Option>, pub id: NodeId, @@ -740,7 +738,7 @@ pub enum Expr_ { ExprAssign(P, P), ExprAssignOp(BinOp, P, P), ExprField(P, SpannedIdent), - ExprTupField(P, Spanned), + ExprTupField(P, Spanned), ExprIndex(P, P), ExprRange(Option>, Option>), @@ -839,7 +837,7 @@ pub struct SequenceRepetition { /// Whether the sequence can be repeated zero (*), or one or more times (+) pub op: KleeneOp, /// The number of `MatchNt`s that appear in the sequence (and subsequences) - pub num_captures: uint, + pub num_captures: usize, } /// A Kleene-style [repetition operator](http://en.wikipedia.org/wiki/Kleene_star) @@ -878,7 +876,7 @@ pub enum TokenTree { } impl TokenTree { - pub fn len(&self) -> uint { + pub fn len(&self) -> usize { match *self { TtToken(_, token::DocComment(_)) => 2, TtToken(_, token::SpecialVarNt(..)) => 2, @@ -893,7 +891,7 @@ impl TokenTree { } } - pub fn get_tt(&self, index: uint) -> TokenTree { + pub fn get_tt(&self, index: usize) -> TokenTree { match (self, index) { (&TtToken(sp, token::DocComment(_)), 0) => { TtToken(sp, token::Pound) @@ -963,7 +961,7 @@ pub enum Mac_ { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show, Copy)] pub enum StrStyle { CookedStr, - RawStr(uint) + RawStr(usize) } pub type Lit = Spanned; @@ -992,7 +990,7 @@ pub enum LitIntType { } impl LitIntType { - pub fn suffix_len(&self) -> uint { + pub fn suffix_len(&self) -> usize { match *self { UnsuffixedIntLit(_) => 0, SignedIntLit(s, _) => s.suffix_len(), @@ -1100,20 +1098,20 @@ impl PartialEq for IntTy { } } -impl fmt::Show for IntTy { +impl fmt::Debug for IntTy { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::String::fmt(self, f) + fmt::Display::fmt(self, f) } } -impl fmt::String for IntTy { +impl fmt::Display for IntTy { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", ast_util::int_ty_to_string(*self, None)) } } impl IntTy { - pub fn suffix_len(&self) -> uint { + pub fn suffix_len(&self) -> usize { match *self { TyIs(true) /* i */ => 1, TyIs(false) /* is */ | TyI8 => 2, @@ -1146,7 +1144,7 @@ impl PartialEq for UintTy { } impl UintTy { - pub fn suffix_len(&self) -> uint { + pub fn suffix_len(&self) -> usize { match *self { TyUs(true) /* u */ => 1, TyUs(false) /* us */ | TyU8 => 2, @@ -1155,13 +1153,13 @@ impl UintTy { } } -impl fmt::Show for UintTy { +impl fmt::Debug for UintTy { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::String::fmt(self, f) + fmt::Display::fmt(self, f) } } -impl fmt::String for UintTy { +impl fmt::Display for UintTy { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", ast_util::uint_ty_to_string(*self, None)) } @@ -1173,20 +1171,20 @@ pub enum FloatTy { TyF64, } -impl fmt::Show for FloatTy { +impl fmt::Debug for FloatTy { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::String::fmt(self, f) + fmt::Display::fmt(self, f) } } -impl fmt::String for FloatTy { +impl fmt::Display for FloatTy { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", ast_util::float_ty_to_string(*self)) } } impl FloatTy { - pub fn suffix_len(&self) -> uint { + pub fn suffix_len(&self) -> usize { match *self { TyF32 | TyF64 => 3, // add F128 handling here } @@ -1222,24 +1220,15 @@ pub enum PrimTy { TyChar } -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)] +#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy, Show)] pub enum Onceness { Once, Many } -impl fmt::Show for Onceness { +impl fmt::Display for Onceness { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::String::fmt(match *self { - Once => "once", - Many => "many", - }, f) - } -} - -impl fmt::String for Onceness { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::String::fmt(match *self { + fmt::Display::fmt(match *self { Once => "once", Many => "many", }, f) @@ -1274,7 +1263,7 @@ pub enum Ty_ { TyPtr(MutTy), /// A reference (`&'a T` or `&'a mut T`) TyRptr(Option, MutTy), - /// A bare function (e.g. `fn(uint) -> bool`) + /// A bare function (e.g. `fn(usize) -> bool`) TyBareFn(P), /// A tuple (`(A, B, C, D,...)`) TyTup(Vec> ), @@ -1358,9 +1347,9 @@ pub enum Unsafety { Normal, } -impl fmt::String for Unsafety { +impl fmt::Display for Unsafety { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::String::fmt(match *self { + fmt::Display::fmt(match *self { Unsafety::Normal => "normal", Unsafety::Unsafe => "unsafe", }, f) @@ -1375,7 +1364,7 @@ pub enum ImplPolarity { Negative, } -impl fmt::Show for ImplPolarity { +impl fmt::Debug for ImplPolarity { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { ImplPolarity::Positive => "positive".fmt(f), @@ -1452,14 +1441,12 @@ pub struct Mod { /// For `mod foo;`, the inner span ranges from the first token /// to the last token in the external file. pub inner: Span, - pub view_items: Vec, pub items: Vec>, } #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub struct ForeignMod { pub abi: Abi, - pub view_items: Vec, pub items: Vec>, } @@ -1518,44 +1505,13 @@ pub enum ViewPath_ { /// or just /// /// `foo::bar::baz` (with `as baz` implicitly on the right) - ViewPathSimple(Ident, Path, NodeId), + ViewPathSimple(Ident, Path), /// `foo::bar::*` - ViewPathGlob(Path, NodeId), + ViewPathGlob(Path), /// `foo::bar::{a,b,c}` - ViewPathList(Path, Vec , NodeId) -} - -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] -pub struct ViewItem { - pub node: ViewItem_, - pub attrs: Vec, - pub vis: Visibility, - pub span: Span, -} - -impl ViewItem { - pub fn id(&self) -> NodeId { - match self.node { - ViewItemExternCrate(_, _, id) => id, - ViewItemUse(ref vp) => match vp.node { - ViewPathSimple(_, _, id) => id, - ViewPathGlob(_, id) => id, - ViewPathList(_, _, id) => id, - } - } - } -} - -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] -pub enum ViewItem_ { - /// Ident: name used to refer to this crate in the code - /// optional (InternedString,StrStyle): if present, this is a location - /// (containing arbitrary characters) from which to fetch the crate sources - /// For example, extern crate whatever = "github.com/rust-lang/rust" - ViewItemExternCrate(Ident, Option<(InternedString,StrStyle)>, NodeId), - ViewItemUse(P), + ViewPathList(Path, Vec) } /// Meta-data associated with an item @@ -1571,7 +1527,7 @@ pub enum AttrStyle { } #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show, Copy)] -pub struct AttrId(pub uint); +pub struct AttrId(pub usize); /// Doc-comments are promoted to attributes that have is_sugared_doc = true #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] @@ -1677,6 +1633,12 @@ pub struct Item { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub enum Item_ { + // Optional location (containing arbitrary characters) from which + // to fetch the crate sources. + // For example, extern crate whatever = "github.com/rust-lang/rust". + ItemExternCrate(Option<(InternedString, StrStyle)>), + ItemUse(P), + ItemStatic(P, Mutability, P), ItemConst(P, P), ItemFn(P, Unsafety, Abi, Generics, P), @@ -1703,6 +1665,8 @@ pub enum Item_ { impl Item_ { pub fn descriptive_variant(&self) -> &str { match *self { + ItemExternCrate(..) => "extern crate", + ItemUse(..) => "use", ItemStatic(..) => "static item", ItemConst(..) => "constant item", ItemFn(..) => "function", diff --git a/src/libsyntax/ast_map/mod.rs b/src/libsyntax/ast_map/mod.rs index f462a730d3aa..8a114e4b7487 100644 --- a/src/libsyntax/ast_map/mod.rs +++ b/src/libsyntax/ast_map/mod.rs @@ -46,7 +46,7 @@ impl PathElem { } } -impl fmt::String for PathElem { +impl fmt::Display for PathElem { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let slot = token::get_name(self.name()); write!(f, "{}", slot) @@ -107,7 +107,6 @@ pub fn path_to_string>(path: PI) -> String { #[derive(Copy, Show)] pub enum Node<'ast> { NodeItem(&'ast Item), - NodeViewItem(&'ast ViewItem), NodeForeignItem(&'ast ForeignItem), NodeTraitItem(&'ast TraitItem), NodeImplItem(&'ast ImplItem), @@ -134,7 +133,6 @@ enum MapEntry<'ast> { /// All the node types, with a parent ID. EntryItem(NodeId, &'ast Item), - EntryViewItem(NodeId, &'ast ViewItem), EntryForeignItem(NodeId, &'ast ForeignItem), EntryTraitItem(NodeId, &'ast TraitItem), EntryImplItem(NodeId, &'ast ImplItem), @@ -169,7 +167,6 @@ impl<'ast> MapEntry<'ast> { fn from_node(p: NodeId, node: Node<'ast>) -> MapEntry<'ast> { match node { NodeItem(n) => EntryItem(p, n), - NodeViewItem(n) => EntryViewItem(p, n), NodeForeignItem(n) => EntryForeignItem(p, n), NodeTraitItem(n) => EntryTraitItem(p, n), NodeImplItem(n) => EntryImplItem(p, n), @@ -188,7 +185,6 @@ impl<'ast> MapEntry<'ast> { fn parent(self) -> Option { Some(match self { EntryItem(id, _) => id, - EntryViewItem(id, _) => id, EntryForeignItem(id, _) => id, EntryTraitItem(id, _) => id, EntryImplItem(id, _) => id, @@ -208,7 +204,6 @@ impl<'ast> MapEntry<'ast> { fn to_node(self) -> Option> { Some(match self { EntryItem(_, n) => NodeItem(n), - EntryViewItem(_, n) => NodeViewItem(n), EntryForeignItem(_, n) => NodeForeignItem(n), EntryTraitItem(_, n) => NodeTraitItem(n), EntryImplItem(_, n) => NodeImplItem(n), @@ -264,12 +259,12 @@ pub struct Map<'ast> { } impl<'ast> Map<'ast> { - fn entry_count(&self) -> uint { + fn entry_count(&self) -> usize { self.map.borrow().len() } fn find_entry(&self, id: NodeId) -> Option> { - self.map.borrow().get(id as uint).map(|e| *e) + self.map.borrow().get(id as usize).map(|e| *e) } pub fn krate(&self) -> &'ast Crate { @@ -341,13 +336,6 @@ impl<'ast> Map<'ast> { } } - pub fn expect_view_item(&self, id: NodeId) -> &'ast ViewItem { - match self.find(id) { - Some(NodeViewItem(view_item)) => view_item, - _ => panic!("expected view item, found {}", self.node_to_string(id)) - } - } - pub fn expect_struct(&self, id: NodeId) -> &'ast StructDef { match self.find(id) { Some(NodeItem(i)) => { @@ -525,7 +513,7 @@ impl<'ast> Map<'ast> { NodesMatchingSuffix { map: self, item_name: parts.last().unwrap(), - in_which: &parts[..(parts.len() - 1)], + in_which: &parts[..parts.len() - 1], idx: 0, } } @@ -533,7 +521,6 @@ impl<'ast> Map<'ast> { pub fn opt_span(&self, id: NodeId) -> Option { let sp = match self.find(id) { Some(NodeItem(item)) => item.span, - Some(NodeViewItem(item)) => item.span, Some(NodeForeignItem(foreign_item)) => foreign_item.span, Some(NodeTraitItem(trait_method)) => { match *trait_method { @@ -652,7 +639,7 @@ impl<'a, 'ast> Iterator for NodesMatchingSuffix<'a, 'ast> { fn next(&mut self) -> Option { loop { let idx = self.idx; - if idx as uint >= self.map.entry_count() { + if idx as usize >= self.map.entry_count() { return None; } self.idx += 1; @@ -744,10 +731,10 @@ impl<'ast> NodeCollector<'ast> { fn insert_entry(&mut self, id: NodeId, entry: MapEntry<'ast>) { debug!("ast_map: {:?} => {:?}", id, entry); let len = self.map.len(); - if id as uint >= len { - self.map.extend(repeat(NotPresent).take(id as uint - len + 1)); + if id as usize >= len { + self.map.extend(repeat(NotPresent).take(id as usize - len + 1)); } - self.map[id as uint] = entry; + self.map[id as usize] = entry; } fn insert(&mut self, id: NodeId, node: Node<'ast>) { @@ -826,11 +813,6 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> { self.parent = parent; } - fn visit_view_item(&mut self, item: &'ast ViewItem) { - self.insert(item.id(), NodeViewItem(item)); - visit::walk_view_item(self, item); - } - fn visit_pat(&mut self, pat: &'ast Pat) { self.insert(pat.id, match pat.node { // Note: this is at least *potentially* a pattern... @@ -904,7 +886,6 @@ pub fn map_crate<'ast, F: FoldOps>(forest: &'ast mut Forest, fold_ops: F) -> Map let krate = mem::replace(&mut forest.krate, Crate { module: Mod { inner: DUMMY_SP, - view_items: vec![], items: vec![], }, attrs: vec![], @@ -1036,7 +1017,6 @@ impl<'a> NodePrinter for pprust::State<'a> { fn print_node(&mut self, node: &Node) -> IoResult<()> { match *node { NodeItem(a) => self.print_item(&*a), - NodeViewItem(a) => self.print_view_item(&*a), NodeForeignItem(a) => self.print_foreign_item(&*a), NodeTraitItem(a) => self.print_trait_method(&*a), NodeImplItem(a) => self.print_impl_item(&*a), @@ -1065,6 +1045,8 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String { Some(NodeItem(item)) => { let path_str = map.path_to_str_with_ident(id, item.ident); let item_str = match item.node { + ItemExternCrate(..) => "extern crate", + ItemUse(..) => "use", ItemStatic(..) => "static", ItemConst(..) => "const", ItemFn(..) => "fn", @@ -1079,9 +1061,6 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String { }; format!("{} {}{}", item_str, path_str, id_str) } - Some(NodeViewItem(item)) => { - format!("view item {}{}", pprust::view_item_to_string(&*item), id_str) - } Some(NodeForeignItem(item)) => { let path_str = map.path_to_str_with_ident(id, item.ident); format!("foreign item {}{}", path_str, id_str) diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index bc7fbd46fd8b..cf0aac5bf4ab 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -156,7 +156,7 @@ pub fn int_ty_max(t: IntTy) -> u64 { } /// Get a string representation of an unsigned int type, with its value. -/// We want to avoid "42uint" in favor of "42u" +/// We want to avoid "42u" in favor of "42us". "42uint" is right out. pub fn uint_ty_to_string(t: UintTy, val: Option) -> String { let s = match t { TyUs(true) if val.is_some() => "u", @@ -319,25 +319,24 @@ pub fn struct_field_visibility(field: ast::StructField) -> Visibility { } /// Maps a binary operator to its precedence -pub fn operator_prec(op: ast::BinOp) -> uint { +pub fn operator_prec(op: ast::BinOp) -> usize { match op { // 'as' sits here with 12 - BiMul | BiDiv | BiRem => 11u, - BiAdd | BiSub => 10u, - BiShl | BiShr => 9u, - BiBitAnd => 8u, - BiBitXor => 7u, - BiBitOr => 6u, - BiLt | BiLe | BiGe | BiGt | BiEq | BiNe => 3u, - BiAnd => 2u, - BiOr => 1u + BiMul | BiDiv | BiRem => 11us, + BiAdd | BiSub => 10us, + BiShl | BiShr => 9us, + BiBitAnd => 8us, + BiBitXor => 7us, + BiBitOr => 6us, + BiLt | BiLe | BiGe | BiGt | BiEq | BiNe => 3us, + BiAnd => 2us, + BiOr => 1us } } /// Precedence of the `as` operator, which is a binary operator /// not appearing in the prior table. -#[allow(non_upper_case_globals)] -pub static as_prec: uint = 12u; +pub const AS_PREC: usize = 12us; pub fn empty_generics() -> Generics { Generics { @@ -410,37 +409,6 @@ impl<'a, 'v, O: IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O> { visit::walk_mod(self, module) } - fn visit_view_item(&mut self, view_item: &ViewItem) { - if !self.pass_through_items { - if self.visited_outermost { - return; - } else { - self.visited_outermost = true; - } - } - match view_item.node { - ViewItemExternCrate(_, _, node_id) => { - self.operation.visit_id(node_id) - } - ViewItemUse(ref view_path) => { - match view_path.node { - ViewPathSimple(_, _, node_id) | - ViewPathGlob(_, node_id) => { - self.operation.visit_id(node_id) - } - ViewPathList(_, ref paths, node_id) => { - self.operation.visit_id(node_id); - for path in paths.iter() { - self.operation.visit_id(path.node.id()) - } - } - } - } - } - visit::walk_view_item(self, view_item); - self.visited_outermost = false; - } - fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) { self.operation.visit_id(foreign_item.id); visit::walk_foreign_item(self, foreign_item) @@ -456,10 +424,24 @@ impl<'a, 'v, O: IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O> { } self.operation.visit_id(item.id); - if let ItemEnum(ref enum_definition, _) = item.node { - for variant in enum_definition.variants.iter() { - self.operation.visit_id(variant.node.id) + match item.node { + ItemUse(ref view_path) => { + match view_path.node { + ViewPathSimple(_, _) | + ViewPathGlob(_) => {} + ViewPathList(_, ref paths) => { + for path in paths.iter() { + self.operation.visit_id(path.node.id()) + } + } + } } + ItemEnum(ref enum_definition, _) => { + for variant in enum_definition.variants.iter() { + self.operation.visit_id(variant.node.id) + } + } + _ => {} } visit::walk_item(self, item); @@ -662,37 +644,6 @@ pub fn walk_pat(pat: &Pat, mut it: F) -> bool where F: FnMut(&Pat) -> bool { walk_pat_(pat, &mut it) } -pub trait EachViewItem { - fn each_view_item(&self, f: F) -> bool where F: FnMut(&ast::ViewItem) -> bool; -} - -struct EachViewItemData where F: FnMut(&ast::ViewItem) -> bool { - callback: F, -} - -impl<'v, F> Visitor<'v> for EachViewItemData where F: FnMut(&ast::ViewItem) -> bool { - fn visit_view_item(&mut self, view_item: &ast::ViewItem) { - let _ = (self.callback)(view_item); - } -} - -impl EachViewItem for ast::Crate { - fn each_view_item(&self, f: F) -> bool where F: FnMut(&ast::ViewItem) -> bool { - let mut visit = EachViewItemData { - callback: f, - }; - visit::walk_crate(&mut visit, self); - true - } -} - -pub fn view_path_id(p: &ViewPath) -> NodeId { - match p.node { - ViewPathSimple(_, _, id) | ViewPathGlob(_, id) - | ViewPathList(_, _, id) => id - } -} - /// Returns true if the given struct def is tuple-like; i.e. that its fields /// are unnamed. pub fn struct_def_is_tuple_like(struct_def: &ast::StructDef) -> bool { diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index d63370b41f58..061600d9420f 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -175,7 +175,7 @@ pub fn mk_word_item(name: InternedString) -> P { P(dummy_spanned(MetaWord(name))) } -thread_local! { static NEXT_ATTR_ID: Cell = Cell::new(0) } +thread_local! { static NEXT_ATTR_ID: Cell = Cell::new(0) } pub fn mk_attr_id() -> AttrId { let id = NEXT_ATTR_ID.with(|slot| { @@ -364,9 +364,9 @@ pub enum StabilityLevel { Stable, } -impl fmt::String for StabilityLevel { +impl fmt::Display for StabilityLevel { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Show::fmt(self, f) + fmt::Debug::fmt(self, f) } } diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index bf26687deede..a5e10f42750b 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -30,8 +30,8 @@ use libc::c_uint; use serialize::{Encodable, Decodable, Encoder, Decoder}; pub trait Pos { - fn from_uint(n: uint) -> Self; - fn to_uint(&self) -> uint; + fn from_usize(n: usize) -> Self; + fn to_usize(&self) -> usize; } /// A byte offset. Keep this small (currently 32-bits), as AST contains @@ -43,21 +43,21 @@ pub struct BytePos(pub u32); /// is not equivalent to a character offset. The CodeMap will convert BytePos /// values to CharPos values as necessary. #[derive(Copy, PartialEq, Hash, PartialOrd, Show)] -pub struct CharPos(pub uint); +pub struct CharPos(pub usize); // FIXME: Lots of boilerplate in these impls, but so far my attempts to fix // have been unsuccessful impl Pos for BytePos { - fn from_uint(n: uint) -> BytePos { BytePos(n as u32) } - fn to_uint(&self) -> uint { let BytePos(n) = *self; n as uint } + fn from_usize(n: usize) -> BytePos { BytePos(n as u32) } + fn to_usize(&self) -> usize { let BytePos(n) = *self; n as usize } } impl Add for BytePos { type Output = BytePos; fn add(self, rhs: BytePos) -> BytePos { - BytePos((self.to_uint() + rhs.to_uint()) as u32) + BytePos((self.to_usize() + rhs.to_usize()) as u32) } } @@ -65,20 +65,20 @@ impl Sub for BytePos { type Output = BytePos; fn sub(self, rhs: BytePos) -> BytePos { - BytePos((self.to_uint() - rhs.to_uint()) as u32) + BytePos((self.to_usize() - rhs.to_usize()) as u32) } } impl Pos for CharPos { - fn from_uint(n: uint) -> CharPos { CharPos(n) } - fn to_uint(&self) -> uint { let CharPos(n) = *self; n } + fn from_usize(n: usize) -> CharPos { CharPos(n) } + fn to_usize(&self) -> usize { let CharPos(n) = *self; n } } impl Add for CharPos { type Output = CharPos; fn add(self, rhs: CharPos) -> CharPos { - CharPos(self.to_uint() + rhs.to_uint()) + CharPos(self.to_usize() + rhs.to_usize()) } } @@ -86,7 +86,7 @@ impl Sub for CharPos { type Output = CharPos; fn sub(self, rhs: CharPos) -> CharPos { - CharPos(self.to_uint() - rhs.to_uint()) + CharPos(self.to_usize() - rhs.to_usize()) } } @@ -173,7 +173,7 @@ pub struct Loc { /// Information about the original source pub file: Rc, /// The (1-based) line number - pub line: uint, + pub line: usize, /// The (0-based) column offset pub col: CharPos } @@ -183,13 +183,13 @@ pub struct Loc { // perhaps they should just be removed. pub struct LocWithOpt { pub filename: FileName, - pub line: uint, + pub line: usize, pub col: CharPos, pub file: Option>, } // used to be structural records. Better names, anyone? -pub struct FileMapAndLine { pub fm: Rc, pub line: uint } +pub struct FileMapAndLine { pub fm: Rc, pub line: usize } pub struct FileMapAndBytePos { pub fm: Rc, pub pos: BytePos } /// The syntax with which a macro was invoked. @@ -258,7 +258,7 @@ pub type FileName = String; pub struct FileLines { pub file: Rc, - pub lines: Vec + pub lines: Vec } /// Identifies an offset of a multi-byte character in a FileMap @@ -267,7 +267,7 @@ pub struct MultiByteChar { /// The absolute offset of the character in the CodeMap pub pos: BytePos, /// The number of bytes, >=2 - pub bytes: uint, + pub bytes: usize, } /// A single source in the CodeMap @@ -306,11 +306,11 @@ impl FileMap { /// get a line from the list of pre-computed line-beginnings /// - pub fn get_line(&self, line_number: uint) -> Option { + pub fn get_line(&self, line_number: usize) -> Option { let lines = self.lines.borrow(); lines.get(line_number).map(|&line| { let begin: BytePos = line - self.start_pos; - let begin = begin.to_uint(); + let begin = begin.to_usize(); let slice = &self.src[begin..]; match slice.find('\n') { Some(e) => &slice[..e], @@ -319,7 +319,7 @@ impl FileMap { }) } - pub fn record_multibyte_char(&self, pos: BytePos, bytes: uint) { + pub fn record_multibyte_char(&self, pos: BytePos, bytes: usize) { assert!(bytes >=2 && bytes <= 4); let mbc = MultiByteChar { pos: pos, @@ -351,7 +351,7 @@ impl CodeMap { let mut files = self.files.borrow_mut(); let start_pos = match files.last() { None => 0, - Some(last) => last.start_pos.to_uint() + last.src.len(), + Some(last) => last.start_pos.to_usize() + last.src.len(), }; // Remove utf-8 BOM if any. @@ -374,7 +374,7 @@ impl CodeMap { let filemap = Rc::new(FileMap { name: filename, src: src.to_string(), - start_pos: Pos::from_uint(start_pos), + start_pos: Pos::from_usize(start_pos), lines: RefCell::new(Vec::new()), multibyte_chars: RefCell::new(Vec::new()), }); @@ -389,7 +389,7 @@ impl CodeMap { (format!("<{}:{}:{}>", pos.file.name, pos.line, - pos.col.to_uint() + 1)).to_string() + pos.col.to_usize() + 1)).to_string() } /// Lookup source information about a BytePos @@ -417,9 +417,9 @@ impl CodeMap { return (format!("{}:{}:{}: {}:{}", lo.filename, lo.line, - lo.col.to_uint() + 1, + lo.col.to_usize() + 1, hi.line, - hi.col.to_uint() + 1)).to_string() + hi.col.to_usize() + 1)).to_string() } pub fn span_to_filename(&self, sp: Span) -> FileName { @@ -430,7 +430,7 @@ impl CodeMap { let lo = self.lookup_char_pos(sp.lo); let hi = self.lookup_char_pos(sp.hi); let mut lines = Vec::new(); - for i in range(lo.line - 1u, hi.line as uint) { + for i in range(lo.line - 1us, hi.line as usize) { lines.push(i); }; FileLines {file: lo.file, lines: lines} @@ -447,7 +447,7 @@ impl CodeMap { if begin.fm.start_pos != end.fm.start_pos { None } else { - Some((&begin.fm.src[begin.pos.to_uint()..end.pos.to_uint()]).to_string()) + Some((&begin.fm.src[begin.pos.to_usize()..end.pos.to_usize()]).to_string()) } } @@ -484,24 +484,24 @@ impl CodeMap { total_extra_bytes += mbc.bytes - 1; // We should never see a byte position in the middle of a // character - assert!(bpos.to_uint() >= mbc.pos.to_uint() + mbc.bytes); + assert!(bpos.to_usize() >= mbc.pos.to_usize() + mbc.bytes); } else { break; } } - assert!(map.start_pos.to_uint() + total_extra_bytes <= bpos.to_uint()); - CharPos(bpos.to_uint() - map.start_pos.to_uint() - total_extra_bytes) + assert!(map.start_pos.to_usize() + total_extra_bytes <= bpos.to_usize()); + CharPos(bpos.to_usize() - map.start_pos.to_usize() - total_extra_bytes) } - fn lookup_filemap_idx(&self, pos: BytePos) -> uint { + fn lookup_filemap_idx(&self, pos: BytePos) -> usize { let files = self.files.borrow(); let files = &*files; let len = files.len(); - let mut a = 0u; + let mut a = 0us; let mut b = len; - while b - a > 1u { - let m = (a + b) / 2u; + while b - a > 1us { + let m = (a + b) / 2us; if files[m].start_pos > pos { b = m; } else { @@ -520,13 +520,13 @@ impl CodeMap { } if a == 0 { panic!("position {} does not resolve to a source location", - pos.to_uint()); + pos.to_usize()); } a -= 1; } if a >= len { panic!("position {} does not resolve to a source location", - pos.to_uint()) + pos.to_usize()) } return a; @@ -537,12 +537,12 @@ impl CodeMap { let files = self.files.borrow(); let f = (*files)[idx].clone(); - let mut a = 0u; + let mut a = 0us; { let lines = f.lines.borrow(); let mut b = lines.len(); - while b - a > 1u { - let m = (a + b) / 2u; + while b - a > 1us { + let m = (a + b) / 2us; if (*lines)[m] > pos { b = m; } else { a = m; } } } @@ -551,7 +551,7 @@ impl CodeMap { fn lookup_pos(&self, pos: BytePos) -> Loc { let FileMapAndLine {fm: f, line: a} = self.lookup_line(pos); - let line = a + 1u; // Line numbers start at 1 + let line = a + 1us; // Line numbers start at 1 let chpos = self.bytepos_to_file_charpos(pos); let linebpos = (*f.lines.borrow())[a]; let linechpos = self.bytepos_to_file_charpos(linebpos); @@ -579,7 +579,7 @@ impl CodeMap { { match id { NO_EXPANSION => f(None), - ExpnId(i) => f(Some(&(*self.expansions.borrow())[i as uint])) + ExpnId(i) => f(Some(&(*self.expansions.borrow())[i as usize])) } } @@ -762,7 +762,7 @@ mod test { assert_eq!(file_lines.file.name, "blork.rs"); assert_eq!(file_lines.lines.len(), 1); - assert_eq!(file_lines.lines[0], 1u); + assert_eq!(file_lines.lines[0], 1us); } #[test] diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index 3f91831a5df7..3eaac0fe333e 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -63,28 +63,13 @@ pub fn strip_items(krate: ast::Crate, in_cfg: F) -> ast::Crate where ctxt.fold_crate(krate) } -fn filter_view_item(cx: &mut Context, - view_item: ast::ViewItem) - -> Option where - F: FnMut(&[ast::Attribute]) -> bool -{ - if view_item_in_cfg(cx, &view_item) { - Some(view_item) - } else { - None - } -} - fn fold_mod(cx: &mut Context, - ast::Mod {inner, - view_items, items}: ast::Mod) -> ast::Mod where + ast::Mod {inner, items}: ast::Mod) + -> ast::Mod where F: FnMut(&[ast::Attribute]) -> bool { ast::Mod { inner: inner, - view_items: view_items.into_iter().filter_map(|a| { - filter_view_item(cx, a).map(|x| cx.fold_view_item(x)) - }).collect(), items: items.into_iter().flat_map(|a| { cx.fold_item(a).into_iter() }).collect() @@ -104,15 +89,12 @@ fn filter_foreign_item(cx: &mut Context, } fn fold_foreign_mod(cx: &mut Context, - ast::ForeignMod {abi, view_items, items}: ast::ForeignMod) + ast::ForeignMod {abi, items}: ast::ForeignMod) -> ast::ForeignMod where F: FnMut(&[ast::Attribute]) -> bool { ast::ForeignMod { abi: abi, - view_items: view_items.into_iter().filter_map(|a| { - filter_view_item(cx, a).map(|x| cx.fold_view_item(x)) - }).collect(), items: items.into_iter() .filter_map(|a| filter_foreign_item(cx, a)) .collect() @@ -216,18 +198,14 @@ fn retain_stmt(cx: &mut Context, stmt: &ast::Stmt) -> bool where fn fold_block(cx: &mut Context, b: P) -> P where F: FnMut(&[ast::Attribute]) -> bool { - b.map(|ast::Block {id, view_items, stmts, expr, rules, span}| { + b.map(|ast::Block {id, stmts, expr, rules, span}| { let resulting_stmts: Vec> = stmts.into_iter().filter(|a| retain_stmt(cx, &**a)).collect(); let resulting_stmts = resulting_stmts.into_iter() .flat_map(|stmt| cx.fold_stmt(stmt).into_iter()) .collect(); - let filtered_view_items = view_items.into_iter().filter_map(|a| { - filter_view_item(cx, a).map(|x| cx.fold_view_item(x)) - }).collect(); ast::Block { id: id, - view_items: filtered_view_items, stmts: resulting_stmts, expr: expr.map(|x| cx.fold_expr(x)), rules: rules, @@ -267,12 +245,6 @@ fn foreign_item_in_cfg(cx: &mut Context, item: &ast::ForeignItem) -> bool return (cx.in_cfg)(item.attrs.as_slice()); } -fn view_item_in_cfg(cx: &mut Context, item: &ast::ViewItem) -> bool where - F: FnMut(&[ast::Attribute]) -> bool -{ - return (cx.in_cfg)(item.attrs.as_slice()); -} - fn trait_method_in_cfg(cx: &mut Context, meth: &ast::TraitItem) -> bool where F: FnMut(&[ast::Attribute]) -> bool { diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index 7213b0fa9556..0c7f6befc4e3 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -26,7 +26,7 @@ use term::WriterWrapper; use term; /// maximum number of lines we will print for each error; arbitrary. -static MAX_LINES: uint = 6u; +static MAX_LINES: usize = 6us; #[derive(Clone, Copy)] pub enum RenderSpan { @@ -92,6 +92,10 @@ impl SpanHandler { self.handler.emit(Some((&self.cm, sp)), msg, Fatal); panic!(FatalError); } + pub fn span_fatal_with_code(&self, sp: Span, msg: &str, code: &str) -> ! { + self.handler.emit_with_code(Some((&self.cm, sp)), msg, code, Fatal); + panic!(FatalError); + } pub fn span_err(&self, sp: Span, msg: &str) { self.handler.emit(Some((&self.cm, sp)), msg, Error); self.handler.bump_err_count(); @@ -137,7 +141,7 @@ impl SpanHandler { /// (fatal, bug, unimpl) may cause immediate exit, /// others log errors for later reporting. pub struct Handler { - err_count: Cell, + err_count: Cell, emit: RefCell>, } @@ -151,20 +155,20 @@ impl Handler { self.bump_err_count(); } pub fn bump_err_count(&self) { - self.err_count.set(self.err_count.get() + 1u); + self.err_count.set(self.err_count.get() + 1us); } - pub fn err_count(&self) -> uint { + pub fn err_count(&self) -> usize { self.err_count.get() } pub fn has_errors(&self) -> bool { - self.err_count.get()> 0u + self.err_count.get() > 0us } pub fn abort_if_errors(&self) { let s; match self.err_count.get() { - 0u => return, - 1u => s = "aborting due to previous error".to_string(), - _ => { + 0us => return, + 1us => s = "aborting due to previous error".to_string(), + _ => { s = format!("aborting due to {} previous errors", self.err_count.get()); } @@ -235,9 +239,9 @@ pub enum Level { Help, } -impl fmt::String for Level { +impl fmt::Display for Level { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use std::fmt::String; + use std::fmt::Display; match *self { Bug => "error: internal compiler error".fmt(f), @@ -280,7 +284,7 @@ fn print_maybe_styled(w: &mut EmitterWriter, // to be miscolored. We assume this is rare enough that we don't // have to worry about it. if msg.ends_with("\n") { - try!(t.write_str(&msg[..(msg.len()-1)])); + try!(t.write_str(&msg[..msg.len()-1])); try!(t.reset()); try!(t.write_str("\n")); } else { @@ -448,7 +452,7 @@ fn highlight_lines(err: &mut EmitterWriter, let mut elided = false; let mut display_lines = &lines.lines[]; if display_lines.len() > MAX_LINES { - display_lines = &display_lines[0u..MAX_LINES]; + display_lines = &display_lines[0us..MAX_LINES]; elided = true; } // Print the offending lines @@ -459,32 +463,32 @@ fn highlight_lines(err: &mut EmitterWriter, } } if elided { - let last_line = display_lines[display_lines.len() - 1u]; - let s = format!("{}:{} ", fm.name, last_line + 1u); + let last_line = display_lines[display_lines.len() - 1us]; + let s = format!("{}:{} ", fm.name, last_line + 1us); try!(write!(&mut err.dst, "{0:1$}...\n", "", s.len())); } // FIXME (#3260) // If there's one line at fault we can easily point to the problem - if lines.lines.len() == 1u { + if lines.lines.len() == 1us { let lo = cm.lookup_char_pos(sp.lo); - let mut digits = 0u; - let mut num = (lines.lines[0] + 1u) / 10u; + let mut digits = 0us; + let mut num = (lines.lines[0] + 1us) / 10us; // how many digits must be indent past? - while num > 0u { num /= 10u; digits += 1u; } + while num > 0us { num /= 10us; digits += 1us; } // indent past |name:## | and the 0-offset column location - let left = fm.name.len() + digits + lo.col.to_uint() + 3u; + let left = fm.name.len() + digits + lo.col.to_usize() + 3us; let mut s = String::new(); // Skip is the number of characters we need to skip because they are // part of the 'filename:line ' part of the previous line. - let skip = fm.name.len() + digits + 3u; + let skip = fm.name.len() + digits + 3us; for _ in range(0, skip) { s.push(' '); } if let Some(orig) = fm.get_line(lines.lines[0]) { - for pos in range(0u, left - skip) { + for pos in range(0us, left - skip) { let cur_char = orig.as_bytes()[pos] as char; // Whenever a tab occurs on the previous line, we insert one on // the error-point-squiggly-line as well (instead of a space). @@ -502,7 +506,7 @@ fn highlight_lines(err: &mut EmitterWriter, let hi = cm.lookup_char_pos(sp.hi); if hi.col != lo.col { // the ^ already takes up one space - let num_squigglies = hi.col.to_uint() - lo.col.to_uint() - 1u; + let num_squigglies = hi.col.to_usize() - lo.col.to_usize() - 1us; for _ in range(0, num_squigglies) { s.push('~'); } @@ -551,7 +555,7 @@ fn custom_highlight_lines(w: &mut EmitterWriter, let last_line_start = format!("{}:{} ", fm.name, lines[lines.len()-1]+1); let hi = cm.lookup_char_pos(sp.hi); // Span seems to use half-opened interval, so subtract 1 - let skip = last_line_start.len() + hi.col.to_uint() - 1; + let skip = last_line_start.len() + hi.col.to_usize() - 1; let mut s = String::new(); for _ in range(0, skip) { s.push(' '); diff --git a/src/libsyntax/diagnostics/macros.rs b/src/libsyntax/diagnostics/macros.rs index 34a193dffd3d..9321d3ca3df1 100644 --- a/src/libsyntax/diagnostics/macros.rs +++ b/src/libsyntax/diagnostics/macros.rs @@ -14,6 +14,14 @@ macro_rules! register_diagnostic { ($code:tt) => (__register_diagnostic! { $code }) } +#[macro_export] +macro_rules! span_fatal { + ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({ + __diagnostic_used!($code); + $session.span_fatal_with_code($span, format!($($message)*).as_slice(), stringify!($code)) + }) +} + #[macro_export] macro_rules! span_err { ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({ @@ -51,3 +59,9 @@ macro_rules! register_diagnostics { ) } +#[macro_export] +macro_rules! register_long_diagnostics { + ($($code:tt: $description:tt),*) => ( + $(register_diagnostic! { $code, $description })* + ) +} diff --git a/src/libsyntax/diagnostics/plugin.rs b/src/libsyntax/diagnostics/plugin.rs index 1469c50061cc..bd5247bbad6a 100644 --- a/src/libsyntax/diagnostics/plugin.rs +++ b/src/libsyntax/diagnostics/plugin.rs @@ -9,7 +9,7 @@ // except according to those terms. use std::cell::RefCell; -use std::collections::HashMap; +use std::collections::BTreeMap; use ast; use ast::{Ident, Name, TokenTree}; use codemap::Span; @@ -19,18 +19,18 @@ use parse::token; use ptr::P; thread_local! { - static REGISTERED_DIAGNOSTICS: RefCell>> = { - RefCell::new(HashMap::new()) + static REGISTERED_DIAGNOSTICS: RefCell>> = { + RefCell::new(BTreeMap::new()) } } thread_local! { - static USED_DIAGNOSTICS: RefCell> = { - RefCell::new(HashMap::new()) + static USED_DIAGNOSTICS: RefCell> = { + RefCell::new(BTreeMap::new()) } } fn with_registered_diagnostics(f: F) -> T where - F: FnOnce(&mut HashMap>) -> T, + F: FnOnce(&mut BTreeMap>) -> T, { REGISTERED_DIAGNOSTICS.with(move |slot| { f(&mut *slot.borrow_mut()) @@ -38,7 +38,7 @@ fn with_registered_diagnostics(f: F) -> T where } fn with_used_diagnostics(f: F) -> T where - F: FnOnce(&mut HashMap) -> T, + F: FnOnce(&mut BTreeMap) -> T, { USED_DIAGNOSTICS.with(move |slot| { f(&mut *slot.borrow_mut()) @@ -65,6 +65,13 @@ pub fn expand_diagnostic_used<'cx>(ecx: &'cx mut ExtCtxt, } () }); + with_registered_diagnostics(|diagnostics| { + if !diagnostics.contains_key(&code.name) { + ecx.span_err(span, &format!( + "used diagnostic code {} not registered", token::get_ident(code).get() + )[]); + } + }); MacExpr::new(quote_expr!(ecx, ())) } diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index bca7131fdb71..9cfdc942c21b 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -548,7 +548,7 @@ pub struct ExtCtxt<'a> { pub exported_macros: Vec, pub syntax_env: SyntaxEnv, - pub recursion_count: uint, + pub recursion_count: usize, } impl<'a> ExtCtxt<'a> { diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index c34142aec39c..92619cf42e4d 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -97,7 +97,6 @@ pub trait AstBuilder { expr: Option>) -> P; fn block_expr(&self, expr: P) -> P; fn block_all(&self, span: Span, - view_items: Vec, stmts: Vec>, expr: Option>) -> P; @@ -116,7 +115,7 @@ pub trait AstBuilder { fn expr_mut_addr_of(&self, sp: Span, e: P) -> P; fn expr_field_access(&self, span: Span, expr: P, ident: ast::Ident) -> P; fn expr_tup_field_access(&self, sp: Span, expr: P, - idx: uint) -> P; + idx: usize) -> P; fn expr_call(&self, span: Span, expr: P, args: Vec>) -> P; fn expr_call_ident(&self, span: Span, id: ast::Ident, args: Vec>) -> P; fn expr_call_global(&self, sp: Span, fn_path: Vec, @@ -134,8 +133,8 @@ pub trait AstBuilder { fn expr_lit(&self, sp: Span, lit: ast::Lit_) -> P; - fn expr_uint(&self, span: Span, i: uint) -> P; - fn expr_int(&self, sp: Span, i: int) -> P; + fn expr_usize(&self, span: Span, i: usize) -> P; + fn expr_int(&self, sp: Span, i: isize) -> P; fn expr_u8(&self, sp: Span, u: u8) -> P; fn expr_bool(&self, sp: Span, value: bool) -> P; @@ -242,7 +241,7 @@ pub trait AstBuilder { fn item_mod(&self, span: Span, inner_span: Span, name: Ident, attrs: Vec, - vi: Vec , items: Vec> ) -> P; + items: Vec>) -> P; fn item_static(&self, span: Span, @@ -280,15 +279,15 @@ pub trait AstBuilder { value: ast::Lit_) -> P; - fn view_use(&self, sp: Span, - vis: ast::Visibility, vp: P) -> ast::ViewItem; - fn view_use_simple(&self, sp: Span, vis: ast::Visibility, path: ast::Path) -> ast::ViewItem; - fn view_use_simple_(&self, sp: Span, vis: ast::Visibility, - ident: ast::Ident, path: ast::Path) -> ast::ViewItem; - fn view_use_list(&self, sp: Span, vis: ast::Visibility, - path: Vec , imports: &[ast::Ident]) -> ast::ViewItem; - fn view_use_glob(&self, sp: Span, - vis: ast::Visibility, path: Vec ) -> ast::ViewItem; + fn item_use(&self, sp: Span, + vis: ast::Visibility, vp: P) -> P; + fn item_use_simple(&self, sp: Span, vis: ast::Visibility, path: ast::Path) -> P; + fn item_use_simple_(&self, sp: Span, vis: ast::Visibility, + ident: ast::Ident, path: ast::Path) -> P; + fn item_use_list(&self, sp: Span, vis: ast::Visibility, + path: Vec, imports: &[ast::Ident]) -> P; + fn item_use_glob(&self, sp: Span, + vis: ast::Visibility, path: Vec) -> P; } impl<'a> AstBuilder for ExtCtxt<'a> { @@ -519,7 +518,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { fn block(&self, span: Span, stmts: Vec>, expr: Option>) -> P { - self.block_all(span, Vec::new(), stmts, expr) + self.block_all(span, stmts, expr) } fn stmt_item(&self, sp: Span, item: P) -> P { @@ -528,15 +527,13 @@ impl<'a> AstBuilder for ExtCtxt<'a> { } fn block_expr(&self, expr: P) -> P { - self.block_all(expr.span, Vec::new(), Vec::new(), Some(expr)) + self.block_all(expr.span, Vec::new(), Some(expr)) } fn block_all(&self, span: Span, - view_items: Vec, stmts: Vec>, expr: Option>) -> P { P(ast::Block { - view_items: view_items, stmts: stmts, expr: expr, id: ast::DUMMY_NODE_ID, @@ -579,7 +576,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { fn expr_field_access(&self, sp: Span, expr: P, ident: ast::Ident) -> P { let field_name = token::get_ident(ident); let field_span = Span { - lo: sp.lo - Pos::from_uint(field_name.get().len()), + lo: sp.lo - Pos::from_usize(field_name.get().len()), hi: sp.hi, expn_id: sp.expn_id, }; @@ -587,9 +584,9 @@ impl<'a> AstBuilder for ExtCtxt<'a> { let id = Spanned { node: ident, span: field_span }; self.expr(sp, ast::ExprField(expr, id)) } - fn expr_tup_field_access(&self, sp: Span, expr: P, idx: uint) -> P { + fn expr_tup_field_access(&self, sp: Span, expr: P, idx: usize) -> P { let field_span = Span { - lo: sp.lo - Pos::from_uint(idx.to_string().len()), + lo: sp.lo - Pos::from_usize(idx.to_string().len()), hi: sp.hi, expn_id: sp.expn_id, }; @@ -641,10 +638,10 @@ impl<'a> AstBuilder for ExtCtxt<'a> { fn expr_lit(&self, sp: Span, lit: ast::Lit_) -> P { self.expr(sp, ast::ExprLit(P(respan(sp, lit)))) } - fn expr_uint(&self, span: Span, i: uint) -> P { + fn expr_usize(&self, span: Span, i: usize) -> P { self.expr_lit(span, ast::LitInt(i as u64, ast::UnsignedIntLit(ast::TyUs(false)))) } - fn expr_int(&self, sp: Span, i: int) -> P { + fn expr_int(&self, sp: Span, i: isize) -> P { self.expr_lit(sp, ast::LitInt(i as u64, ast::SignedIntLit(ast::TyIs(false), ast::Sign::new(i)))) } @@ -710,7 +707,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { let loc = self.codemap().lookup_char_pos(span.lo); let expr_file = self.expr_str(span, token::intern_and_get_ident(&loc.file.name[])); - let expr_line = self.expr_uint(span, loc.line); + let expr_line = self.expr_usize(span, loc.line); let expr_file_line_tuple = self.expr_tuple(span, vec!(expr_file, expr_line)); let expr_file_line_ptr = self.expr_addr_of(span, expr_file_line_tuple); self.expr_call_global( @@ -1031,16 +1028,14 @@ impl<'a> AstBuilder for ExtCtxt<'a> { } fn item_mod(&self, span: Span, inner_span: Span, name: Ident, - attrs: Vec , - vi: Vec , - items: Vec> ) -> P { + attrs: Vec, + items: Vec>) -> P { self.item( span, name, attrs, ast::ItemMod(ast::Mod { inner: inner_span, - view_items: vi, items: items, }) ) @@ -1101,47 +1096,47 @@ impl<'a> AstBuilder for ExtCtxt<'a> { P(respan(sp, ast::MetaNameValue(name, respan(sp, value)))) } - fn view_use(&self, sp: Span, - vis: ast::Visibility, vp: P) -> ast::ViewItem { - ast::ViewItem { - node: ast::ViewItemUse(vp), - attrs: Vec::new(), + fn item_use(&self, sp: Span, + vis: ast::Visibility, vp: P) -> P { + P(ast::Item { + id: ast::DUMMY_NODE_ID, + ident: special_idents::invalid, + attrs: vec![], + node: ast::ItemUse(vp), vis: vis, span: sp - } + }) } - fn view_use_simple(&self, sp: Span, vis: ast::Visibility, path: ast::Path) -> ast::ViewItem { + fn item_use_simple(&self, sp: Span, vis: ast::Visibility, path: ast::Path) -> P { let last = path.segments.last().unwrap().identifier; - self.view_use_simple_(sp, vis, last, path) + self.item_use_simple_(sp, vis, last, path) } - fn view_use_simple_(&self, sp: Span, vis: ast::Visibility, - ident: ast::Ident, path: ast::Path) -> ast::ViewItem { - self.view_use(sp, vis, + fn item_use_simple_(&self, sp: Span, vis: ast::Visibility, + ident: ast::Ident, path: ast::Path) -> P { + self.item_use(sp, vis, P(respan(sp, ast::ViewPathSimple(ident, - path, - ast::DUMMY_NODE_ID)))) + path)))) } - fn view_use_list(&self, sp: Span, vis: ast::Visibility, - path: Vec , imports: &[ast::Ident]) -> ast::ViewItem { + fn item_use_list(&self, sp: Span, vis: ast::Visibility, + path: Vec, imports: &[ast::Ident]) -> P { let imports = imports.iter().map(|id| { respan(sp, ast::PathListIdent { name: *id, id: ast::DUMMY_NODE_ID }) }).collect(); - self.view_use(sp, vis, + self.item_use(sp, vis, P(respan(sp, ast::ViewPathList(self.path(sp, path), - imports, - ast::DUMMY_NODE_ID)))) + imports)))) } - fn view_use_glob(&self, sp: Span, - vis: ast::Visibility, path: Vec ) -> ast::ViewItem { - self.view_use(sp, vis, + fn item_use_glob(&self, sp: Span, + vis: ast::Visibility, path: Vec) -> P { + self.item_use(sp, vis, P(respan(sp, - ast::ViewPathGlob(self.path(sp, path), ast::DUMMY_NODE_ID)))) + ast::ViewPathGlob(self.path(sp, path))))) } } diff --git a/src/libsyntax/ext/deriving/decodable.rs b/src/libsyntax/ext/deriving/decodable.rs index 8edbf018f22e..e458bd58e8b6 100644 --- a/src/libsyntax/ext/deriving/decodable.rs +++ b/src/libsyntax/ext/deriving/decodable.rs @@ -114,7 +114,7 @@ fn decodable_substructure(cx: &mut ExtCtxt, trait_span: Span, cx.expr_try(span, cx.expr_method_call(span, blkdecoder.clone(), read_struct_field, vec!(cx.expr_str(span, name), - cx.expr_uint(span, field), + cx.expr_usize(span, field), exprdecode.clone()))) }); let result = cx.expr_ok(trait_span, result); @@ -123,7 +123,7 @@ fn decodable_substructure(cx: &mut ExtCtxt, trait_span: Span, cx.ident_of("read_struct"), vec!( cx.expr_str(trait_span, token::get_ident(substr.type_ident)), - cx.expr_uint(trait_span, nfields), + cx.expr_usize(trait_span, nfields), cx.lambda_expr_1(trait_span, result, blkarg) )) } @@ -143,14 +143,14 @@ fn decodable_substructure(cx: &mut ExtCtxt, trait_span: Span, path, parts, |cx, span, _, field| { - let idx = cx.expr_uint(span, field); + let idx = cx.expr_usize(span, field); cx.expr_try(span, cx.expr_method_call(span, blkdecoder.clone(), rvariant_arg, vec!(idx, exprdecode.clone()))) }); arms.push(cx.arm(v_span, - vec!(cx.pat_lit(v_span, cx.expr_uint(v_span, i))), + vec!(cx.pat_lit(v_span, cx.expr_usize(v_span, i))), decoded)); } @@ -179,14 +179,14 @@ fn decodable_substructure(cx: &mut ExtCtxt, trait_span: Span, /// Create a decoder for a single enum variant/struct: /// - `outer_pat_path` is the path to this enum variant/struct -/// - `getarg` should retrieve the `uint`-th field with name `@str`. +/// - `getarg` should retrieve the `usize`-th field with name `@str`. fn decode_static_fields(cx: &mut ExtCtxt, trait_span: Span, outer_pat_path: ast::Path, fields: &StaticFields, mut getarg: F) -> P where - F: FnMut(&mut ExtCtxt, Span, InternedString, uint) -> P, + F: FnMut(&mut ExtCtxt, Span, InternedString, usize) -> P, { match *fields { Unnamed(ref fields) => { diff --git a/src/libsyntax/ext/deriving/default.rs b/src/libsyntax/ext/deriving/default.rs index 36c3f2c0ccb3..f8fdd8575bd6 100644 --- a/src/libsyntax/ext/deriving/default.rs +++ b/src/libsyntax/ext/deriving/default.rs @@ -79,7 +79,7 @@ fn default_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructur StaticEnum(..) => { cx.span_err(trait_span, "`Default` cannot be derived for enums, only structs"); // let compilation continue - cx.expr_uint(trait_span, 0) + cx.expr_usize(trait_span, 0) } _ => cx.span_bug(trait_span, "Non-static method in `derive(Default)`") }; diff --git a/src/libsyntax/ext/deriving/encodable.rs b/src/libsyntax/ext/deriving/encodable.rs index 801ae213a7bc..4c78a7b6a0cf 100644 --- a/src/libsyntax/ext/deriving/encodable.rs +++ b/src/libsyntax/ext/deriving/encodable.rs @@ -16,7 +16,7 @@ //! //! ```ignore //! #[derive(Encodable, Decodable)] -//! struct Node { id: uint } +//! struct Node { id: usize } //! ``` //! //! would generate two implementations like: @@ -27,7 +27,7 @@ //! s.emit_struct("Node", 1, |this| { //! this.emit_struct_field("id", 0, |this| { //! Encodable::encode(&self.id, this) -//! /* this.emit_uint(self.id) can also be used */ +//! /* this.emit_usize(self.id) can also be used */ //! }) //! }) //! } @@ -192,7 +192,7 @@ fn encodable_substructure(cx: &mut ExtCtxt, trait_span: Span, let call = cx.expr_method_call(span, blkencoder.clone(), emit_struct_field, vec!(cx.expr_str(span, name), - cx.expr_uint(span, i), + cx.expr_usize(span, i), lambda)); // last call doesn't need a try! @@ -218,7 +218,7 @@ fn encodable_substructure(cx: &mut ExtCtxt, trait_span: Span, cx.ident_of("emit_struct"), vec!( cx.expr_str(trait_span, token::get_ident(substr.type_ident)), - cx.expr_uint(trait_span, fields.len()), + cx.expr_usize(trait_span, fields.len()), blk )) } @@ -239,7 +239,7 @@ fn encodable_substructure(cx: &mut ExtCtxt, trait_span: Span, let lambda = cx.lambda_expr_1(span, enc, blkarg); let call = cx.expr_method_call(span, blkencoder.clone(), emit_variant_arg, - vec!(cx.expr_uint(span, i), + vec!(cx.expr_usize(span, i), lambda)); let call = if i != last { cx.expr_try(span, call) @@ -262,8 +262,8 @@ fn encodable_substructure(cx: &mut ExtCtxt, trait_span: Span, let call = cx.expr_method_call(trait_span, blkencoder, cx.ident_of("emit_enum_variant"), vec!(name, - cx.expr_uint(trait_span, idx), - cx.expr_uint(trait_span, fields.len()), + cx.expr_usize(trait_span, idx), + cx.expr_usize(trait_span, fields.len()), blk)); let blk = cx.lambda_expr_1(trait_span, call, blkarg); let ret = cx.expr_method_call(trait_span, diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs index 293e4befd3bb..272b04640101 100644 --- a/src/libsyntax/ext/deriving/generic/mod.rs +++ b/src/libsyntax/ext/deriving/generic/mod.rs @@ -28,7 +28,7 @@ //! arguments: //! //! - `Struct`, when `Self` is a struct (including tuple structs, e.g -//! `struct T(int, char)`). +//! `struct T(i32, char)`). //! - `EnumMatching`, when `Self` is an enum and all the arguments are the //! same variant of the enum (e.g. `Some(1)`, `Some(3)` and `Some(4)`) //! - `EnumNonMatchingCollapsed` when `Self` is an enum and the arguments @@ -54,17 +54,17 @@ //! following snippet //! //! ```rust -//! struct A { x : int } +//! struct A { x : i32 } //! -//! struct B(int); +//! struct B(i32); //! //! enum C { -//! C0(int), -//! C1 { x: int } +//! C0(i32), +//! C1 { x: i32 } //! } //! ``` //! -//! The `int`s in `B` and `C0` don't have an identifier, so the +//! The `i32`s in `B` and `C0` don't have an identifier, so the //! `Option`s would be `None` for them. //! //! In the static cases, the structure is summarised, either into the just @@ -90,8 +90,8 @@ //! trait PartialEq { //! fn eq(&self, other: &Self); //! } -//! impl PartialEq for int { -//! fn eq(&self, other: &int) -> bool { +//! impl PartialEq for i32 { +//! fn eq(&self, other: &i32) -> bool { //! *self == *other //! } //! } @@ -117,7 +117,7 @@ //! //! ```{.text} //! Struct(vec![FieldInfo { -//! span: , +//! span: , //! name: None, //! self_: //! other: vec![] @@ -132,7 +132,7 @@ //! ```{.text} //! EnumMatching(0, , //! vec![FieldInfo { -//! span: +//! span: //! name: None, //! self_: , //! other: vec![] @@ -179,7 +179,7 @@ //! StaticStruct(, Unnamed(vec![])) //! //! StaticEnum(, -//! vec![(, , Unnamed(vec![])), +//! vec![(, , Unnamed(vec![])), //! (, , Named(vec![(, )]))]) //! ``` @@ -294,7 +294,7 @@ pub enum SubstructureFields<'a> { /// Matching variants of the enum: variant index, ast::Variant, /// fields: the field name is only non-`None` in the case of a struct /// variant. - EnumMatching(uint, &'a ast::Variant, Vec), + EnumMatching(usize, &'a ast::Variant, Vec), /// Non-matching variants of the enum, but with all state hidden from /// the consequent code. The first component holds `Ident`s for all of @@ -719,7 +719,7 @@ impl<'a> MethodDef<'a> { /// ``` /// #[derive(PartialEq)] - /// struct A { x: int, y: int } + /// struct A { x: i32, y: i32 } /// /// // equivalent to: /// impl PartialEq for A { @@ -748,7 +748,7 @@ impl<'a> MethodDef<'a> { let mut raw_fields = Vec::new(); // ~[[fields of self], // [fields of next Self arg], [etc]] let mut patterns = Vec::new(); - for i in range(0u, self_args.len()) { + for i in range(0us, self_args.len()) { let struct_path= cx.path(DUMMY_SP, vec!( type_ident )); let (pat, ident_expr) = trait_.create_struct_pattern(cx, @@ -825,7 +825,7 @@ impl<'a> MethodDef<'a> { /// #[derive(PartialEq)] /// enum A { /// A1, - /// A2(int) + /// A2(i32) /// } /// /// // is equivalent to @@ -837,8 +837,8 @@ impl<'a> MethodDef<'a> { /// (&A2(ref __self_0), /// &A2(ref __arg_1_0)) => (*__self_0).eq(&(*__arg_1_0)), /// _ => { - /// let __self_vi = match *self { A1(..) => 0u, A2(..) => 1u }; - /// let __arg_1_vi = match *__arg_1 { A1(..) => 0u, A2(..) => 1u }; + /// let __self_vi = match *self { A1(..) => 0us, A2(..) => 1us }; + /// let __arg_1_vi = match *__arg_1 { A1(..) => 0us, A2(..) => 1us }; /// false /// } /// } @@ -882,8 +882,8 @@ impl<'a> MethodDef<'a> { /// (Variant2, Variant2, Variant2) => ... // delegate Matching on Variant2 /// ... /// _ => { - /// let __this_vi = match this { Variant1 => 0u, Variant2 => 1u, ... }; - /// let __that_vi = match that { Variant1 => 0u, Variant2 => 1u, ... }; + /// let __this_vi = match this { Variant1 => 0us, Variant2 => 1us, ... }; + /// let __that_vi = match that { Variant1 => 0us, Variant2 => 1us, ... }; /// ... // catch-all remainder can inspect above variant index values. /// } /// } @@ -915,7 +915,7 @@ impl<'a> MethodDef<'a> { .collect::>(); // The `vi_idents` will be bound, solely in the catch-all, to - // a series of let statements mapping each self_arg to a uint + // a series of let statements mapping each self_arg to a usize // corresponding to its variant index. let vi_idents: Vec = self_arg_names.iter() .map(|name| { let vi_suffix = format!("{}_vi", &name[]); @@ -1039,19 +1039,19 @@ impl<'a> MethodDef<'a> { }).collect(); // Build a series of let statements mapping each self_arg - // to a uint corresponding to its variant index. + // to a usize corresponding to its variant index. // i.e. for `enum E { A, B(1), C(T, T) }`, and a deriving // with three Self args, builds three statements: // // ``` // let __self0_vi = match self { - // A => 0u, B(..) => 1u, C(..) => 2u + // A => 0us, B(..) => 1us, C(..) => 2us // }; // let __self1_vi = match __arg1 { - // A => 0u, B(..) => 1u, C(..) => 2u + // A => 0us, B(..) => 1us, C(..) => 2us // }; // let __self2_vi = match __arg2 { - // A => 0u, B(..) => 1u, C(..) => 2u + // A => 0us, B(..) => 1us, C(..) => 2us // }; // ``` let mut index_let_stmts: Vec> = Vec::new(); @@ -1073,7 +1073,7 @@ impl<'a> MethodDef<'a> { // // } let arm_expr = cx.expr_block( - cx.block_all(sp, Vec::new(), index_let_stmts, Some(arm_expr))); + cx.block_all(sp, index_let_stmts, Some(arm_expr))); // Builds arm: // _ => { let __self0_vi = ...; diff --git a/src/libsyntax/ext/deriving/generic/ty.rs b/src/libsyntax/ext/deriving/generic/ty.rs index 5e6a9c91ce03..85682d41b5ff 100644 --- a/src/libsyntax/ext/deriving/generic/ty.rs +++ b/src/libsyntax/ext/deriving/generic/ty.rs @@ -32,7 +32,7 @@ pub enum PtrTy<'a> { Raw(ast::Mutability), } -/// A path, e.g. `::std::option::Option::` (global). Has support +/// A path, e.g. `::std::option::Option::` (global). Has support /// for type parameters and a lifetime. #[derive(Clone)] pub struct Path<'a> { @@ -91,7 +91,7 @@ pub enum Ty<'a> { /// &/Box/ Ty Ptr(Box>, PtrTy<'a>), /// mod::mod::Type<[lifetime], [Params...]>, including a plain type - /// parameter, and things like `int` + /// parameter, and things like `i32` Literal(Path<'a>), /// includes unit Tuple(Vec> ) diff --git a/src/libsyntax/ext/deriving/hash.rs b/src/libsyntax/ext/deriving/hash.rs index 08336be87d10..8dac864c2ae3 100644 --- a/src/libsyntax/ext/deriving/hash.rs +++ b/src/libsyntax/ext/deriving/hash.rs @@ -89,7 +89,7 @@ fn hash_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) // iteration function. let discriminant = match variant.node.disr_expr { Some(ref d) => d.clone(), - None => cx.expr_uint(trait_span, index) + None => cx.expr_usize(trait_span, index) }; stmts.push(call_hash(trait_span, discriminant)); diff --git a/src/libsyntax/ext/deriving/mod.rs b/src/libsyntax/ext/deriving/mod.rs index 603c44780071..e52a2b513ce1 100644 --- a/src/libsyntax/ext/deriving/mod.rs +++ b/src/libsyntax/ext/deriving/mod.rs @@ -99,7 +99,9 @@ pub fn expand_meta_derive(cx: &mut ExtCtxt, "Rand" => expand!(rand::expand_deriving_rand), + // NOTE(stage0): remove "Show" "Show" => expand!(show::expand_deriving_show), + "Debug" => expand!(show::expand_deriving_show), "Default" => expand!(default::expand_deriving_default), diff --git a/src/libsyntax/ext/deriving/rand.rs b/src/libsyntax/ext/deriving/rand.rs index b5435896791c..bb902d7059c8 100644 --- a/src/libsyntax/ext/deriving/rand.rs +++ b/src/libsyntax/ext/deriving/rand.rs @@ -80,10 +80,10 @@ fn rand_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) if variants.is_empty() { cx.span_err(trait_span, "`Rand` cannot be derived for enums with no variants"); // let compilation continue - return cx.expr_uint(trait_span, 0); + return cx.expr_usize(trait_span, 0); } - let variant_count = cx.expr_uint(trait_span, variants.len()); + let variant_count = cx.expr_usize(trait_span, variants.len()); let rand_name = cx.path_all(trait_span, true, @@ -115,7 +115,7 @@ fn rand_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) variant_count); let mut arms = variants.iter().enumerate().map(|(i, &(ident, v_span, ref summary))| { - let i_expr = cx.expr_uint(v_span, i); + let i_expr = cx.expr_usize(v_span, i); let pat = cx.pat_lit(v_span, i_expr); let path = cx.path(v_span, vec![substr.type_ident, ident]); diff --git a/src/libsyntax/ext/deriving/show.rs b/src/libsyntax/ext/deriving/show.rs index 48034ce50ab5..f5b5d4dda199 100644 --- a/src/libsyntax/ext/deriving/show.rs +++ b/src/libsyntax/ext/deriving/show.rs @@ -35,7 +35,7 @@ pub fn expand_deriving_show(cx: &mut ExtCtxt, let trait_def = TraitDef { span: span, attributes: Vec::new(), - path: Path::new(vec!("std", "fmt", "Show")), + path: Path::new(vec!("std", "fmt", "Debug")), additional_bounds: Vec::new(), generics: LifetimeBounds::empty(), methods: vec!( @@ -67,7 +67,7 @@ fn show_substructure(cx: &mut ExtCtxt, span: Span, Struct(_) => substr.type_ident, EnumMatching(_, v, _) => v.node.name, EnumNonMatchingCollapsed(..) | StaticStruct(..) | StaticEnum(..) => { - cx.span_bug(span, "nonsensical .fields in `#[derive(Show)]`") + cx.span_bug(span, "nonsensical .fields in `#[derive(Debug)]`") } }; diff --git a/src/libsyntax/ext/env.rs b/src/libsyntax/ext/env.rs index 9b54e259761d..9f6bf352b040 100644 --- a/src/libsyntax/ext/env.rs +++ b/src/libsyntax/ext/env.rs @@ -104,7 +104,7 @@ pub fn expand_env<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) let e = match os::getenv(var.get()) { None => { cx.span_err(sp, msg.get()); - cx.expr_uint(sp, 0) + cx.expr_usize(sp, 0) } Some(s) => cx.expr_str(sp, token::intern_and_get_ident(&s[])) }; diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index c95bdeefd454..629991799e73 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -206,7 +206,6 @@ pub fn expand_expr(e: P, fld: &mut MacroExpander) -> P { // wrap the if-let expr in a block let span = els.span; let blk = P(ast::Block { - view_items: vec![], stmts: vec![], expr: Some(P(els)), id: ast::DUMMY_NODE_ID, @@ -273,7 +272,7 @@ fn expand_mac_invoc(mac: ast::Mac, span: codemap::Span, // in this file. // Token-tree macros: MacInvocTT(pth, tts, _) => { - if pth.segments.len() > 1u { + if pth.segments.len() > 1us { fld.cx.span_err(pth.span, "expected macro name without module \ separators"); @@ -799,8 +798,7 @@ pub fn expand_block(blk: P, fld: &mut MacroExpander) -> P { // expand the elements of a block. pub fn expand_block_elts(b: P, fld: &mut MacroExpander) -> P { - b.map(|Block {id, view_items, stmts, expr, rules, span}| { - let new_view_items = view_items.into_iter().map(|x| fld.fold_view_item(x)).collect(); + b.map(|Block {id, stmts, expr, rules, span}| { let new_stmts = stmts.into_iter().flat_map(|x| { // perform all pending renames let renamed_stmt = { @@ -821,7 +819,6 @@ pub fn expand_block_elts(b: P, fld: &mut MacroExpander) -> P { }); Block { id: fld.new_id(id), - view_items: new_view_items, stmts: new_stmts, expr: new_expr, rules: rules, @@ -844,7 +841,7 @@ fn expand_pat(p: P, fld: &mut MacroExpander) -> P { }, _ => unreachable!() }; - if pth.segments.len() > 1u { + if pth.segments.len() > 1us { fld.cx.span_err(pth.span, "expected macro name without module separators"); return DummyResult::raw_pat(span); } @@ -1311,7 +1308,7 @@ fn new_span(cx: &ExtCtxt, sp: Span) -> Span { pub struct ExpansionConfig { pub crate_name: String, pub enable_quotes: bool, - pub recursion_limit: uint, + pub recursion_limit: usize, } impl ExpansionConfig { @@ -1507,7 +1504,7 @@ mod test { #[should_fail] #[test] fn macros_cant_escape_fns_test () { let src = "fn bogus() {macro_rules! z (() => (3+4));}\ - fn inty() -> int { z!() }".to_string(); + fn inty() -> i32 { z!() }".to_string(); let sess = parse::new_parse_sess(); let crate_ast = parse::parse_crate_from_source_str( "".to_string(), @@ -1521,7 +1518,7 @@ mod test { #[should_fail] #[test] fn macros_cant_escape_mods_test () { let src = "mod foo {macro_rules! z (() => (3+4));}\ - fn inty() -> int { z!() }".to_string(); + fn inty() -> i32 { z!() }".to_string(); let sess = parse::new_parse_sess(); let crate_ast = parse::parse_crate_from_source_str( "".to_string(), @@ -1533,7 +1530,7 @@ mod test { // macro_use modules should allow macros to escape #[test] fn macros_can_escape_flattened_mods_test () { let src = "#[macro_use] mod foo {macro_rules! z (() => (3+4));}\ - fn inty() -> int { z!() }".to_string(); + fn inty() -> i32 { z!() }".to_string(); let sess = parse::new_parse_sess(); let crate_ast = parse::parse_crate_from_source_str( "".to_string(), @@ -1564,8 +1561,8 @@ mod test { // should be able to use a bound identifier as a literal in a macro definition: #[test] fn self_macro_parsing(){ expand_crate_str( - "macro_rules! foo ((zz) => (287u;)); - fn f(zz : int) {foo!(zz);}".to_string() + "macro_rules! foo ((zz) => (287;)); + fn f(zz: i32) {foo!(zz);}".to_string() ); } @@ -1595,29 +1592,29 @@ mod test { // in principle, you might want to control this boolean on a per-varref basis, // but that would make things even harder to understand, and might not be // necessary for thorough testing. - type RenamingTest = (&'static str, Vec>, bool); + type RenamingTest = (&'static str, Vec>, bool); #[test] fn automatic_renaming () { let tests: Vec = vec!(// b & c should get new names throughout, in the expr too: - ("fn a() -> int { let b = 13; let c = b; b+c }", + ("fn a() -> i32 { let b = 13; let c = b; b+c }", vec!(vec!(0,1),vec!(2)), false), // both x's should be renamed (how is this causing a bug?) - ("fn main () {let x: int = 13;x;}", + ("fn main () {let x: i32 = 13;x;}", vec!(vec!(0)), false), // the use of b after the + should be renamed, the other one not: - ("macro_rules! f (($x:ident) => (b + $x)); fn a() -> int { let b = 13; f!(b)}", + ("macro_rules! f (($x:ident) => (b + $x)); fn a() -> i32 { let b = 13; f!(b)}", vec!(vec!(1)), false), // the b before the plus should not be renamed (requires marks) - ("macro_rules! f (($x:ident) => ({let b=9; ($x + b)})); fn a() -> int { f!(b)}", + ("macro_rules! f (($x:ident) => ({let b=9; ($x + b)})); fn a() -> i32 { f!(b)}", vec!(vec!(1)), false), // the marks going in and out of letty should cancel, allowing that $x to // capture the one following the semicolon. // this was an awesome test case, and caught a *lot* of bugs. ("macro_rules! letty(($x:ident) => (let $x = 15;)); macro_rules! user(($x:ident) => ({letty!($x); $x})); - fn main() -> int {user!(z)}", + fn main() -> i32 {user!(z)}", vec!(vec!(0)), false) ); for (idx,s) in tests.iter().enumerate() { @@ -1680,13 +1677,13 @@ mod test { // can't write this test case until we have macro-generating macros. // method arg hygiene - // method expands to fn get_x(&self_0, x_1:int) {self_0 + self_2 + x_3 + x_1} + // method expands to fn get_x(&self_0, x_1: i32) {self_0 + self_2 + x_3 + x_1} #[test] fn method_arg_hygiene(){ run_renaming_test( &("macro_rules! inject_x (()=>(x)); macro_rules! inject_self (()=>(self)); struct A; - impl A{fn get_x(&self, x: int) {self + inject_self!() + inject_x!() + x;} }", + impl A{fn get_x(&self, x: i32) {self + inject_self!() + inject_x!() + x;} }", vec!(vec!(0),vec!(3)), true), 0) @@ -1706,21 +1703,21 @@ mod test { } // item fn hygiene - // expands to fn q(x_1:int){fn g(x_2:int){x_2 + x_1};} + // expands to fn q(x_1: i32){fn g(x_2: i32){x_2 + x_1};} #[test] fn issue_9383(){ run_renaming_test( - &("macro_rules! bad_macro (($ex:expr) => (fn g(x:int){ x + $ex })); - fn q(x:int) { bad_macro!(x); }", + &("macro_rules! bad_macro (($ex:expr) => (fn g(x: i32){ x + $ex })); + fn q(x: i32) { bad_macro!(x); }", vec!(vec!(1),vec!(0)),true), 0) } // closure arg hygiene (ExprClosure) - // expands to fn f(){(|x_1 : int| {(x_2 + x_1)})(3);} + // expands to fn f(){(|x_1 : i32| {(x_2 + x_1)})(3);} #[test] fn closure_arg_hygiene(){ run_renaming_test( &("macro_rules! inject_x (()=>(x)); - fn f(){(|x : int| {(inject_x!() + x)})(3);}", + fn f(){(|x : i32| {(inject_x!() + x)})(3);}", vec!(vec!(1)), true), 0) @@ -1729,7 +1726,7 @@ mod test { // macro_rules in method position. Sadly, unimplemented. #[test] fn macro_in_method_posn(){ expand_crate_str( - "macro_rules! my_method (() => (fn thirteen(&self) -> int {13})); + "macro_rules! my_method (() => (fn thirteen(&self) -> i32 {13})); struct A; impl A{ my_method!(); } fn f(){A.thirteen;}".to_string()); @@ -1749,7 +1746,7 @@ mod test { } // run one of the renaming tests - fn run_renaming_test(t: &RenamingTest, test_idx: uint) { + fn run_renaming_test(t: &RenamingTest, test_idx: usize) { let invalid_name = token::special_idents::invalid.name; let (teststr, bound_connections, bound_ident_check) = match *t { (ref str,ref conns, bic) => (str.to_string(), conns.clone(), bic) @@ -1876,7 +1873,7 @@ foo_module!(); // it's the name of a 0-ary variant, and that 'i' appears twice in succession. #[test] fn crate_bindings_test(){ - let the_crate = string_to_crate("fn main (a : int) -> int {|b| { + let the_crate = string_to_crate("fn main (a: i32) -> i32 {|b| { match 34 {None => 3, Some(i) | i => j, Foo{k:z,l:y} => \"banana\"}} }".to_string()); let idents = crate_bindings(&the_crate); assert_eq!(idents, strs_to_idents(vec!("a","b","None","i","i","z","y"))); @@ -1885,10 +1882,10 @@ foo_module!(); // test the IdentRenamer directly #[test] fn ident_renamer_test () { - let the_crate = string_to_crate("fn f(x : int){let x = x; x}".to_string()); + let the_crate = string_to_crate("fn f(x: i32){let x = x; x}".to_string()); let f_ident = token::str_to_ident("f"); let x_ident = token::str_to_ident("x"); - let int_ident = token::str_to_ident("int"); + let int_ident = token::str_to_ident("i32"); let renames = vec!((x_ident,Name(16))); let mut renamer = IdentRenamer{renames: &renames}; let renamed_crate = renamer.fold_crate(the_crate); @@ -1900,10 +1897,10 @@ foo_module!(); // test the PatIdentRenamer; only PatIdents get renamed #[test] fn pat_ident_renamer_test () { - let the_crate = string_to_crate("fn f(x : int){let x = x; x}".to_string()); + let the_crate = string_to_crate("fn f(x: i32){let x = x; x}".to_string()); let f_ident = token::str_to_ident("f"); let x_ident = token::str_to_ident("x"); - let int_ident = token::str_to_ident("int"); + let int_ident = token::str_to_ident("i32"); let renames = vec!((x_ident,Name(16))); let mut renamer = PatIdentRenamer{renames: &renames}; let renamed_crate = renamer.fold_crate(the_crate); diff --git a/src/libsyntax/ext/format.rs b/src/libsyntax/ext/format.rs index f512b33f0244..8ea9d6168ef4 100644 --- a/src/libsyntax/ext/format.rs +++ b/src/libsyntax/ext/format.rs @@ -31,7 +31,7 @@ enum ArgumentType { } enum Position { - Exact(uint), + Exact(usize), Named(String), } @@ -61,11 +61,11 @@ struct Context<'a, 'b:'a> { /// Stays `true` if all formatting parameters are default (as in "{}{}"). all_pieces_simple: bool, - name_positions: HashMap, + name_positions: HashMap, /// Updated as arguments are consumed or methods are entered - nest_level: uint, - next_arg: uint, + nest_level: usize, + next_arg: usize, } /// Parses the arguments from the given list of tokens, returning None @@ -326,11 +326,11 @@ impl<'a, 'b> Context<'a, 'b> { match c { parse::CountIs(i) => { self.ecx.expr_call_global(sp, Context::rtpath(self.ecx, "CountIs"), - vec!(self.ecx.expr_uint(sp, i))) + vec!(self.ecx.expr_usize(sp, i))) } parse::CountIsParam(i) => { self.ecx.expr_call_global(sp, Context::rtpath(self.ecx, "CountIsParam"), - vec!(self.ecx.expr_uint(sp, i))) + vec!(self.ecx.expr_usize(sp, i))) } parse::CountImplied => { let path = self.ecx.path_global(sp, Context::rtpath(self.ecx, @@ -349,7 +349,7 @@ impl<'a, 'b> Context<'a, 'b> { }; let i = i + self.args.len(); self.ecx.expr_call_global(sp, Context::rtpath(self.ecx, "CountIsParam"), - vec!(self.ecx.expr_uint(sp, i))) + vec!(self.ecx.expr_usize(sp, i))) } } } @@ -382,7 +382,7 @@ impl<'a, 'b> Context<'a, 'b> { } parse::ArgumentIs(i) => { self.ecx.expr_call_global(sp, Context::rtpath(self.ecx, "ArgumentIs"), - vec!(self.ecx.expr_uint(sp, i))) + vec!(self.ecx.expr_usize(sp, i))) } // Named arguments are converted to positional arguments at // the end of the list of arguments @@ -393,7 +393,7 @@ impl<'a, 'b> Context<'a, 'b> { }; let i = i + self.args.len(); self.ecx.expr_call_global(sp, Context::rtpath(self.ecx, "ArgumentIs"), - vec!(self.ecx.expr_uint(sp, i))) + vec!(self.ecx.expr_usize(sp, i))) } }; @@ -432,7 +432,7 @@ impl<'a, 'b> Context<'a, 'b> { } }; let align = self.ecx.expr_path(align); - let flags = self.ecx.expr_uint(sp, arg.format.flags); + let flags = self.ecx.expr_usize(sp, arg.format.flags); let prec = self.trans_count(arg.format.precision); let width = self.trans_count(arg.format.width); let path = self.ecx.path_global(sp, Context::rtpath(self.ecx, "FormatSpec")); @@ -603,8 +603,8 @@ impl<'a, 'b> Context<'a, 'b> { let trait_ = match *ty { Known(ref tyname) => { match &tyname[] { - "" => "String", - "?" => "Show", + "" => "Display", + "?" => "Debug", "e" => "LowerExp", "E" => "UpperExp", "o" => "Octal", diff --git a/src/libsyntax/ext/mtwt.rs b/src/libsyntax/ext/mtwt.rs index ae8ff118fcc0..7adc443759fe 100644 --- a/src/libsyntax/ext/mtwt.rs +++ b/src/libsyntax/ext/mtwt.rs @@ -187,7 +187,7 @@ fn resolve_internal(id: Ident, } let resolved = { - let result = (*table.table.borrow())[id.ctxt as uint]; + let result = (*table.table.borrow())[id.ctxt as usize]; match result { EmptyCtxt => id.name, // ignore marks here: @@ -231,7 +231,7 @@ fn marksof_internal(ctxt: SyntaxContext, let mut result = Vec::new(); let mut loopvar = ctxt; loop { - let table_entry = (*table.table.borrow())[loopvar as uint]; + let table_entry = (*table.table.borrow())[loopvar as usize]; match table_entry { EmptyCtxt => { return result; @@ -258,7 +258,7 @@ fn marksof_internal(ctxt: SyntaxContext, /// FAILS when outside is not a mark. pub fn outer_mark(ctxt: SyntaxContext) -> Mrk { with_sctable(|sctable| { - match (*sctable.table.borrow())[ctxt as uint] { + match (*sctable.table.borrow())[ctxt as usize] { Mark(mrk, _) => mrk, _ => panic!("can't retrieve outer mark when outside is not a mark") } @@ -330,7 +330,7 @@ mod tests { let mut result = Vec::new(); loop { let table = table.table.borrow(); - match (*table)[sc as uint] { + match (*table)[sc as usize] { EmptyCtxt => {return result;}, Mark(mrk,tail) => { result.push(M(mrk)); @@ -398,7 +398,7 @@ mod tests { assert_eq! (marksof_internal (ans, stopname,&t), vec!(16));} // rename where stop doesn't match: { let chain = vec!(M(9), - R(id(name1.uint() as u32, + R(id(name1.usize() as u32, apply_mark_internal (4, EMPTY_CTXT,&mut t)), Name(100101102)), M(14)); @@ -407,7 +407,7 @@ mod tests { // rename where stop does match { let name1sc = apply_mark_internal(4, EMPTY_CTXT, &mut t); let chain = vec!(M(9), - R(id(name1.uint() as u32, name1sc), + R(id(name1.usize() as u32, name1sc), stopname), M(14)); let ans = unfold_test_sc(chain,EMPTY_CTXT,&mut t); diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs index c42b188302cc..7e345a2d078f 100644 --- a/src/libsyntax/ext/quote.rs +++ b/src/libsyntax/ext/quote.rs @@ -352,18 +352,11 @@ pub mod rt { impl<'a> ExtParseUtils for ExtCtxt<'a> { fn parse_item(&self, s: String) -> P { - let res = parse::parse_item_from_source_str( + parse::parse_item_from_source_str( "".to_string(), s, self.cfg(), - self.parse_sess()); - match res { - Some(ast) => ast, - None => { - error!("parse error"); - panic!() - } - } + self.parse_sess()).expect("parse error") } fn parse_stmt(&self, s: String) -> P { @@ -588,7 +581,7 @@ fn mk_token(cx: &ExtCtxt, sp: Span, tok: &token::Token) -> P { } token::Literal(token::StrRaw(ident, n), suf) => { - return mk_lit!("StrRaw", suf, mk_name(cx, sp, ident.ident()), cx.expr_uint(sp, n)) + return mk_lit!("StrRaw", suf, mk_name(cx, sp, ident.ident()), cx.expr_usize(sp, n)) } token::Ident(ident, style) => { @@ -716,7 +709,7 @@ fn expand_tts(cx: &ExtCtxt, sp: Span, tts: &[ast::TokenTree]) // try removing it when enough of them are gone. let mut p = cx.new_parser_from_tts(tts); - p.quote_depth += 1u; + p.quote_depth += 1us; let cx_expr = p.parse_expr(); if !p.eat(&token::Comma) { @@ -767,7 +760,6 @@ fn expand_tts(cx: &ExtCtxt, sp: Span, tts: &[ast::TokenTree]) vector.extend(mk_tts(cx, &tts[]).into_iter()); let block = cx.expr_block( cx.block_all(sp, - Vec::new(), vector, Some(cx.expr_ident(sp, id_ext("tt"))))); @@ -778,18 +770,18 @@ fn expand_wrapper(cx: &ExtCtxt, sp: Span, cx_expr: P, expr: P) -> P { - let uses = [ - &["syntax", "ext", "quote", "rt"], - ].iter().map(|path| { - let path = path.iter().map(|s| s.to_string()).collect(); - cx.view_use_glob(sp, ast::Inherited, ids_ext(path)) - }).collect(); - // Explicitly borrow to avoid moving from the invoker (#16992) let cx_expr_borrow = cx.expr_addr_of(sp, cx.expr_deref(sp, cx_expr)); let stmt_let_ext_cx = cx.stmt_let(sp, false, id_ext("ext_cx"), cx_expr_borrow); - cx.expr_block(cx.block_all(sp, uses, vec!(stmt_let_ext_cx), Some(expr))) + let stmts = [ + &["syntax", "ext", "quote", "rt"], + ].iter().map(|path| { + let path = path.iter().map(|s| s.to_string()).collect(); + cx.stmt_item(sp, cx.item_use_glob(sp, ast::Inherited, ids_ext(path))) + }).chain(Some(stmt_let_ext_cx).into_iter()).collect(); + + cx.expr_block(cx.block_all(sp, stmts, Some(expr))) } fn expand_parse_call(cx: &ExtCtxt, diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs index 31a1a838b133..a74adbf40851 100644 --- a/src/libsyntax/ext/source_util.rs +++ b/src/libsyntax/ext/source_util.rs @@ -35,7 +35,7 @@ pub fn expand_line(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) let topmost = cx.original_span_in_file(); let loc = cx.codemap().lookup_char_pos(topmost.lo); - base::MacExpr::new(cx.expr_uint(topmost, loc.line)) + base::MacExpr::new(cx.expr_usize(topmost, loc.line)) } /* column!(): expands to the current column number */ @@ -45,7 +45,7 @@ pub fn expand_column(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) let topmost = cx.original_span_in_file(); let loc = cx.codemap().lookup_char_pos(topmost.lo); - base::MacExpr::new(cx.expr_uint(topmost, loc.col.to_uint())) + base::MacExpr::new(cx.expr_usize(topmost, loc.col.to_usize())) } /// file!(): expands to the current filename */ diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index 9eda4bcef994..d115f2ed6208 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -110,14 +110,14 @@ enum TokenTreeOrTokenTreeVec { } impl TokenTreeOrTokenTreeVec { - fn len(&self) -> uint { + fn len(&self) -> usize { match self { &TtSeq(ref v) => v.len(), &Tt(ref tt) => tt.len(), } } - fn get_tt(&self, index: uint) -> TokenTree { + fn get_tt(&self, index: usize) -> TokenTree { match self { &TtSeq(ref v) => v[index].clone(), &Tt(ref tt) => tt.get_tt(index), @@ -129,7 +129,7 @@ impl TokenTreeOrTokenTreeVec { #[derive(Clone)] struct MatcherTtFrame { elts: TokenTreeOrTokenTreeVec, - idx: uint, + idx: usize, } #[derive(Clone)] @@ -137,16 +137,16 @@ pub struct MatcherPos { stack: Vec, top_elts: TokenTreeOrTokenTreeVec, sep: Option, - idx: uint, + idx: usize, up: Option>, matches: Vec>>, - match_lo: uint, - match_cur: uint, - match_hi: uint, + match_lo: usize, + match_cur: usize, + match_hi: usize, sp_lo: BytePos, } -pub fn count_names(ms: &[TokenTree]) -> uint { +pub fn count_names(ms: &[TokenTree]) -> usize { ms.iter().fold(0, |count, elt| { count + match elt { &TtSequence(_, ref seq) => { @@ -171,11 +171,11 @@ pub fn initial_matcher_pos(ms: Rc>, sep: Option, lo: ByteP stack: vec![], top_elts: TtSeq(ms), sep: sep, - idx: 0u, + idx: 0us, up: None, matches: matches, - match_lo: 0u, - match_cur: 0u, + match_lo: 0us, + match_cur: 0us, match_hi: match_idx_hi, sp_lo: lo } @@ -206,7 +206,7 @@ pub enum NamedMatch { pub fn nameize(p_s: &ParseSess, ms: &[TokenTree], res: &[Rc]) -> HashMap> { fn n_rec(p_s: &ParseSess, m: &TokenTree, res: &[Rc], - ret_val: &mut HashMap>, idx: &mut uint) { + ret_val: &mut HashMap>, idx: &mut usize) { match m { &TtSequence(_, ref seq) => { for next_m in seq.tts.iter() { @@ -238,7 +238,7 @@ pub fn nameize(p_s: &ParseSess, ms: &[TokenTree], res: &[Rc]) } } let mut ret_val = HashMap::new(); - let mut idx = 0u; + let mut idx = 0us; for m in ms.iter() { n_rec(p_s, m, res, &mut ret_val, &mut idx) } ret_val } @@ -383,7 +383,7 @@ pub fn parse(sess: &ParseSess, if seq.op == ast::ZeroOrMore { let mut new_ei = ei.clone(); new_ei.match_cur += seq.num_captures; - new_ei.idx += 1u; + new_ei.idx += 1us; //we specifically matched zero repeats. for idx in range(ei.match_cur, ei.match_cur + seq.num_captures) { (&mut new_ei.matches[idx]).push(Rc::new(MatchedSeq(vec![], sp))); @@ -398,7 +398,7 @@ pub fn parse(sess: &ParseSess, cur_eis.push(box MatcherPos { stack: vec![], sep: seq.separator.clone(), - idx: 0u, + idx: 0us, matches: matches, match_lo: ei_t.match_cur, match_cur: ei_t.match_cur, @@ -442,20 +442,20 @@ pub fn parse(sess: &ParseSess, /* error messages here could be improved with links to orig. rules */ if token_name_eq(&tok, &token::Eof) { - if eof_eis.len() == 1u { + if eof_eis.len() == 1us { let mut v = Vec::new(); for dv in (&mut eof_eis[0]).matches.iter_mut() { v.push(dv.pop().unwrap()); } return Success(nameize(sess, ms, &v[])); - } else if eof_eis.len() > 1u { + } else if eof_eis.len() > 1us { return Error(sp, "ambiguity: multiple successful parses".to_string()); } else { return Failure(sp, "unexpected end of macro invocation".to_string()); } } else { - if (bb_eis.len() > 0u && next_eis.len() > 0u) - || bb_eis.len() > 1u { + if (bb_eis.len() > 0us && next_eis.len() > 0us) + || bb_eis.len() > 1us { let nts = bb_eis.iter().map(|ei| { match ei.top_elts.get_tt(ei.idx) { TtToken(_, MatchNt(bind, name, _, _)) => { @@ -469,12 +469,12 @@ pub fn parse(sess: &ParseSess, "local ambiguity: multiple parsing options: \ built-in NTs {} or {} other options.", nts, next_eis.len()).to_string()); - } else if bb_eis.len() == 0u && next_eis.len() == 0u { + } else if bb_eis.len() == 0us && next_eis.len() == 0us { return Failure(sp, format!("no rules expected the token `{}`", pprust::token_to_string(&tok)).to_string()); - } else if next_eis.len() > 0u { + } else if next_eis.len() > 0us { /* Now process the next token */ - while next_eis.len() > 0u { + while next_eis.len() > 0us { cur_eis.push(next_eis.pop().unwrap()); } rdr.next_token(); @@ -488,7 +488,7 @@ pub fn parse(sess: &ParseSess, let match_cur = ei.match_cur; (&mut ei.matches[match_cur]).push(Rc::new(MatchedNonterminal( parse_nt(&mut rust_parser, name_string.get())))); - ei.idx += 1u; + ei.idx += 1us; ei.match_cur += 1; } _ => panic!() @@ -501,16 +501,16 @@ pub fn parse(sess: &ParseSess, } } - assert!(cur_eis.len() > 0u); + assert!(cur_eis.len() > 0us); } } pub fn parse_nt(p: &mut Parser, name: &str) -> Nonterminal { match name { "tt" => { - p.quote_depth += 1u; //but in theory, non-quoted tts might be useful + p.quote_depth += 1us; //but in theory, non-quoted tts might be useful let res = token::NtTT(P(p.parse_token_tree())); - p.quote_depth -= 1u; + p.quote_depth -= 1us; return res; } _ => {} diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 270df72eb0e4..8350e0222ef8 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -8,8 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use ast::{TokenTree, TtDelimited, TtSequence, TtToken}; -use ast; +use ast::{self, TokenTree, TtDelimited, TtSequence, TtToken}; use codemap::{Span, DUMMY_SP}; use ext::base::{ExtCtxt, MacResult, SyntaxExtension}; use ext::base::{NormalTT, TTMacroExpander}; @@ -19,9 +18,8 @@ use ext::tt::macro_parser::{parse, parse_or_else}; use parse::lexer::{new_tt_reader, new_tt_reader_with_doc_flag}; use parse::parser::Parser; use parse::attr::ParserAttr; -use parse::token::{special_idents, gensym_ident, NtTT, Token}; +use parse::token::{self, special_idents, gensym_ident, NtTT, Token}; use parse::token::Token::*; -use parse::token; use print; use ptr::P; @@ -336,16 +334,20 @@ fn check_matcher<'a, I>(cx: &mut ExtCtxt, matcher: I, follow: &Token) let tok = if let TtToken(_, ref tok) = *token { tok } else { unreachable!() }; // If T' is in the set FOLLOW(NT), continue. Else, reject. - match &next_token { - &Eof => return Some((sp, tok.clone())), - _ if is_in_follow(cx, &next_token, frag_spec.as_str()) => continue, - next => { + match (&next_token, is_in_follow(cx, &next_token, frag_spec.as_str())) { + (&Eof, _) => return Some((sp, tok.clone())), + (_, Ok(true)) => continue, + (next, Ok(false)) => { cx.span_err(sp, format!("`${0}:{1}` is followed by `{2}`, which \ is not allowed for `{1}` fragments", name.as_str(), frag_spec.as_str(), token_to_string(next)).as_slice()); continue }, + (_, Err(msg)) => { + cx.span_err(sp, msg.as_slice()); + continue + } } }, TtSequence(sp, ref seq) => { @@ -412,51 +414,50 @@ fn check_matcher<'a, I>(cx: &mut ExtCtxt, matcher: I, follow: &Token) last } -fn is_in_follow(cx: &ExtCtxt, tok: &Token, frag: &str) -> bool { +fn is_in_follow(_: &ExtCtxt, tok: &Token, frag: &str) -> Result { if let &CloseDelim(_) = tok { - return true; - } - - match frag { - "item" => { - // since items *must* be followed by either a `;` or a `}`, we can - // accept anything after them - true - }, - "block" => { - // anything can follow block, the braces provide a easy boundary to - // maintain - true - }, - "stmt" | "expr" => { - match *tok { - FatArrow | Comma | Semi => true, - _ => false - } - }, - "pat" => { - match *tok { - FatArrow | Comma | Eq => true, - _ => false - } - }, - "path" | "ty" => { - match *tok { - Comma | FatArrow | Colon | Eq | Gt => true, - Ident(i, _) if i.as_str() == "as" => true, - _ => false - } - }, - "ident" => { - // being a single token, idents are harmless - true - }, - "meta" | "tt" => { - // being either a single token or a delimited sequence, tt is - // harmless - true - }, - _ => cx.bug(format!("unrecognized builtin nonterminal {}", - frag).as_slice()), + Ok(true) + } else { + match frag { + "item" => { + // since items *must* be followed by either a `;` or a `}`, we can + // accept anything after them + Ok(true) + }, + "block" => { + // anything can follow block, the braces provide a easy boundary to + // maintain + Ok(true) + }, + "stmt" | "expr" => { + match *tok { + FatArrow | Comma | Semi => Ok(true), + _ => Ok(false) + } + }, + "pat" => { + match *tok { + FatArrow | Comma | Eq => Ok(true), + _ => Ok(false) + } + }, + "path" | "ty" => { + match *tok { + Comma | FatArrow | Colon | Eq | Gt => Ok(true), + Ident(i, _) if i.as_str() == "as" => Ok(true), + _ => Ok(false) + } + }, + "ident" => { + // being a single token, idents are harmless + Ok(true) + }, + "meta" | "tt" => { + // being either a single token or a delimited sequence, tt is + // harmless + Ok(true) + }, + _ => Err(format!("unrecognized builtin nonterminal `{}`", frag)) + } } } diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index 94b8356130ae..0bf20b8f3e15 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -27,7 +27,7 @@ use std::collections::HashMap; #[derive(Clone)] struct TtFrame { forest: TokenTree, - idx: uint, + idx: usize, dotdotdoted: bool, sep: Option, } @@ -43,8 +43,8 @@ pub struct TtReader<'a> { // Some => return imported_from as the next token crate_name_next: Option, - repeat_idx: Vec, - repeat_len: Vec, + repeat_idx: Vec, + repeat_len: Vec, /* cached: */ pub cur_tok: Token, pub cur_span: Span, @@ -124,7 +124,7 @@ fn lookup_cur_matched(r: &TtReader, name: Ident) -> Option> { #[derive(Clone)] enum LockstepIterSize { LisUnconstrained, - LisConstraint(uint, Ident), + LisConstraint(usize, Ident), LisContradiction(String), } @@ -223,7 +223,7 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan { r.repeat_len.pop(); } } else { /* repeat */ - *r.repeat_idx.last_mut().unwrap() += 1u; + *r.repeat_idx.last_mut().unwrap() += 1us; r.stack.last_mut().unwrap().idx = 0; match r.stack.last().unwrap().sep.clone() { Some(tk) => { diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 989126cd8d64..e6046fb50dd3 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -73,7 +73,7 @@ static KNOWN_FEATURES: &'static [(&'static str, &'static str, Status)] = &[ ("rustc_diagnostic_macros", "1.0.0", Active), ("unboxed_closures", "1.0.0", Active), - ("import_shadowing", "1.0.0", Active), + ("import_shadowing", "1.0.0", Removed), ("advanced_slice_patterns", "1.0.0", Active), ("tuple_indexing", "1.0.0", Accepted), ("associated_types", "1.0.0", Accepted), @@ -138,7 +138,6 @@ enum Status { pub struct Features { pub unboxed_closures: bool, pub rustc_diagnostic_macros: bool, - pub import_shadowing: bool, pub visible_private_types: bool, pub quote: bool, pub old_orphan_check: bool, @@ -151,7 +150,6 @@ impl Features { Features { unboxed_closures: false, rustc_diagnostic_macros: false, - import_shadowing: false, visible_private_types: false, quote: false, old_orphan_check: false, @@ -249,22 +247,6 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { } } - fn visit_view_item(&mut self, i: &ast::ViewItem) { - match i.node { - ast::ViewItemUse(..) => {} - ast::ViewItemExternCrate(..) => { - for attr in i.attrs.iter() { - if attr.check_name("plugin") { - self.gate_feature("plugin", attr.span, - "compiler plugins are experimental \ - and possibly buggy"); - } - } - } - } - visit::walk_view_item(self, i) - } - fn visit_item(&mut self, i: &ast::Item) { for attr in i.attrs.iter() { if attr.name() == "thread_local" { @@ -283,6 +265,14 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { } } match i.node { + ast::ItemExternCrate(_) => { + if attr::contains_name(&i.attrs[], "plugin") { + self.gate_feature("plugin", i.span, + "compiler plugins are experimental \ + and possibly buggy"); + } + } + ast::ItemForeignMod(ref foreign_module) => { if attr::contains_name(&i.attrs[], "link_args") { self.gate_feature("link_args", i.span, @@ -563,7 +553,6 @@ fn check_crate_inner(cm: &CodeMap, span_handler: &SpanHandler, krate: &ast::C Features { unboxed_closures: cx.has_feature("unboxed_closures"), rustc_diagnostic_macros: cx.has_feature("rustc_diagnostic_macros"), - import_shadowing: cx.has_feature("import_shadowing"), visible_private_types: cx.has_feature("visible_private_types"), quote: cx.has_feature("quote"), old_orphan_check: cx.has_feature("old_orphan_check"), diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index f484650ad5b0..9f8427cc8aed 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -78,10 +78,6 @@ pub trait Folder : Sized { noop_fold_view_path(view_path, self) } - fn fold_view_item(&mut self, vi: ViewItem) -> ViewItem { - noop_fold_view_item(vi, self) - } - fn fold_foreign_item(&mut self, ni: P) -> P { noop_fold_foreign_item(ni, self) } @@ -174,8 +170,8 @@ pub trait Folder : Sized { noop_fold_ident(i, self) } - fn fold_uint(&mut self, i: uint) -> uint { - noop_fold_uint(i, self) + fn fold_usize(&mut self, i: usize) -> usize { + noop_fold_usize(i, self) } fn fold_path(&mut self, p: Path) -> Path { @@ -349,16 +345,13 @@ pub fn noop_fold_meta_items(meta_items: Vec>, fld: &mut T pub fn noop_fold_view_path(view_path: P, fld: &mut T) -> P { view_path.map(|Spanned {node, span}| Spanned { node: match node { - ViewPathSimple(ident, path, node_id) => { - let id = fld.new_id(node_id); - ViewPathSimple(ident, fld.fold_path(path), id) + ViewPathSimple(ident, path) => { + ViewPathSimple(ident, fld.fold_path(path)) } - ViewPathGlob(path, node_id) => { - let id = fld.new_id(node_id); - ViewPathGlob(fld.fold_path(path), id) + ViewPathGlob(path) => { + ViewPathGlob(fld.fold_path(path)) } - ViewPathList(path, path_list_idents, node_id) => { - let id = fld.new_id(node_id); + ViewPathList(path, path_list_idents) => { ViewPathList(fld.fold_path(path), path_list_idents.move_map(|path_list_ident| { Spanned { @@ -373,8 +366,7 @@ pub fn noop_fold_view_path(view_path: P, fld: &mut T) -> P< }, span: fld.new_span(path_list_ident.span) } - }), - id) + })) } }, span: fld.new_span(span) @@ -470,11 +462,10 @@ pub fn noop_fold_qpath(qpath: P, fld: &mut T) -> P { }) } -pub fn noop_fold_foreign_mod(ForeignMod {abi, view_items, items}: ForeignMod, +pub fn noop_fold_foreign_mod(ForeignMod {abi, items}: ForeignMod, fld: &mut T) -> ForeignMod { ForeignMod { abi: abi, - view_items: view_items.move_map(|x| fld.fold_view_item(x)), items: items.move_map(|x| fld.fold_foreign_item(x)), } } @@ -505,7 +496,7 @@ pub fn noop_fold_ident(i: Ident, _: &mut T) -> Ident { i } -pub fn noop_fold_uint(i: uint, _: &mut T) -> uint { +pub fn noop_fold_usize(i: usize, _: &mut T) -> usize { i } @@ -953,28 +944,9 @@ fn noop_fold_variant_arg(VariantArg {id, ty}: VariantArg, folder: &mu } } -pub fn noop_fold_view_item(ViewItem {node, attrs, vis, span}: ViewItem, - folder: &mut T) -> ViewItem { - ViewItem { - node: match node { - ViewItemExternCrate(ident, string, node_id) => { - ViewItemExternCrate(ident, string, - folder.new_id(node_id)) - } - ViewItemUse(view_path) => { - ViewItemUse(folder.fold_view_path(view_path)) - } - }, - attrs: attrs.move_map(|a| folder.fold_attribute(a)), - vis: vis, - span: folder.new_span(span) - } -} - pub fn noop_fold_block(b: P, folder: &mut T) -> P { - b.map(|Block {id, view_items, stmts, expr, rules, span}| Block { + b.map(|Block {id, stmts, expr, rules, span}| Block { id: folder.new_id(id), - view_items: view_items.move_map(|x| folder.fold_view_item(x)), stmts: stmts.into_iter().flat_map(|s| folder.fold_stmt(s).into_iter()).collect(), expr: expr.map(|x| folder.fold_expr(x)), rules: rules, @@ -984,6 +956,10 @@ pub fn noop_fold_block(b: P, folder: &mut T) -> P { pub fn noop_fold_item_underscore(i: Item_, folder: &mut T) -> Item_ { match i { + ItemExternCrate(string) => ItemExternCrate(string), + ItemUse(view_path) => { + ItemUse(folder.fold_view_path(view_path)) + } ItemStatic(t, m, e) => { ItemStatic(folder.fold_ty(t), m, folder.fold_expr(e)) } @@ -1103,10 +1079,9 @@ pub fn noop_fold_type_method(m: TypeMethod, fld: &mut T) -> TypeMetho } } -pub fn noop_fold_mod(Mod {inner, view_items, items}: Mod, folder: &mut T) -> Mod { +pub fn noop_fold_mod(Mod {inner, items}: Mod, folder: &mut T) -> Mod { Mod { inner: folder.new_span(inner), - view_items: view_items.move_map(|x| folder.fold_view_item(x)), items: items.into_iter().flat_map(|x| folder.fold_item(x).into_iter()).collect(), } } @@ -1137,9 +1112,8 @@ pub fn noop_fold_crate(Crate {module, attrs, config, mut exported_mac } None => (ast::Mod { inner: span, - view_items: Vec::new(), - items: Vec::new(), - }, Vec::new(), span) + items: vec![], + }, vec![], span) }; for def in exported_macros.iter_mut() { @@ -1371,7 +1345,7 @@ pub fn noop_fold_expr(Expr {id, node, span}: Expr, folder: &mut T) -> } ExprTupField(el, ident) => { ExprTupField(folder.fold_expr(el), - respan(ident.span, folder.fold_uint(ident.node))) + respan(ident.span, folder.fold_usize(ident.node))) } ExprIndex(el, er) => { ExprIndex(folder.fold_expr(el), folder.fold_expr(er)) diff --git a/src/libsyntax/owned_slice.rs b/src/libsyntax/owned_slice.rs index 707e540a17bf..872354024e93 100644 --- a/src/libsyntax/owned_slice.rs +++ b/src/libsyntax/owned_slice.rs @@ -22,7 +22,7 @@ pub struct OwnedSlice { data: Box<[T]> } -impl fmt::Show for OwnedSlice { +impl fmt::Debug for OwnedSlice { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { self.data.fmt(fmt) } diff --git a/src/libsyntax/parse/lexer/comments.rs b/src/libsyntax/parse/lexer/comments.rs index 16ade904be88..c58136b30aa1 100644 --- a/src/libsyntax/parse/lexer/comments.rs +++ b/src/libsyntax/parse/lexer/comments.rs @@ -22,7 +22,7 @@ use print::pprust; use std::io; use std::str; use std::string::String; -use std::uint; +use std::usize; #[derive(Clone, Copy, PartialEq)] pub enum CommentStyle { @@ -62,7 +62,7 @@ pub fn doc_comment_style(comment: &str) -> ast::AttrStyle { pub fn strip_doc_comment_decoration(comment: &str) -> String { /// remove whitespace-only lines from the start/end of lines fn vertical_trim(lines: Vec ) -> Vec { - let mut i = 0u; + let mut i = 0us; let mut j = lines.len(); // first line of all-stars should be omitted if lines.len() > 0 && @@ -87,7 +87,7 @@ pub fn strip_doc_comment_decoration(comment: &str) -> String { /// remove a "[ \t]*\*" block from each line, if possible fn horizontal_trim(lines: Vec ) -> Vec { - let mut i = uint::MAX; + let mut i = usize::MAX; let mut can_trim = true; let mut first = true; for line in lines.iter() { @@ -116,7 +116,7 @@ pub fn strip_doc_comment_decoration(comment: &str) -> String { if can_trim { lines.iter().map(|line| { - (&line[(i + 1)..line.len()]).to_string() + (&line[i + 1..line.len()]).to_string() }).collect() } else { lines @@ -132,7 +132,7 @@ pub fn strip_doc_comment_decoration(comment: &str) -> String { } if comment.starts_with("/*") { - let lines = comment[3u..(comment.len() - 2u)] + let lines = comment[3..comment.len() - 2] .lines_any() .map(|s| s.to_string()) .collect:: >(); @@ -158,7 +158,7 @@ fn push_blank_line_comment(rdr: &StringReader, comments: &mut Vec) { fn consume_whitespace_counting_blank_lines(rdr: &mut StringReader, comments: &mut Vec) { while is_whitespace(rdr.curr) && !rdr.is_eof() { - if rdr.col == CharPos(0u) && rdr.curr_is('\n') { + if rdr.col == CharPos(0us) && rdr.curr_is('\n') { push_blank_line_comment(rdr, &mut *comments); } rdr.bump(); @@ -206,10 +206,10 @@ fn read_line_comments(rdr: &mut StringReader, code_to_the_left: bool, /// Returns None if the first col chars of s contain a non-whitespace char. /// Otherwise returns Some(k) where k is first char offset after that leading /// whitespace. Note k may be outside bounds of s. -fn all_whitespace(s: &str, col: CharPos) -> Option { +fn all_whitespace(s: &str, col: CharPos) -> Option { let len = s.len(); - let mut col = col.to_uint(); - let mut cursor: uint = 0; + let mut col = col.to_usize(); + let mut cursor: usize = 0; while col > 0 && cursor < len { let r: str::CharRange = s.char_range_at(cursor); if !r.ch.is_whitespace() { @@ -267,7 +267,7 @@ fn read_block_comment(rdr: &mut StringReader, assert!(!curr_line.contains_char('\n')); lines.push(curr_line); } else { - let mut level: int = 1; + let mut level: isize = 1; while level > 0 { debug!("=== block comment level {}", level); if rdr.is_eof() { @@ -305,7 +305,7 @@ fn read_block_comment(rdr: &mut StringReader, let mut style = if code_to_the_left { Trailing } else { Isolated }; rdr.consume_non_eol_whitespace(); - if !rdr.is_eof() && !rdr.curr_is('\n') && lines.len() == 1u { + if !rdr.is_eof() && !rdr.curr_is('\n') && lines.len() == 1us { style = Mixed; } debug!("<<< block comment"); @@ -399,9 +399,9 @@ mod test { } #[test] fn test_block_doc_comment_3() { - let comment = "/**\n let a: *int;\n *a = 5;\n*/"; + let comment = "/**\n let a: *i32;\n *a = 5;\n*/"; let stripped = strip_doc_comment_decoration(comment); - assert_eq!(stripped, " let a: *int;\n *a = 5;"); + assert_eq!(stripped, " let a: *i32;\n *a = 5;"); } #[test] fn test_block_doc_comment_4() { diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index 4cdafb36eecc..3b9dcf530098 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -212,8 +212,8 @@ impl<'a> StringReader<'a> { /// offending string to the error message fn fatal_span_verbose(&self, from_pos: BytePos, to_pos: BytePos, mut m: String) -> ! { m.push_str(": "); - let from = self.byte_offset(from_pos).to_uint(); - let to = self.byte_offset(to_pos).to_uint(); + let from = self.byte_offset(from_pos).to_usize(); + let to = self.byte_offset(to_pos).to_usize(); m.push_str(&self.filemap.src[from..to]); self.fatal_span_(from_pos, to_pos, &m[]); } @@ -271,15 +271,15 @@ impl<'a> StringReader<'a> { fn with_str_from_to(&self, start: BytePos, end: BytePos, f: F) -> T where F: FnOnce(&str) -> T, { - f(self.filemap.src.slice( - self.byte_offset(start).to_uint(), - self.byte_offset(end).to_uint())) + f(&self.filemap.src[ + self.byte_offset(start).to_usize().. + self.byte_offset(end).to_usize()]) } /// Converts CRLF to LF in the given string, raising an error on bare CR. fn translate_crlf<'b>(&self, start: BytePos, s: &'b str, errmsg: &'b str) -> CowString<'b> { - let mut i = 0u; + let mut i = 0us; while i < s.len() { let str::CharRange { ch, next } = s.char_range_at(i); if ch == '\r' { @@ -295,7 +295,7 @@ impl<'a> StringReader<'a> { return s.into_cow(); fn translate_crlf_(rdr: &StringReader, start: BytePos, - s: &str, errmsg: &str, mut i: uint) -> String { + s: &str, errmsg: &str, mut i: usize) -> String { let mut buf = String::with_capacity(s.len()); let mut j = 0; while i < s.len() { @@ -321,7 +321,7 @@ impl<'a> StringReader<'a> { /// discovered, add it to the FileMap's list of line start offsets. pub fn bump(&mut self) { self.last_pos = self.pos; - let current_byte_offset = self.byte_offset(self.pos).to_uint(); + let current_byte_offset = self.byte_offset(self.pos).to_usize(); if current_byte_offset < self.filemap.src.len() { assert!(self.curr.is_some()); let last_char = self.curr.unwrap(); @@ -329,12 +329,12 @@ impl<'a> StringReader<'a> { .src .char_range_at(current_byte_offset); let byte_offset_diff = next.next - current_byte_offset; - self.pos = self.pos + Pos::from_uint(byte_offset_diff); + self.pos = self.pos + Pos::from_usize(byte_offset_diff); self.curr = Some(next.ch); - self.col = self.col + CharPos(1u); + self.col = self.col + CharPos(1us); if last_char == '\n' { self.filemap.next_line(self.last_pos); - self.col = CharPos(0u); + self.col = CharPos(0us); } if byte_offset_diff > 1 { @@ -346,7 +346,7 @@ impl<'a> StringReader<'a> { } pub fn nextch(&self) -> Option { - let offset = self.byte_offset(self.pos).to_uint(); + let offset = self.byte_offset(self.pos).to_usize(); if offset < self.filemap.src.len() { Some(self.filemap.src.char_at(offset)) } else { @@ -359,7 +359,7 @@ impl<'a> StringReader<'a> { } pub fn nextnextch(&self) -> Option { - let offset = self.byte_offset(self.pos).to_uint(); + let offset = self.byte_offset(self.pos).to_usize(); let s = self.filemap.src.as_slice(); if offset >= s.len() { return None } let str::CharRange { next, .. } = s.char_range_at(offset); @@ -472,7 +472,7 @@ impl<'a> StringReader<'a> { cmap.files.borrow_mut().push(self.filemap.clone()); let loc = cmap.lookup_char_pos_adj(self.last_pos); debug!("Skipping a shebang"); - if loc.line == 1u && loc.col == CharPos(0u) { + if loc.line == 1us && loc.col == CharPos(0us) { // FIXME: Add shebang "token", return it let start = self.last_pos; while !self.curr_is('\n') && !self.is_eof() { self.bump(); } @@ -519,7 +519,7 @@ impl<'a> StringReader<'a> { let is_doc_comment = self.curr_is('*') || self.curr_is('!'); let start_bpos = self.last_pos - BytePos(2); - let mut level: int = 1; + let mut level: isize = 1; let mut has_cr = false; while level > 0 { if self.is_eof() { @@ -586,10 +586,10 @@ impl<'a> StringReader<'a> { /// `\x00` marker. #[inline(never)] fn scan_embedded_hygienic_ident(&mut self) -> ast::Ident { - fn bump_expecting_char<'a,D:fmt::Show>(r: &mut StringReader<'a>, - c: char, - described_c: D, - whence: &str) { + fn bump_expecting_char<'a,D:fmt::Debug>(r: &mut StringReader<'a>, + c: char, + described_c: D, + whence: &str) { match r.curr { Some(r_c) if r_c == c => r.bump(), Some(r_c) => panic!("expected {:?}, hit {:?}, {}", described_c, r_c, whence), @@ -645,8 +645,8 @@ impl<'a> StringReader<'a> { /// Scan through any digits (base `radix`) or underscores, and return how /// many digits there were. - fn scan_digits(&mut self, radix: uint) -> uint { - let mut len = 0u; + fn scan_digits(&mut self, radix: usize) -> usize { + let mut len = 0us; loop { let c = self.curr; if c == Some('_') { debug!("skipping a _"); self.bump(); continue; } @@ -724,7 +724,7 @@ impl<'a> StringReader<'a> { /// Scan over `n_digits` hex digits, stopping at `delim`, reporting an /// error if too many or too few digits are encountered. fn scan_hex_digits(&mut self, - n_digits: uint, + n_digits: usize, delim: char, below_0x7f_only: bool) -> bool { @@ -799,14 +799,14 @@ impl<'a> StringReader<'a> { if self.curr == Some('{') { self.scan_unicode_escape(delim) } else { - let res = self.scan_hex_digits(4u, delim, false); + let res = self.scan_hex_digits(4us, delim, false); let sp = codemap::mk_sp(escaped_pos, self.last_pos); self.old_escape_warning(sp); res } } 'U' if !ascii_only => { - let res = self.scan_hex_digits(8u, delim, false); + let res = self.scan_hex_digits(8us, delim, false); let sp = codemap::mk_sp(escaped_pos, self.last_pos); self.old_escape_warning(sp); res @@ -877,7 +877,7 @@ impl<'a> StringReader<'a> { fn scan_unicode_escape(&mut self, delim: char) -> bool { self.bump(); // past the { let start_bpos = self.last_pos; - let mut count: uint = 0; + let mut count = 0us; let mut accum_int = 0; while !self.curr_is('}') && count <= 6 { @@ -935,13 +935,13 @@ impl<'a> StringReader<'a> { /// Check that a base is valid for a floating literal, emitting a nice /// error if it isn't. - fn check_float_base(&mut self, start_bpos: BytePos, last_bpos: BytePos, base: uint) { + fn check_float_base(&mut self, start_bpos: BytePos, last_bpos: BytePos, base: usize) { match base { - 16u => self.err_span_(start_bpos, last_bpos, "hexadecimal float literal is not \ - supported"), - 8u => self.err_span_(start_bpos, last_bpos, "octal float literal is not supported"), - 2u => self.err_span_(start_bpos, last_bpos, "binary float literal is not supported"), - _ => () + 16us => self.err_span_(start_bpos, last_bpos, "hexadecimal float literal is not \ + supported"), + 8us => self.err_span_(start_bpos, last_bpos, "octal float literal is not supported"), + 2us => self.err_span_(start_bpos, last_bpos, "binary float literal is not supported"), + _ => () } } @@ -1189,7 +1189,7 @@ impl<'a> StringReader<'a> { 'r' => { let start_bpos = self.last_pos; self.bump(); - let mut hash_count = 0u; + let mut hash_count = 0us; while self.curr_is('#') { self.bump(); hash_count += 1; @@ -1374,7 +1374,7 @@ impl<'a> StringReader<'a> { fn scan_raw_byte_string(&mut self) -> token::Lit { let start_bpos = self.last_pos; self.bump(); - let mut hash_count = 0u; + let mut hash_count = 0us; while self.curr_is('#') { self.bump(); hash_count += 1; @@ -1616,9 +1616,9 @@ mod test { test!("1.0", Float, "1.0"); test!("1.0e10", Float, "1.0e10"); - assert_eq!(setup(&mk_sh(), "2u".to_string()).next_token().tok, + assert_eq!(setup(&mk_sh(), "2us".to_string()).next_token().tok, token::Literal(token::Integer(token::intern("2")), - Some(token::intern("u")))); + Some(token::intern("us")))); assert_eq!(setup(&mk_sh(), "r###\"raw\"###suffix".to_string()).next_token().tok, token::Literal(token::StrRaw(token::intern("raw"), 3), Some(token::intern("suffix")))); diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index dd376fe9e10e..8cb7ee5b3374 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -181,7 +181,7 @@ pub fn parse_tts_from_source_str(name: String, name, source ); - p.quote_depth += 1u; + p.quote_depth += 1us; // right now this is re-creating the token trees from ... token trees. maybe_aborted(p.parse_all_token_trees(),p) } @@ -324,7 +324,7 @@ pub mod with_hygiene { name, source ); - p.quote_depth += 1u; + p.quote_depth += 1us; // right now this is re-creating the token trees from ... token trees. maybe_aborted(p.parse_all_token_trees(),p) } @@ -364,7 +364,7 @@ pub mod with_hygiene { } /// Abort if necessary -pub fn maybe_aborted(result: T, mut p: Parser) -> T { +pub fn maybe_aborted(result: T, p: Parser) -> T { p.abort_if_errors(); result } @@ -373,7 +373,7 @@ pub fn maybe_aborted(result: T, mut p: Parser) -> T { /// Rather than just accepting/rejecting a given literal, unescapes it as /// well. Can take any slice prefixed by a character escape. Returns the /// character and the number of characters consumed. -pub fn char_lit(lit: &str) -> (char, int) { +pub fn char_lit(lit: &str) -> (char, isize) { use std::{num, char}; let mut chars = lit.chars(); @@ -400,19 +400,19 @@ pub fn char_lit(lit: &str) -> (char, int) { let msg = format!("lexer should have rejected a bad character escape {}", lit); let msg2 = &msg[]; - fn esc(len: uint, lit: &str) -> Option<(char, int)> { + fn esc(len: usize, lit: &str) -> Option<(char, isize)> { num::from_str_radix(&lit[2..len], 16) .and_then(char::from_u32) - .map(|x| (x, len as int)) + .map(|x| (x, len as isize)) } - let unicode_escape = |&: | -> Option<(char, int)> + let unicode_escape = |&: | -> Option<(char, isize)> if lit.as_bytes()[2] == b'{' { let idx = lit.find('}').expect(msg2); let subslice = &lit[3..idx]; num::from_str_radix(subslice, 16) .and_then(char::from_u32) - .map(|x| (x, subslice.chars().count() as int + 4)) + .map(|x| (x, subslice.chars().count() as isize + 4)) } else { esc(6, lit) }; @@ -436,7 +436,7 @@ pub fn str_lit(lit: &str) -> String { let error = |&: i| format!("lexer should have rejected {} at {}", lit, i); /// Eat everything up to a non-whitespace - fn eat<'a>(it: &mut iter::Peekable<(uint, char), str::CharIndices<'a>>) { + fn eat<'a>(it: &mut iter::Peekable<(usize, char), str::CharIndices<'a>>) { loop { match it.peek().map(|x| x.1) { Some(' ') | Some('\n') | Some('\r') | Some('\t') => { @@ -567,13 +567,13 @@ pub fn float_lit(s: &str, suffix: Option<&str>, sd: &SpanHandler, sp: Span) -> a } /// Parse a string representing a byte literal into its final form. Similar to `char_lit` -pub fn byte_lit(lit: &str) -> (u8, uint) { +pub fn byte_lit(lit: &str) -> (u8, usize) { let err = |&: i| format!("lexer accepted invalid byte literal {} step {}", lit, i); if lit.len() == 1 { (lit.as_bytes()[0], 1) } else { - assert!(lit.as_bytes()[0] == b'\\', err(0i)); + assert!(lit.as_bytes()[0] == b'\\', err(0is)); let b = match lit.as_bytes()[1] { b'"' => b'"', b'n' => b'\n', @@ -605,7 +605,7 @@ pub fn binary_lit(lit: &str) -> Rc> { let error = |&: i| format!("lexer should have rejected {} at {}", lit, i); /// Eat everything up to a non-whitespace - fn eat<'a, I: Iterator>(it: &mut iter::Peekable<(uint, u8), I>) { + fn eat<'a, I: Iterator>(it: &mut iter::Peekable<(usize, u8), I>) { loop { match it.peek().map(|x| x.1) { Some(b' ') | Some(b'\n') | Some(b'\r') | Some(b'\t') => { @@ -683,9 +683,9 @@ pub fn integer_lit(s: &str, suffix: Option<&str>, sd: &SpanHandler, sp: Span) -> match suffix { Some(suf) if looks_like_width_suffix(&['f'], suf) => { match base { - 16u => sd.span_err(sp, "hexadecimal float literal is not supported"), - 8u => sd.span_err(sp, "octal float literal is not supported"), - 2u => sd.span_err(sp, "binary float literal is not supported"), + 16us => sd.span_err(sp, "hexadecimal float literal is not supported"), + 8us => sd.span_err(sp, "octal float literal is not supported"), + 2us => sd.span_err(sp, "binary float literal is not supported"), _ => () } let ident = token::intern_and_get_ident(&*s); @@ -757,11 +757,10 @@ mod test { use attr::{first_attr_value_str_by_name, AttrMetaMethods}; use parse::parser::Parser; use parse::token::{str_to_ident}; - use print::pprust::view_item_to_string; + use print::pprust::item_to_string; use ptr::P; use util::parser_testing::{string_to_tts, string_to_parser}; - use util::parser_testing::{string_to_expr, string_to_item}; - use util::parser_testing::{string_to_stmt, string_to_view_item}; + use util::parser_testing::{string_to_expr, string_to_item, string_to_stmt}; // produce a codemap::span fn sp(a: u32, b: u32) -> Span { @@ -854,7 +853,7 @@ mod test { #[test] fn string_to_tts_1 () { - let tts = string_to_tts("fn a (b : int) { b; }".to_string()); + let tts = string_to_tts("fn a (b : i32) { b; }".to_string()); assert_eq!(json::encode(&tts), "[\ {\ @@ -918,7 +917,7 @@ mod test { {\ \"variant\":\"Ident\",\ \"fields\":[\ - \"int\",\ + \"i32\",\ \"Plain\"\ ]\ }\ @@ -1030,8 +1029,8 @@ mod test { // check the contents of the tt manually: #[test] fn parse_fundecl () { - // this test depends on the intern order of "fn" and "int" - assert!(string_to_item("fn a (b : int) { b; }".to_string()) == + // this test depends on the intern order of "fn" and "i32" + assert_eq!(string_to_item("fn a (b : i32) { b; }".to_string()), Some( P(ast::Item{ident:str_to_ident("a"), attrs:Vec::new(), @@ -1045,7 +1044,7 @@ mod test { segments: vec!( ast::PathSegment { identifier: - str_to_ident("int"), + str_to_ident("i32"), parameters: ast::PathParameters::none(), } ), @@ -1079,7 +1078,6 @@ mod test { } }, P(ast::Block { - view_items: Vec::new(), stmts: vec!(P(Spanned{ node: ast::StmtSemi(P(ast::Expr{ id: ast::DUMMY_NODE_ID, @@ -1111,25 +1109,25 @@ mod test { #[test] fn parse_use() { let use_s = "use foo::bar::baz;"; - let vitem = string_to_view_item(use_s.to_string()); - let vitem_s = view_item_to_string(&vitem); + let vitem = string_to_item(use_s.to_string()).unwrap(); + let vitem_s = item_to_string(&*vitem); assert_eq!(&vitem_s[], use_s); let use_s = "use foo::bar as baz;"; - let vitem = string_to_view_item(use_s.to_string()); - let vitem_s = view_item_to_string(&vitem); + let vitem = string_to_item(use_s.to_string()).unwrap(); + let vitem_s = item_to_string(&*vitem); assert_eq!(&vitem_s[], use_s); } #[test] fn parse_extern_crate() { let ex_s = "extern crate foo;"; - let vitem = string_to_view_item(ex_s.to_string()); - let vitem_s = view_item_to_string(&vitem); + let vitem = string_to_item(ex_s.to_string()).unwrap(); + let vitem_s = item_to_string(&*vitem); assert_eq!(&vitem_s[], ex_s); let ex_s = "extern crate \"foo\" as bar;"; - let vitem = string_to_view_item(ex_s.to_string()); - let vitem_s = view_item_to_string(&vitem); + let vitem = string_to_item(ex_s.to_string()).unwrap(); + let vitem_s = item_to_string(&*vitem); assert_eq!(&vitem_s[], ex_s); } @@ -1158,19 +1156,19 @@ mod test { #[test] fn span_of_self_arg_pat_idents_are_correct() { - let srcs = ["impl z { fn a (&self, &myarg: int) {} }", - "impl z { fn a (&mut self, &myarg: int) {} }", - "impl z { fn a (&'a self, &myarg: int) {} }", - "impl z { fn a (self, &myarg: int) {} }", - "impl z { fn a (self: Foo, &myarg: int) {} }", + let srcs = ["impl z { fn a (&self, &myarg: i32) {} }", + "impl z { fn a (&mut self, &myarg: i32) {} }", + "impl z { fn a (&'a self, &myarg: i32) {} }", + "impl z { fn a (self, &myarg: i32) {} }", + "impl z { fn a (self: Foo, &myarg: i32) {} }", ]; for &src in srcs.iter() { let spans = get_spans_of_pat_idents(src); let Span{ lo, hi, .. } = spans[0]; - assert!("self" == &src[lo.to_uint()..hi.to_uint()], + assert!("self" == &src[lo.to_usize()..hi.to_usize()], "\"{}\" != \"self\". src=\"{}\"", - &src[lo.to_uint()..hi.to_uint()], src) + &src[lo.to_usize()..hi.to_usize()], src) } } diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs index 9d03ec73af8b..a3600506057a 100644 --- a/src/libsyntax/parse/obsolete.rs +++ b/src/libsyntax/parse/obsolete.rs @@ -62,7 +62,7 @@ impl<'a> ParserObsoleteMethods for parser::Parser<'a> { "use a `move ||` expression instead", ), ObsoleteSyntax::ClosureType => ( - "`|uint| -> bool` closure type syntax", + "`|usize| -> bool` closure type syntax", "use unboxed closures instead, no type annotation needed" ), ObsoleteSyntax::Sized => ( diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 83a7504bc498..e59dbe52b769 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -9,7 +9,6 @@ // except according to those terms. pub use self::PathParsingMode::*; -use self::ItemOrViewItem::*; use abi; use ast::{AssociatedType, BareFnTy}; @@ -35,6 +34,7 @@ use ast::{ForeignItem, ForeignItemStatic, ForeignItemFn, ForeignMod, FunctionRet use ast::{Ident, Inherited, ImplItem, Item, Item_, ItemStatic}; use ast::{ItemEnum, ItemFn, ItemForeignMod, ItemImpl, ItemConst}; use ast::{ItemMac, ItemMod, ItemStruct, ItemTrait, ItemTy}; +use ast::{ItemExternCrate, ItemUse}; use ast::{LifetimeDef, Lit, Lit_}; use ast::{LitBool, LitChar, LitByte, LitBinary}; use ast::{LitStr, LitInt, Local, LocalLet}; @@ -59,11 +59,10 @@ use ast::{TyParam, TyParamBound, TyParen, TyPath, TyPolyTraitRef, TyPtr, TyQPath use ast::{TyRptr, TyTup, TyU32, TyVec, UnUniq}; use ast::{TypeImplItem, TypeTraitItem, Typedef, UnboxedClosureKind}; use ast::{UnnamedField, UnsafeBlock}; -use ast::{ViewItem, ViewItem_, ViewItemExternCrate, ViewItemUse}; use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple}; use ast::{Visibility, WhereClause}; use ast; -use ast_util::{self, as_prec, ident_to_path, operator_prec}; +use ast_util::{self, AS_PREC, ident_to_path, operator_prec}; use codemap::{self, Span, BytePos, Spanned, spanned, mk_sp}; use diagnostic; use ext::tt::macro_parser; @@ -94,7 +93,6 @@ bitflags! { const RESTRICTION_STMT_EXPR = 0b0001, const RESTRICTION_NO_BAR_OP = 0b0010, const RESTRICTION_NO_STRUCT_LITERAL = 0b0100, - const RESTRICTION_NO_DOTS = 0b1000, } } @@ -122,14 +120,9 @@ pub enum BoundParsingMode { Modified, } -enum ItemOrViewItem { - /// Indicates a failure to parse any kind of item. The attributes are - /// returned. - IoviNone(Vec), - IoviItem(P), - IoviForeignItem(P), - IoviViewItem(ViewItem) -} +/// The `Err` case indicates a failure to parse any kind of item. +/// The attributes are returned. +type MaybeItem = Result, Vec>; /// Possibly accept an `token::Interpolated` expression (a pre-parsed expression @@ -231,19 +224,6 @@ macro_rules! maybe_whole { } } ); - (iovi $p:expr, $constructor:ident) => ( - { - let found = match ($p).token { - token::Interpolated(token::$constructor(_)) => { - Some(($p).bump_and_get()) - } - _ => None - }; - if let Some(token::Interpolated(token::$constructor(x))) = found { - return IoviItem(x.clone()); - } - } - ); (pair_empty $p:expr, $constructor:ident) => ( { let found = match ($p).token { @@ -269,14 +249,6 @@ fn maybe_append(mut lhs: Vec, rhs: Option>) lhs } - -struct ParsedItemsAndViewItems { - attrs_remaining: Vec, - view_items: Vec, - items: Vec> , - foreign_items: Vec> -} - /* ident is handled by common.rs */ pub struct Parser<'a> { @@ -291,11 +263,11 @@ pub struct Parser<'a> { /// the previous token or None (only stashed sometimes). pub last_token: Option>, pub buffer: [TokenAndSpan; 4], - pub buffer_start: int, - pub buffer_end: int, - pub tokens_consumed: uint, + pub buffer_start: isize, + pub buffer_end: isize, + pub tokens_consumed: usize, pub restrictions: Restrictions, - pub quote_depth: uint, // not (yet) related to the quasiquoter + pub quote_depth: usize, // not (yet) related to the quasiquoter pub reader: Box, pub interner: Rc, /// The set of seen errors about obsolete syntax. Used to suppress @@ -382,18 +354,18 @@ impl<'a> Parser<'a> { } /// Convert the current token to a string using self's reader - pub fn this_token_to_string(&mut self) -> String { + pub fn this_token_to_string(&self) -> String { Parser::token_to_string(&self.token) } - pub fn unexpected_last(&mut self, t: &token::Token) -> ! { + pub fn unexpected_last(&self, t: &token::Token) -> ! { let token_str = Parser::token_to_string(t); let last_span = self.last_span; self.span_fatal(last_span, &format!("unexpected token: `{}`", token_str)[]); } - pub fn unexpected(&mut self) -> ! { + pub fn unexpected(&self) -> ! { let this_token = self.this_token_to_string(); self.fatal(&format!("unexpected token: `{}`", this_token)[]); } @@ -660,7 +632,7 @@ impl<'a> Parser<'a> { } } - pub fn expect_no_suffix(&mut self, sp: Span, kind: &str, suffix: Option) { + pub fn expect_no_suffix(&self, sp: Span, kind: &str, suffix: Option) { match suffix { None => {/* everything ok */} Some(suf) => { @@ -768,7 +740,7 @@ impl<'a> Parser<'a> { // would encounter a `>` and stop. This lets the parser handle trailing // commas in generic parameters, because it can stop either after // parsing a type or after parsing a comma. - for i in iter::count(0u, 1) { + for i in iter::count(0us, 1) { if self.check(&token::Gt) || self.token == token::BinOp(token::Shr) || self.token == token::Ge @@ -933,9 +905,9 @@ impl<'a> Parser<'a> { self.reader.real_token() } else { // Avoid token copies with `replace`. - let buffer_start = self.buffer_start as uint; - let next_index = (buffer_start + 1) & 3 as uint; - self.buffer_start = next_index as int; + let buffer_start = self.buffer_start as usize; + let next_index = (buffer_start + 1) & 3 as usize; + self.buffer_start = next_index as isize; let placeholder = TokenAndSpan { tok: token::Underscore, @@ -945,7 +917,7 @@ impl<'a> Parser<'a> { }; self.span = next.sp; self.token = next.tok; - self.tokens_consumed += 1u; + self.tokens_consumed += 1us; self.expected_tokens.clear(); // check after each token self.check_unknown_macro_variable(); @@ -967,55 +939,55 @@ impl<'a> Parser<'a> { self.token = next; self.span = mk_sp(lo, hi); } - pub fn buffer_length(&mut self) -> int { + pub fn buffer_length(&mut self) -> isize { if self.buffer_start <= self.buffer_end { return self.buffer_end - self.buffer_start; } return (4 - self.buffer_start) + self.buffer_end; } - pub fn look_ahead(&mut self, distance: uint, f: F) -> R where + pub fn look_ahead(&mut self, distance: usize, f: F) -> R where F: FnOnce(&token::Token) -> R, { - let dist = distance as int; + let dist = distance as isize; while self.buffer_length() < dist { - self.buffer[self.buffer_end as uint] = self.reader.real_token(); + self.buffer[self.buffer_end as usize] = self.reader.real_token(); self.buffer_end = (self.buffer_end + 1) & 3; } - f(&self.buffer[((self.buffer_start + dist - 1) & 3) as uint].tok) + f(&self.buffer[((self.buffer_start + dist - 1) & 3) as usize].tok) } - pub fn fatal(&mut self, m: &str) -> ! { + pub fn fatal(&self, m: &str) -> ! { self.sess.span_diagnostic.span_fatal(self.span, m) } - pub fn span_fatal(&mut self, sp: Span, m: &str) -> ! { + pub fn span_fatal(&self, sp: Span, m: &str) -> ! { self.sess.span_diagnostic.span_fatal(sp, m) } - pub fn span_fatal_help(&mut self, sp: Span, m: &str, help: &str) -> ! { + pub fn span_fatal_help(&self, sp: Span, m: &str, help: &str) -> ! { self.span_err(sp, m); self.span_help(sp, help); panic!(diagnostic::FatalError); } - pub fn span_note(&mut self, sp: Span, m: &str) { + pub fn span_note(&self, sp: Span, m: &str) { self.sess.span_diagnostic.span_note(sp, m) } - pub fn span_help(&mut self, sp: Span, m: &str) { + pub fn span_help(&self, sp: Span, m: &str) { self.sess.span_diagnostic.span_help(sp, m) } - pub fn bug(&mut self, m: &str) -> ! { + pub fn bug(&self, m: &str) -> ! { self.sess.span_diagnostic.span_bug(self.span, m) } - pub fn warn(&mut self, m: &str) { + pub fn warn(&self, m: &str) { self.sess.span_diagnostic.span_warn(self.span, m) } - pub fn span_warn(&mut self, sp: Span, m: &str) { + pub fn span_warn(&self, sp: Span, m: &str) { self.sess.span_diagnostic.span_warn(sp, m) } - pub fn span_err(&mut self, sp: Span, m: &str) { + pub fn span_err(&self, sp: Span, m: &str) { self.sess.span_diagnostic.span_err(sp, m) } - pub fn span_bug(&mut self, sp: Span, m: &str) -> ! { + pub fn span_bug(&self, sp: Span, m: &str) -> ! { self.sess.span_diagnostic.span_bug(sp, m) } - pub fn abort_if_errors(&mut self) { + pub fn abort_if_errors(&self) { self.sess.span_diagnostic.handler().abort_if_errors(); } @@ -1496,7 +1468,7 @@ impl<'a> Parser<'a> { self.expect(&token::OpenDelim(token::Bracket)); let t = self.parse_ty_sum(); - // Parse the `; e` in `[ int; e ]` + // Parse the `; e` in `[ i32; e ]` // where `e` is a const expression let t = match self.maybe_parse_fixed_length_of_vec() { None => TyVec(t), @@ -1670,7 +1642,7 @@ impl<'a> Parser<'a> { } /// Matches token_lit = LIT_INTEGER | ... - pub fn lit_from_token(&mut self, tok: &token::Token) -> Lit_ { + pub fn lit_from_token(&self, tok: &token::Token) -> Lit_ { match *tok { token::Interpolated(token::NtExpr(ref v)) => { match v.node { @@ -2084,7 +2056,7 @@ impl<'a> Parser<'a> { ExprField(expr, ident) } - pub fn mk_tup_field(&mut self, expr: P, idx: codemap::Spanned) -> ast::Expr_ { + pub fn mk_tup_field(&mut self, expr: P, idx: codemap::Spanned) -> ast::Expr_ { ExprTupField(expr, idx) } @@ -2483,7 +2455,7 @@ impl<'a> Parser<'a> { hi = self.span.hi; self.bump(); - let index = n.as_str().parse::(); + let index = n.as_str().parse::(); match index { Some(n) => { let id = spanned(dot, hi, n); @@ -2509,7 +2481,7 @@ impl<'a> Parser<'a> { }; self.span_help(last_span, &format!("try parenthesizing the first index; e.g., `(foo.{}){}`", - float.trunc() as uint, + float.trunc() as usize, &float.fract().to_string()[1..])[]); } self.abort_if_errors(); @@ -2636,7 +2608,7 @@ impl<'a> Parser<'a> { } pub fn check_unknown_macro_variable(&mut self) { - if self.quote_depth == 0u { + if self.quote_depth == 0us { match self.token { token::SubstNt(name, _) => self.fatal(&format!("unknown macro variable `{}`", @@ -2705,7 +2677,7 @@ impl<'a> Parser<'a> { token_str)[]) }, /* we ought to allow different depths of unquotation */ - token::Dollar | token::SubstNt(..) if p.quote_depth > 0u => { + token::Dollar | token::SubstNt(..) if p.quote_depth > 0us => { p.parse_unquoted() } _ => { @@ -2802,13 +2774,6 @@ impl<'a> Parser<'a> { hi = e.span.hi; ex = ExprAddrOf(m, e); } - token::DotDot if !self.restrictions.contains(RESTRICTION_NO_DOTS) => { - // A range, closed above: `..expr`. - self.bump(); - let e = self.parse_expr(); - hi = e.span.hi; - ex = self.mk_range(None, Some(e)); - } token::Ident(_, _) => { if !self.token.is_keyword(keywords::Box) { return self.parse_dot_or_call_expr(); @@ -2863,7 +2828,7 @@ impl<'a> Parser<'a> { } /// Parse an expression of binops of at least min_prec precedence - pub fn parse_more_binops(&mut self, lhs: P, min_prec: uint) -> P { + pub fn parse_more_binops(&mut self, lhs: P, min_prec: usize) -> P { if self.expr_is_complete(&*lhs) { return lhs; } // Prevent dynamic borrow errors later on by limiting the @@ -2882,10 +2847,10 @@ impl<'a> Parser<'a> { self.check_no_chained_comparison(&*lhs, cur_op) } let cur_prec = operator_prec(cur_op); - if cur_prec > min_prec { + if cur_prec >= min_prec { self.bump(); let expr = self.parse_prefix_expr(); - let rhs = self.parse_more_binops(expr, cur_prec); + let rhs = self.parse_more_binops(expr, cur_prec + 1); let lhs_span = lhs.span; let rhs_span = rhs.span; let binary = self.mk_binary(cur_op, lhs, rhs); @@ -2896,7 +2861,7 @@ impl<'a> Parser<'a> { } } None => { - if as_prec > min_prec && self.eat_keyword(keywords::As) { + if AS_PREC >= min_prec && self.eat_keyword(keywords::As) { let rhs = self.parse_ty(); let _as = self.mk_expr(lhs.span.lo, rhs.span.hi, @@ -2921,7 +2886,7 @@ impl<'a> Parser<'a> { "Chained comparison operators require parentheses"); if op == BiLt && outer_op == BiGt { self.span_help(op_span, - "Use ::< instead of < if you meant to specify type arguments."); + "use ::< instead of < if you meant to specify type arguments"); } } _ => {} @@ -2932,8 +2897,24 @@ impl<'a> Parser<'a> { /// actually, this seems to be the main entry point for /// parsing an arbitrary expression. pub fn parse_assign_expr(&mut self) -> P { - let lhs = self.parse_binops(); - self.parse_assign_expr_with(lhs) + match self.token { + token::DotDot => { + // prefix-form of range notation '..expr' + // This has the same precedence as assignment expressions + // (much lower than other prefix expressions) to be consistent + // with the postfix-form 'expr..' + let lo = self.span.lo; + self.bump(); + let rhs = self.parse_binops(); + let hi = rhs.span.hi; + let ex = self.mk_range(None, Some(rhs)); + self.mk_expr(lo, hi, ex) + } + _ => { + let lhs = self.parse_binops(); + self.parse_assign_expr_with(lhs) + } + } } pub fn parse_assign_expr_with(&mut self, lhs: P) -> P { @@ -2965,11 +2946,11 @@ impl<'a> Parser<'a> { self.mk_expr(span.lo, rhs_span.hi, assign_op) } // A range expression, either `expr..expr` or `expr..`. - token::DotDot if !self.restrictions.contains(RESTRICTION_NO_DOTS) => { + token::DotDot => { self.bump(); - let opt_end = if self.token.can_begin_expr() { - let end = self.parse_expr_res(RESTRICTION_NO_DOTS); + let opt_end = if self.is_at_start_of_range_notation_rhs() { + let end = self.parse_binops(); Some(end) } else { None @@ -2987,6 +2968,18 @@ impl<'a> Parser<'a> { } } + fn is_at_start_of_range_notation_rhs(&self) -> bool { + if self.token.can_begin_expr() { + // parse `for i in 1.. { }` as infinite loop, not as `for i in (1..{})`. + if self.token == token::OpenDelim(token::Brace) { + return !self.restrictions.contains(RESTRICTION_NO_STRUCT_LITERAL); + } + true + } else { + false + } + } + /// Parse an 'if' or 'if let' expression ('if' token already eaten) pub fn parse_if_expr(&mut self) -> P { if self.token.is_keyword(keywords::Let) { @@ -3032,8 +3025,7 @@ impl<'a> Parser<'a> { let body = self.parse_expr(); let fakeblock = P(ast::Block { id: ast::DUMMY_NODE_ID, - view_items: Vec::new(), - stmts: Vec::new(), + stmts: vec![], span: body.span, expr: Some(body), rules: DefaultBlock, @@ -3731,20 +3723,13 @@ impl<'a> Parser<'a> { } else { let found_attrs = !item_attrs.is_empty(); let item_err = Parser::expected_item_err(&item_attrs[]); - match self.parse_item_or_view_item(item_attrs, false) { - IoviItem(i) => { + match self.parse_item_(item_attrs, false) { + Ok(i) => { let hi = i.span.hi; let decl = P(spanned(lo, hi, DeclItem(i))); P(spanned(lo, hi, StmtDecl(decl, ast::DUMMY_NODE_ID))) } - IoviViewItem(vi) => { - self.span_fatal(vi.span, - "view items must be declared at the top of the block"); - } - IoviForeignItem(_) => { - self.fatal("foreign items are not allowed here"); - } - IoviNone(_) => { + Err(_) => { if found_attrs { let last_span = self.last_span; self.span_err(last_span, item_err); @@ -3794,36 +3779,17 @@ impl<'a> Parser<'a> { (inner, self.parse_block_tail_(lo, DefaultBlock, next)) } - /// Precondition: already parsed the '{' or '#{' - /// I guess that also means "already parsed the 'impure'" if - /// necessary, and this should take a qualifier. - /// Some blocks start with "#{"... + /// Precondition: already parsed the '{'. fn parse_block_tail(&mut self, lo: BytePos, s: BlockCheckMode) -> P { self.parse_block_tail_(lo, s, Vec::new()) } /// Parse the rest of a block expression or function body fn parse_block_tail_(&mut self, lo: BytePos, s: BlockCheckMode, - first_item_attrs: Vec ) -> P { - let mut stmts = Vec::new(); + first_item_attrs: Vec) -> P { + let mut stmts = vec![]; let mut expr = None; - - // wouldn't it be more uniform to parse view items only, here? - let ParsedItemsAndViewItems { - attrs_remaining, - view_items, - items, - .. - } = self.parse_items_and_view_items(first_item_attrs, - false, false); - - for item in items.into_iter() { - let span = item.span; - let decl = P(spanned(span.lo, span.hi, DeclItem(item))); - stmts.push(P(spanned(span.lo, span.hi, StmtDecl(decl, ast::DUMMY_NODE_ID)))); - } - - let mut attributes_box = attrs_remaining; + let mut attributes_box = first_item_attrs; while self.token != token::CloseDelim(token::Brace) { // parsing items even when they're not allowed lets us give @@ -3932,7 +3898,6 @@ impl<'a> Parser<'a> { let hi = self.span.hi; self.bump(); P(ast::Block { - view_items: view_items, stmts: stmts, expr: expr, id: ast::DUMMY_NODE_ID, @@ -4795,7 +4760,7 @@ impl<'a> Parser<'a> { Some(attrs)) } - /// Parse a::B + /// Parse a::B fn parse_trait_ref(&mut self) -> TraitRef { ast::TraitRef { path: self.parse_path(LifetimeAndTypesWithoutColons), @@ -4814,7 +4779,7 @@ impl<'a> Parser<'a> { } } - /// Parse for<'l> a::B + /// Parse for<'l> a::B fn parse_poly_trait_ref(&mut self) -> PolyTraitRef { let lifetime_defs = self.parse_late_bound_lifetime_defs(); @@ -5031,39 +4996,34 @@ impl<'a> Parser<'a> { first_item_attrs: Vec, inner_lo: BytePos) -> Mod { - // parse all of the items up to closing or an attribute. - // view items are legal here. - let ParsedItemsAndViewItems { - attrs_remaining, - view_items, - items: starting_items, - .. - } = self.parse_items_and_view_items(first_item_attrs, true, true); - let mut items: Vec> = starting_items; - let attrs_remaining_len = attrs_remaining.len(); + // Parse all of the items up to closing or an attribute. + + let mut attrs = first_item_attrs; + attrs.push_all(&self.parse_outer_attributes()[]); + let mut items = vec![]; + + loop { + match self.parse_item_(attrs, true) { + Err(returned_attrs) => { + attrs = returned_attrs; + break + } + Ok(item) => { + attrs = self.parse_outer_attributes(); + items.push(item) + } + } + } // don't think this other loop is even necessary.... - let mut first = true; while self.token != term { - let mut attrs = self.parse_outer_attributes(); - if first { - let mut tmp = attrs_remaining.clone(); - tmp.push_all(&attrs[]); - attrs = tmp; - first = false; - } - debug!("parse_mod_items: parse_item_or_view_item(attrs={:?})", - attrs); - match self.parse_item_or_view_item(attrs, - true /* macros allowed */) { - IoviItem(item) => items.push(item), - IoviViewItem(view_item) => { - self.span_fatal(view_item.span, - "view items must be declared at the top of \ - the module"); - } - _ => { + let mut attrs = mem::replace(&mut attrs, vec![]); + attrs.push_all(&self.parse_outer_attributes()[]); + debug!("parse_mod_items: parse_item_(attrs={:?})", attrs); + match self.parse_item_(attrs, true /* macros allowed */) { + Ok(item) => items.push(item), + Err(_) => { let token_str = self.this_token_to_string(); self.fatal(&format!("expected item, found `{}`", token_str)[]) @@ -5071,16 +5031,15 @@ impl<'a> Parser<'a> { } } - if first && attrs_remaining_len > 0u { + if !attrs.is_empty() { // We parsed attributes for the first item but didn't find it let last_span = self.last_span; self.span_err(last_span, - Parser::expected_item_err(&attrs_remaining[])); + Parser::expected_item_err(&attrs[])); } ast::Mod { inner: mk_sp(inner_lo, self.span.lo), - view_items: view_items, items: items } } @@ -5223,7 +5182,7 @@ impl<'a> Parser<'a> { Some(i) => { let mut err = String::from_str("circular modules: "); let len = included_mod_stack.len(); - for p in included_mod_stack.slice(i, len).iter() { + for p in included_mod_stack[i.. len].iter() { err.push_str(&p.display().as_cow()[]); err.push_str(" -> "); } @@ -5298,23 +5257,12 @@ impl<'a> Parser<'a> { /// parse_foreign_items. fn parse_foreign_mod_items(&mut self, abi: abi::Abi, - first_item_attrs: Vec ) + first_item_attrs: Vec) -> ForeignMod { - let ParsedItemsAndViewItems { - attrs_remaining, - view_items, - items: _, - foreign_items, - } = self.parse_foreign_items(first_item_attrs, true); - if !attrs_remaining.is_empty() { - let last_span = self.last_span; - self.span_err(last_span, - Parser::expected_item_err(&attrs_remaining[])); - } + let foreign_items = self.parse_foreign_items(first_item_attrs); assert!(self.token == token::CloseDelim(token::Brace)); ast::ForeignMod { abi: abi, - view_items: view_items, items: foreign_items } } @@ -5329,8 +5277,8 @@ impl<'a> Parser<'a> { fn parse_item_extern_crate(&mut self, lo: BytePos, visibility: Visibility, - attrs: Vec ) - -> ItemOrViewItem { + attrs: Vec) + -> P { let span = self.span; let (maybe_path, ident) = match self.token { @@ -5374,12 +5322,13 @@ impl<'a> Parser<'a> { } }; - IoviViewItem(ast::ViewItem { - node: ViewItemExternCrate(ident, maybe_path, ast::DUMMY_NODE_ID), - attrs: attrs, - vis: visibility, - span: mk_sp(lo, self.last_span.hi) - }) + let last_span = self.last_span; + self.mk_item(lo, + last_span.hi, + ident, + ItemExternCrate(maybe_path), + visibility, + attrs) } /// Parse `extern` for foreign ABIs @@ -5396,8 +5345,8 @@ impl<'a> Parser<'a> { lo: BytePos, opt_abi: Option, visibility: Visibility, - attrs: Vec ) - -> ItemOrViewItem { + attrs: Vec) + -> P { self.expect(&token::OpenDelim(token::Brace)); @@ -5408,13 +5357,12 @@ impl<'a> Parser<'a> { self.expect(&token::CloseDelim(token::Brace)); let last_span = self.last_span; - let item = self.mk_item(lo, - last_span.hi, - special_idents::invalid, - ItemForeignMod(m), - visibility, - maybe_append(attrs, Some(inner))); - return IoviItem(item); + self.mk_item(lo, + last_span.hi, + special_idents::invalid, + ItemForeignMod(m), + visibility, + maybe_append(attrs, Some(inner))) } /// Parse type Foo = Bar; @@ -5556,14 +5504,12 @@ impl<'a> Parser<'a> { } } - /// Parse one of the items or view items allowed by the - /// flags; on failure, return IoviNone. + /// Parse one of the items allowed by the flags; on failure, + /// return `Err(remaining_attrs)`. /// NB: this function no longer parses the items inside an /// extern crate. - fn parse_item_or_view_item(&mut self, - attrs: Vec , - macros_allowed: bool) - -> ItemOrViewItem { + fn parse_item_(&mut self, attrs: Vec, + macros_allowed: bool) -> MaybeItem { let nt_item = match self.token { token::Interpolated(token::NtItem(ref item)) => { Some((**item).clone()) @@ -5576,7 +5522,7 @@ impl<'a> Parser<'a> { let mut attrs = attrs; mem::swap(&mut item.attrs, &mut attrs); item.attrs.extend(attrs.into_iter()); - return IoviItem(P(item)); + return Ok(P(item)); } None => {} } @@ -5585,22 +5531,24 @@ impl<'a> Parser<'a> { let visibility = self.parse_visibility(); - // must be a view item: if self.eat_keyword(keywords::Use) { - // USE ITEM (IoviViewItem) - let view_item = self.parse_use(); + // USE ITEM + let item_ = ItemUse(self.parse_view_path()); self.expect(&token::Semi); - return IoviViewItem(ast::ViewItem { - node: view_item, - attrs: attrs, - vis: visibility, - span: mk_sp(lo, self.last_span.hi) - }); + + let last_span = self.last_span; + let item = self.mk_item(lo, + last_span.hi, + token::special_idents::invalid, + item_, + visibility, + attrs); + return Ok(item); } - // either a view item or an item: + if self.eat_keyword(keywords::Extern) { if self.eat_keyword(keywords::Crate) { - return self.parse_item_extern_crate(lo, visibility, attrs); + return Ok(self.parse_item_extern_crate(lo, visibility, attrs)); } let opt_abi = self.parse_opt_abi(); @@ -5617,9 +5565,9 @@ impl<'a> Parser<'a> { item_, visibility, maybe_append(attrs, extra_attrs)); - return IoviItem(item); + return Ok(item); } else if self.check(&token::OpenDelim(token::Brace)) { - return self.parse_item_foreign_mod(lo, opt_abi, visibility, attrs); + return Ok(self.parse_item_foreign_mod(lo, opt_abi, visibility, attrs)); } let span = self.span; @@ -5634,7 +5582,6 @@ impl<'a> Parser<'a> { self.span_err(span, "`virtual` structs have been removed from the language"); } - // the rest are all guaranteed to be items: if self.token.is_keyword(keywords::Static) { // STATIC ITEM self.bump(); @@ -5647,7 +5594,7 @@ impl<'a> Parser<'a> { item_, visibility, maybe_append(attrs, extra_attrs)); - return IoviItem(item); + return Ok(item); } if self.token.is_keyword(keywords::Const) { // CONST ITEM @@ -5665,10 +5612,10 @@ impl<'a> Parser<'a> { item_, visibility, maybe_append(attrs, extra_attrs)); - return IoviItem(item); + return Ok(item); } if self.token.is_keyword(keywords::Unsafe) && - self.look_ahead(1u, |t| t.is_keyword(keywords::Trait)) + self.look_ahead(1us, |t| t.is_keyword(keywords::Trait)) { // UNSAFE TRAIT ITEM self.expect_keyword(keywords::Unsafe); @@ -5682,10 +5629,10 @@ impl<'a> Parser<'a> { item_, visibility, maybe_append(attrs, extra_attrs)); - return IoviItem(item); + return Ok(item); } if self.token.is_keyword(keywords::Unsafe) && - self.look_ahead(1u, |t| t.is_keyword(keywords::Impl)) + self.look_ahead(1us, |t| t.is_keyword(keywords::Impl)) { // IMPL ITEM self.expect_keyword(keywords::Unsafe); @@ -5698,7 +5645,7 @@ impl<'a> Parser<'a> { item_, visibility, maybe_append(attrs, extra_attrs)); - return IoviItem(item); + return Ok(item); } if self.token.is_keyword(keywords::Fn) { // FUNCTION ITEM @@ -5712,10 +5659,10 @@ impl<'a> Parser<'a> { item_, visibility, maybe_append(attrs, extra_attrs)); - return IoviItem(item); + return Ok(item); } if self.token.is_keyword(keywords::Unsafe) - && self.look_ahead(1u, |t| *t != token::OpenDelim(token::Brace)) { + && self.look_ahead(1us, |t| *t != token::OpenDelim(token::Brace)) { // UNSAFE FUNCTION ITEM self.bump(); let abi = if self.eat_keyword(keywords::Extern) { @@ -5733,7 +5680,7 @@ impl<'a> Parser<'a> { item_, visibility, maybe_append(attrs, extra_attrs)); - return IoviItem(item); + return Ok(item); } if self.eat_keyword(keywords::Mod) { // MODULE ITEM @@ -5746,7 +5693,7 @@ impl<'a> Parser<'a> { item_, visibility, maybe_append(attrs, extra_attrs)); - return IoviItem(item); + return Ok(item); } if self.eat_keyword(keywords::Type) { // TYPE ITEM @@ -5758,7 +5705,7 @@ impl<'a> Parser<'a> { item_, visibility, maybe_append(attrs, extra_attrs)); - return IoviItem(item); + return Ok(item); } if self.eat_keyword(keywords::Enum) { // ENUM ITEM @@ -5770,7 +5717,7 @@ impl<'a> Parser<'a> { item_, visibility, maybe_append(attrs, extra_attrs)); - return IoviItem(item); + return Ok(item); } if self.eat_keyword(keywords::Trait) { // TRAIT ITEM @@ -5783,7 +5730,7 @@ impl<'a> Parser<'a> { item_, visibility, maybe_append(attrs, extra_attrs)); - return IoviItem(item); + return Ok(item); } if self.eat_keyword(keywords::Impl) { // IMPL ITEM @@ -5795,7 +5742,7 @@ impl<'a> Parser<'a> { item_, visibility, maybe_append(attrs, extra_attrs)); - return IoviItem(item); + return Ok(item); } if self.eat_keyword(keywords::Struct) { // STRUCT ITEM @@ -5807,32 +5754,30 @@ impl<'a> Parser<'a> { item_, visibility, maybe_append(attrs, extra_attrs)); - return IoviItem(item); + return Ok(item); } self.parse_macro_use_or_failure(attrs,macros_allowed,lo,visibility) } - /// Parse a foreign item; on failure, return IoviNone. - fn parse_foreign_item(&mut self, - attrs: Vec , - macros_allowed: bool) - -> ItemOrViewItem { - maybe_whole!(iovi self, NtItem); + /// Parse a foreign item; on failure, return `Err(remaining_attrs)`. + fn parse_foreign_item(&mut self, attrs: Vec) + -> Result, Vec> { let lo = self.span.lo; let visibility = self.parse_visibility(); if self.token.is_keyword(keywords::Static) { // FOREIGN STATIC ITEM - let item = self.parse_item_foreign_static(visibility, attrs); - return IoviForeignItem(item); + return Ok(self.parse_item_foreign_static(visibility, attrs)); } if self.token.is_keyword(keywords::Fn) || self.token.is_keyword(keywords::Unsafe) { // FOREIGN FUNCTION ITEM - let item = self.parse_item_foreign_fn(visibility, attrs); - return IoviForeignItem(item); + return Ok(self.parse_item_foreign_fn(visibility, attrs)); } - self.parse_macro_use_or_failure(attrs,macros_allowed,lo,visibility) + + // FIXME #5668: this will occur for a macro invocation: + let item = try!(self.parse_macro_use_or_failure(attrs, true, lo, visibility)); + self.span_fatal(item.span, "macros cannot expand to foreign items"); } /// This is the fall-through for parsing items. @@ -5842,7 +5787,7 @@ impl<'a> Parser<'a> { macros_allowed: bool, lo: BytePos, visibility: Visibility - ) -> ItemOrViewItem { + ) -> MaybeItem { if macros_allowed && !self.token.is_any_keyword() && self.look_ahead(1, |t| *t == token::Not) && (self.look_ahead(2, |t| t.is_plain_ident()) @@ -5891,7 +5836,7 @@ impl<'a> Parser<'a> { item_, visibility, attrs); - return IoviItem(item); + return Ok(item); } // FAILURE TO PARSE ITEM @@ -5902,7 +5847,7 @@ impl<'a> Parser<'a> { self.span_fatal(last_span, "unmatched visibility `pub`"); } } - return IoviNone(attrs); + Err(attrs) } pub fn parse_item_with_outer_attributes(&mut self) -> Option> { @@ -5911,30 +5856,9 @@ impl<'a> Parser<'a> { } pub fn parse_item(&mut self, attrs: Vec) -> Option> { - match self.parse_item_or_view_item(attrs, true) { - IoviNone(_) => None, - IoviViewItem(_) => - self.fatal("view items are not allowed here"), - IoviForeignItem(_) => - self.fatal("foreign items are not allowed here"), - IoviItem(item) => Some(item) - } + self.parse_item_(attrs, true).ok() } - /// Parse a ViewItem, e.g. `use foo::bar` or `extern crate foo` - pub fn parse_view_item(&mut self, attrs: Vec) -> ViewItem { - match self.parse_item_or_view_item(attrs, false) { - IoviViewItem(vi) => vi, - _ => self.fatal("expected `use` or `extern crate`"), - } - } - - /// Parse, e.g., "use a::b::{z,y}" - fn parse_use(&mut self) -> ViewItem_ { - return ViewItemUse(self.parse_view_path()); - } - - /// Matches view_path : MOD? non_global_path as IDENT /// | MOD? non_global_path MOD_SEP LBRACE RBRACE /// | MOD? non_global_path MOD_SEP LBRACE ident_seq RBRACE @@ -5959,8 +5883,7 @@ impl<'a> Parser<'a> { global: false, segments: Vec::new() }; - return P(spanned(lo, self.span.hi, - ViewPathList(path, idents, ast::DUMMY_NODE_ID))); + return P(spanned(lo, self.span.hi, ViewPathList(path, idents))); } let first_ident = self.parse_ident(); @@ -5994,8 +5917,7 @@ impl<'a> Parser<'a> { } }).collect() }; - return P(spanned(lo, self.span.hi, - ViewPathList(path, idents, ast::DUMMY_NODE_ID))); + return P(spanned(lo, self.span.hi, ViewPathList(path, idents))); } // foo::bar::* @@ -6011,15 +5933,14 @@ impl<'a> Parser<'a> { } }).collect() }; - return P(spanned(lo, self.span.hi, - ViewPathGlob(path, ast::DUMMY_NODE_ID))); + return P(spanned(lo, self.span.hi, ViewPathGlob(path))); } _ => break } } } - let mut rename_to = path[path.len() - 1u]; + let mut rename_to = path[path.len() - 1us]; let path = ast::Path { span: mk_sp(lo, self.last_span.hi), global: false, @@ -6033,136 +5954,39 @@ impl<'a> Parser<'a> { if self.eat_keyword(keywords::As) { rename_to = self.parse_ident() } - P(spanned(lo, - self.last_span.hi, - ViewPathSimple(rename_to, path, ast::DUMMY_NODE_ID))) - } - - /// Parses a sequence of items. Stops when it finds program - /// text that can't be parsed as an item - /// - mod_items uses extern_mod_allowed = true - /// - block_tail_ uses extern_mod_allowed = false - fn parse_items_and_view_items(&mut self, - first_item_attrs: Vec , - mut extern_mod_allowed: bool, - macros_allowed: bool) - -> ParsedItemsAndViewItems { - let mut attrs = first_item_attrs; - attrs.push_all(&self.parse_outer_attributes()[]); - // First, parse view items. - let mut view_items : Vec = Vec::new(); - let mut items = Vec::new(); - - // I think this code would probably read better as a single - // loop with a mutable three-state-variable (for extern crates, - // view items, and regular items) ... except that because - // of macros, I'd like to delay that entire check until later. - loop { - match self.parse_item_or_view_item(attrs, macros_allowed) { - IoviNone(attrs) => { - return ParsedItemsAndViewItems { - attrs_remaining: attrs, - view_items: view_items, - items: items, - foreign_items: Vec::new() - } - } - IoviViewItem(view_item) => { - match view_item.node { - ViewItemUse(..) => { - // `extern crate` must precede `use`. - extern_mod_allowed = false; - } - ViewItemExternCrate(..) if !extern_mod_allowed => { - self.span_err(view_item.span, - "\"extern crate\" declarations are \ - not allowed here"); - } - ViewItemExternCrate(..) => {} - } - view_items.push(view_item); - } - IoviItem(item) => { - items.push(item); - attrs = self.parse_outer_attributes(); - break; - } - IoviForeignItem(_) => { - panic!(); - } - } - attrs = self.parse_outer_attributes(); - } - - // Next, parse items. - loop { - match self.parse_item_or_view_item(attrs, macros_allowed) { - IoviNone(returned_attrs) => { - attrs = returned_attrs; - break - } - IoviViewItem(view_item) => { - attrs = self.parse_outer_attributes(); - self.span_err(view_item.span, - "`use` and `extern crate` declarations must precede items"); - } - IoviItem(item) => { - attrs = self.parse_outer_attributes(); - items.push(item) - } - IoviForeignItem(_) => { - panic!(); - } - } - } - - ParsedItemsAndViewItems { - attrs_remaining: attrs, - view_items: view_items, - items: items, - foreign_items: Vec::new() - } + P(spanned(lo, self.last_span.hi, ViewPathSimple(rename_to, path))) } /// Parses a sequence of foreign items. Stops when it finds program /// text that can't be parsed as an item - fn parse_foreign_items(&mut self, first_item_attrs: Vec , - macros_allowed: bool) - -> ParsedItemsAndViewItems { + fn parse_foreign_items(&mut self, first_item_attrs: Vec) + -> Vec> { let mut attrs = first_item_attrs; attrs.push_all(&self.parse_outer_attributes()[]); let mut foreign_items = Vec::new(); loop { - match self.parse_foreign_item(attrs, macros_allowed) { - IoviNone(returned_attrs) => { + match self.parse_foreign_item(attrs) { + Ok(foreign_item) => { + foreign_items.push(foreign_item); + } + Err(returned_attrs) => { if self.check(&token::CloseDelim(token::Brace)) { attrs = returned_attrs; break } self.unexpected(); - }, - IoviViewItem(view_item) => { - // I think this can't occur: - self.span_err(view_item.span, - "`use` and `extern crate` declarations must precede items"); - } - IoviItem(item) => { - // FIXME #5668: this will occur for a macro invocation: - self.span_fatal(item.span, "macros cannot expand to foreign items"); - } - IoviForeignItem(foreign_item) => { - foreign_items.push(foreign_item); } } attrs = self.parse_outer_attributes(); } - ParsedItemsAndViewItems { - attrs_remaining: attrs, - view_items: Vec::new(), - items: Vec::new(), - foreign_items: foreign_items + if !attrs.is_empty() { + let last_span = self.last_span; + self.span_err(last_span, + Parser::expected_item_err(&attrs[])); } + + foreign_items } /// Parses a source module as a crate. This is the main diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index e5aef12e8279..a129fd19d940 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -83,9 +83,9 @@ pub enum Lit { Integer(ast::Name), Float(ast::Name), Str_(ast::Name), - StrRaw(ast::Name, uint), /* raw str delimited by n hash symbols */ + StrRaw(ast::Name, usize), /* raw str delimited by n hash symbols */ Binary(ast::Name), - BinaryRaw(ast::Name, uint), /* raw binary str delimited by n hash symbols */ + BinaryRaw(ast::Name, usize), /* raw binary str delimited by n hash symbols */ } impl Lit { @@ -375,7 +375,7 @@ pub enum Nonterminal { NtTT(P), // needs P'ed to break a circularity } -impl fmt::Show for Nonterminal { +impl fmt::Debug for Nonterminal { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { NtItem(..) => f.pad("NtItem(..)"), @@ -651,15 +651,15 @@ impl BytesContainer for InternedString { } } -impl fmt::Show for InternedString { +impl fmt::Debug for InternedString { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::String::fmt(self, f) + fmt::Debug::fmt(&self.string[], f) } } -impl fmt::String for InternedString { +impl fmt::Display for InternedString { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", &self.string[]) + fmt::Display::fmt(&self.string[], f) } } @@ -724,7 +724,7 @@ pub fn intern(s: &str) -> ast::Name { get_ident_interner().intern(s) } -/// gensym's a new uint, using the current interner. +/// gensym's a new usize, using the current interner. #[inline] pub fn gensym(s: &str) -> ast::Name { get_ident_interner().gensym(s) @@ -757,7 +757,7 @@ pub fn fresh_name(src: &ast::Ident) -> ast::Name { // create a fresh mark. pub fn fresh_mark() -> ast::Mrk { - gensym("mark").uint() as u32 + gensym("mark").usize() as u32 } #[cfg(test)] diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs index 06d510d37bd3..0b1bd2829410 100644 --- a/src/libsyntax/print/pp.rs +++ b/src/libsyntax/print/pp.rs @@ -31,7 +31,7 @@ //! //! In particular you'll see a certain amount of churn related to INTEGER vs. //! CARDINAL in the Mesa implementation. Mesa apparently interconverts the two -//! somewhat readily? In any case, I've used uint for indices-in-buffers and +//! somewhat readily? In any case, I've used usize for indices-in-buffers and //! ints for character-sizes-and-indentation-offsets. This respects the need //! for ints to "go negative" while carrying a pending-calculation balance, and //! helps differentiate all the numbers flying around internally (slightly). @@ -71,19 +71,19 @@ pub enum Breaks { #[derive(Clone, Copy)] pub struct BreakToken { - offset: int, - blank_space: int + offset: isize, + blank_space: isize } #[derive(Clone, Copy)] pub struct BeginToken { - offset: int, + offset: isize, breaks: Breaks } #[derive(Clone)] pub enum Token { - String(String, int), + String(String, isize), Break(BreakToken), Begin(BeginToken), End, @@ -122,25 +122,25 @@ pub fn tok_str(token: &Token) -> String { } pub fn buf_str(toks: &[Token], - szs: &[int], - left: uint, - right: uint, - lim: uint) + szs: &[isize], + left: usize, + right: usize, + lim: usize) -> String { let n = toks.len(); assert_eq!(n, szs.len()); let mut i = left; let mut l = lim; let mut s = string::String::from_str("["); - while i != right && l != 0u { - l -= 1u; + while i != right && l != 0us { + l -= 1us; if i != left { s.push_str(", "); } s.push_str(&format!("{}={}", szs[i], tok_str(&toks[i]))[]); - i += 1u; + i += 1us; i %= n; } s.push(']'); @@ -155,25 +155,25 @@ pub enum PrintStackBreak { #[derive(Copy)] pub struct PrintStackElem { - offset: int, + offset: isize, pbreak: PrintStackBreak } -static SIZE_INFINITY: int = 0xffff; +static SIZE_INFINITY: isize = 0xffff; -pub fn mk_printer(out: Box, linewidth: uint) -> Printer { +pub fn mk_printer(out: Box, linewidth: usize) -> Printer { // Yes 3, it makes the ring buffers big enough to never // fall behind. - let n: uint = 3 * linewidth; + let n: usize = 3 * linewidth; debug!("mk_printer {}", linewidth); let token: Vec = repeat(Token::Eof).take(n).collect(); - let size: Vec = repeat(0i).take(n).collect(); - let scan_stack: Vec = repeat(0u).take(n).collect(); + let size: Vec = repeat(0is).take(n).collect(); + let scan_stack: Vec = repeat(0us).take(n).collect(); Printer { out: out, buf_len: n, - margin: linewidth as int, - space: linewidth as int, + margin: linewidth as isize, + space: linewidth as isize, left: 0, right: 0, token: token, @@ -267,40 +267,40 @@ pub fn mk_printer(out: Box, linewidth: uint) -> Printer { /// called 'print'. pub struct Printer { pub out: Box, - buf_len: uint, + buf_len: usize, /// Width of lines we're constrained to - margin: int, + margin: isize, /// Number of spaces left on line - space: int, + space: isize, /// Index of left side of input stream - left: uint, + left: usize, /// Index of right side of input stream - right: uint, + right: usize, /// Ring-buffer stream goes through token: Vec , /// Ring-buffer of calculated sizes - size: Vec , + size: Vec , /// Running size of stream "...left" - left_total: int, + left_total: isize, /// Running size of stream "...right" - right_total: int, + right_total: isize, /// Pseudo-stack, really a ring too. Holds the /// primary-ring-buffers index of the Begin that started the /// current block, possibly with the most recent Break after that /// Begin (if there is any) on top of it. Stuff is flushed off the /// bottom as it becomes irrelevant due to the primary ring-buffer /// advancing. - scan_stack: Vec , + scan_stack: Vec , /// Top==bottom disambiguator scan_stack_empty: bool, /// Index of top of scan_stack - top: uint, + top: usize, /// Index of bottom of scan_stack - bottom: uint, + bottom: usize, /// Stack of blocks-in-progress being flushed by print print_stack: Vec , /// Buffered indentation to avoid writing trailing whitespace - pending_indentation: int, + pending_indentation: isize, } impl Printer { @@ -326,8 +326,8 @@ impl Printer { if self.scan_stack_empty { self.left_total = 1; self.right_total = 1; - self.left = 0u; - self.right = 0u; + self.left = 0us; + self.right = 0us; } else { self.advance_right(); } debug!("pp Begin({})/buffer ~[{},{}]", b.offset, self.left, self.right); @@ -355,8 +355,8 @@ impl Printer { if self.scan_stack_empty { self.left_total = 1; self.right_total = 1; - self.left = 0u; - self.right = 0u; + self.left = 0us; + self.right = 0us; } else { self.advance_right(); } debug!("pp Break({})/buffer ~[{},{}]", b.offset, self.left, self.right); @@ -405,43 +405,43 @@ impl Printer { } Ok(()) } - pub fn scan_push(&mut self, x: uint) { + pub fn scan_push(&mut self, x: usize) { debug!("scan_push {}", x); if self.scan_stack_empty { self.scan_stack_empty = false; } else { - self.top += 1u; + self.top += 1us; self.top %= self.buf_len; assert!((self.top != self.bottom)); } self.scan_stack[self.top] = x; } - pub fn scan_pop(&mut self) -> uint { + pub fn scan_pop(&mut self) -> usize { assert!((!self.scan_stack_empty)); let x = self.scan_stack[self.top]; if self.top == self.bottom { self.scan_stack_empty = true; } else { - self.top += self.buf_len - 1u; self.top %= self.buf_len; + self.top += self.buf_len - 1us; self.top %= self.buf_len; } return x; } - pub fn scan_top(&mut self) -> uint { + pub fn scan_top(&mut self) -> usize { assert!((!self.scan_stack_empty)); return self.scan_stack[self.top]; } - pub fn scan_pop_bottom(&mut self) -> uint { + pub fn scan_pop_bottom(&mut self) -> usize { assert!((!self.scan_stack_empty)); let x = self.scan_stack[self.bottom]; if self.top == self.bottom { self.scan_stack_empty = true; } else { - self.bottom += 1u; self.bottom %= self.buf_len; + self.bottom += 1us; self.bottom %= self.buf_len; } return x; } pub fn advance_right(&mut self) { - self.right += 1u; + self.right += 1us; self.right %= self.buf_len; assert!((self.right != self.left)); } @@ -471,7 +471,7 @@ impl Printer { break; } - self.left += 1u; + self.left += 1us; self.left %= self.buf_len; left_size = self.size[self.left]; @@ -479,7 +479,7 @@ impl Printer { Ok(()) } - pub fn check_stack(&mut self, k: int) { + pub fn check_stack(&mut self, k: isize) { if !self.scan_stack_empty { let x = self.scan_top(); match self.token[x] { @@ -506,21 +506,21 @@ impl Printer { } } } - pub fn print_newline(&mut self, amount: int) -> io::IoResult<()> { + pub fn print_newline(&mut self, amount: isize) -> io::IoResult<()> { debug!("NEWLINE {}", amount); let ret = write!(self.out, "\n"); self.pending_indentation = 0; self.indent(amount); return ret; } - pub fn indent(&mut self, amount: int) { + pub fn indent(&mut self, amount: isize) { debug!("INDENT {}", amount); self.pending_indentation += amount; } pub fn get_top(&mut self) -> PrintStackElem { let print_stack = &mut self.print_stack; let n = print_stack.len(); - if n != 0u { + if n != 0us { (*print_stack)[n - 1] } else { PrintStackElem { @@ -536,7 +536,7 @@ impl Printer { } write!(self.out, "{}", s) } - pub fn print(&mut self, token: Token, l: int) -> io::IoResult<()> { + pub fn print(&mut self, token: Token, l: isize) -> io::IoResult<()> { debug!("print {} {} (remaining line space={})", tok_str(&token), l, self.space); debug!("{}", buf_str(&self.token[], @@ -565,7 +565,7 @@ impl Printer { Token::End => { debug!("print End -> pop End"); let print_stack = &mut self.print_stack; - assert!((print_stack.len() != 0u)); + assert!((print_stack.len() != 0us)); print_stack.pop().unwrap(); Ok(()) } @@ -620,25 +620,25 @@ impl Printer { // Convenience functions to talk to the printer. // // "raw box" -pub fn rbox(p: &mut Printer, indent: uint, b: Breaks) -> io::IoResult<()> { +pub fn rbox(p: &mut Printer, indent: usize, b: Breaks) -> io::IoResult<()> { p.pretty_print(Token::Begin(BeginToken { - offset: indent as int, + offset: indent as isize, breaks: b })) } -pub fn ibox(p: &mut Printer, indent: uint) -> io::IoResult<()> { +pub fn ibox(p: &mut Printer, indent: usize) -> io::IoResult<()> { rbox(p, indent, Breaks::Inconsistent) } -pub fn cbox(p: &mut Printer, indent: uint) -> io::IoResult<()> { +pub fn cbox(p: &mut Printer, indent: usize) -> io::IoResult<()> { rbox(p, indent, Breaks::Consistent) } -pub fn break_offset(p: &mut Printer, n: uint, off: int) -> io::IoResult<()> { +pub fn break_offset(p: &mut Printer, n: usize, off: isize) -> io::IoResult<()> { p.pretty_print(Token::Break(BreakToken { offset: off, - blank_space: n as int + blank_space: n as isize })) } @@ -651,7 +651,7 @@ pub fn eof(p: &mut Printer) -> io::IoResult<()> { } pub fn word(p: &mut Printer, wrd: &str) -> io::IoResult<()> { - p.pretty_print(Token::String(/* bad */ wrd.to_string(), wrd.len() as int)) + p.pretty_print(Token::String(/* bad */ wrd.to_string(), wrd.len() as isize)) } pub fn huge_word(p: &mut Printer, wrd: &str) -> io::IoResult<()> { @@ -662,23 +662,23 @@ pub fn zero_word(p: &mut Printer, wrd: &str) -> io::IoResult<()> { p.pretty_print(Token::String(/* bad */ wrd.to_string(), 0)) } -pub fn spaces(p: &mut Printer, n: uint) -> io::IoResult<()> { +pub fn spaces(p: &mut Printer, n: usize) -> io::IoResult<()> { break_offset(p, n, 0) } pub fn zerobreak(p: &mut Printer) -> io::IoResult<()> { - spaces(p, 0u) + spaces(p, 0us) } pub fn space(p: &mut Printer) -> io::IoResult<()> { - spaces(p, 1u) + spaces(p, 1us) } pub fn hardbreak(p: &mut Printer) -> io::IoResult<()> { - spaces(p, SIZE_INFINITY as uint) + spaces(p, SIZE_INFINITY as usize) } -pub fn hardbreak_tok_offset(off: int) -> Token { +pub fn hardbreak_tok_offset(off: isize) -> Token { Token::Break(BreakToken {offset: off, blank_space: SIZE_INFINITY}) } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index b59e770c6ba5..d1cd7631c82d 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -54,8 +54,8 @@ impl PpAnn for NoAnn {} #[derive(Copy)] pub struct CurrentCommentAndLiteral { - cur_cmnt: uint, - cur_lit: uint, + cur_cmnt: usize, + cur_lit: usize, } pub struct State<'a> { @@ -92,10 +92,10 @@ pub fn rust_printer_annotated<'a>(writer: Box, } #[allow(non_upper_case_globals)] -pub const indent_unit: uint = 4u; +pub const indent_unit: usize = 4us; #[allow(non_upper_case_globals)] -pub const default_columns: uint = 78u; +pub const default_columns: usize = 78us; /// Requires you to pass an input filename and reader so that /// it can scan the input text for comments and literals to @@ -337,10 +337,6 @@ pub fn item_to_string(i: &ast::Item) -> String { $to_string(|s| s.print_item(i)) } -pub fn view_item_to_string(i: &ast::ViewItem) -> String { - $to_string(|s| s.print_view_item(i)) -} - pub fn generics_to_string(generics: &ast::Generics) -> String { $to_string(|s| s.print_generics(generics)) } @@ -381,7 +377,7 @@ pub fn block_to_string(blk: &ast::Block) -> String { // containing cbox, will be closed by print-block at } try!(s.cbox(indent_unit)); // head-ibox, will be closed by print-block after { - try!(s.ibox(0u)); + try!(s.ibox(0us)); s.print_block(blk) }) } @@ -459,7 +455,7 @@ fn needs_parentheses(expr: &ast::Expr) -> bool { } impl<'a> State<'a> { - pub fn ibox(&mut self, u: uint) -> IoResult<()> { + pub fn ibox(&mut self, u: usize) -> IoResult<()> { self.boxes.push(pp::Breaks::Inconsistent); pp::ibox(&mut self.s, u) } @@ -469,13 +465,13 @@ impl<'a> State<'a> { pp::end(&mut self.s) } - pub fn cbox(&mut self, u: uint) -> IoResult<()> { + pub fn cbox(&mut self, u: usize) -> IoResult<()> { self.boxes.push(pp::Breaks::Consistent); pp::cbox(&mut self.s, u) } // "raw box" - pub fn rbox(&mut self, u: uint, b: pp::Breaks) -> IoResult<()> { + pub fn rbox(&mut self, u: usize, b: pp::Breaks) -> IoResult<()> { self.boxes.push(b); pp::rbox(&mut self.s, u, b) } @@ -514,13 +510,13 @@ impl<'a> State<'a> { } pub fn bclose_(&mut self, span: codemap::Span, - indented: uint) -> IoResult<()> { + indented: usize) -> IoResult<()> { self.bclose_maybe_open(span, indented, true) } pub fn bclose_maybe_open (&mut self, span: codemap::Span, - indented: uint, close_box: bool) -> IoResult<()> { + indented: usize, close_box: bool) -> IoResult<()> { try!(self.maybe_print_comment(span.hi)); - try!(self.break_offset_if_not_bol(1u, -(indented as int))); + try!(self.break_offset_if_not_bol(1us, -(indented as isize))); try!(word(&mut self.s, "}")); if close_box { try!(self.end()); // close the outer-box @@ -567,8 +563,8 @@ impl<'a> State<'a> { if !self.is_bol() { try!(space(&mut self.s)); } Ok(()) } - pub fn break_offset_if_not_bol(&mut self, n: uint, - off: int) -> IoResult<()> { + pub fn break_offset_if_not_bol(&mut self, n: usize, + off: isize) -> IoResult<()> { if !self.is_bol() { break_offset(&mut self.s, n, off) } else { @@ -595,7 +591,7 @@ impl<'a> State<'a> { pub fn commasep(&mut self, b: Breaks, elts: &[T], mut op: F) -> IoResult<()> where F: FnMut(&mut State, &T) -> IoResult<()>, { - try!(self.rbox(0u, b)); + try!(self.rbox(0us, b)); let mut first = true; for elt in elts.iter() { if first { first = false; } else { try!(self.word_space(",")); } @@ -613,13 +609,13 @@ impl<'a> State<'a> { F: FnMut(&mut State, &T) -> IoResult<()>, G: FnMut(&T) -> codemap::Span, { - try!(self.rbox(0u, b)); + try!(self.rbox(0us, b)); let len = elts.len(); - let mut i = 0u; + let mut i = 0us; for elt in elts.iter() { try!(self.maybe_print_comment(get_span(elt).hi)); try!(op(self, elt)); - i += 1u; + i += 1us; if i < len { try!(word(&mut self.s, ",")); try!(self.maybe_print_trailing_comment(get_span(elt), @@ -638,9 +634,6 @@ impl<'a> State<'a> { pub fn print_mod(&mut self, _mod: &ast::Mod, attrs: &[ast::Attribute]) -> IoResult<()> { try!(self.print_inner_attributes(attrs)); - for vitem in _mod.view_items.iter() { - try!(self.print_view_item(vitem)); - } for item in _mod.items.iter() { try!(self.print_item(&**item)); } @@ -650,9 +643,6 @@ impl<'a> State<'a> { pub fn print_foreign_mod(&mut self, nmod: &ast::ForeignMod, attrs: &[ast::Attribute]) -> IoResult<()> { try!(self.print_inner_attributes(attrs)); - for vitem in nmod.view_items.iter() { - try!(self.print_view_item(vitem)); - } for item in nmod.items.iter() { try!(self.print_foreign_item(&**item)); } @@ -670,7 +660,7 @@ impl<'a> State<'a> { pub fn print_type(&mut self, ty: &ast::Ty) -> IoResult<()> { try!(self.maybe_print_comment(ty.span.lo)); - try!(self.ibox(0u)); + try!(self.ibox(0us)); match ty.node { ast::TyVec(ref ty) => { try!(word(&mut self.s, "[")); @@ -809,6 +799,28 @@ impl<'a> State<'a> { try!(self.print_outer_attributes(&item.attrs[])); try!(self.ann.pre(self, NodeItem(item))); match item.node { + ast::ItemExternCrate(ref optional_path) => { + try!(self.head(&visibility_qualified(item.vis, + "extern crate")[])); + for &(ref p, style) in optional_path.iter() { + try!(self.print_string(p.get(), style)); + try!(space(&mut self.s)); + try!(word(&mut self.s, "as")); + try!(space(&mut self.s)); + } + try!(self.print_ident(item.ident)); + try!(word(&mut self.s, ";")); + try!(self.end()); // end inner head-block + try!(self.end()); // end outer head-block + } + ast::ItemUse(ref vp) => { + try!(self.head(&visibility_qualified(item.vis, + "use")[])); + try!(self.print_view_path(&**vp)); + try!(word(&mut self.s, ";")); + try!(self.end()); // end inner head-block + try!(self.end()); // end outer head-block + } ast::ItemStatic(ref ty, m, ref expr) => { try!(self.head(&visibility_qualified(item.vis, "static")[])); @@ -871,7 +883,7 @@ impl<'a> State<'a> { } ast::ItemTy(ref ty, ref params) => { try!(self.ibox(indent_unit)); - try!(self.ibox(0u)); + try!(self.ibox(0us)); try!(self.word_nbsp(&visibility_qualified(item.vis, "type")[])); try!(self.print_ident(item.ident)); try!(self.print_generics(params)); @@ -1152,11 +1164,20 @@ impl<'a> State<'a> { pub fn print_tts(&mut self, tts: &[ast::TokenTree]) -> IoResult<()> { try!(self.ibox(0)); + let mut suppress_space = false; for (i, tt) in tts.iter().enumerate() { - if i != 0 { + if i != 0 && !suppress_space { try!(space(&mut self.s)); } try!(self.print_tt(tt)); + // There should be no space between the module name and the following `::` in paths, + // otherwise imported macros get re-parsed from crate metadata incorrectly (#20701) + suppress_space = match tt { + &ast::TtToken(_, token::Ident(_, token::ModName)) | + &ast::TtToken(_, token::MatchNt(_, _, _, token::ModName)) | + &ast::TtToken(_, token::SubstNt(_, token::ModName)) => true, + _ => false + } } self.end() } @@ -1262,7 +1283,7 @@ impl<'a> State<'a> { pub fn print_outer_attributes(&mut self, attrs: &[ast::Attribute]) -> IoResult<()> { - let mut count = 0u; + let mut count = 0us; for attr in attrs.iter() { match attr.node.style { ast::AttrOuter => { @@ -1280,7 +1301,7 @@ impl<'a> State<'a> { pub fn print_inner_attributes(&mut self, attrs: &[ast::Attribute]) -> IoResult<()> { - let mut count = 0u; + let mut count = 0us; for attr in attrs.iter() { match attr.node.style { ast::AttrInner => { @@ -1355,7 +1376,7 @@ impl<'a> State<'a> { } pub fn print_block_unclosed_indent(&mut self, blk: &ast::Block, - indented: uint) -> IoResult<()> { + indented: usize) -> IoResult<()> { self.print_block_maybe_unclosed(blk, indented, &[], false) } @@ -1367,7 +1388,7 @@ impl<'a> State<'a> { pub fn print_block_maybe_unclosed(&mut self, blk: &ast::Block, - indented: uint, + indented: usize, attrs: &[ast::Attribute], close_box: bool) -> IoResult<()> { match blk.rules { @@ -1380,9 +1401,6 @@ impl<'a> State<'a> { try!(self.print_inner_attributes(attrs)); - for vi in blk.view_items.iter() { - try!(self.print_view_item(vi)); - } for st in blk.stmts.iter() { try!(self.print_stmt(&**st)); } @@ -1404,8 +1422,8 @@ impl<'a> State<'a> { match _else.node { // "another else-if" ast::ExprIf(ref i, ref then, ref e) => { - try!(self.cbox(indent_unit - 1u)); - try!(self.ibox(0u)); + try!(self.cbox(indent_unit - 1us)); + try!(self.ibox(0us)); try!(word(&mut self.s, " else if ")); try!(self.print_expr(&**i)); try!(space(&mut self.s)); @@ -1414,8 +1432,8 @@ impl<'a> State<'a> { } // "another else-if-let" ast::ExprIfLet(ref pat, ref expr, ref then, ref e) => { - try!(self.cbox(indent_unit - 1u)); - try!(self.ibox(0u)); + try!(self.cbox(indent_unit - 1us)); + try!(self.ibox(0us)); try!(word(&mut self.s, " else if let ")); try!(self.print_pat(&**pat)); try!(space(&mut self.s)); @@ -1427,8 +1445,8 @@ impl<'a> State<'a> { } // "final else" ast::ExprBlock(ref b) => { - try!(self.cbox(indent_unit - 1u)); - try!(self.ibox(0u)); + try!(self.cbox(indent_unit - 1us)); + try!(self.ibox(0us)); try!(word(&mut self.s, " else ")); self.print_block(&**b) } @@ -1590,11 +1608,11 @@ impl<'a> State<'a> { ident: ast::SpannedIdent, tys: &[P], args: &[P]) -> IoResult<()> { - let base_args = args.slice_from(1); + let base_args = &args[1..]; try!(self.print_expr(&*args[0])); try!(word(&mut self.s, ".")); try!(self.print_ident(ident.node)); - if tys.len() > 0u { + if tys.len() > 0us { try!(word(&mut self.s, "::<")); try!(self.commasep(Inconsistent, tys, |s, ty| s.print_type(&**ty))); @@ -1765,7 +1783,7 @@ impl<'a> State<'a> { // containing cbox, will be closed by print-block at } try!(self.cbox(indent_unit)); // head-box, will be closed by print-block after { - try!(self.ibox(0u)); + try!(self.ibox(0us)); try!(self.print_block(&**blk)); } ast::ExprAssign(ref lhs, ref rhs) => { @@ -1789,7 +1807,7 @@ impl<'a> State<'a> { ast::ExprTupField(ref expr, id) => { try!(self.print_expr(&**expr)); try!(word(&mut self.s, ".")); - try!(self.print_uint(id.node)); + try!(self.print_usize(id.node)); } ast::ExprIndex(ref expr, ref index) => { try!(self.print_expr(&**expr)); @@ -1951,7 +1969,7 @@ impl<'a> State<'a> { self.ann.post(self, NodeIdent(&ident)) } - pub fn print_uint(&mut self, i: uint) -> IoResult<()> { + pub fn print_usize(&mut self, i: usize) -> IoResult<()> { word(&mut self.s, &i.to_string()[]) } @@ -2142,7 +2160,7 @@ impl<'a> State<'a> { }, |f| f.node.pat.span)); if etc { - if fields.len() != 0u { try!(self.word_space(",")); } + if fields.len() != 0us { try!(self.word_space(",")); } try!(word(&mut self.s, "..")); } try!(space(&mut self.s)); @@ -2209,7 +2227,7 @@ impl<'a> State<'a> { try!(space(&mut self.s)); } try!(self.cbox(indent_unit)); - try!(self.ibox(0u)); + try!(self.ibox(0us)); try!(self.print_outer_attributes(&arm.attrs[])); let mut first = true; for p in arm.pats.iter() { @@ -2295,7 +2313,7 @@ impl<'a> State<'a> { -> IoResult<()> { // It is unfortunate to duplicate the commasep logic, but we want the // self type and the args all in the same box. - try!(self.rbox(0u, Inconsistent)); + try!(self.rbox(0us, Inconsistent)); let mut first = true; for &explicit_self in opt_explicit_self.iter() { let m = match explicit_self { @@ -2312,7 +2330,7 @@ impl<'a> State<'a> { let args = if first { &decl.inputs[] } else { - decl.inputs.slice_from(1) + &decl.inputs[1..] }; for arg in args.iter() { @@ -2470,7 +2488,7 @@ impl<'a> State<'a> { try!(word(&mut self.s, "<")); let mut ints = Vec::new(); - for i in range(0u, total) { + for i in range(0us, total) { ints.push(i); } @@ -2577,7 +2595,7 @@ impl<'a> State<'a> { pub fn print_view_path(&mut self, vp: &ast::ViewPath) -> IoResult<()> { match vp.node { - ast::ViewPathSimple(ident, ref path, _) => { + ast::ViewPathSimple(ident, ref path) => { try!(self.print_path(path, false)); // FIXME(#6993) can't compare identifiers directly here @@ -2591,12 +2609,12 @@ impl<'a> State<'a> { Ok(()) } - ast::ViewPathGlob(ref path, _) => { + ast::ViewPathGlob(ref path) => { try!(self.print_path(path, false)); word(&mut self.s, "::*") } - ast::ViewPathList(ref path, ref idents, _) => { + ast::ViewPathList(ref path, ref idents) => { if path.segments.is_empty() { try!(word(&mut self.s, "{")); } else { @@ -2618,33 +2636,6 @@ impl<'a> State<'a> { } } - pub fn print_view_item(&mut self, item: &ast::ViewItem) -> IoResult<()> { - try!(self.hardbreak_if_not_bol()); - try!(self.maybe_print_comment(item.span.lo)); - try!(self.print_outer_attributes(&item.attrs[])); - try!(self.print_visibility(item.vis)); - match item.node { - ast::ViewItemExternCrate(id, ref optional_path, _) => { - try!(self.head("extern crate")); - for &(ref p, style) in optional_path.iter() { - try!(self.print_string(p.get(), style)); - try!(space(&mut self.s)); - try!(word(&mut self.s, "as")); - try!(space(&mut self.s)); - } - try!(self.print_ident(id)); - } - - ast::ViewItemUse(ref vp) => { - try!(self.head("use")); - try!(self.print_view_path(&**vp)); - } - } - try!(word(&mut self.s, ";")); - try!(self.end()); // end inner head-block - self.end() // end outer head-block - } - pub fn print_mutability(&mut self, mutbl: ast::Mutability) -> IoResult<()> { match mutbl { @@ -2788,7 +2779,7 @@ impl<'a> State<'a> { if span.hi < (*cmnt).pos && (*cmnt).pos < next && span_line.line == comment_line.line { try!(self.print_comment(cmnt)); - self.cur_cmnt_and_lit.cur_cmnt += 1u; + self.cur_cmnt_and_lit.cur_cmnt += 1us; } } _ => () @@ -2806,7 +2797,7 @@ impl<'a> State<'a> { match self.next_comment() { Some(ref cmnt) => { try!(self.print_comment(cmnt)); - self.cur_cmnt_and_lit.cur_cmnt += 1u; + self.cur_cmnt_and_lit.cur_cmnt += 1us; } _ => break } @@ -2888,7 +2879,7 @@ impl<'a> State<'a> { while self.cur_cmnt_and_lit.cur_lit < lits.len() { let ltrl = (*lits)[self.cur_cmnt_and_lit.cur_lit].clone(); if ltrl.pos > pos { return None; } - self.cur_cmnt_and_lit.cur_lit += 1u; + self.cur_cmnt_and_lit.cur_lit += 1us; if ltrl.pos == pos { return Some(ltrl); } } None @@ -2903,7 +2894,7 @@ impl<'a> State<'a> { Some(ref cmnt) => { if (*cmnt).pos < pos { try!(self.print_comment(cmnt)); - self.cur_cmnt_and_lit.cur_cmnt += 1u; + self.cur_cmnt_and_lit.cur_cmnt += 1us; } else { break; } } _ => break @@ -2916,7 +2907,7 @@ impl<'a> State<'a> { cmnt: &comments::Comment) -> IoResult<()> { match cmnt.style { comments::Mixed => { - assert_eq!(cmnt.lines.len(), 1u); + assert_eq!(cmnt.lines.len(), 1us); try!(zerobreak(&mut self.s)); try!(word(&mut self.s, &cmnt.lines[0][])); zerobreak(&mut self.s) @@ -2935,11 +2926,11 @@ impl<'a> State<'a> { } comments::Trailing => { try!(word(&mut self.s, " ")); - if cmnt.lines.len() == 1u { + if cmnt.lines.len() == 1us { try!(word(&mut self.s, &cmnt.lines[0][])); hardbreak(&mut self.s) } else { - try!(self.ibox(0u)); + try!(self.ibox(0us)); for line in cmnt.lines.iter() { if !line.is_empty() { try!(word(&mut self.s, &line[])); @@ -3047,7 +3038,7 @@ impl<'a> State<'a> { } } -fn repeat(s: &str, n: uint) -> String { iter::repeat(s).take(n).collect() } +fn repeat(s: &str, n: usize) -> String { iter::repeat(s).take(n).collect() } #[cfg(test)] mod test { diff --git a/src/libsyntax/ptr.rs b/src/libsyntax/ptr.rs index 37fa8703706e..01f3839b0390 100644 --- a/src/libsyntax/ptr.rs +++ b/src/libsyntax/ptr.rs @@ -36,7 +36,7 @@ //! implementation changes (using a special thread-local heap, for example). //! Moreover, a switch to, e.g. `P<'a, T>` would be easy and mostly automated. -use std::fmt::{self, Show}; +use std::fmt::{self, Display, Debug}; use std::hash::{Hash, Hasher}; use std::ops::Deref; use std::ptr; @@ -100,9 +100,14 @@ impl PartialEq for P { impl Eq for P {} -impl Show for P { +impl Debug for P { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - (**self).fmt(f) + Debug::fmt(&**self, f) + } +} +impl Display for P { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + Display::fmt(&**self, f) } } diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs index 28b9eaa54aab..d75fbcf199db 100644 --- a/src/libsyntax/std_inject.rs +++ b/src/libsyntax/std_inject.rs @@ -20,8 +20,6 @@ use parse::token; use ptr::P; use util::small_vector::SmallVector; -use std::mem; - pub fn maybe_inject_crates_ref(krate: ast::Crate, alt_std_name: Option) -> ast::Crate { if use_std(&krate) { @@ -60,20 +58,16 @@ impl<'a> fold::Folder for StandardLibraryInjector<'a> { None => token::intern_and_get_ident("std"), }; - let mut vis = vec!(ast::ViewItem { - node: ast::ViewItemExternCrate(token::str_to_ident("std"), - Some((actual_crate_name, ast::CookedStr)), - ast::DUMMY_NODE_ID), + krate.module.items.insert(0, P(ast::Item { + id: ast::DUMMY_NODE_ID, + ident: token::str_to_ident("std"), attrs: vec!( attr::mk_attr_outer(attr::mk_attr_id(), attr::mk_word_item( InternedString::new("macro_use")))), + node: ast::ItemExternCrate(Some((actual_crate_name, ast::CookedStr))), vis: ast::Inherited, span: DUMMY_SP - }); - - // `extern crate` must be precede `use` items - mem::swap(&mut vis, &mut krate.module.view_items); - krate.module.view_items.extend(vis.into_iter()); + })); // don't add #![no_std] here, that will block the prelude injection later. // Add it during the prelude injection instead. @@ -123,7 +117,7 @@ impl<'a> fold::Folder for PreludeInjector<'a> { } } - fn fold_mod(&mut self, ast::Mod {inner, view_items, items}: ast::Mod) -> ast::Mod { + fn fold_mod(&mut self, mut mod_: ast::Mod) -> ast::Mod { let prelude_path = ast::Path { span: DUMMY_SP, global: false, @@ -143,18 +137,11 @@ impl<'a> fold::Folder for PreludeInjector<'a> { ], }; - let (crates, uses): (Vec<_>, _) = view_items.iter().cloned().partition(|x| { - match x.node { - ast::ViewItemExternCrate(..) => true, - _ => false, - } - }); - - // add prelude after any `extern crate` but before any `use` - let mut view_items = crates; - let vp = P(codemap::dummy_spanned(ast::ViewPathGlob(prelude_path, ast::DUMMY_NODE_ID))); - view_items.push(ast::ViewItem { - node: ast::ViewItemUse(vp), + let vp = P(codemap::dummy_spanned(ast::ViewPathGlob(prelude_path))); + mod_.items.insert(0, P(ast::Item { + id: ast::DUMMY_NODE_ID, + ident: special_idents::invalid, + node: ast::ItemUse(vp), attrs: vec![ast::Attribute { span: DUMMY_SP, node: ast::Attribute_ { @@ -170,14 +157,9 @@ impl<'a> fold::Folder for PreludeInjector<'a> { }], vis: ast::Inherited, span: DUMMY_SP, - }); - view_items.extend(uses.into_iter()); + })); - fold::noop_fold_mod(ast::Mod { - inner: inner, - view_items: view_items, - items: items - }, self) + fold::noop_fold_mod(mod_, self) } } diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index c7d7b57e66ef..4b6657d67a4b 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -105,11 +105,11 @@ impl<'a> fold::Folder for TestHarnessGenerator<'a> { // Add a special __test module to the crate that will contain code // generated for the test harness let (mod_, reexport) = mk_test_module(&mut self.cx); - folded.module.items.push(mod_); match reexport { - Some(re) => folded.module.view_items.push(re), + Some(re) => folded.module.items.push(re), None => {} } + folded.module.items.push(mod_); folded } @@ -205,22 +205,19 @@ impl<'a> fold::Folder for TestHarnessGenerator<'a> { fn mk_reexport_mod(cx: &mut TestCtxt, tests: Vec, tested_submods: Vec<(ast::Ident, ast::Ident)>) -> (P, ast::Ident) { - let mut view_items = Vec::new(); let super_ = token::str_to_ident("super"); - view_items.extend(tests.into_iter().map(|r| { - cx.ext_cx.view_use_simple(DUMMY_SP, ast::Public, + let items = tests.into_iter().map(|r| { + cx.ext_cx.item_use_simple(DUMMY_SP, ast::Public, cx.ext_cx.path(DUMMY_SP, vec![super_, r])) - })); - view_items.extend(tested_submods.into_iter().map(|(r, sym)| { + }).chain(tested_submods.into_iter().map(|(r, sym)| { let path = cx.ext_cx.path(DUMMY_SP, vec![super_, r, sym]); - cx.ext_cx.view_use_simple_(DUMMY_SP, ast::Public, r, path) + cx.ext_cx.item_use_simple_(DUMMY_SP, ast::Public, r, path) })); let reexport_mod = ast::Mod { inner: DUMMY_SP, - view_items: view_items, - items: Vec::new(), + items: items.collect(), }; let sym = token::gensym_ident("__test_reexports"); @@ -357,8 +354,8 @@ fn is_bench_fn(cx: &TestCtxt, i: &ast::Item) -> bool { let tparm_cnt = generics.ty_params.len(); // NB: inadequate check, but we're running // well before resolve, can't get too deep. - input_cnt == 1u - && no_output && tparm_cnt == 0u + input_cnt == 1us + && no_output && tparm_cnt == 0us } _ => false } @@ -406,24 +403,24 @@ mod __test { */ -fn mk_std(cx: &TestCtxt) -> ast::ViewItem { +fn mk_std(cx: &TestCtxt) -> P { let id_test = token::str_to_ident("test"); - let (vi, vis) = if cx.is_test_crate { - (ast::ViewItemUse( + let (vi, vis, ident) = if cx.is_test_crate { + (ast::ItemUse( P(nospan(ast::ViewPathSimple(id_test, - path_node(vec!(id_test)), - ast::DUMMY_NODE_ID)))), - ast::Public) + path_node(vec!(id_test)))))), + ast::Public, token::special_idents::invalid) } else { - (ast::ViewItemExternCrate(id_test, None, ast::DUMMY_NODE_ID), - ast::Inherited) + (ast::ItemExternCrate(None), ast::Inherited, id_test) }; - ast::ViewItem { + P(ast::Item { + id: ast::DUMMY_NODE_ID, + ident: ident, node: vi, - attrs: Vec::new(), + attrs: vec![], vis: vis, span: DUMMY_SP - } + }) } fn mk_main(cx: &mut TestCtxt) -> P { @@ -450,8 +447,9 @@ fn mk_main(cx: &mut TestCtxt) -> P { token::str_to_ident("args")]); // use std::slice::AsSlice let as_slice_path = P(nospan(ast::ViewPathSimple(token::str_to_ident("AsSlice"), - as_slice_path, ast::DUMMY_NODE_ID))); - let use_as_slice = ecx.view_use(sp, ast::Inherited, as_slice_path); + as_slice_path))); + let use_as_slice = ecx.item_use(sp, ast::Inherited, as_slice_path); + let use_as_slice = ecx.stmt_item(sp, use_as_slice); // ::std::os::args() let os_args_path_expr = ecx.expr_path(os_args_path); let call_os_args = ecx.expr_call(sp, os_args_path_expr, vec![]); @@ -469,7 +467,7 @@ fn mk_main(cx: &mut TestCtxt) -> P { let main_attr = ecx.attribute(sp, main_meta); // pub fn main() { ... } let main_ret_ty = ecx.ty(sp, ast::TyTup(vec![])); - let main_body = ecx.block_all(sp, vec![use_as_slice], vec![call_test_main], None); + let main_body = ecx.block_all(sp, vec![use_as_slice, call_test_main], None); let main = ast::ItemFn(ecx.fn_decl(vec![], main_ret_ty), ast::Unsafety::Normal, ::abi::Rust, empty_generics(), main_body); let main = P(ast::Item { @@ -484,9 +482,9 @@ fn mk_main(cx: &mut TestCtxt) -> P { return main; } -fn mk_test_module(cx: &mut TestCtxt) -> (P, Option) { +fn mk_test_module(cx: &mut TestCtxt) -> (P, Option>) { // Link to test crate - let view_items = vec!(mk_std(cx)); + let import = mk_std(cx); // A constant vector of test descriptors. let tests = mk_tests(cx); @@ -497,40 +495,40 @@ fn mk_test_module(cx: &mut TestCtxt) -> (P, Option) { let testmod = ast::Mod { inner: DUMMY_SP, - view_items: view_items, - items: vec!(mainfn, tests), + items: vec![import, mainfn, tests], }; let item_ = ast::ItemMod(testmod); let mod_ident = token::gensym_ident("__test"); - let item = ast::Item { - ident: mod_ident, + let item = P(ast::Item { id: ast::DUMMY_NODE_ID, + ident: mod_ident, + attrs: vec![], node: item_, vis: ast::Public, span: DUMMY_SP, - attrs: vec![], - }; + }); let reexport = cx.reexport_test_harness_main.as_ref().map(|s| { // building `use = __test::main` let reexport_ident = token::str_to_ident(s.get()); let use_path = nospan(ast::ViewPathSimple(reexport_ident, - path_node(vec![mod_ident, token::str_to_ident("main")]), - ast::DUMMY_NODE_ID)); + path_node(vec![mod_ident, token::str_to_ident("main")]))); - ast::ViewItem { - node: ast::ViewItemUse(P(use_path)), + P(ast::Item { + id: ast::DUMMY_NODE_ID, + ident: token::special_idents::invalid, attrs: vec![], + node: ast::ItemUse(P(use_path)), vis: ast::Inherited, span: DUMMY_SP - } + }) }); - debug!("Synthetic test module:\n{}\n", pprust::item_to_string(&item)); + debug!("Synthetic test module:\n{}\n", pprust::item_to_string(&*item)); - (P(item), reexport) + (item, reexport) } fn nospan(t: T) -> codemap::Spanned { diff --git a/src/libsyntax/util/interner.rs b/src/libsyntax/util/interner.rs index 5dca39f1aea0..1b35b1b04a31 100644 --- a/src/libsyntax/util/interner.rs +++ b/src/libsyntax/util/interner.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! An "interner" is a data structure that associates values with uint tags and +//! An "interner" is a data structure that associates values with usize tags and //! allows bidirectional lookup; i.e. given a value, one can easily find the //! type, and vice versa. @@ -70,10 +70,10 @@ impl + Clone + 'static> Interner { pub fn get(&self, idx: Name) -> T { let vect = self.vect.borrow(); - (*vect)[idx.uint()].clone() + (*vect)[idx.usize()].clone() } - pub fn len(&self) -> uint { + pub fn len(&self) -> usize { let vect = self.vect.borrow(); (*vect).len() } @@ -114,9 +114,16 @@ impl Ord for RcStr { } } -impl fmt::Show for RcStr { +impl fmt::Debug for RcStr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use std::fmt::Show; + use std::fmt::Debug; + self[].fmt(f) + } +} + +impl fmt::Display for RcStr { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use std::fmt::Display; self[].fmt(f) } } @@ -190,16 +197,16 @@ impl StrInterner { let new_idx = Name(self.len() as u32); // leave out of map to avoid colliding let mut vect = self.vect.borrow_mut(); - let existing = (*vect)[idx.uint()].clone(); + let existing = (*vect)[idx.usize()].clone(); vect.push(existing); new_idx } pub fn get(&self, idx: Name) -> RcStr { - (*self.vect.borrow())[idx.uint()].clone() + (*self.vect.borrow())[idx.usize()].clone() } - pub fn len(&self) -> uint { + pub fn len(&self) -> usize { self.vect.borrow().len() } diff --git a/src/libsyntax/util/parser_testing.rs b/src/libsyntax/util/parser_testing.rs index 83bbff8473d0..89854f5d979a 100644 --- a/src/libsyntax/util/parser_testing.rs +++ b/src/libsyntax/util/parser_testing.rs @@ -69,13 +69,6 @@ pub fn string_to_stmt(source_str : String) -> P { }) } -/// Parse a string, return a view item -pub fn string_to_view_item (source_str : String) -> ast::ViewItem { - with_error_checking_parse(source_str, |p| { - p.parse_view_item(Vec::new()) - }) -} - /// Parse a string, return a pat. Uses "irrefutable"... which doesn't /// (currently) affect parsing. pub fn string_to_pat(source_str: String) -> P { @@ -130,10 +123,10 @@ pub fn matches_codepattern(a : &str, b : &str) -> bool { } } -/// Given a string and an index, return the first uint >= idx +/// Given a string and an index, return the first usize >= idx /// that is a non-ws-char or is outside of the legal range of /// the string. -fn scan_for_non_ws_or_end(a : &str, idx: uint) -> uint { +fn scan_for_non_ws_or_end(a : &str, idx: usize) -> usize { let mut i = idx; let len = a.len(); while (i < len) && (is_whitespace(a.char_at(i))) { diff --git a/src/libsyntax/util/small_vector.rs b/src/libsyntax/util/small_vector.rs index 22f2fb36fc88..21a7d6808475 100644 --- a/src/libsyntax/util/small_vector.rs +++ b/src/libsyntax/util/small_vector.rs @@ -89,7 +89,7 @@ impl SmallVector { } } - pub fn get<'a>(&'a self, idx: uint) -> &'a T { + pub fn get<'a>(&'a self, idx: usize) -> &'a T { match self.repr { One(ref v) if idx == 0 => v, Many(ref vs) => &vs[idx], @@ -127,7 +127,7 @@ impl SmallVector { IntoIter { repr: repr } } - pub fn len(&self) -> uint { + pub fn len(&self) -> usize { match self.repr { Zero => 0, One(..) => 1, @@ -166,7 +166,7 @@ impl Iterator for IntoIter { } } - fn size_hint(&self) -> (uint, Option) { + fn size_hint(&self) -> (usize, Option) { match self.repr { ZeroIterator => (0, Some(0)), OneIterator(..) => (1, Some(1)), @@ -192,17 +192,17 @@ mod test { #[test] fn test_len() { - let v: SmallVector = SmallVector::zero(); + let v: SmallVector = SmallVector::zero(); assert_eq!(0, v.len()); - assert_eq!(1, SmallVector::one(1i).len()); - assert_eq!(5, SmallVector::many(vec!(1i, 2, 3, 4, 5)).len()); + assert_eq!(1, SmallVector::one(1is).len()); + assert_eq!(5, SmallVector::many(vec!(1is, 2, 3, 4, 5)).len()); } #[test] fn test_push_get() { let mut v = SmallVector::zero(); - v.push(1i); + v.push(1is); assert_eq!(1, v.len()); assert_eq!(&1, v.get(0)); v.push(2); @@ -215,7 +215,7 @@ mod test { #[test] fn test_from_iter() { - let v: SmallVector = (vec!(1i, 2, 3)).into_iter().collect(); + let v: SmallVector = (vec![1is, 2, 3]).into_iter().collect(); assert_eq!(3, v.len()); assert_eq!(&1, v.get(0)); assert_eq!(&2, v.get(1)); @@ -225,31 +225,31 @@ mod test { #[test] fn test_move_iter() { let v = SmallVector::zero(); - let v: Vec = v.into_iter().collect(); + let v: Vec = v.into_iter().collect(); assert_eq!(Vec::new(), v); - let v = SmallVector::one(1i); - assert_eq!(vec!(1i), v.into_iter().collect::>()); + let v = SmallVector::one(1is); + assert_eq!(vec!(1is), v.into_iter().collect::>()); - let v = SmallVector::many(vec!(1i, 2i, 3i)); - assert_eq!(vec!(1i, 2i, 3i), v.into_iter().collect::>()); + let v = SmallVector::many(vec!(1is, 2is, 3is)); + assert_eq!(vec!(1is, 2is, 3is), v.into_iter().collect::>()); } #[test] #[should_fail] fn test_expect_one_zero() { - let _: int = SmallVector::zero().expect_one(""); + let _: isize = SmallVector::zero().expect_one(""); } #[test] #[should_fail] fn test_expect_one_many() { - SmallVector::many(vec!(1i, 2)).expect_one(""); + SmallVector::many(vec!(1is, 2)).expect_one(""); } #[test] fn test_expect_one_one() { - assert_eq!(1i, SmallVector::one(1i).expect_one("")); - assert_eq!(1i, SmallVector::many(vec!(1i)).expect_one("")); + assert_eq!(1is, SmallVector::one(1is).expect_one("")); + assert_eq!(1is, SmallVector::many(vec!(1is)).expect_one("")); } } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 7778b4fa34aa..eb906788aa7f 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -62,7 +62,6 @@ pub trait Visitor<'v> : Sized { self.visit_name(span, ident.name); } fn visit_mod(&mut self, m: &'v Mod, _s: Span, _n: NodeId) { walk_mod(self, m) } - fn visit_view_item(&mut self, i: &'v ViewItem) { walk_view_item(self, i) } fn visit_foreign_item(&mut self, i: &'v ForeignItem) { walk_foreign_item(self, i) } fn visit_item(&mut self, i: &'v Item) { walk_item(self, i) } fn visit_local(&mut self, l: &'v Local) { walk_local(self, l) } @@ -166,51 +165,11 @@ pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate) { } pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod) { - for view_item in module.view_items.iter() { - visitor.visit_view_item(view_item) - } - for item in module.items.iter() { visitor.visit_item(&**item) } } -pub fn walk_view_item<'v, V: Visitor<'v>>(visitor: &mut V, vi: &'v ViewItem) { - match vi.node { - ViewItemExternCrate(name, _, _) => { - visitor.visit_ident(vi.span, name) - } - ViewItemUse(ref vp) => { - match vp.node { - ViewPathSimple(ident, ref path, id) => { - visitor.visit_ident(vp.span, ident); - visitor.visit_path(path, id); - } - ViewPathGlob(ref path, id) => { - visitor.visit_path(path, id); - } - ViewPathList(ref prefix, ref list, _) => { - for id in list.iter() { - match id.node { - PathListIdent { name, .. } => { - visitor.visit_ident(id.span, name); - } - PathListMod { .. } => () - } - } - - // Note that the `prefix` here is not a complete - // path, so we don't use `visit_path`. - walk_path(visitor, prefix); - } - } - } - } - for attr in vi.attrs.iter() { - visitor.visit_attribute(attr); - } -} - pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local) { visitor.visit_pat(&*local.pat); walk_ty_opt(visitor, &local.ty); @@ -269,6 +228,32 @@ pub fn walk_trait_ref<'v,V>(visitor: &mut V, pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) { visitor.visit_ident(item.span, item.ident); match item.node { + ItemExternCrate(..) => {} + ItemUse(ref vp) => { + match vp.node { + ViewPathSimple(ident, ref path) => { + visitor.visit_ident(vp.span, ident); + visitor.visit_path(path, item.id); + } + ViewPathGlob(ref path) => { + visitor.visit_path(path, item.id); + } + ViewPathList(ref prefix, ref list) => { + for id in list.iter() { + match id.node { + PathListIdent { name, .. } => { + visitor.visit_ident(id.span, name); + } + PathListMod { .. } => () + } + } + + // Note that the `prefix` here is not a complete + // path, so we don't use `visit_path`. + walk_path(visitor, prefix); + } + } + } ItemStatic(ref typ, _, ref expr) | ItemConst(ref typ, ref expr) => { visitor.visit_ty(&**typ); @@ -285,9 +270,6 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) { visitor.visit_mod(module, item.span, item.id) } ItemForeignMod(ref foreign_module) => { - for view_item in foreign_module.view_items.iter() { - visitor.visit_view_item(view_item) - } for foreign_item in foreign_module.items.iter() { visitor.visit_foreign_item(&**foreign_item) } @@ -732,9 +714,6 @@ pub fn walk_struct_field<'v, V: Visitor<'v>>(visitor: &mut V, } pub fn walk_block<'v, V: Visitor<'v>>(visitor: &mut V, block: &'v Block) { - for view_item in block.view_items.iter() { - visitor.visit_view_item(view_item) - } for statement in block.stmts.iter() { visitor.visit_stmt(&**statement) } diff --git a/src/libterm/terminfo/mod.rs b/src/libterm/terminfo/mod.rs index 4933938f3383..2ef0bca3785c 100644 --- a/src/libterm/terminfo/mod.rs +++ b/src/libterm/terminfo/mod.rs @@ -197,7 +197,7 @@ impl TerminfoTerminal { let mut file = entry.unwrap(); let ti = parse(&mut file, false); if ti.is_err() { - debug!("error parsing terminfo entry: {:?}", ti.unwrap_err()); + debug!("error parsing terminfo entry: {:?}", ti.err().unwrap()); return None; } diff --git a/src/libterm/terminfo/parm.rs b/src/libterm/terminfo/parm.rs index b0bce8f31120..0b51a976c0e8 100644 --- a/src/libterm/terminfo/parm.rs +++ b/src/libterm/terminfo/parm.rs @@ -624,7 +624,7 @@ mod test { }; let res = get_res("%p1", cap, &[p], vars); assert!(res.is_ok(), - "Op {} failed with 1 stack entry: {}", cap, res.unwrap_err()); + "Op {} failed with 1 stack entry: {}", cap, res.err().unwrap()); } let caps = ["%+", "%-", "%*", "%/", "%m", "%&", "%|", "%A", "%O"]; for &cap in caps.iter() { @@ -636,7 +636,7 @@ mod test { "Binop {} succeeded incorrectly with 1 stack entry", cap); let res = get_res("%{1}%{2}", cap, &[], vars); assert!(res.is_ok(), - "Binop {} failed with 2 stack entries: {:?}", cap, res.unwrap_err()); + "Binop {} failed with 2 stack entries: {:?}", cap, res.err().unwrap()); } } @@ -651,15 +651,15 @@ mod test { for &(op, bs) in v.iter() { let s = format!("%{{1}}%{{2}}%{}%d", op); let res = expand(s.as_bytes(), &[], &mut Variables::new()); - assert!(res.is_ok(), res.unwrap_err()); + assert!(res.is_ok(), res.err().unwrap()); assert_eq!(res.unwrap(), vec!(b'0' + bs[0])); let s = format!("%{{1}}%{{1}}%{}%d", op); let res = expand(s.as_bytes(), &[], &mut Variables::new()); - assert!(res.is_ok(), res.unwrap_err()); + assert!(res.is_ok(), res.err().unwrap()); assert_eq!(res.unwrap(), vec!(b'0' + bs[1])); let s = format!("%{{2}}%{{1}}%{}%d", op); let res = expand(s.as_bytes(), &[], &mut Variables::new()); - assert!(res.is_ok(), res.unwrap_err()); + assert!(res.is_ok(), res.err().unwrap()); assert_eq!(res.unwrap(), vec!(b'0' + bs[2])); } } @@ -669,15 +669,15 @@ mod test { let mut vars = Variables::new(); let s = b"\\E[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m"; let res = expand(s, &[Number(1)], &mut vars); - assert!(res.is_ok(), res.unwrap_err()); + assert!(res.is_ok(), res.err().unwrap()); assert_eq!(res.unwrap(), "\\E[31m".bytes().collect::>()); let res = expand(s, &[Number(8)], &mut vars); - assert!(res.is_ok(), res.unwrap_err()); + assert!(res.is_ok(), res.err().unwrap()); assert_eq!(res.unwrap(), "\\E[90m".bytes().collect::>()); let res = expand(s, &[Number(42)], &mut vars); - assert!(res.is_ok(), res.unwrap_err()); + assert!(res.is_ok(), res.err().unwrap()); assert_eq!(res.unwrap(), "\\E[38;5;42m".bytes().collect::>()); } diff --git a/src/libterm/terminfo/parser/compiled.rs b/src/libterm/terminfo/parser/compiled.rs index 4735b6e8f2ad..eb300beae9fa 100644 --- a/src/libterm/terminfo/parser/compiled.rs +++ b/src/libterm/terminfo/parser/compiled.rs @@ -284,12 +284,12 @@ pub fn parse(file: &mut io::Reader, longnames: bool) // Find the offset of the NUL we want to go to - let nulpos = string_table[(offset as uint) .. (string_table_bytes as uint)] + let nulpos = string_table[offset as uint .. string_table_bytes as uint] .iter().position(|&b| b == 0); match nulpos { Some(len) => { string_map.insert(name.to_string(), - string_table[(offset as uint) .. + string_table[offset as uint .. (offset as uint + len)].to_vec()) }, None => { diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 512120243c31..91031b153286 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -43,15 +43,14 @@ #![feature(path)] #![feature(rustc_private)] #![feature(std_misc)] +#![feature(hash)] extern crate getopts; -extern crate regex; extern crate serialize; extern crate "serialize" as rustc_serialize; extern crate term; pub use self::TestFn::*; -pub use self::MetricChange::*; pub use self::ColorConfig::*; pub use self::TestResult::*; pub use self::TestName::*; @@ -61,18 +60,14 @@ use self::OutputLocation::*; use stats::Stats; use getopts::{OptGroup, optflag, optopt}; -use regex::Regex; -use serialize::{json, Decodable, Encodable}; +use serialize::Encodable; use term::Terminal; use term::color::{Color, RED, YELLOW, GREEN, CYAN}; use std::any::Any; use std::cmp; use std::collections::BTreeMap; -use std::f64; -use std::fmt::Show; use std::fmt; -use std::io::fs::PathExtensions; use std::io::stdio::StdWriter; use std::io::{File, ChanReader, ChanWriter}; use std::io; @@ -89,8 +84,7 @@ use std::time::Duration; pub mod test { pub use {Bencher, TestName, TestResult, TestDesc, TestDescAndFn, TestOpts, TrFailed, TrIgnored, TrOk, - Metric, MetricMap, MetricAdded, MetricRemoved, - MetricChange, Improvement, Regression, LikelyNoise, + Metric, MetricMap, StaticTestFn, StaticTestName, DynTestName, DynTestFn, run_test, test_main, test_main_static, filter_tests, parse_opts, StaticBenchFn, ShouldFail}; @@ -116,9 +110,9 @@ impl TestName { } } } -impl fmt::String for TestName { +impl fmt::Display for TestName { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::String::fmt(self.as_slice(), f) + fmt::Display::fmt(self.as_slice(), f) } } @@ -179,7 +173,7 @@ impl TestFn { } } -impl fmt::Show for TestFn { +impl fmt::Debug for TestFn { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str(match *self { StaticTestFn(..) => "StaticTestFn(..)", @@ -249,18 +243,6 @@ impl Clone for MetricMap { } } -/// Analysis of a single change in metric -#[derive(Copy, PartialEq, Show)] -pub enum MetricChange { - LikelyNoise, - MetricAdded, - MetricRemoved, - Improvement(f64), - Regression(f64) -} - -pub type MetricDiff = BTreeMap; - // The default console test runner. It accepts the command line // arguments and a vector of test_descs. pub fn test_main(args: &[String], tests: Vec ) { @@ -303,20 +285,13 @@ pub enum ColorConfig { } pub struct TestOpts { - pub filter: Option, + pub filter: Option, pub run_ignored: bool, pub run_tests: bool, pub run_benchmarks: bool, - pub ratchet_metrics: Option, - pub ratchet_noise_percent: Option, - pub save_metrics: Option, - pub test_shard: Option<(uint,uint)>, pub logfile: Option, pub nocapture: bool, pub color: ColorConfig, - pub show_boxplot: bool, - pub boxplot_width: uint, - pub show_all_stats: bool, } impl TestOpts { @@ -327,16 +302,9 @@ impl TestOpts { run_ignored: false, run_tests: false, run_benchmarks: false, - ratchet_metrics: None, - ratchet_noise_percent: None, - save_metrics: None, - test_shard: None, logfile: None, nocapture: false, color: AutoColor, - show_boxplot: false, - boxplot_width: 50, - show_all_stats: false, } } } @@ -349,28 +317,14 @@ fn optgroups() -> Vec { getopts::optflag("", "test", "Run tests and not benchmarks"), getopts::optflag("", "bench", "Run benchmarks instead of tests"), getopts::optflag("h", "help", "Display this message (longer with --help)"), - getopts::optopt("", "save-metrics", "Location to save bench metrics", - "PATH"), - getopts::optopt("", "ratchet-metrics", - "Location to load and save metrics from. The metrics \ - loaded are cause benchmarks to fail if they run too \ - slowly", "PATH"), - getopts::optopt("", "ratchet-noise-percent", - "Tests within N% of the recorded metrics will be \ - considered as passing", "PERCENTAGE"), getopts::optopt("", "logfile", "Write logs to the specified file instead \ of stdout", "PATH"), - getopts::optopt("", "test-shard", "run shard A, of B shards, worth of the testsuite", - "A.B"), getopts::optflag("", "nocapture", "don't capture stdout/stderr of each \ task, allow printing directly"), getopts::optopt("", "color", "Configure coloring of output: auto = colorize if stdout is a tty and tests are run on serially (default); always = always colorize output; - never = never colorize output;", "auto|always|never"), - getopts::optflag("", "boxplot", "Display a boxplot of the benchmark statistics"), - getopts::optopt("", "boxplot-width", "Set the boxplot width (default 50)", "WIDTH"), - getopts::optflag("", "stats", "Display the benchmark min, max, and quartiles")) + never = never colorize output;", "auto|always|never")) } fn usage(binary: &str) { @@ -417,11 +371,7 @@ pub fn parse_opts(args: &[String]) -> Option { if matches.opt_present("h") { usage(args[0].as_slice()); return None; } let filter = if matches.free.len() > 0 { - let s = matches.free[0].as_slice(); - match Regex::new(s) { - Ok(re) => Some(re), - Err(e) => return Some(Err(format!("could not parse /{}/: {:?}", s, e))) - } + Some(matches.free[0].clone()) } else { None }; @@ -435,19 +385,6 @@ pub fn parse_opts(args: &[String]) -> Option { let run_tests = ! run_benchmarks || matches.opt_present("test"); - let ratchet_metrics = matches.opt_str("ratchet-metrics"); - let ratchet_metrics = ratchet_metrics.map(|s| Path::new(s)); - - let ratchet_noise_percent = matches.opt_str("ratchet-noise-percent"); - let ratchet_noise_percent = - ratchet_noise_percent.map(|s| s.as_slice().parse::().unwrap()); - - let save_metrics = matches.opt_str("save-metrics"); - let save_metrics = save_metrics.map(|s| Path::new(s)); - - let test_shard = matches.opt_str("test-shard"); - let test_shard = opt_shard(test_shard); - let mut nocapture = matches.opt_present("nocapture"); if !nocapture { nocapture = os::getenv("RUST_TEST_NOCAPTURE").is_some(); @@ -463,63 +400,19 @@ pub fn parse_opts(args: &[String]) -> Option { v))), }; - let show_boxplot = matches.opt_present("boxplot"); - let boxplot_width = match matches.opt_str("boxplot-width") { - Some(width) => { - match FromStr::from_str(width.as_slice()) { - Some(width) => width, - None => { - return Some(Err(format!("argument for --boxplot-width must be a uint"))); - } - } - } - None => 50, - }; - - let show_all_stats = matches.opt_present("stats"); - let test_opts = TestOpts { filter: filter, run_ignored: run_ignored, run_tests: run_tests, run_benchmarks: run_benchmarks, - ratchet_metrics: ratchet_metrics, - ratchet_noise_percent: ratchet_noise_percent, - save_metrics: save_metrics, - test_shard: test_shard, logfile: logfile, nocapture: nocapture, color: color, - show_boxplot: show_boxplot, - boxplot_width: boxplot_width, - show_all_stats: show_all_stats, }; Some(Ok(test_opts)) } -pub fn opt_shard(maybestr: Option) -> Option<(uint,uint)> { - match maybestr { - None => None, - Some(s) => { - let mut it = s.split('.'); - match (it.next().and_then(|s| s.parse::()), - it.next().and_then(|s| s.parse::()), - it.next()) { - (Some(a), Some(b), None) => { - if a <= 0 || a > b { - panic!("tried to run shard {a}.{b}, but {a} is out of bounds \ - (should be between 1 and {b}", a=a, b=b) - } - Some((a, b)) - } - _ => None, - } - } - } -} - - #[derive(Clone, PartialEq)] pub struct BenchSamples { ns_iter_summ: stats::Summary, @@ -546,9 +439,6 @@ struct ConsoleTestState { log_out: Option, out: OutputLocation, use_color: bool, - show_boxplot: bool, - boxplot_width: uint, - show_all_stats: bool, total: uint, passed: uint, failed: uint, @@ -575,9 +465,6 @@ impl ConsoleTestState { out: out, log_out: log_out, use_color: use_color(opts), - show_boxplot: opts.show_boxplot, - boxplot_width: opts.boxplot_width, - show_all_stats: opts.show_all_stats, total: 0u, passed: 0u, failed: 0u, @@ -609,22 +496,6 @@ impl ConsoleTestState { self.write_pretty("bench", term::color::CYAN) } - pub fn write_added(&mut self) -> io::IoResult<()> { - self.write_pretty("added", term::color::GREEN) - } - - pub fn write_improved(&mut self) -> io::IoResult<()> { - self.write_pretty("improved", term::color::GREEN) - } - - pub fn write_removed(&mut self) -> io::IoResult<()> { - self.write_pretty("removed", term::color::YELLOW) - } - - pub fn write_regressed(&mut self) -> io::IoResult<()> { - self.write_pretty("regressed", term::color::RED) - } - pub fn write_pretty(&mut self, word: &str, color: term::color::Color) -> io::IoResult<()> { @@ -669,33 +540,13 @@ impl ConsoleTestState { TrIgnored => self.write_ignored(), TrMetrics(ref mm) => { try!(self.write_metric()); - self.write_plain(format!(": {}", fmt_metrics(mm)).as_slice()) + self.write_plain(format!(": {}", mm.fmt_metrics()).as_slice()) } TrBench(ref bs) => { try!(self.write_bench()); - if self.show_boxplot { - let mut wr = Vec::new(); - - try!(stats::write_boxplot(&mut wr, &bs.ns_iter_summ, self.boxplot_width)); - - let s = String::from_utf8(wr).unwrap(); - - try!(self.write_plain(format!(": {}", s).as_slice())); - } - - if self.show_all_stats { - let mut wr = Vec::new(); - - try!(stats::write_5_number_summary(&mut wr, &bs.ns_iter_summ)); - - let s = String::from_utf8(wr).unwrap(); - - try!(self.write_plain(format!(": {}", s).as_slice())); - } else { - try!(self.write_plain(format!(": {}", - fmt_bench_samples(bs)).as_slice())); - } + try!(self.write_plain(format!(": {}", + fmt_bench_samples(bs)).as_slice())); Ok(()) } @@ -712,7 +563,7 @@ impl ConsoleTestState { TrOk => "ok".to_string(), TrFailed => "failed".to_string(), TrIgnored => "ignored".to_string(), - TrMetrics(ref mm) => fmt_metrics(mm), + TrMetrics(ref mm) => mm.fmt_metrics(), TrBench(ref bs) => fmt_bench_samples(bs) }, test.name.as_slice()); o.write(s.as_bytes()) @@ -748,85 +599,14 @@ impl ConsoleTestState { Ok(()) } - pub fn write_metric_diff(&mut self, diff: &MetricDiff) -> io::IoResult<()> { - let mut noise = 0u; - let mut improved = 0u; - let mut regressed = 0u; - let mut added = 0u; - let mut removed = 0u; - - for (k, v) in diff.iter() { - match *v { - LikelyNoise => noise += 1, - MetricAdded => { - added += 1; - try!(self.write_added()); - try!(self.write_plain(format!(": {}\n", *k).as_slice())); - } - MetricRemoved => { - removed += 1; - try!(self.write_removed()); - try!(self.write_plain(format!(": {}\n", *k).as_slice())); - } - Improvement(pct) => { - improved += 1; - try!(self.write_plain(format!(": {} ", *k).as_slice())); - try!(self.write_improved()); - try!(self.write_plain(format!(" by {:.2}%\n", - pct as f64).as_slice())); - } - Regression(pct) => { - regressed += 1; - try!(self.write_plain(format!(": {} ", *k).as_slice())); - try!(self.write_regressed()); - try!(self.write_plain(format!(" by {:.2}%\n", - pct as f64).as_slice())); - } - } - } - try!(self.write_plain(format!("result of ratchet: {} metrics added, \ - {} removed, {} improved, {} regressed, \ - {} noise\n", - added, removed, improved, regressed, - noise).as_slice())); - if regressed == 0 { - try!(self.write_plain("updated ratchet file\n")); - } else { - try!(self.write_plain("left ratchet file untouched\n")); - } - Ok(()) - } - - pub fn write_run_finish(&mut self, - ratchet_metrics: &Option, - ratchet_pct: Option) -> io::IoResult { + pub fn write_run_finish(&mut self) -> io::IoResult { assert!(self.passed + self.failed + self.ignored + self.measured == self.total); - let ratchet_success = match *ratchet_metrics { - None => true, - Some(ref pth) => { - try!(self.write_plain(format!("\nusing metrics ratchet: {:?}\n", - pth.display()).as_slice())); - match ratchet_pct { - None => (), - Some(pct) => - try!(self.write_plain(format!("with noise-tolerance \ - forced to: {}%\n", - pct).as_slice())) - } - let (diff, ok) = self.metrics.ratchet(pth, ratchet_pct); - try!(self.write_metric_diff(&diff)); - ok - } - }; - - let test_success = self.failed == 0u; - if !test_success { + let success = self.failed == 0u; + if !success { try!(self.write_failures()); } - let success = ratchet_success && test_success; - try!(self.write_plain("\ntest result: ")); if success { // There's no parallelism at this point so it's safe to use color @@ -841,15 +621,6 @@ impl ConsoleTestState { } } -pub fn fmt_metrics(mm: &MetricMap) -> String { - let MetricMap(ref mm) = *mm; - let v : Vec = mm.iter() - .map(|(k,v)| format!("{}: {} (+/- {})", *k, - v.value as f64, v.noise as f64)) - .collect(); - v.connect(", ") -} - pub fn fmt_bench_samples(bs: &BenchSamples) -> String { if bs.mb_s != 0 { format!("{:>9} ns/iter (+/- {}) = {} MB/s", @@ -920,15 +691,7 @@ pub fn run_tests_console(opts: &TestOpts, tests: Vec ) -> io::IoR None => {} } try!(run_tests(opts, tests, |x| callback(&x, &mut st))); - match opts.save_metrics { - None => (), - Some(ref pth) => { - try!(st.metrics.save(pth)); - try!(st.write_plain(format!("\nmetrics saved to: {:?}", - pth.display()).as_slice())); - } - } - return st.write_run_finish(&opts.ratchet_metrics, opts.ratchet_noise_percent); + return st.write_run_finish(); } #[test] @@ -949,9 +712,6 @@ fn should_sort_failures_before_printing_them() { log_out: None, out: Raw(Vec::new()), use_color: false, - show_boxplot: false, - boxplot_width: 0, - show_all_stats: false, total: 0u, passed: 0u, failed: 0u, @@ -1075,9 +835,10 @@ pub fn filter_tests(opts: &TestOpts, tests: Vec) -> Vec filtered, - Some(ref re) => { - filtered.into_iter() - .filter(|test| re.is_match(test.desc.name.as_slice())).collect() + Some(ref filter) => { + filtered.into_iter().filter(|test| { + test.desc.name.as_slice().contains(&filter[]) + }).collect() } }; @@ -1102,18 +863,7 @@ pub fn filter_tests(opts: &TestOpts, tests: Vec) -> Vec filtered, - Some((a,b)) => { - filtered.into_iter().enumerate() - // note: using a - 1 so that the valid shards, for example, are - // 1.2 and 2.2 instead of 0.2 and 1.2 - .filter(|&(i,_)| i % b == (a - 1)) - .map(|(_,t)| t) - .collect() - } - } + filtered } pub fn run_test(opts: &TestOpts, @@ -1204,87 +954,6 @@ impl MetricMap { MetricMap(BTreeMap::new()) } - /// Load MetricDiff from a file. - /// - /// # Panics - /// - /// This function will panic if the path does not exist or the path does not - /// contain a valid metric map. - pub fn load(p: &Path) -> MetricMap { - assert!(p.exists()); - let mut f = File::open(p).unwrap(); - let value = json::from_reader(&mut f as &mut io::Reader).unwrap(); - let mut decoder = json::Decoder::new(value); - MetricMap(match Decodable::decode(&mut decoder) { - Ok(t) => t, - Err(e) => panic!("failure decoding JSON: {:?}", e) - }) - } - - /// Write MetricDiff to a file. - pub fn save(&self, p: &Path) -> io::IoResult<()> { - let mut file = try!(File::create(p)); - let MetricMap(ref map) = *self; - write!(&mut file, "{}", json::as_json(map)) - } - - /// Compare against another MetricMap. Optionally compare all - /// measurements in the maps using the provided `noise_pct` as a - /// percentage of each value to consider noise. If `None`, each - /// measurement's noise threshold is independently chosen as the - /// maximum of that measurement's recorded noise quantity in either - /// map. - pub fn compare_to_old(&self, old: &MetricMap, - noise_pct: Option) -> MetricDiff { - let mut diff : MetricDiff = BTreeMap::new(); - let MetricMap(ref selfmap) = *self; - let MetricMap(ref old) = *old; - for (k, vold) in old.iter() { - let r = match selfmap.get(k) { - None => MetricRemoved, - Some(v) => { - let delta = v.value - vold.value; - let noise = match noise_pct { - None => vold.noise.abs().max(v.noise.abs()), - Some(pct) => vold.value * pct / 100.0 - }; - if delta.abs() <= noise { - LikelyNoise - } else { - let pct = delta.abs() / vold.value.max(f64::EPSILON) * 100.0; - if vold.noise < 0.0 { - // When 'noise' is negative, it means we want - // to see deltas that go up over time, and can - // only tolerate slight negative movement. - if delta < 0.0 { - Regression(pct) - } else { - Improvement(pct) - } - } else { - // When 'noise' is positive, it means we want - // to see deltas that go down over time, and - // can only tolerate slight positive movements. - if delta < 0.0 { - Improvement(pct) - } else { - Regression(pct) - } - } - } - } - }; - diff.insert((*k).clone(), r); - } - let MetricMap(ref map) = *self; - for (k, _) in map.iter() { - if !diff.contains_key(k) { - diff.insert((*k).clone(), MetricAdded); - } - } - diff - } - /// Insert a named `value` (+/- `noise`) metric into the map. The value /// must be non-negative. The `noise` indicates the uncertainty of the /// metric, which doubles as the "noise range" of acceptable @@ -1307,31 +976,13 @@ impl MetricMap { map.insert(name.to_string(), m); } - /// Attempt to "ratchet" an external metric file. This involves loading - /// metrics from a metric file (if it exists), comparing against - /// the metrics in `self` using `compare_to_old`, and rewriting the - /// file to contain the metrics in `self` if none of the - /// `MetricChange`s are `Regression`. Returns the diff as well - /// as a boolean indicating whether the ratchet succeeded. - pub fn ratchet(&self, p: &Path, pct: Option) -> (MetricDiff, bool) { - let old = if p.exists() { - MetricMap::load(p) - } else { - MetricMap::new() - }; - - let diff : MetricDiff = self.compare_to_old(&old, pct); - let ok = diff.iter().all(|(_, v)| { - match *v { - Regression(_) => false, - _ => true - } - }); - - if ok { - self.save(p).unwrap(); - } - return (diff, ok) + pub fn fmt_metrics(&self) -> String { + let MetricMap(ref mm) = *self; + let v : Vec = mm.iter() + .map(|(k,v)| format!("{}: {} (+/- {})", *k, + v.value as f64, v.noise as f64)) + .collect(); + v.connect(", ") } } @@ -1474,8 +1125,7 @@ pub mod bench { mod tests { use test::{TrFailed, TrIgnored, TrOk, filter_tests, parse_opts, TestDesc, TestDescAndFn, TestOpts, run_test, - Metric, MetricMap, MetricAdded, MetricRemoved, - Improvement, Regression, LikelyNoise, + Metric, MetricMap, StaticTestName, DynTestName, DynTestFn, ShouldFail}; use std::io::TempDir; use std::thunk::Thunk; @@ -1583,16 +1233,6 @@ mod tests { assert!(res == TrFailed); } - #[test] - fn first_free_arg_should_be_a_filter() { - let args = vec!("progname".to_string(), "some_regex_filter".to_string()); - let opts = match parse_opts(args.as_slice()) { - Some(Ok(o)) => o, - _ => panic!("Malformed arg in first_free_arg_should_be_a_filter") - }; - assert!(opts.filter.expect("should've found filter").is_match("some_regex_filter")) - } - #[test] fn parse_ignored_flag() { let args = vec!("progname".to_string(), @@ -1689,37 +1329,6 @@ mod tests { } } - #[test] - pub fn filter_tests_regex() { - let mut opts = TestOpts::new(); - opts.filter = Some(::regex::Regex::new("a.*b.+c").unwrap()); - - let mut names = ["yes::abXc", "yes::aXXXbXXXXc", - "no::XYZ", "no::abc"]; - names.sort(); - - fn test_fn() {} - let tests = names.iter().map(|name| { - TestDescAndFn { - desc: TestDesc { - name: DynTestName(name.to_string()), - ignore: false, - should_fail: ShouldFail::No, - }, - testfn: DynTestFn(Thunk::new(test_fn)) - } - }).collect(); - let filtered = filter_tests(&opts, tests); - - let expected: Vec<&str> = - names.iter().map(|&s| s).filter(|name| name.starts_with("yes")).collect(); - - assert_eq!(filtered.len(), expected.len()); - for (test, expected_name) in filtered.iter().zip(expected.iter()) { - assert_eq!(test.desc.name.as_slice(), *expected_name); - } - } - #[test] pub fn test_metricmap_compare() { let mut m1 = MetricMap::new(); @@ -1741,81 +1350,5 @@ mod tests { m1.insert_metric("in-both-want-upwards-and-improved", 1000.0, -10.0); m2.insert_metric("in-both-want-upwards-and-improved", 2000.0, -10.0); - - let diff1 = m2.compare_to_old(&m1, None); - - assert_eq!(*(diff1.get(&"in-both-noise".to_string()).unwrap()), LikelyNoise); - assert_eq!(*(diff1.get(&"in-first-noise".to_string()).unwrap()), MetricRemoved); - assert_eq!(*(diff1.get(&"in-second-noise".to_string()).unwrap()), MetricAdded); - assert_eq!(*(diff1.get(&"in-both-want-downwards-but-regressed".to_string()).unwrap()), - Regression(100.0)); - assert_eq!(*(diff1.get(&"in-both-want-downwards-and-improved".to_string()).unwrap()), - Improvement(50.0)); - assert_eq!(*(diff1.get(&"in-both-want-upwards-but-regressed".to_string()).unwrap()), - Regression(50.0)); - assert_eq!(*(diff1.get(&"in-both-want-upwards-and-improved".to_string()).unwrap()), - Improvement(100.0)); - assert_eq!(diff1.len(), 7); - - let diff2 = m2.compare_to_old(&m1, Some(200.0)); - - assert_eq!(*(diff2.get(&"in-both-noise".to_string()).unwrap()), LikelyNoise); - assert_eq!(*(diff2.get(&"in-first-noise".to_string()).unwrap()), MetricRemoved); - assert_eq!(*(diff2.get(&"in-second-noise".to_string()).unwrap()), MetricAdded); - assert_eq!(*(diff2.get(&"in-both-want-downwards-but-regressed".to_string()).unwrap()), - LikelyNoise); - assert_eq!(*(diff2.get(&"in-both-want-downwards-and-improved".to_string()).unwrap()), - LikelyNoise); - assert_eq!(*(diff2.get(&"in-both-want-upwards-but-regressed".to_string()).unwrap()), - LikelyNoise); - assert_eq!(*(diff2.get(&"in-both-want-upwards-and-improved".to_string()).unwrap()), - LikelyNoise); - assert_eq!(diff2.len(), 7); - } - - #[test] - pub fn ratchet_test() { - - let dpth = TempDir::new("test-ratchet").ok().expect("missing test for ratchet"); - let pth = dpth.path().join("ratchet.json"); - - let mut m1 = MetricMap::new(); - m1.insert_metric("runtime", 1000.0, 2.0); - m1.insert_metric("throughput", 50.0, 2.0); - - let mut m2 = MetricMap::new(); - m2.insert_metric("runtime", 1100.0, 2.0); - m2.insert_metric("throughput", 50.0, 2.0); - - m1.save(&pth).unwrap(); - - // Ask for a ratchet that should fail to advance. - let (diff1, ok1) = m2.ratchet(&pth, None); - assert_eq!(ok1, false); - assert_eq!(diff1.len(), 2); - assert_eq!(*(diff1.get(&"runtime".to_string()).unwrap()), Regression(10.0)); - assert_eq!(*(diff1.get(&"throughput".to_string()).unwrap()), LikelyNoise); - - // Check that it was not rewritten. - let m3 = MetricMap::load(&pth); - let MetricMap(m3) = m3; - assert_eq!(m3.len(), 2); - assert_eq!(*(m3.get(&"runtime".to_string()).unwrap()), Metric::new(1000.0, 2.0)); - assert_eq!(*(m3.get(&"throughput".to_string()).unwrap()), Metric::new(50.0, 2.0)); - - // Ask for a ratchet with an explicit noise-percentage override, - // that should advance. - let (diff2, ok2) = m2.ratchet(&pth, Some(10.0)); - assert_eq!(ok2, true); - assert_eq!(diff2.len(), 2); - assert_eq!(*(diff2.get(&"runtime".to_string()).unwrap()), LikelyNoise); - assert_eq!(*(diff2.get(&"throughput".to_string()).unwrap()), LikelyNoise); - - // Check that it was rewritten. - let m4 = MetricMap::load(&pth); - let MetricMap(m4) = m4; - assert_eq!(m4.len(), 2); - assert_eq!(*(m4.get(&"runtime".to_string()).unwrap()), Metric::new(1100.0, 2.0)); - assert_eq!(*(m4.get(&"throughput".to_string()).unwrap()), Metric::new(50.0, 2.0)); } } diff --git a/src/libtest/stats.rs b/src/libtest/stats.rs index 6061c4fd1d3d..76b85cc10cd8 100644 --- a/src/libtest/stats.rs +++ b/src/libtest/stats.rs @@ -13,9 +13,7 @@ use std::cmp::Ordering::{self, Less, Greater, Equal}; use std::collections::hash_map::Entry::{Occupied, Vacant}; use std::collections::hash_map::{self, Hasher}; -use std::fmt; use std::hash::Hash; -use std::io; use std::mem; use std::num::{Float, FromPrimitive}; @@ -332,111 +330,6 @@ pub fn winsorize(samples: &mut [T], pct: T) { } } -/// Render writes the min, max and quartiles of the provided `Summary` to the provided `Writer`. -pub fn write_5_number_summary(w: &mut W, - s: &Summary) -> io::IoResult<()> { - let (q1,q2,q3) = s.quartiles; - write!(w, "(min={}, q1={}, med={}, q3={}, max={})", - s.min, - q1, - q2, - q3, - s.max) -} - -/// Render a boxplot to the provided writer. The boxplot shows the min, max and quartiles of the -/// provided `Summary` (thus includes the mean) and is scaled to display within the range of the -/// nearest multiple-of-a-power-of-ten above and below the min and max of possible values, and -/// target `width_hint` characters of display (though it will be wider if necessary). -/// -/// As an example, the summary with 5-number-summary `(min=15, q1=17, med=20, q3=24, max=31)` might -/// display as: -/// -/// ```{.ignore} -/// 10 | [--****#******----------] | 40 -/// ``` -pub fn write_boxplot( - w: &mut W, - s: &Summary, - width_hint: uint) - -> io::IoResult<()> { - - let (q1,q2,q3) = s.quartiles; - - // the .abs() handles the case where numbers are negative - let ten: T = FromPrimitive::from_uint(10).unwrap(); - let lomag = ten.powf(s.min.abs().log10().floor()); - let himag = ten.powf(s.max.abs().log10().floor()); - - // need to consider when the limit is zero - let zero: T = Float::zero(); - let lo = if lomag == Float::zero() { - zero - } else { - (s.min / lomag).floor() * lomag - }; - - let hi = if himag == Float::zero() { - zero - } else { - (s.max / himag).ceil() * himag - }; - - let range = hi - lo; - - let lostr = lo.to_string(); - let histr = hi.to_string(); - - let overhead_width = lostr.len() + histr.len() + 4; - let range_width = width_hint - overhead_width; - let range_float = FromPrimitive::from_uint(range_width).unwrap(); - let char_step = range / range_float; - - try!(write!(w, "{} |", lostr)); - - let mut c = 0; - let mut v = lo; - - while c < range_width && v < s.min { - try!(write!(w, " ")); - v = v + char_step; - c += 1; - } - try!(write!(w, "[")); - c += 1; - while c < range_width && v < q1 { - try!(write!(w, "-")); - v = v + char_step; - c += 1; - } - while c < range_width && v < q2 { - try!(write!(w, "*")); - v = v + char_step; - c += 1; - } - try!(write!(w, "#")); - c += 1; - while c < range_width && v < q3 { - try!(write!(w, "*")); - v = v + char_step; - c += 1; - } - while c < range_width && v < s.max { - try!(write!(w, "-")); - v = v + char_step; - c += 1; - } - try!(write!(w, "]")); - while c < range_width { - try!(write!(w, " ")); - v = v + char_step; - c += 1; - } - - try!(write!(w, "| {}", histr)); - Ok(()) -} - /// Returns a HashMap with the number of occurrences of every element in the /// sequence that the iterator exposes. pub fn freq_count(mut iter: T) -> hash_map::HashMap @@ -458,8 +351,6 @@ pub fn freq_count(mut iter: T) -> hash_map::HashMap mod tests { use stats::Stats; use stats::Summary; - use stats::write_5_number_summary; - use stats::write_boxplot; use std::io; use std::f64; @@ -479,10 +370,6 @@ mod tests { let mut w = io::stdout(); let w = &mut w; (write!(w, "\n")).unwrap(); - write_5_number_summary(w, &summ2).unwrap(); - (write!(w, "\n")).unwrap(); - write_boxplot(w, &summ2, 50).unwrap(); - (write!(w, "\n")).unwrap(); assert_eq!(summ.sum, summ2.sum); assert_eq!(summ.min, summ2.min); @@ -1028,23 +915,6 @@ mod tests { check(val, summ); } - #[test] - fn test_boxplot_nonpositive() { - fn t(s: &Summary, expected: String) { - let mut m = Vec::new(); - write_boxplot(&mut m, s, 30).unwrap(); - let out = String::from_utf8(m).unwrap(); - assert_eq!(out, expected); - } - - t(&Summary::new(&[-2.0f64, -1.0f64]), - "-2 |[------******#*****---]| -1".to_string()); - t(&Summary::new(&[0.0f64, 2.0f64]), - "0 |[-------*****#*******---]| 2".to_string()); - t(&Summary::new(&[-2.0f64, 0.0f64]), - "-2 |[------******#******---]| 0".to_string()); - - } #[test] fn test_sum_f64s() { assert_eq!([0.5f64, 3.2321f64, 1.5678f64].sum(), 5.2999); diff --git a/src/libunicode/u_str.rs b/src/libunicode/u_str.rs index 1cdbb6c83560..adcb52537094 100644 --- a/src/libunicode/u_str.rs +++ b/src/libunicode/u_str.rs @@ -249,8 +249,8 @@ impl<'a> Iterator for Graphemes<'a> { Some(cat) }; - let retstr = self.string.slice_to(idx); - self.string = self.string.slice_from(idx); + let retstr = &self.string[..idx]; + self.string = &self.string[idx..]; Some(retstr) } } @@ -350,8 +350,8 @@ impl<'a> DoubleEndedIterator for Graphemes<'a> { Some(cat) }; - let retstr = self.string.slice_from(idx); - self.string = self.string.slice_to(idx); + let retstr = &self.string[idx..]; + self.string = &self.string[..idx]; Some(retstr) } } diff --git a/src/rt/rust_builtin.c b/src/rt/rust_builtin.c index 5dc07f859aed..03cd3fd6b88e 100644 --- a/src/rt/rust_builtin.c +++ b/src/rt/rust_builtin.c @@ -41,29 +41,6 @@ //include valgrind.h after stdint.h so that uintptr_t is defined for msys2 w64 #include "valgrind/valgrind.h" -#ifdef __ANDROID__ -time_t -timegm(struct tm *tm) -{ - time_t ret; - char *tz; - - tz = getenv("TZ"); - if (tz) - tz = strdup(tz); - setenv("TZ", "", 1); - tzset(); - ret = mktime(tm); - if (tz) { - setenv("TZ", tz, 1); - free(tz); - } else - unsetenv("TZ"); - tzset(); - return ret; -} -#endif - #ifdef __APPLE__ #if (TARGET_OS_IPHONE) extern char **environ; @@ -100,121 +77,6 @@ rust_list_dir_val(struct dirent* entry_ptr) { } #endif -typedef struct { - int32_t tm_sec; - int32_t tm_min; - int32_t tm_hour; - int32_t tm_mday; - int32_t tm_mon; - int32_t tm_year; - int32_t tm_wday; - int32_t tm_yday; - int32_t tm_isdst; - int32_t tm_gmtoff; - int32_t tm_nsec; -} rust_tm; - -void rust_tm_to_tm(rust_tm* in_tm, struct tm* out_tm) { - memset(out_tm, 0, sizeof(struct tm)); - out_tm->tm_sec = in_tm->tm_sec; - out_tm->tm_min = in_tm->tm_min; - out_tm->tm_hour = in_tm->tm_hour; - out_tm->tm_mday = in_tm->tm_mday; - out_tm->tm_mon = in_tm->tm_mon; - out_tm->tm_year = in_tm->tm_year; - out_tm->tm_wday = in_tm->tm_wday; - out_tm->tm_yday = in_tm->tm_yday; - out_tm->tm_isdst = in_tm->tm_isdst; -} - -void tm_to_rust_tm(struct tm* in_tm, - rust_tm* out_tm, - int32_t gmtoff, - int32_t nsec) { - out_tm->tm_sec = in_tm->tm_sec; - out_tm->tm_min = in_tm->tm_min; - out_tm->tm_hour = in_tm->tm_hour; - out_tm->tm_mday = in_tm->tm_mday; - out_tm->tm_mon = in_tm->tm_mon; - out_tm->tm_year = in_tm->tm_year; - out_tm->tm_wday = in_tm->tm_wday; - out_tm->tm_yday = in_tm->tm_yday; - out_tm->tm_isdst = in_tm->tm_isdst; - out_tm->tm_gmtoff = gmtoff; - out_tm->tm_nsec = nsec; -} - -#if defined(__WIN32__) -#define TZSET() _tzset() -#if defined(_MSC_VER) && (_MSC_VER >= 1400) -#define GMTIME(clock, result) gmtime_s((result), (clock)) -#define LOCALTIME(clock, result) localtime_s((result), (clock)) -#define TIMEGM(result) _mkgmtime64(result) -#else -struct tm* GMTIME(const time_t *clock, struct tm *result) { - struct tm* t = gmtime(clock); - if (t == NULL || result == NULL) { return NULL; } - *result = *t; - return result; -} -struct tm* LOCALTIME(const time_t *clock, struct tm *result) { - struct tm* t = localtime(clock); - if (t == NULL || result == NULL) { return NULL; } - *result = *t; - return result; -} -#define TIMEGM(result) mktime((result)) - _timezone -#endif -#else -#define TZSET() tzset() -#define GMTIME(clock, result) gmtime_r((clock), (result)) -#define LOCALTIME(clock, result) localtime_r((clock), (result)) -#define TIMEGM(result) timegm(result) -#endif - -void -rust_tzset() { - TZSET(); -} - -void -rust_gmtime(int64_t sec, int32_t nsec, rust_tm *timeptr) { - struct tm tm; - time_t s = sec; - GMTIME(&s, &tm); - - tm_to_rust_tm(&tm, timeptr, 0, nsec); -} - -void -rust_localtime(int64_t sec, int32_t nsec, rust_tm *timeptr) { - struct tm tm; - time_t s = sec; - LOCALTIME(&s, &tm); - -#if defined(__WIN32__) - int32_t gmtoff = -timezone; -#else - int32_t gmtoff = tm.tm_gmtoff; -#endif - - tm_to_rust_tm(&tm, timeptr, gmtoff, nsec); -} - -int64_t -rust_timegm(rust_tm* timeptr) { - struct tm t; - rust_tm_to_tm(timeptr, &t); - return TIMEGM(&t); -} - -int64_t -rust_mktime(rust_tm* timeptr) { - struct tm t; - rust_tm_to_tm(timeptr, &t); - return mktime(&t); -} - #ifndef _WIN32 DIR* diff --git a/src/rustbook/book.rs b/src/rustbook/book.rs index 20346449fd16..3047e93137f9 100644 --- a/src/rustbook/book.rs +++ b/src/rustbook/book.rs @@ -13,7 +13,6 @@ use std::io::BufferedReader; use std::iter; use std::iter::AdditiveIterator; -use regex::Regex; pub struct BookItem { pub title: String, @@ -94,8 +93,6 @@ pub fn parse_summary(input: R, src: &Path) -> Result[\t ]*)\*[:space:]*\[(?P.*)\]\((?P<path>.*)\)"; - let item_re = Regex::new(regex).unwrap(); let mut top_items = vec!(); let mut stack = vec!(); let mut errors = vec!(); @@ -117,45 +114,51 @@ pub fn parse_summary<R: Reader>(input: R, src: &Path) -> Result<Book, Vec<String } }; - item_re.captures(&line[]).map(|cap| { - let given_path = cap.name("path"); - let title = cap.name("title").unwrap().to_string(); + let star_idx = match line.find_str("*") { Some(i) => i, None => continue }; - let path_from_root = match src.join(given_path.unwrap()).path_relative_from(src) { - Some(p) => p, - None => { - errors.push(format!("paths in SUMMARY.md must be relative, \ - but path '{}' for section '{}' is not.", - given_path.unwrap(), title)); - Path::new("") - } - }; - let path_to_root = Path::new(iter::repeat("../") - .take(path_from_root.components().count() - 1) - .collect::<String>()); - let item = BookItem { - title: title, - path: path_from_root, - path_to_root: path_to_root, - children: vec!(), - }; - let level = cap.name("indent").unwrap().chars().map(|c| { - match c { - ' ' => 1us, - '\t' => 4, - _ => unreachable!() - } - }).sum() / 4 + 1; + let start_bracket = star_idx + line[star_idx..].find_str("[").unwrap(); + let end_bracket = start_bracket + line[start_bracket..].find_str("](").unwrap(); + let start_paren = end_bracket + 1; + let end_paren = start_paren + line[start_paren..].find_str(")").unwrap(); - if level > stack.len() + 1 { - errors.push(format!("section '{}' is indented too deeply; \ - found {}, expected {} or less", - item.title, level, stack.len() + 1)); - } else if level <= stack.len() { - collapse(&mut stack, &mut top_items, level); + let given_path = &line[start_paren + 1 .. end_paren]; + let title = line[start_bracket + 1..end_bracket].to_string(); + let indent = &line[..star_idx]; + + let path_from_root = match src.join(given_path).path_relative_from(src) { + Some(p) => p, + None => { + errors.push(format!("paths in SUMMARY.md must be relative, \ + but path '{}' for section '{}' is not.", + given_path, title)); + Path::new("") } - stack.push(item) - }); + }; + let path_to_root = Path::new(iter::repeat("../") + .take(path_from_root.components().count() - 1) + .collect::<String>()); + let item = BookItem { + title: title, + path: path_from_root, + path_to_root: path_to_root, + children: vec!(), + }; + let level = indent.chars().map(|c| { + match c { + ' ' => 1us, + '\t' => 4, + _ => unreachable!() + } + }).sum() / 4 + 1; + + if level > stack.len() + 1 { + errors.push(format!("section '{}' is indented too deeply; \ + found {}, expected {} or less", + item.title, level, stack.len() + 1)); + } else if level <= stack.len() { + collapse(&mut stack, &mut top_items, level); + } + stack.push(item) } if errors.is_empty() { diff --git a/src/rustbook/build.rs b/src/rustbook/build.rs index 50a6ad43aeeb..93601c0f61bf 100644 --- a/src/rustbook/build.rs +++ b/src/rustbook/build.rs @@ -22,8 +22,6 @@ use book::{Book, BookItem}; use css; use javascript; -use regex::Regex; - use rustdoc; struct Build; @@ -81,9 +79,6 @@ fn render(book: &Book, tgt: &Path) -> CliResult<()> { let out_path = tgt.join(item.path.dirname()); - let regex = r"\[(?P<title>[^]]*)\]\((?P<url_stem>[^)]*)\.(?P<ext>md|markdown)\)"; - let md_urls = Regex::new(regex).unwrap(); - let src; if os::args().len() < 3 { src = os::getcwd().unwrap().clone(); @@ -94,7 +89,7 @@ fn render(book: &Book, tgt: &Path) -> CliResult<()> { let markdown_data = try!(File::open(&src.join(&item.path)).read_to_string()); let preprocessed_path = tmp.path().join(item.path.filename().unwrap()); { - let urls = md_urls.replace_all(&markdown_data[], "[$title]($url_stem.html)"); + let urls = markdown_data.replace(".md)", ".html)"); try!(File::create(&preprocessed_path) .write_str(&urls[])); } diff --git a/src/rustbook/main.rs b/src/rustbook/main.rs index 6d9078c66873..3e571bad09ca 100644 --- a/src/rustbook/main.rs +++ b/src/rustbook/main.rs @@ -14,11 +14,8 @@ #![feature(io)] #![feature(os)] #![feature(path)] -#![feature(rustc_private)] #![feature(rustdoc)] -extern crate regex; - extern crate rustdoc; use std::os; diff --git a/src/snapshots.txt b/src/snapshots.txt index 16fb109bb7d2..8b5027857334 100644 --- a/src/snapshots.txt +++ b/src/snapshots.txt @@ -1,3 +1,12 @@ +S 2015-01-20 9006c3c + freebsd-x86_64 240b30b33263d175e30f925ed1e1e1a4e553a513 + linux-i386 544c2063b8d5035342c705b881b8868244c1e9a1 + linux-x86_64 eb41db80978210a013a8dcf8f4fe804969197337 + macos-i386 3ed08c5ae66367e85b8f2b207615d45bfd9cf89d + macos-x86_64 d102760316b90b17d54b0bef02ca6dc35f82e6bd + winnt-i386 6940fef6caa2f64d158b8f5eb00afd5c8e0c71a5 + winnt-x86_64 36b6f239fe1264bceb4b8202e692b7d49947eebe + S 2015-01-15 9ade482 freebsd-x86_64 eb8f52c6e8dc24a293456d5e4dc5d1072442e758 linux-i386 0197ad7179d74eba06a8b46432548caf226aa03d diff --git a/src/test/run-make/dep-info-custom/bar.rs b/src/test/auxiliary/blind-item-mixed-crate-use-item-foo.rs similarity index 78% rename from src/test/run-make/dep-info-custom/bar.rs rename to src/test/auxiliary/blind-item-mixed-crate-use-item-foo.rs index 4c79f7e28553..f129b4b77bb9 100644 --- a/src/test/run-make/dep-info-custom/bar.rs +++ b/src/test/auxiliary/blind-item-mixed-crate-use-item-foo.rs @@ -1,4 +1,4 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -8,4 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub fn bar() {} +#![crate_type="lib"] + +pub const X: () = (); diff --git a/src/test/run-make/dep-info-custom/foo.rs b/src/test/auxiliary/blind-item-mixed-crate-use-item-foo2.rs similarity index 78% rename from src/test/run-make/dep-info-custom/foo.rs rename to src/test/auxiliary/blind-item-mixed-crate-use-item-foo2.rs index 2661b1f4eb49..91fa91245510 100644 --- a/src/test/run-make/dep-info-custom/foo.rs +++ b/src/test/auxiliary/blind-item-mixed-crate-use-item-foo2.rs @@ -1,4 +1,4 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -8,4 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub fn foo() {} +#![crate_type="lib"] + +pub const Y: () = (); diff --git a/src/test/auxiliary/macro_with_super_1.rs b/src/test/auxiliary/macro_with_super_1.rs new file mode 100644 index 000000000000..fd2e52bb3550 --- /dev/null +++ b/src/test/auxiliary/macro_with_super_1.rs @@ -0,0 +1,26 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type = "lib"] + +#[macro_export] +macro_rules! declare { + () => ( + pub fn aaa() {} + + pub mod bbb { + use super::aaa; + + pub fn ccc() { + aaa(); + } + } + ) +} diff --git a/src/test/auxiliary/roman_numerals.rs b/src/test/auxiliary/roman_numerals.rs index 519f32fc248b..a4edc6072790 100644 --- a/src/test/auxiliary/roman_numerals.rs +++ b/src/test/auxiliary/roman_numerals.rs @@ -20,7 +20,7 @@ use syntax::codemap::Span; use syntax::parse::token; use syntax::ast::{TokenTree, TtToken}; use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacExpr}; -use syntax::ext::build::AstBuilder; // trait for expr_uint +use syntax::ext::build::AstBuilder; // trait for expr_usize use rustc::plugin::Registry; // WARNING WARNING WARNING WARNING WARNING @@ -61,7 +61,7 @@ fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) } } - MacExpr::new(cx.expr_uint(sp, total)) + MacExpr::new(cx.expr_usize(sp, total)) } #[plugin_registrar] diff --git a/src/test/bench/shootout-binarytrees.rs b/src/test/bench/shootout-binarytrees.rs index 58e2430b0ffa..4182f8b651b2 100644 --- a/src/test/bench/shootout-binarytrees.rs +++ b/src/test/bench/shootout-binarytrees.rs @@ -41,7 +41,7 @@ extern crate arena; use std::iter::range_step; -use std::thread::Thread; +use std::thread::{Thread, JoinGuard}; use arena::TypedArena; struct Tree<'a> { @@ -71,6 +71,18 @@ fn bottom_up_tree<'r>(arena: &'r TypedArena<Tree<'r>>, item: i32, depth: i32) } } +fn inner(depth: i32, iterations: i32) -> String { + let mut chk = 0; + for i in 1 .. iterations + 1 { + let arena = TypedArena::new(); + let a = bottom_up_tree(&arena, i, depth); + let b = bottom_up_tree(&arena, -i, depth); + chk += item_check(&a) + item_check(&b); + } + format!("{}\t trees of depth {}\t check: {}", + iterations * 2, depth, chk) +} + fn main() { let args = std::os::args(); let args = args.as_slice(); @@ -97,20 +109,10 @@ fn main() { let long_lived_tree = bottom_up_tree(&long_lived_arena, 0, max_depth); let messages = range_step(min_depth, max_depth + 1, 2).map(|depth| { - use std::num::Int; - let iterations = 2.pow((max_depth - depth + min_depth) as usize); - Thread::scoped(move|| { - let mut chk = 0; - for i in 1 .. iterations + 1 { - let arena = TypedArena::new(); - let a = bottom_up_tree(&arena, i, depth); - let b = bottom_up_tree(&arena, -i, depth); - chk += item_check(&a) + item_check(&b); - } - format!("{}\t trees of depth {}\t check: {}", - iterations * 2, depth, chk) - }) - }).collect::<Vec<_>>(); + use std::num::Int; + let iterations = 2.pow((max_depth - depth + min_depth) as usize); + Thread::scoped(move || inner(depth, iterations)) + }).collect::<Vec<_>>(); for message in messages.into_iter() { println!("{}", message.join().ok().unwrap()); diff --git a/src/test/bench/shootout-fannkuch-redux.rs b/src/test/bench/shootout-fannkuch-redux.rs index e8e8ac484852..daabae88bdf6 100644 --- a/src/test/bench/shootout-fannkuch-redux.rs +++ b/src/test/bench/shootout-fannkuch-redux.rs @@ -103,7 +103,7 @@ impl Perm { let d = idx / self.fact[i] as i32; self.cnt[i] = d; idx %= self.fact[i] as i32; - for (place, val) in pp.iter_mut().zip(self.perm.p[..(i+1)].iter()) { + for (place, val) in pp.iter_mut().zip(self.perm.p[..i+1].iter()) { *place = (*val) as u8 } diff --git a/src/test/bench/shootout-fasta.rs b/src/test/bench/shootout-fasta.rs index e9da34615c19..1b849cd12f57 100644 --- a/src/test/bench/shootout-fasta.rs +++ b/src/test/bench/shootout-fasta.rs @@ -97,7 +97,7 @@ fn make_fasta<W: Writer, I: Iterator<Item=u8>>( } n -= nb; line[nb] = '\n' as u8; - try!(wr.write(&line[..(nb+1)])); + try!(wr.write(&line[..nb+1])); } Ok(()) } diff --git a/src/test/bench/shootout-k-nucleotide-pipes.rs b/src/test/bench/shootout-k-nucleotide-pipes.rs index 03268b401933..fdaeb9e74f59 100644 --- a/src/test/bench/shootout-k-nucleotide-pipes.rs +++ b/src/test/bench/shootout-k-nucleotide-pipes.rs @@ -101,11 +101,11 @@ fn windows_with_carry<F>(bb: &[u8], nn: uint, mut it: F) -> Vec<u8> where let len = bb.len(); while ii < len - (nn - 1u) { - it(&bb[ii..(ii+nn)]); + it(&bb[ii..ii+nn]); ii += 1u; } - return bb[(len - (nn - 1u))..len].to_vec(); + return bb[len - (nn - 1u)..len].to_vec(); } fn make_sequence_processor(sz: uint, diff --git a/src/test/bench/shootout-regex-dna.rs b/src/test/bench/shootout-regex-dna.rs deleted file mode 100644 index 074c05923129..000000000000 --- a/src/test/bench/shootout-regex-dna.rs +++ /dev/null @@ -1,126 +0,0 @@ -// The Computer Language Benchmarks Game -// http://benchmarksgame.alioth.debian.org/ -// -// contributed by the Rust Project Developers - -// Copyright (c) 2014 The Rust Project Developers -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// - Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// - Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in -// the documentation and/or other materials provided with the -// distribution. -// -// - Neither the name of "The Computer Language Benchmarks Game" nor -// the name of "The Computer Language Shootout Benchmarks" nor the -// names of its contributors may be used to endorse or promote -// products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED -// OF THE POSSIBILITY OF SUCH DAMAGE. - -// ignore-stage1 -// ignore-cross-compile #12102 - -#![feature(box_syntax)] - -extern crate regex; - -use std::io; -use regex::{NoExpand, Regex}; -use std::sync::{Arc, Future}; - -macro_rules! regex { - ($e:expr) => (Regex::new($e).unwrap()) -} - -fn count_matches(seq: &str, variant: &Regex) -> int { - let mut n = 0; - for _ in variant.find_iter(seq) { - n += 1; - } - n -} - -fn main() { - let mut rdr = if std::os::getenv("RUST_BENCH").is_some() { - let fd = io::File::open(&Path::new("shootout-k-nucleotide.data")); - box io::BufferedReader::new(fd) as Box<io::Reader> - } else { - box io::stdin() as Box<io::Reader> - }; - let mut seq = rdr.read_to_string().unwrap(); - let ilen = seq.len(); - - seq = regex!(">[^\n]*\n|\n").replace_all(seq.as_slice(), NoExpand("")); - let seq_arc = Arc::new(seq.clone()); // copy before it moves - let clen = seq.len(); - - let mut seqlen = Future::spawn(move|| { - let substs = vec![ - (regex!("B"), "(c|g|t)"), - (regex!("D"), "(a|g|t)"), - (regex!("H"), "(a|c|t)"), - (regex!("K"), "(g|t)"), - (regex!("M"), "(a|c)"), - (regex!("N"), "(a|c|g|t)"), - (regex!("R"), "(a|g)"), - (regex!("S"), "(c|g)"), - (regex!("V"), "(a|c|g)"), - (regex!("W"), "(a|t)"), - (regex!("Y"), "(c|t)"), - ]; - let mut seq = seq; - for (re, replacement) in substs.into_iter() { - seq = re.replace_all(seq.as_slice(), NoExpand(replacement)); - } - seq.len() - }); - - let variants = vec![ - regex!("agggtaaa|tttaccct"), - regex!("[cgt]gggtaaa|tttaccc[acg]"), - regex!("a[act]ggtaaa|tttacc[agt]t"), - regex!("ag[act]gtaaa|tttac[agt]ct"), - regex!("agg[act]taaa|ttta[agt]cct"), - regex!("aggg[acg]aaa|ttt[cgt]ccct"), - regex!("agggt[cgt]aa|tt[acg]accct"), - regex!("agggta[cgt]a|t[acg]taccct"), - regex!("agggtaa[cgt]|[acg]ttaccct"), - ]; - let (mut variant_strs, mut counts) = (vec!(), vec!()); - for variant in variants.into_iter() { - let seq_arc_copy = seq_arc.clone(); - variant_strs.push(variant.to_string()); - counts.push(Future::spawn(move|| { - count_matches(seq_arc_copy.as_slice(), &variant) - })); - } - - for (i, variant) in variant_strs.iter().enumerate() { - println!("{} {}", variant, counts[i].get()); - } - println!(""); - println!("{}", ilen); - println!("{}", clen); - println!("{}", seqlen.get()); -} diff --git a/src/test/compile-fail-fulldeps/gated-plugin.rs b/src/test/compile-fail-fulldeps/gated-plugin.rs index 89090d5f38ab..be9e57e2d195 100644 --- a/src/test/compile-fail-fulldeps/gated-plugin.rs +++ b/src/test/compile-fail-fulldeps/gated-plugin.rs @@ -11,8 +11,7 @@ // aux-build:macro_crate_test.rs // ignore-stage1 -#[plugin] #[no_link] +#[plugin] #[no_link] extern crate macro_crate_test; //~^ ERROR compiler plugins are experimental and possibly buggy -extern crate macro_crate_test; fn main() {} diff --git a/src/test/compile-fail/blind-item-block-item-shadow.rs b/src/test/compile-fail/blind-item-block-item-shadow.rs new file mode 100644 index 000000000000..d4adaa042b2b --- /dev/null +++ b/src/test/compile-fail/blind-item-block-item-shadow.rs @@ -0,0 +1,20 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +mod foo { pub struct Bar; } + +fn main() { + { + struct Bar; + use foo::Bar; + //~^ ERROR import `Bar` conflicts with type in this module + //~^^ ERROR import `Bar` conflicts with value in this module + } +} diff --git a/src/test/compile-fail/blind-item-block-middle.rs b/src/test/compile-fail/blind-item-block-middle.rs new file mode 100644 index 000000000000..fbb0730f0146 --- /dev/null +++ b/src/test/compile-fail/blind-item-block-middle.rs @@ -0,0 +1,18 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +mod foo { struct bar; } + +fn main() { + let bar = 5; + //~^ ERROR declaration of `bar` shadows an enum variant or unit-like struct in scope + use foo::bar; + //~^ ERROR imports are not allowed after non-item statements +} diff --git a/src/test/run-make/test-shard-completeness/main.rs b/src/test/compile-fail/blind-item-item-shadow.rs similarity index 69% rename from src/test/run-make/test-shard-completeness/main.rs rename to src/test/compile-fail/blind-item-item-shadow.rs index 5eabd630b093..9f21d6a92340 100644 --- a/src/test/run-make/test-shard-completeness/main.rs +++ b/src/test/compile-fail/blind-item-item-shadow.rs @@ -1,4 +1,4 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -8,9 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![crate_type = "lib"] +mod foo { pub mod foo { } } -#[test] -fn test_1() { } -#[test] -fn test_2() { } +use foo::foo; //~ ERROR import `foo` conflicts with existing submodule + +fn main() {} diff --git a/src/test/compile-fail/lint-renaming.rs b/src/test/compile-fail/blind-item-local-shadow.rs similarity index 60% rename from src/test/compile-fail/lint-renaming.rs rename to src/test/compile-fail/blind-item-local-shadow.rs index 7ffec37772fe..a28f5f6e5571 100644 --- a/src/test/compile-fail/lint-renaming.rs +++ b/src/test/compile-fail/blind-item-local-shadow.rs @@ -1,4 +1,4 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -8,9 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Check that lint deprecation works - -#[deny(unused_variable)] //~ warning: lint unused_variable has been renamed to unused_variables -pub fn main() { - let x = 0u8; //~ error: unused variable: +mod bar { + pub fn foo() -> bool { true } +} + +fn main() { + let foo = |&:| false; + use bar::foo; + //~^ ERROR imports are not allowed after non-item statements + assert_eq!(foo(), false); } diff --git a/src/test/compile-fail/dst-index.rs b/src/test/compile-fail/dst-index.rs index 2a66b87fece3..876c98298dc5 100644 --- a/src/test/compile-fail/dst-index.rs +++ b/src/test/compile-fail/dst-index.rs @@ -12,7 +12,7 @@ // can't be used as rvalues use std::ops::Index; -use std::fmt::Show; +use std::fmt::Debug; struct S; @@ -31,9 +31,9 @@ struct T; impl Copy for T {} impl Index<usize> for T { - type Output = Show + 'static; + type Output = Debug + 'static; - fn index<'a>(&'a self, idx: &usize) -> &'a (Show + 'static) { + fn index<'a>(&'a self, idx: &usize) -> &'a (Debug + 'static) { static x: usize = 42; &x } diff --git a/src/test/compile-fail/hrtb-precedence-of-plus-error-message.rs b/src/test/compile-fail/hrtb-precedence-of-plus-error-message.rs index 41a0be37add4..db67249bbd93 100644 --- a/src/test/compile-fail/hrtb-precedence-of-plus-error-message.rs +++ b/src/test/compile-fail/hrtb-precedence-of-plus-error-message.rs @@ -19,17 +19,17 @@ trait Bar { struct Foo<'a> { a: &'a Bar+'a, //~^ ERROR E0178 - //~^^ NOTE perhaps you meant `&'a (Bar + 'a)`? + //~^^ HELP perhaps you meant `&'a (Bar + 'a)`? b: &'a mut Bar+'a, //~^ ERROR E0178 - //~^^ NOTE perhaps you meant `&'a mut (Bar + 'a)`? + //~^^ HELP perhaps you meant `&'a mut (Bar + 'a)`? c: Box<Bar+'a>, // OK, no paren needed in this context d: fn() -> Bar+'a, //~^ ERROR E0178 - //~^^ NOTE perhaps you forgot parentheses + //~^^ HELP perhaps you forgot parentheses //~^^^ WARN deprecated syntax } diff --git a/src/test/compile-fail/issue-14853.rs b/src/test/compile-fail/issue-14853.rs index 22ba54fea146..51deb99a4f2c 100644 --- a/src/test/compile-fail/issue-14853.rs +++ b/src/test/compile-fail/issue-14853.rs @@ -8,12 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::fmt::Show; +use std::fmt::Debug; trait Str {} trait Something { - fn yay<T: Show>(_: Option<Self>, thing: &[T]); + fn yay<T: Debug>(_: Option<Self>, thing: &[T]); } struct X { data: u32 } diff --git a/src/test/compile-fail/issue-15094.rs b/src/test/compile-fail/issue-15094.rs index 5b33069b5950..2c03a9e07332 100644 --- a/src/test/compile-fail/issue-15094.rs +++ b/src/test/compile-fail/issue-15094.rs @@ -12,19 +12,19 @@ use std::{fmt, ops}; -struct Shower<T> { +struct Debuger<T> { x: T } -impl<T: fmt::Show> ops::Fn<(), ()> for Shower<T> { +impl<T: fmt::Debug> ops::Fn<(), ()> for Debuger<T> { fn call(&self, _args: ()) { //~^ ERROR `call` has an incompatible type for trait: expected "rust-call" fn, found "Rust" fn println!("{:?}", self.x); } } -fn make_shower<T>(x: T) -> Shower<T> { - Shower { x: x } +fn make_shower<T>(x: T) -> Debuger<T> { + Debuger { x: x } } pub fn main() { diff --git a/src/test/run-make/dep-info-custom/lib.rs b/src/test/compile-fail/issue-21356.rs similarity index 78% rename from src/test/run-make/dep-info-custom/lib.rs rename to src/test/compile-fail/issue-21356.rs index 14baa8ca55a3..979534ab30cd 100644 --- a/src/test/run-make/dep-info-custom/lib.rs +++ b/src/test/compile-fail/issue-21356.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![crate_name="foo"] +macro_rules! test { ($wrong:t_ty ..) => () } + //~^ ERROR: unrecognized builtin nonterminal `t_ty` -pub mod foo; -pub mod bar; +fn main() {} diff --git a/src/test/compile-fail/lint-type-limits.rs b/src/test/compile-fail/lint-type-limits.rs index a2bc464ac497..3eae12f234fe 100644 --- a/src/test/compile-fail/lint-type-limits.rs +++ b/src/test/compile-fail/lint-type-limits.rs @@ -10,7 +10,7 @@ #![allow(dead_code)] -// compile-flags: -D type-limits +// compile-flags: -D unused-comparisons fn main() { } fn foo() { diff --git a/src/test/compile-fail/liveness-use-after-send.rs b/src/test/compile-fail/liveness-use-after-send.rs index 4ba24800f5d3..a49339ecd7f2 100644 --- a/src/test/compile-fail/liveness-use-after-send.rs +++ b/src/test/compile-fail/liveness-use-after-send.rs @@ -8,13 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn send<T:Send + std::fmt::Show>(ch: _chan<T>, data: T) { +fn send<T:Send + std::fmt::Debug>(ch: _chan<T>, data: T) { println!("{:?}", ch); println!("{:?}", data); panic!(); } -#[derive(Show)] +#[derive(Debug)] struct _chan<T>(isize); // Tests that "log(debug, message);" is flagged as using diff --git a/src/test/compile-fail/method-suggestion-no-duplication.rs b/src/test/compile-fail/method-suggestion-no-duplication.rs new file mode 100644 index 000000000000..627fc6f0b05f --- /dev/null +++ b/src/test/compile-fail/method-suggestion-no-duplication.rs @@ -0,0 +1,22 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// issue #21405 + +fn foo<F>(f: F) where F: FnMut(usize) {} + +fn main() { + foo(|s| s.is_empty()); + //~^ ERROR does not implement any method + //~^^ HELP #1: `core::slice::SliceExt` + //~^^^ HELP #2: `core::str::StrExt` + //~^^^^ HELP #3: `collections::slice::SliceExt` + //~^^^^^ HELP #4: `collections::str::StrExt` +} diff --git a/src/test/compile-fail/range-1.rs b/src/test/compile-fail/range-1.rs index 9888c0856953..fdae5f795469 100644 --- a/src/test/compile-fail/range-1.rs +++ b/src/test/compile-fail/range-1.rs @@ -21,6 +21,6 @@ pub fn main() { // Unsized type. let arr: &[_] = &[1us, 2, 3]; - let range = (*arr)..; + let range = *arr..; //~^ ERROR the trait `core::marker::Sized` is not implemented } diff --git a/src/test/compile-fail/range-2.rs b/src/test/compile-fail/range-2.rs index 6d176ca3700b..9d89f4b05c5b 100644 --- a/src/test/compile-fail/range-2.rs +++ b/src/test/compile-fail/range-2.rs @@ -12,7 +12,7 @@ pub fn main() { let r = { - (&42is)..&42 + &42is..&42 //~^ ERROR borrowed value does not live long enough //~^^ ERROR borrowed value does not live long enough }; diff --git a/src/test/compile-fail/issue-9957.rs b/src/test/compile-fail/range-3.rs similarity index 75% rename from src/test/compile-fail/issue-9957.rs rename to src/test/compile-fail/range-3.rs index b1204e828900..fe79165236f8 100644 --- a/src/test/compile-fail/issue-9957.rs +++ b/src/test/compile-fail/range-3.rs @@ -8,8 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub extern crate core; //~ ERROR: `pub` visibility is not allowed +// Test range syntax - syntax errors. -fn main() { - pub use std::usize; //~ ERROR: imports in functions are never reachable -} +pub fn main() { + let r = 1..2..3; + //~^ ERROR expected one of `.`, `;`, or an operator, found `..` +} \ No newline at end of file diff --git a/src/test/compile-fail/range-4.rs b/src/test/compile-fail/range-4.rs new file mode 100644 index 000000000000..bbd6ae289cce --- /dev/null +++ b/src/test/compile-fail/range-4.rs @@ -0,0 +1,16 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test range syntax - syntax errors. + +pub fn main() { + let r = ..1..2; + //~^ ERROR expected one of `.`, `;`, or an operator, found `..` +} \ No newline at end of file diff --git a/src/test/compile-fail/regions-assoc-type-region-bound-in-trait-not-met.rs b/src/test/compile-fail/regions-assoc-type-region-bound-in-trait-not-met.rs new file mode 100644 index 000000000000..f833361e3b50 --- /dev/null +++ b/src/test/compile-fail/regions-assoc-type-region-bound-in-trait-not-met.rs @@ -0,0 +1,31 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that the compiler checks that arbitrary region bounds declared +// in the trait must be satisfied on the impl. Issue #20890. + +trait Foo<'a> { type Value: 'a; } + +impl<'a> Foo<'a> for &'a i16 { + // OK. + type Value = &'a i32; +} + +impl<'a> Foo<'static> for &'a i32 { + //~^ ERROR cannot infer + type Value = &'a i32; +} + +impl<'a,'b> Foo<'b> for &'a i64 { + //~^ ERROR cannot infer + type Value = &'a i32; +} + +fn main() { } diff --git a/src/test/compile-fail/regions-assoc-type-static-bound-in-trait-not-met.rs b/src/test/compile-fail/regions-assoc-type-static-bound-in-trait-not-met.rs new file mode 100644 index 000000000000..0871d8b01f6e --- /dev/null +++ b/src/test/compile-fail/regions-assoc-type-static-bound-in-trait-not-met.rs @@ -0,0 +1,26 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that the compiler checks that the 'static bound declared in +// the trait must be satisfied on the impl. Issue #20890. + +trait Foo { type Value: 'static; } + +impl<'a> Foo for &'a i32 { + //~^ ERROR cannot infer + type Value = &'a i32; +} + +impl<'a> Foo for i32 { + // OK. + type Value = i32; +} + +fn main() { } diff --git a/src/test/compile-fail/require-parens-for-chained-comparison.rs b/src/test/compile-fail/require-parens-for-chained-comparison.rs index 7513815ad730..f5d8c5748147 100644 --- a/src/test/compile-fail/require-parens-for-chained-comparison.rs +++ b/src/test/compile-fail/require-parens-for-chained-comparison.rs @@ -19,5 +19,5 @@ fn main() { f<X>(); //~^ ERROR: Chained comparison operators require parentheses - //~^^ HELP: Use ::< instead of < if you meant to specify type arguments. + //~^^ HELP: use ::< instead of < if you meant to specify type arguments } diff --git a/src/test/compile-fail/shadowed-lifetime.rs b/src/test/compile-fail/shadowed-lifetime.rs index 57a2744d8f88..bf8a8f5046e7 100644 --- a/src/test/compile-fail/shadowed-lifetime.rs +++ b/src/test/compile-fail/shadowed-lifetime.rs @@ -13,18 +13,18 @@ struct Foo<'a>(&'a isize); impl<'a> Foo<'a> { - //~^ HELP shadowed lifetime `'a` declared here + //~^ NOTE shadowed lifetime `'a` declared here fn shadow_in_method<'a>(&'a self) -> &'a isize { //~^ WARNING lifetime name `'a` shadows another lifetime name that is already in scope - //~| HELP deprecated + //~| NOTE deprecated self.0 } fn shadow_in_type<'b>(&'b self) -> &'b isize { - //~^ HELP shadowed lifetime `'b` declared here + //~^ NOTE shadowed lifetime `'b` declared here let x: for<'b> fn(&'b isize) = panic!(); //~^ WARNING lifetime name `'b` shadows another lifetime name that is already in scope - //~| HELP deprecated + //~| NOTE deprecated self.0 } diff --git a/src/test/compile-fail/struct-fields-hints-no-dupe.rs b/src/test/compile-fail/struct-fields-hints-no-dupe.rs new file mode 100644 index 000000000000..8df9ffd6cc73 --- /dev/null +++ b/src/test/compile-fail/struct-fields-hints-no-dupe.rs @@ -0,0 +1,24 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct A { + foo : i32, + car : i32, + barr : i32 +} + +fn main() { + let a = A { + foo : 5, + bar : 42,//~ ERROR structure `A` has no field named `bar` + //~^ HELP did you mean `barr`? + car : 9, + }; +} diff --git a/src/test/compile-fail/struct-fields-hints.rs b/src/test/compile-fail/struct-fields-hints.rs new file mode 100644 index 000000000000..37001f1e60a0 --- /dev/null +++ b/src/test/compile-fail/struct-fields-hints.rs @@ -0,0 +1,23 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct A { + foo : i32, + car : i32, + barr : i32 +} + +fn main() { + let a = A { + foo : 5, + bar : 42,//~ ERROR structure `A` has no field named `bar` + //~^ HELP did you mean `car`? + }; +} diff --git a/src/test/compile-fail/struct-fields-typo.rs b/src/test/compile-fail/struct-fields-typo.rs new file mode 100644 index 000000000000..c897dc55204b --- /dev/null +++ b/src/test/compile-fail/struct-fields-typo.rs @@ -0,0 +1,24 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct BuildData { + foo: isize, + bar: f32 +} + +fn main() { + let foo = BuildData { + foo: 0, + bar: 0.5, + }; + let x = foo.baa;//~ ERROR attempted access of field `baa` on type `BuildData` + //~^ HELP did you mean `bar`? + println!("{}", x); +} diff --git a/src/test/compile-fail/unnecessary-private.rs b/src/test/compile-fail/unnecessary-private.rs index 6e6ffd23c4a8..e3707292f249 100644 --- a/src/test/compile-fail/unnecessary-private.rs +++ b/src/test/compile-fail/unnecessary-private.rs @@ -1,4 +1,4 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -9,6 +9,7 @@ // except according to those terms. fn main() { + pub use std::uint; //~ ERROR: visibility has no effect pub struct A; //~ ERROR: visibility has no effect pub enum B {} //~ ERROR: visibility has no effect pub trait C { //~ ERROR: visibility has no effect diff --git a/src/test/compile-fail/unsized2.rs b/src/test/compile-fail/unsized2.rs index 604f7ba3255c..a47d81e38ccb 100644 --- a/src/test/compile-fail/unsized2.rs +++ b/src/test/compile-fail/unsized2.rs @@ -16,5 +16,5 @@ pub fn main() { f<type>(); //~^ ERROR expected identifier, found keyword `type` //~^^ ERROR: Chained comparison operators require parentheses - //~^^^ HELP: Use ::< instead of < if you meant to specify type arguments. + //~^^^ HELP: use ::< instead of < if you meant to specify type arguments } diff --git a/src/test/compile-fail/warn-path-statement.rs b/src/test/compile-fail/warn-path-statement.rs index 304900df776c..d205e2a2e4e0 100644 --- a/src/test/compile-fail/warn-path-statement.rs +++ b/src/test/compile-fail/warn-path-statement.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -D path-statement +// compile-flags: -D path-statements fn main() { let x = 10is; diff --git a/src/test/debuginfo/associated-types.rs b/src/test/debuginfo/associated-types.rs new file mode 100644 index 000000000000..6a624e39e326 --- /dev/null +++ b/src/test/debuginfo/associated-types.rs @@ -0,0 +1,152 @@ +// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-android: FIXME(#10381) +// min-lldb-version: 310 + +// compile-flags:-g + +// === GDB TESTS =================================================================================== +// gdb-command:run + +// gdb-command:print arg +// gdb-check:$1 = {b = -1, b1 = 0} +// gdb-command:continue + +// gdb-command:print inferred +// gdb-check:$2 = 1 +// gdb-command:print explicitly +// gdb-check:$3 = 1 +// gdb-command:continue + +// gdb-command:print arg +// gdb-check:$4 = 2 +// gdb-command:continue + +// gdb-command:print arg +// gdb-check:$5 = {4, 5} +// gdb-command:continue + +// gdb-command:print a +// gdb-check:$6 = 6 +// gdb-command:print b +// gdb-check:$7 = 7 +// gdb-command:continue + +// gdb-command:print a +// gdb-check:$8 = 8 +// gdb-command:print b +// gdb-check:$9 = 9 +// gdb-command:continue + +// === LLDB TESTS ================================================================================== +// lldb-command:run + +// lldb-command:print arg +// lldb-check:[...]$0 = Struct<i32> { b: -1, b1: 0 } +// lldb-command:continue + +// lldb-command:print inferred +// lldb-check:[...]$1 = 1 +// lldb-command:print explicitly +// lldb-check:[...]$2 = 1 +// lldb-command:continue + +// lldb-command:print arg +// lldb-check:[...]$3 = 2 +// lldb-command:continue + +// lldb-command:print arg +// lldb-check:[...]$4 = (4, 5) +// lldb-command:continue + +// lldb-command:print a +// lldb-check:[...]$5 = 6 +// lldb-command:print b +// lldb-check:[...]$6 = 7 +// lldb-command:continue + +// lldb-command:print a +// lldb-check:[...]$7 = 8 +// lldb-command:print b +// lldb-check:[...]$8 = 9 +// lldb-command:continue + +#![allow(unused_variables)] +#![allow(dead_code)] +#![omit_gdb_pretty_printer_section] + +trait TraitWithAssocType { + type Type; + + fn get_value(&self) -> Self::Type; +} +impl TraitWithAssocType for i32 { + type Type = i64; + + fn get_value(&self) -> i64 { *self as i64 } +} + +struct Struct<T: TraitWithAssocType> { + b: T, + b1: T::Type, +} + +enum Enum<T: TraitWithAssocType> { + Variant1(T, T::Type), + Variant2(T::Type, T) +} + +fn assoc_struct<T: TraitWithAssocType>(arg: Struct<T>) { + zzz(); // #break +} + +fn assoc_local<T: TraitWithAssocType>(x: T) { + let inferred = x.get_value(); + let explicitly: T::Type = x.get_value(); + + zzz(); // #break +} + +fn assoc_arg<T: TraitWithAssocType>(arg: T::Type) { + zzz(); // #break +} + +fn assoc_return_value<T: TraitWithAssocType>(arg: T) -> T::Type { + return arg.get_value(); +} + +fn assoc_tuple<T: TraitWithAssocType>(arg: (T, T::Type)) { + zzz(); // #break +} + +fn assoc_enum<T: TraitWithAssocType>(arg: Enum<T>) { + + match arg { + Enum::Variant1(a, b) => { + zzz(); // #break + } + Enum::Variant2(a, b) => { + zzz(); // #break + } + } +} + +fn main() { + assoc_struct(Struct { b: -1i32, b1: 0i64 }); + assoc_local(1i32); + assoc_arg::<i32>(2i64); + assoc_return_value(3i32); + assoc_tuple((4i32, 5i64)); + assoc_enum(Enum::Variant1(6i32, 7i64)); + assoc_enum(Enum::Variant2(8i64, 9i32)); +} + +fn zzz() { () } \ No newline at end of file diff --git a/src/test/debuginfo/issue7712.rs b/src/test/debuginfo/issue7712.rs index 94458a7fb4bc..124cdfb436ca 100644 --- a/src/test/debuginfo/issue7712.rs +++ b/src/test/debuginfo/issue7712.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags:--debuginfo=1 +// compile-flags:-C debuginfo=1 // min-lldb-version: 310 pub trait TraitWithDefaultMethod : Sized { diff --git a/src/test/debuginfo/lexical-scope-in-parameterless-closure.rs b/src/test/debuginfo/lexical-scope-in-parameterless-closure.rs index b2617c577425..0050b9273e82 100644 --- a/src/test/debuginfo/lexical-scope-in-parameterless-closure.rs +++ b/src/test/debuginfo/lexical-scope-in-parameterless-closure.rs @@ -11,7 +11,7 @@ // ignore-android: FIXME(#10381) // min-lldb-version: 310 -// compile-flags:--debuginfo=1 +// compile-flags:-C debuginfo=1 // gdb-command:run // lldb-command:run diff --git a/src/test/debuginfo/limited-debuginfo.rs b/src/test/debuginfo/limited-debuginfo.rs index 00de4497cedb..76a0fd583956 100644 --- a/src/test/debuginfo/limited-debuginfo.rs +++ b/src/test/debuginfo/limited-debuginfo.rs @@ -12,7 +12,7 @@ // ignore-lldb -// compile-flags:--debuginfo=1 +// compile-flags:-C debuginfo=1 // Make sure functions have proper names // gdb-command:info functions diff --git a/src/test/debuginfo/vec-slices.rs b/src/test/debuginfo/vec-slices.rs index 949dffaac068..3ceb3946f3c0 100644 --- a/src/test/debuginfo/vec-slices.rs +++ b/src/test/debuginfo/vec-slices.rs @@ -9,6 +9,7 @@ // except according to those terms. // ignore-android: FIXME(#10381) +// ignore-windows // min-lldb-version: 310 // compile-flags:-g diff --git a/src/test/pretty/issue-4264.pp b/src/test/pretty/issue-4264.pp index dac6e628d10d..c18d076c0d31 100644 --- a/src/test/pretty/issue-4264.pp +++ b/src/test/pretty/issue-4264.pp @@ -1,8 +1,8 @@ #![no_std] -#[macro_use] -extern crate "std" as std; #[prelude_import] use std::prelude::v1::*; +#[macro_use] +extern crate "std" as std; // 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. diff --git a/src/test/run-fail/assert-eq-macro-panic.rs b/src/test/run-fail/assert-eq-macro-panic.rs index 4b1a420cb788..69ed025070b4 100644 --- a/src/test/run-fail/assert-eq-macro-panic.rs +++ b/src/test/run-fail/assert-eq-macro-panic.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern:assertion failed: `(left == right) && (right == left)` (left: `14i`, right: `15i`) +// error-pattern:assertion failed: `(left == right) && (right == left)` (left: `14`, right: `15`) fn main() { assert_eq!(14i,15i); diff --git a/src/test/run-fail/issue-20971.rs b/src/test/run-fail/issue-20971.rs new file mode 100644 index 000000000000..818f0e139419 --- /dev/null +++ b/src/test/run-fail/issue-20971.rs @@ -0,0 +1,34 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Regression test for Issue #20971. + +// error-pattern:Hello, world! + +pub trait Parser { + type Input; + fn parse(&mut self, input: <Self as Parser>::Input); +} + +impl Parser for () { + type Input = (); + fn parse(&mut self, input: ()) { + + } +} + +pub fn many() -> Box<Parser<Input=<() as Parser>::Input> + 'static> { + panic!("Hello, world!") +} + +fn main() { + many() + .parse(()); +} diff --git a/src/test/run-make/crate-data-smoke/Makefile b/src/test/run-make/crate-data-smoke/Makefile index 093796e1dc2c..1afda457411d 100644 --- a/src/test/run-make/crate-data-smoke/Makefile +++ b/src/test/run-make/crate-data-smoke/Makefile @@ -1,10 +1,10 @@ -include ../tools.mk all: - [ `$(RUSTC) --print-crate-name crate.rs` = "foo" ] - [ `$(RUSTC) --print-file-name crate.rs` = "$(call BIN,foo)" ] - [ `$(RUSTC) --print-file-name --crate-type=lib \ + [ `$(RUSTC) --print crate-name crate.rs` = "foo" ] + [ `$(RUSTC) --print file-names crate.rs` = "$(call BIN,foo)" ] + [ `$(RUSTC) --print file-names --crate-type=lib \ --test crate.rs` = "$(call BIN,foo)" ] - [ `$(RUSTC) --print-file-name --test lib.rs` = "$(call BIN,mylib)" ] - $(RUSTC) --print-file-name lib.rs - $(RUSTC) --print-file-name rlib.rs + [ `$(RUSTC) --print file-names --test lib.rs` = "$(call BIN,mylib)" ] + $(RUSTC) --print file-names lib.rs + $(RUSTC) --print file-names rlib.rs diff --git a/src/test/run-make/dep-info-custom/Makefile b/src/test/run-make/dep-info-custom/Makefile deleted file mode 100644 index efa6dfe981bb..000000000000 --- a/src/test/run-make/dep-info-custom/Makefile +++ /dev/null @@ -1,25 +0,0 @@ --include ../tools.mk - -# FIXME: ignore freebsd/windows -# (windows: see `../dep-info/Makefile`) -ifneq ($(shell uname),FreeBSD) -ifndef IS_WINDOWS -all: - $(RUSTC) --dep-info $(TMPDIR)/custom-deps-file.d --crate-type=lib lib.rs - sleep 1 - touch foo.rs - -rm -f $(TMPDIR)/done - $(MAKE) -drf Makefile.foo - rm $(TMPDIR)/done - pwd - $(MAKE) -drf Makefile.foo - rm $(TMPDIR)/done && exit 1 || exit 0 -else -all: - -endif - -else -all: - -endif diff --git a/src/test/run-make/dep-info-custom/Makefile.foo b/src/test/run-make/dep-info-custom/Makefile.foo deleted file mode 100644 index 88be7630e839..000000000000 --- a/src/test/run-make/dep-info-custom/Makefile.foo +++ /dev/null @@ -1,7 +0,0 @@ -LIB := $(shell $(RUSTC) --print file-names --crate-type=lib lib.rs) - -$(TMPDIR)/$(LIB): - $(RUSTC) --dep-info $(TMPDIR)/custom-deps-file.d --crate-type=lib lib.rs - touch $(TMPDIR)/done - --include $(TMPDIR)/custom-deps-file.d diff --git a/src/test/run-make/dep-info-spaces/Makefile b/src/test/run-make/dep-info-spaces/Makefile index 72dca3d3c90d..eda8cb700810 100644 --- a/src/test/run-make/dep-info-spaces/Makefile +++ b/src/test/run-make/dep-info-spaces/Makefile @@ -5,7 +5,7 @@ ifneq ($(shell uname),FreeBSD) ifndef IS_WINDOWS all: - $(RUSTC) --dep-info $(TMPDIR)/custom-deps-file.d --crate-type=lib lib.rs + $(RUSTC) --emit link,dep-info --crate-type=lib lib.rs sleep 1 touch 'foo foo.rs' -rm -f $(TMPDIR)/done diff --git a/src/test/run-make/dep-info-spaces/Makefile.foo b/src/test/run-make/dep-info-spaces/Makefile.foo index 0e187565d6d3..2f4cc486d866 100644 --- a/src/test/run-make/dep-info-spaces/Makefile.foo +++ b/src/test/run-make/dep-info-spaces/Makefile.foo @@ -1,7 +1,7 @@ -LIB := $(shell $(RUSTC) --print-file-name --crate-type=lib lib.rs) +LIB := $(shell $(RUSTC) --print file-names --crate-type=lib lib.rs) $(TMPDIR)/$(LIB): - $(RUSTC) --dep-info $(TMPDIR)/custom-deps-file.d --crate-type=lib lib.rs + $(RUSTC) --emit link,dep-info --crate-type=lib lib.rs touch $(TMPDIR)/done --include $(TMPDIR)/custom-deps-file.d +-include $(TMPDIR)/lib.d diff --git a/src/test/run-make/dep-info/Makefile b/src/test/run-make/dep-info/Makefile index 6835ef34b0b2..a1828cd1f5d7 100644 --- a/src/test/run-make/dep-info/Makefile +++ b/src/test/run-make/dep-info/Makefile @@ -7,7 +7,7 @@ ifneq ($(shell uname),FreeBSD) ifndef IS_WINDOWS all: - $(RUSTC) --dep-info --crate-type=lib lib.rs + $(RUSTC) --emit dep-info,link --crate-type=lib lib.rs sleep 2 touch foo.rs -rm -f $(TMPDIR)/done diff --git a/src/test/run-make/error-writing-dependencies/Makefile b/src/test/run-make/error-writing-dependencies/Makefile index 9f91618bda49..89fbfa0a1bf9 100644 --- a/src/test/run-make/error-writing-dependencies/Makefile +++ b/src/test/run-make/error-writing-dependencies/Makefile @@ -2,7 +2,7 @@ all: # Let's get a nice error message - $(RUSTC) foo.rs --dep-info foo/bar/baz 2>&1 | \ + $(BARE_RUSTC) foo.rs --emit dep-info --out-dir foo/bar/baz 2>&1 | \ grep "error writing dependencies" # Make sure the filename shows up - $(RUSTC) foo.rs --dep-info foo/bar/baz 2>&1 | grep "baz" + $(BARE_RUSTC) foo.rs --emit dep-info --out-dir foo/bar/baz 2>&1 | grep "baz" diff --git a/src/test/run-make/graphviz-flowgraph/Makefile b/src/test/run-make/graphviz-flowgraph/Makefile index 4ac8cb7ae1da..1533729de945 100644 --- a/src/test/run-make/graphviz-flowgraph/Makefile +++ b/src/test/run-make/graphviz-flowgraph/Makefile @@ -13,7 +13,7 @@ all: $(patsubst %.rs,$(TMPDIR)/%.check,$(FILES)) RUSTC_LIB=$(RUSTC) --crate-type=lib define FIND_LAST_BLOCK -LASTBLOCKNUM_$(1) := $(shell $(RUSTC_LIB) --pretty=expanded,identified $(1) \ +LASTBLOCKNUM_$(1) := $(shell $(RUSTC_LIB) -Z unstable-options --pretty=expanded,identified $(1) \ | grep block | tail -1 | sed -e 's@.*/\* block \([0-9]*\) \*/.*@\1@') diff --git a/src/test/run-make/issue-19371/foo.rs b/src/test/run-make/issue-19371/foo.rs index fe7df6411599..867008cd2591 100644 --- a/src/test/run-make/issue-19371/foo.rs +++ b/src/test/run-make/issue-19371/foo.rs @@ -44,7 +44,7 @@ fn basic_sess(sysroot: Path) -> Session { opts.output_types = vec![OutputTypeExe]; opts.maybe_sysroot = Some(sysroot); - let descriptions = Registry::new(&rustc::DIAGNOSTICS); + let descriptions = Registry::new(&rustc::diagnostics::DIAGNOSTICS); let sess = build_session(opts, None, descriptions); sess } diff --git a/src/test/run-make/pretty-expanded-hygiene/Makefile b/src/test/run-make/pretty-expanded-hygiene/Makefile index 11763446437d..136d7643ade3 100644 --- a/src/test/run-make/pretty-expanded-hygiene/Makefile +++ b/src/test/run-make/pretty-expanded-hygiene/Makefile @@ -3,7 +3,8 @@ REPLACEMENT := s/[0-9][0-9]*\#[0-9][0-9]*/$(shell date)/g all: - $(RUSTC) -o $(TMPDIR)/input.out --pretty expanded,hygiene input.rs + $(RUSTC) -o $(TMPDIR)/input.out -Z unstable-options \ + --pretty expanded,hygiene input.rs # the name/ctxt numbers are very internals-dependent and thus # change relatively frequently, and testing for their exact values diff --git a/src/test/run-make/pretty-expanded/Makefile b/src/test/run-make/pretty-expanded/Makefile index dda441ae3d1e..7a8dc8d871ca 100644 --- a/src/test/run-make/pretty-expanded/Makefile +++ b/src/test/run-make/pretty-expanded/Makefile @@ -1,4 +1,5 @@ -include ../tools.mk all: - $(RUSTC) -o $(TMPDIR)/input.expanded.rs --pretty=expanded input.rs + $(RUSTC) -o $(TMPDIR)/input.expanded.rs -Z unstable-options \ + --pretty=expanded input.rs diff --git a/src/test/run-make/pretty-print-path-suffix/Makefile b/src/test/run-make/pretty-print-path-suffix/Makefile index f58a6527ac68..9f0c3f5120df 100644 --- a/src/test/run-make/pretty-print-path-suffix/Makefile +++ b/src/test/run-make/pretty-print-path-suffix/Makefile @@ -1,9 +1,9 @@ -include ../tools.mk all: - $(RUSTC) -o $(TMPDIR)/foo.out --pretty normal=foo input.rs - $(RUSTC) -o $(TMPDIR)/nest_foo.out --pretty normal=nest::foo input.rs - $(RUSTC) -o $(TMPDIR)/foo_method.out --pretty normal=foo_method input.rs + $(RUSTC) -o $(TMPDIR)/foo.out -Z unstable-options --pretty normal=foo input.rs + $(RUSTC) -o $(TMPDIR)/nest_foo.out -Z unstable-options --pretty normal=nest::foo input.rs + $(RUSTC) -o $(TMPDIR)/foo_method.out -Z unstable-options --pretty normal=foo_method input.rs diff -u $(TMPDIR)/foo.out foo.pp diff -u $(TMPDIR)/nest_foo.out nest_foo.pp diff -u $(TMPDIR)/foo_method.out foo_method.pp diff --git a/src/test/run-make/pretty-print-to-file/Makefile b/src/test/run-make/pretty-print-to-file/Makefile index 1c1242ada8a6..8909dee11f0f 100644 --- a/src/test/run-make/pretty-print-to-file/Makefile +++ b/src/test/run-make/pretty-print-to-file/Makefile @@ -1,5 +1,5 @@ -include ../tools.mk all: - $(RUSTC) -o $(TMPDIR)/input.out --pretty=normal input.rs + $(RUSTC) -o $(TMPDIR)/input.out --pretty=normal -Z unstable-options input.rs diff -u $(TMPDIR)/input.out input.pp diff --git a/src/test/run-make/rustdoc-negative-impl/Makefile b/src/test/run-make/rustdoc-negative-impl/Makefile new file mode 100644 index 000000000000..1316ee256e14 --- /dev/null +++ b/src/test/run-make/rustdoc-negative-impl/Makefile @@ -0,0 +1,6 @@ +-include ../tools.mk + +all: foo.rs + $(HOST_RPATH_ENV) $(RUSTDOC) -w html -o $(TMPDIR)/doc foo.rs + $(HTMLDOCCK) $(TMPDIR)/doc foo.rs + diff --git a/src/test/run-make/rustdoc-negative-impl/foo.rs b/src/test/run-make/rustdoc-negative-impl/foo.rs new file mode 100644 index 000000000000..eaa3af865637 --- /dev/null +++ b/src/test/run-make/rustdoc-negative-impl/foo.rs @@ -0,0 +1,22 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(optin_builtin_traits)] + +// @matches foo/struct.Alpha.html '//pre' "pub struct Alpha" +pub struct Alpha; +// @matches foo/struct.Bravo.html '//pre' "pub struct Bravo<B>" +pub struct Bravo<B>; + +// @matches foo/struct.Alpha.html '//*[@class="impl"]//code' "impl !.*Send.* for .*Alpha" +impl !Send for Alpha {} + +// @matches foo/struct.Bravo.html '//*[@class="impl"]//code' "impl<B> !.*Send.* for .*Bravo.*<B>" +impl<B> !Send for Bravo<B> {} diff --git a/src/test/run-make/test-shard-completeness/Makefile b/src/test/run-make/test-shard-completeness/Makefile deleted file mode 100644 index 16ab12a82526..000000000000 --- a/src/test/run-make/test-shard-completeness/Makefile +++ /dev/null @@ -1,7 +0,0 @@ --include ../tools.mk - -all: - # Running all the shards should hit every test - $(RUSTC) --test main.rs - $(call RUN,main) --test-shard 1.2 | grep "test_1 ... ok" - $(call RUN,main) --test-shard 2.2 | grep "test_2 ... ok" diff --git a/src/test/run-make/tools.mk b/src/test/run-make/tools.mk index 971295405aae..1c791f0690ca 100644 --- a/src/test/run-make/tools.mk +++ b/src/test/run-make/tools.mk @@ -5,7 +5,8 @@ HOST_RPATH_ENV = \ TARGET_RPATH_ENV = \ $(LD_LIB_PATH_ENVVAR)="$(TMPDIR):$(TARGET_RPATH_DIR):$($(LD_LIB_PATH_ENVVAR))" -RUSTC := $(HOST_RPATH_ENV) $(RUSTC) --out-dir $(TMPDIR) -L $(TMPDIR) +BARE_RUSTC := $(HOST_RPATH_ENV) $(RUSTC) +RUSTC := $(BARE_RUSTC) --out-dir $(TMPDIR) -L $(TMPDIR) CC := $(CC) -L $(TMPDIR) HTMLDOCCK := $(PYTHON) $(S)/src/etc/htmldocck.py diff --git a/src/test/run-pass/blind-item-mixed-crate-use-item.rs b/src/test/run-pass/blind-item-mixed-crate-use-item.rs new file mode 100644 index 000000000000..80c73e5e60b5 --- /dev/null +++ b/src/test/run-pass/blind-item-mixed-crate-use-item.rs @@ -0,0 +1,33 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:blind-item-mixed-crate-use-item-foo.rs +// aux-build:blind-item-mixed-crate-use-item-foo2.rs + +mod m { + pub fn f<T>(_: T, _: (), _: ()) { } + pub fn g<T>(_: T, _: (), _: ()) { } +} + +const BAR: () = (); +struct Data; +use m::f; +extern crate "blind-item-mixed-crate-use-item-foo" as foo; + +fn main() { + const BAR2: () = (); + struct Data2; + use m::g; + + extern crate "blind-item-mixed-crate-use-item-foo2" as foo2; + + f(Data, BAR, foo::X); + g(Data2, BAR2, foo2::Y); +} diff --git a/src/test/run-pass/blind-item-mixed-use-item.rs b/src/test/run-pass/blind-item-mixed-use-item.rs new file mode 100644 index 000000000000..a3dad01acf17 --- /dev/null +++ b/src/test/run-pass/blind-item-mixed-use-item.rs @@ -0,0 +1,27 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +mod m { + pub fn f<T>(_: T, _: ()) { } + pub fn g<T>(_: T, _: ()) { } +} + +const BAR: () = (); +struct Data; +use m::f; + +fn main() { + const BAR2: () = (); + struct Data2; + use m::g; + + f(Data, BAR); + g(Data2, BAR2); +} diff --git a/src/test/run-pass/cfg_attr.rs b/src/test/run-pass/cfg_attr.rs index 7e508d91c877..9bef7f70420e 100644 --- a/src/test/run-pass/cfg_attr.rs +++ b/src/test/run-pass/cfg_attr.rs @@ -10,44 +10,44 @@ // compile-flags:--cfg set1 --cfg set2 #![allow(dead_code)] -use std::fmt::Show; +use std::fmt::Debug; -struct NotShowable; +struct NotDebugable; -#[cfg_attr(set1, derive(Show))] +#[cfg_attr(set1, derive(Debug))] struct Set1; -#[cfg_attr(notset, derive(Show))] -struct Notset(NotShowable); +#[cfg_attr(notset, derive(Debug))] +struct Notset(NotDebugable); -#[cfg_attr(not(notset), derive(Show))] +#[cfg_attr(not(notset), derive(Debug))] struct NotNotset; -#[cfg_attr(not(set1), derive(Show))] -struct NotSet1(NotShowable); +#[cfg_attr(not(set1), derive(Debug))] +struct NotSet1(NotDebugable); -#[cfg_attr(all(set1, set2), derive(Show))] +#[cfg_attr(all(set1, set2), derive(Debug))] struct AllSet1Set2; -#[cfg_attr(all(set1, notset), derive(Show))] -struct AllSet1Notset(NotShowable); +#[cfg_attr(all(set1, notset), derive(Debug))] +struct AllSet1Notset(NotDebugable); -#[cfg_attr(any(set1, notset), derive(Show))] +#[cfg_attr(any(set1, notset), derive(Debug))] struct AnySet1Notset; -#[cfg_attr(any(notset, notset2), derive(Show))] -struct AnyNotsetNotset2(NotShowable); +#[cfg_attr(any(notset, notset2), derive(Debug))] +struct AnyNotsetNotset2(NotDebugable); -#[cfg_attr(all(not(notset), any(set1, notset)), derive(Show))] +#[cfg_attr(all(not(notset), any(set1, notset)), derive(Debug))] struct Complex; -#[cfg_attr(any(notset, not(any(set1, notset))), derive(Show))] -struct ComplexNot(NotShowable); +#[cfg_attr(any(notset, not(any(set1, notset))), derive(Debug))] +struct ComplexNot(NotDebugable); -#[cfg_attr(any(target_endian = "little", target_endian = "big"), derive(Show))] +#[cfg_attr(any(target_endian = "little", target_endian = "big"), derive(Debug))] struct KeyValue; -fn is_show<T: Show>() {} +fn is_show<T: Debug>() {} fn main() { is_show::<Set1>(); diff --git a/src/test/run-pass/coerce-expect-unsized.rs b/src/test/run-pass/coerce-expect-unsized.rs index f590e6e07283..ee19d9e69b30 100644 --- a/src/test/run-pass/coerce-expect-unsized.rs +++ b/src/test/run-pass/coerce-expect-unsized.rs @@ -11,7 +11,7 @@ #![allow(unknown_features)] #![feature(box_syntax)] -use std::fmt::Show; +use std::fmt::Debug; // Check that coercions apply at the pointer level and don't cause // rvalue expressions to be unsized. See #20169 for more information. @@ -21,16 +21,21 @@ pub fn main() { let _: Box<[int]> = box if true { [1, 2, 3] } else { [1, 3, 4] }; let _: Box<[int]> = box match true { true => [1, 2, 3], false => [1, 3, 4] }; let _: Box<Fn(int) -> _> = box { |x| (x as u8) }; - let _: Box<Show> = box if true { false } else { true }; - let _: Box<Show> = box match true { true => 'a', false => 'b' }; + let _: Box<Debug> = box if true { false } else { true }; + let _: Box<Debug> = box match true { true => 'a', false => 'b' }; let _: &[int] = &{ [1, 2, 3] }; let _: &[int] = &if true { [1, 2, 3] } else { [1, 3, 4] }; let _: &[int] = &match true { true => [1, 2, 3], false => [1, 3, 4] }; let _: &Fn(int) -> _ = &{ |x| (x as u8) }; - let _: &Show = &if true { false } else { true }; - let _: &Show = &match true { true => 'a', false => 'b' }; + let _: &Debug = &if true { false } else { true }; + let _: &Debug = &match true { true => 'a', false => 'b' }; let _: Box<[int]> = Box::new([1, 2, 3]); let _: Box<Fn(int) -> _> = Box::new(|x| (x as u8)); + + let _: Vec<Box<Fn(int) -> _>> = vec![ + Box::new(|x| (x as u8)), + box |x| (x as i16 as u8), + ]; } diff --git a/src/test/run-pass/coherence-where-clause.rs b/src/test/run-pass/coherence-where-clause.rs index 99c475b72072..78b603690fda 100644 --- a/src/test/run-pass/coherence-where-clause.rs +++ b/src/test/run-pass/coherence-where-clause.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::fmt::Show; +use std::fmt::Debug; use std::default::Default; trait MyTrait { @@ -23,7 +23,7 @@ impl<T> MyTrait for T } } -#[derive(Clone,Show,PartialEq)] +#[derive(Clone,Debug,PartialEq)] struct MyType { dummy: uint } @@ -35,7 +35,7 @@ impl MyTrait for MyType { } fn test_eq<M>(m: M, n: M) -where M : MyTrait + Show + PartialEq +where M : MyTrait + Debug + PartialEq { assert_eq!(m.get(), n); } diff --git a/src/test/run-pass/const-block.rs b/src/test/run-pass/const-block.rs index 84acd3c4ecd7..cdb96e5dcbfc 100644 --- a/src/test/run-pass/const-block.rs +++ b/src/test/run-pass/const-block.rs @@ -14,7 +14,7 @@ use std::marker::Sync; struct Foo { - a: uint, + a: usize, b: *const () } @@ -24,27 +24,24 @@ fn foo<T>(a: T) -> T { a } -static BLOCK_INTEGRAL: uint = { 1 }; +static BLOCK_INTEGRAL: usize = { 1 }; static BLOCK_EXPLICIT_UNIT: () = { () }; static BLOCK_IMPLICIT_UNIT: () = { }; static BLOCK_FLOAT: f64 = { 1.0 }; -static BLOCK_ENUM: Option<uint> = { Some(100) }; +static BLOCK_ENUM: Option<usize> = { Some(100) }; static BLOCK_STRUCT: Foo = { Foo { a: 12, b: 0 as *const () } }; -static BLOCK_UNSAFE: uint = unsafe { 1000 }; +static BLOCK_UNSAFE: usize = unsafe { 1000 }; -// FIXME: #13970 -// static BLOCK_FN_INFERRED: fn(uint) -> uint = { foo }; +static BLOCK_FN_INFERRED: fn(usize) -> usize = { foo }; -// FIXME: #13971 -// static BLOCK_FN: fn(uint) -> uint = { foo::<uint> }; +static BLOCK_FN: fn(usize) -> usize = { foo::<usize> }; -// FIXME: #13972 -// static BLOCK_ENUM_CONSTRUCTOR: fn(uint) -> Option<uint> = { Some }; +static BLOCK_ENUM_CONSTRUCTOR: fn(usize) -> Option<usize> = { Some }; -// FIXME: #13973 -// static BLOCK_UNSAFE_SAFE_PTR: &'static int = unsafe { &*(0xdeadbeef as *int) }; -// static BLOCK_UNSAFE_SAFE_PTR_2: &'static int = unsafe { -// static X: *int = 0xdeadbeef as *int; +// FIXME #13972 +// static BLOCK_UNSAFE_SAFE_PTR: &'static isize = unsafe { &*(0xdeadbeef as *const isize) }; +// static BLOCK_UNSAFE_SAFE_PTR_2: &'static isize = unsafe { +// const X: *const isize = 0xdeadbeef as *const isize; // &*X // }; @@ -57,17 +54,10 @@ pub fn main() { assert_eq!(BLOCK_STRUCT.b, 0 as *const ()); assert_eq!(BLOCK_ENUM, Some(100)); assert_eq!(BLOCK_UNSAFE, 1000); - - // FIXME: #13970 - // assert_eq!(BLOCK_FN_INFERRED(300), 300); - - // FIXME: #13971 - // assert_eq!(BLOCK_FN(300), 300); - - // FIXME: #13972 - // assert_eq!(BLOCK_ENUM_CONSTRUCTOR(200), Some(200)); - - // FIXME: #13973 - // assert_eq!(BLOCK_UNSAFE_SAFE_PTR as *int as uint, 0xdeadbeef_u); - // assert_eq!(BLOCK_UNSAFE_SAFE_PTR_2 as *int as uint, 0xdeadbeef_u); + assert_eq!(BLOCK_FN_INFERRED(300), 300); + assert_eq!(BLOCK_FN(300), 300); + assert_eq!(BLOCK_ENUM_CONSTRUCTOR(200), Some(200)); + // FIXME #13972 + // assert_eq!(BLOCK_UNSAFE_SAFE_PTR as *const isize as usize, 0xdeadbeef_us); + // assert_eq!(BLOCK_UNSAFE_SAFE_PTR_2 as *const isize as usize, 0xdeadbeef_us); } diff --git a/src/test/run-pass/crate-name-attr-used.rs b/src/test/run-pass/crate-name-attr-used.rs index 95c7d331264e..f04a760e5f65 100644 --- a/src/test/run-pass/crate-name-attr-used.rs +++ b/src/test/run-pass/crate-name-attr-used.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags:--crate-name crate-name-attr-used -F unused-attribute +// compile-flags:--crate-name crate-name-attr-used -F unused-attributes #![crate_name = "crate-name-attr-used"] diff --git a/src/test/run-pass/deriving-show-2.rs b/src/test/run-pass/deriving-show-2.rs index 8465f521e439..acd07bc98d31 100644 --- a/src/test/run-pass/deriving-show-2.rs +++ b/src/test/run-pass/deriving-show-2.rs @@ -10,39 +10,39 @@ use std::fmt; -#[derive(Show)] +#[derive(Debug)] enum A {} -#[derive(Show)] +#[derive(Debug)] enum B { B1, B2, B3 } -#[derive(Show)] +#[derive(Debug)] enum C { C1(int), C2(B), C3(String) } -#[derive(Show)] +#[derive(Debug)] enum D { D1{ a: int } } -#[derive(Show)] +#[derive(Debug)] struct E; -#[derive(Show)] +#[derive(Debug)] struct F(int); -#[derive(Show)] +#[derive(Debug)] struct G(int, int); -#[derive(Show)] +#[derive(Debug)] struct H { a: int } -#[derive(Show)] +#[derive(Debug)] struct I { a: int, b: int } -#[derive(Show)] +#[derive(Debug)] struct J(Custom); struct Custom; -impl fmt::Show for Custom { +impl fmt::Debug for Custom { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "yay") } } -trait ToShow { +trait ToDebug { fn to_show(&self) -> String; } -impl<T: fmt::Show> ToShow for T { +impl<T: fmt::Debug> ToDebug for T { fn to_show(&self) -> String { format!("{:?}", self) } @@ -51,12 +51,12 @@ impl<T: fmt::Show> ToShow for T { pub fn main() { assert_eq!(B::B1.to_show(), "B1".to_string()); assert_eq!(B::B2.to_show(), "B2".to_string()); - assert_eq!(C::C1(3).to_show(), "C1(3i)".to_string()); + assert_eq!(C::C1(3).to_show(), "C1(3)".to_string()); assert_eq!(C::C2(B::B2).to_show(), "C2(B2)".to_string()); - assert_eq!(D::D1{ a: 2 }.to_show(), "D1 { a: 2i }".to_string()); + assert_eq!(D::D1{ a: 2 }.to_show(), "D1 { a: 2 }".to_string()); assert_eq!(E.to_show(), "E".to_string()); - assert_eq!(F(3).to_show(), "F(3i)".to_string()); - assert_eq!(G(3, 4).to_show(), "G(3i, 4i)".to_string()); - assert_eq!(I{ a: 2, b: 4 }.to_show(), "I { a: 2i, b: 4i }".to_string()); + assert_eq!(F(3).to_show(), "F(3)".to_string()); + assert_eq!(G(3, 4).to_show(), "G(3, 4)".to_string()); + assert_eq!(I{ a: 2, b: 4 }.to_show(), "I { a: 2, b: 4 }".to_string()); assert_eq!(J(Custom).to_show(), "J(yay)".to_string()); } diff --git a/src/test/run-pass/deriving-show.rs b/src/test/run-pass/deriving-show.rs index 99c73dd94a6b..7986b97685f6 100644 --- a/src/test/run-pass/deriving-show.rs +++ b/src/test/run-pass/deriving-show.rs @@ -8,16 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[derive(Show)] +#[derive(Debug)] struct Unit; -#[derive(Show)] +#[derive(Debug)] struct Tuple(int, uint); -#[derive(Show)] +#[derive(Debug)] struct Struct { x: int, y: uint } -#[derive(Show)] +#[derive(Debug)] enum Enum { Nullary, Variant(int, uint), @@ -32,9 +32,9 @@ macro_rules! t { pub fn main() { t!(Unit, "Unit"); - t!(Tuple(1, 2), "Tuple(1i, 2u)"); - t!(Struct { x: 1, y: 2 }, "Struct { x: 1i, y: 2u }"); + t!(Tuple(1, 2), "Tuple(1, 2)"); + t!(Struct { x: 1, y: 2 }, "Struct { x: 1, y: 2 }"); t!(Enum::Nullary, "Nullary"); - t!(Enum::Variant(1, 2), "Variant(1i, 2u)"); - t!(Enum::StructVariant { x: 1, y: 2 }, "StructVariant { x: 1i, y: 2u }"); + t!(Enum::Variant(1, 2), "Variant(1, 2)"); + t!(Enum::StructVariant { x: 1, y: 2 }, "StructVariant { x: 1, y: 2 }"); } diff --git a/src/test/run-pass/dst-index.rs b/src/test/run-pass/dst-index.rs index dfb28fc9344d..0c7ecfcefff3 100644 --- a/src/test/run-pass/dst-index.rs +++ b/src/test/run-pass/dst-index.rs @@ -12,7 +12,7 @@ // work and don't ICE. use std::ops::Index; -use std::fmt::Show; +use std::fmt::Debug; struct S; @@ -27,16 +27,16 @@ impl Index<uint> for S { struct T; impl Index<uint> for T { - type Output = Show + 'static; + type Output = Debug + 'static; - fn index<'a>(&'a self, idx: &uint) -> &'a (Show + 'static) { + fn index<'a>(&'a self, idx: &uint) -> &'a (Debug + 'static) { static X: uint = 42; - &X as &(Show + 'static) + &X as &(Debug + 'static) } } fn main() { assert_eq!(&S[0], "hello"); &T[0]; - // let x = &x as &Show; + // let x = &x as &Debug; } diff --git a/src/test/run-pass/ifmt.rs b/src/test/run-pass/ifmt.rs index dbc23a63bbad..56de6726bfb2 100644 --- a/src/test/run-pass/ifmt.rs +++ b/src/test/run-pass/ifmt.rs @@ -32,7 +32,7 @@ impl fmt::UpperHex for B { f.write_str("adios") } } -impl fmt::String for C { +impl fmt::Display for C { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad_integral(true, "☃", "123") } @@ -62,8 +62,8 @@ pub fn main() { t!(format!("{}", 10i), "10"); t!(format!("{}", 10u), "10"); t!(format!("{:?}", '☃'), "'\\u{2603}'"); - t!(format!("{:?}", 10i), "10i"); - t!(format!("{:?}", 10u), "10u"); + t!(format!("{:?}", 10i), "10"); + t!(format!("{:?}", 10u), "10"); t!(format!("{:?}", "true"), "\"true\""); t!(format!("{:?}", "foo\nbar"), "\"foo\\nbar\""); t!(format!("{:o}", 10u), "12"); @@ -71,22 +71,22 @@ pub fn main() { t!(format!("{:X}", 10u), "A"); t!(format!("{}", "foo"), "foo"); t!(format!("{}", "foo".to_string()), "foo"); - t!(format!("{:p}", 0x1234 as *const int), "0x1234"); - t!(format!("{:p}", 0x1234 as *mut int), "0x1234"); + t!(format!("{:p}", 0x1234 as *const isize), "0x1234"); + t!(format!("{:p}", 0x1234 as *mut isize), "0x1234"); t!(format!("{:x}", A), "aloha"); t!(format!("{:X}", B), "adios"); t!(format!("foo {} ☃☃☃☃☃☃", "bar"), "foo bar ☃☃☃☃☃☃"); t!(format!("{1} {0}", 0i, 1i), "1 0"); - t!(format!("{foo} {bar}", foo=0i, bar=1i), "0 1"); - t!(format!("{foo} {1} {bar} {0}", 0i, 1i, foo=2i, bar=3i), "2 1 3 0"); + t!(format!("{foo} {bar}", foo=0i, bar=1is), "0 1"); + t!(format!("{foo} {1} {bar} {0}", 0is, 1is, foo=2is, bar=3is), "2 1 3 0"); t!(format!("{} {0}", "a"), "a a"); t!(format!("{foo_bar}", foo_bar=1i), "1"); t!(format!("{}", 5i + 5i), "10"); t!(format!("{:#4}", C), "☃123"); // FIXME(#20676) - // let a: &fmt::Show = &1i; - // t!(format!("{:?}", a), "1i"); + // let a: &fmt::Debug = &1i; + // t!(format!("{:?}", a), "1"); // Formatting strings and their arguments @@ -153,7 +153,7 @@ pub fn main() { // make sure that format! doesn't cause spurious unused-unsafe warnings when // it's inside of an outer unsafe block unsafe { - let a: int = ::std::mem::transmute(3u); + let a: isize = ::std::mem::transmute(3u); format!("{}", a); } @@ -214,8 +214,8 @@ fn test_format_args() { fn test_order() { // Make sure format!() arguments are always evaluated in a left-to-right // ordering - fn foo() -> int { - static mut FOO: int = 0; + fn foo() -> isize { + static mut FOO: isize = 0; unsafe { FOO += 1; FOO diff --git a/src/test/run-pass/init-large-type.rs b/src/test/run-pass/init-large-type.rs index 0534d0c054f4..8ee6054f8ba5 100644 --- a/src/test/run-pass/init-large-type.rs +++ b/src/test/run-pass/init-large-type.rs @@ -14,6 +14,8 @@ #![feature(intrinsics)] +use std::thread::Thread; + extern "rust-intrinsic" { pub fn init<T>() -> T; } @@ -21,5 +23,8 @@ extern "rust-intrinsic" { const SIZE: usize = 1024 * 1024; fn main() { - let _memory: [u8; SIZE] = unsafe { init() }; + // do the test in a new thread to avoid (spurious?) stack overflows + let _ = Thread::scoped(|| { + let _memory: [u8; SIZE] = unsafe { init() }; + }).join(); } diff --git a/src/test/run-pass/issue-20676.rs b/src/test/run-pass/issue-20676.rs index fd99fc01a23d..01a2322ae939 100644 --- a/src/test/run-pass/issue-20676.rs +++ b/src/test/run-pass/issue-20676.rs @@ -15,6 +15,6 @@ use std::fmt; fn main() { - let a: &fmt::Show = &1_i32; + let a: &fmt::Debug = &1_i32; format!("{:?}", a); } diff --git a/src/test/run-pass/issue-20763-1.rs b/src/test/run-pass/issue-20763-1.rs new file mode 100644 index 000000000000..911ee715da28 --- /dev/null +++ b/src/test/run-pass/issue-20763-1.rs @@ -0,0 +1,32 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +trait T0 { type O; } + +struct S<A>(A); +impl<A> T0 for S<A> { type O = A; } + +trait T1: T0 { + // this looks okay but as we see below, `f` is unusable + fn m0<F: Fn(<Self as T0>::O) -> bool>(self, f: F) -> bool; +} + +// complains about the bounds on F here not being required by the trait +impl<A> T1 for S<A> { + fn m0<F: Fn(A) -> bool>(self, f: F) -> bool { f(self.0) } +} + +// // complains about mismatched types: <S<A> as T0>::O vs. A +// impl<A> T1 for S<A> +// { +// fn m0<F: Fn(<Self as T0>::O) -> bool>(self, f: F) -> bool { f(self.0) } +// } + +fn main() { } diff --git a/src/test/run-pass/issue-20763-2.rs b/src/test/run-pass/issue-20763-2.rs new file mode 100644 index 000000000000..a17c7b6ade48 --- /dev/null +++ b/src/test/run-pass/issue-20763-2.rs @@ -0,0 +1,27 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +trait T0 { type O; } + +struct S<A>(A); +impl<A> T0 for S<A> { type O = A; } + +trait T1: T0 { + // this looks okay but as we see below, `f` is unusable + fn m0<F: Fn(<Self as T0>::O) -> bool>(self, f: F) -> bool; +} + +// complains about mismatched types: <S<A> as T0>::O vs. A +impl<A> T1 for S<A> +{ + fn m0<F: Fn(<Self as T0>::O) -> bool>(self, f: F) -> bool { f(self.0) } +} + +fn main() { } diff --git a/src/test/run-pass/issue-20797.rs b/src/test/run-pass/issue-20797.rs new file mode 100644 index 000000000000..089b6f319751 --- /dev/null +++ b/src/test/run-pass/issue-20797.rs @@ -0,0 +1,94 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-android +// ignore-windows + +// Regression test for #20797. + +use std::default::Default; +use std::io::IoResult; +use std::io::fs; +use std::io::fs::PathExtensions; + +/// A strategy for acquiring more subpaths to walk. +pub trait Strategy { + type P: PathExtensions; + /// Get additional subpaths from a given path. + fn get_more(&self, item: &Self::P) -> IoResult<Vec<Self::P>>; + /// Determine whether a path should be walked further. + /// This is run against each item from `get_more()`. + fn prune(&self, p: &Self::P) -> bool; +} + +/// The basic fully-recursive strategy. Nothing is pruned. +#[derive(Copy, Default)] +pub struct Recursive; + +impl Strategy for Recursive { + type P = Path; + fn get_more(&self, p: &Path) -> IoResult<Vec<Path>> { fs::readdir(p) } + + fn prune(&self, _: &Path) -> bool { false } +} + +/// A directory walker of `P` using strategy `S`. +pub struct Subpaths<S: Strategy> { + stack: Vec<S::P>, + strategy: S, +} + +impl<S: Strategy> Subpaths<S> { + /// Create a directory walker with a root path and strategy. + pub fn new(p: &S::P, strategy: S) -> IoResult<Subpaths<S>> { + let stack = try!(strategy.get_more(p)); + Ok(Subpaths { stack: stack, strategy: strategy }) + } +} + +impl<S: Default + Strategy> Subpaths<S> { + /// Create a directory walker with a root path and a default strategy. + pub fn walk(p: &S::P) -> IoResult<Subpaths<S>> { + Subpaths::new(p, Default::default()) + } +} + +impl<S: Default + Strategy> Default for Subpaths<S> { + fn default() -> Subpaths<S> { + Subpaths { stack: Vec::new(), strategy: Default::default() } + } +} + +impl<S: Strategy> Iterator for Subpaths<S> { + type Item = S::P; + fn next (&mut self) -> Option<S::P> { + let mut opt_path = self.stack.pop(); + while opt_path.is_some() && self.strategy.prune(opt_path.as_ref().unwrap()) { + opt_path = self.stack.pop(); + } + match opt_path { + Some(path) => { + if PathExtensions::is_dir(&path) { + let result = self.strategy.get_more(&path); + match result { + Ok(dirs) => { self.stack.extend(dirs.into_iter()); }, + Err(..) => { } + } + } + Some(path) + } + None => None, + } + } +} + +fn main() { + let mut walker: Subpaths<Recursive> = Subpaths::walk(&Path::new("/home")).unwrap(); +} diff --git a/src/test/run-pass/issue-20953.rs b/src/test/run-pass/issue-20953.rs new file mode 100644 index 000000000000..647302bbc930 --- /dev/null +++ b/src/test/run-pass/issue-20953.rs @@ -0,0 +1,19 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + let mut shrinker: Box<Iterator<Item=i32>> = Box::new(vec![1].into_iter()); + println!("{:?}", shrinker.next()); + for v in shrinker { assert!(false); } + + let mut shrinker: &mut Iterator<Item=i32> = &mut vec![1].into_iter(); + println!("{:?}", shrinker.next()); + for v in shrinker { assert!(false); } +} diff --git a/src/libregex/test/mod.rs b/src/test/run-pass/issue-21361.rs similarity index 63% rename from src/libregex/test/mod.rs rename to src/test/run-pass/issue-21361.rs index e11094b11747..bb20b3a32156 100644 --- a/src/libregex/test/mod.rs +++ b/src/test/run-pass/issue-21361.rs @@ -8,17 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -macro_rules! regex { - ($re:expr) => ( - match ::regex::Regex::new($re) { - Ok(re) => re, - Err(err) => panic!("{:?}", err), - } - ); +fn main() { + let v = vec![1, 2, 3]; + let boxed: Box<Iterator<Item=i32>> = Box::new(v.into_iter()); + assert_eq!(boxed.max(), Some(3)); + + let v = vec![1, 2, 3]; + let boxed: &mut Iterator<Item=i32> = &mut v.into_iter(); + assert_eq!(boxed.max(), Some(3)); } - -#[path = "bench.rs"] -mod dynamic_bench; -#[path = "tests.rs"] -mod dynamic_tests; - diff --git a/src/test/run-pass/issue-3559.rs b/src/test/run-pass/issue-3559.rs index 633832f424c8..0118fce4ec34 100644 --- a/src/test/run-pass/issue-3559.rs +++ b/src/test/run-pass/issue-3559.rs @@ -24,6 +24,6 @@ pub fn main() { let mut table = HashMap::new(); table.insert("one".to_string(), 1i); table.insert("two".to_string(), 2i); - assert!(check_strs(format!("{:?}", table).as_slice(), "HashMap {\"one\": 1i, \"two\": 2i}") || - check_strs(format!("{:?}", table).as_slice(), "HashMap {\"two\": 2i, \"one\": 1i}")); + assert!(check_strs(format!("{:?}", table).as_slice(), "HashMap {\"one\": 1, \"two\": 2}") || + check_strs(format!("{:?}", table).as_slice(), "HashMap {\"two\": 2, \"one\": 1}")); } diff --git a/src/test/run-pass/issue-4252.rs b/src/test/run-pass/issue-4252.rs index 3606aff05ff5..9d5f8576c633 100644 --- a/src/test/run-pass/issue-4252.rs +++ b/src/test/run-pass/issue-4252.rs @@ -11,28 +11,28 @@ #![feature(unsafe_destructor)] trait X { - fn call<T: std::fmt::Show>(&self, x: &T); - fn default_method<T: std::fmt::Show>(&self, x: &T) { + fn call<T: std::fmt::Debug>(&self, x: &T); + fn default_method<T: std::fmt::Debug>(&self, x: &T) { println!("X::default_method {:?}", x); } } -#[derive(Show)] +#[derive(Debug)] struct Y(int); -#[derive(Show)] +#[derive(Debug)] struct Z<T> { x: T } impl X for Y { - fn call<T: std::fmt::Show>(&self, x: &T) { + fn call<T: std::fmt::Debug>(&self, x: &T) { println!("X::call {:?} {:?}", self, x); } } #[unsafe_destructor] -impl<T: X + std::fmt::Show> Drop for Z<T> { +impl<T: X + std::fmt::Debug> Drop for Z<T> { fn drop(&mut self) { // These statements used to cause an ICE. self.x.call(self); diff --git a/src/test/run-pass/issue-8898.rs b/src/test/run-pass/issue-8898.rs index f845db9c4216..379b8f7700e5 100644 --- a/src/test/run-pass/issue-8898.rs +++ b/src/test/run-pass/issue-8898.rs @@ -8,17 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn assert_repr_eq<T: std::fmt::Show>(obj : T, expected : String) { +fn assert_repr_eq<T: std::fmt::Debug>(obj : T, expected : String) { assert_eq!(expected, format!("{:?}", obj)); } pub fn main() { - let abc = [1i, 2, 3]; + let abc = [1, 2, 3]; let tf = [true, false]; let x = [(), ()]; let slice = &x[..1]; - assert_repr_eq(&abc[], "[1i, 2i, 3i]".to_string()); + assert_repr_eq(&abc[], "[1, 2, 3]".to_string()); assert_repr_eq(&tf[], "[true, false]".to_string()); assert_repr_eq(&x[], "[(), ()]".to_string()); assert_repr_eq(slice, "[()]".to_string()); diff --git a/src/test/run-pass/log-knows-the-names-of-variants-in-std.rs b/src/test/run-pass/log-knows-the-names-of-variants-in-std.rs index 7fb2390b84b7..c4b45ae0f0e6 100644 --- a/src/test/run-pass/log-knows-the-names-of-variants-in-std.rs +++ b/src/test/run-pass/log-knows-the-names-of-variants-in-std.rs @@ -8,19 +8,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[derive(Clone, Show)] +#[derive(Clone, Debug)] enum foo { a(uint), b(String), } -fn check_log<T: std::fmt::Show>(exp: String, v: T) { +fn check_log<T: std::fmt::Debug>(exp: String, v: T) { assert_eq!(exp, format!("{:?}", v)); } pub fn main() { - let mut x = Some(foo::a(22u)); - let exp = "Some(a(22u))".to_string(); + let mut x = Some(foo::a(22)); + let exp = "Some(a(22))".to_string(); let act = format!("{:?}", x); assert_eq!(act, exp); check_log(exp, x); diff --git a/src/test/run-pass/log-knows-the-names-of-variants.rs b/src/test/run-pass/log-knows-the-names-of-variants.rs index 45fd2098dc42..e8852377957f 100644 --- a/src/test/run-pass/log-knows-the-names-of-variants.rs +++ b/src/test/run-pass/log-knows-the-names-of-variants.rs @@ -8,20 +8,20 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[derive(Show)] +#[derive(Debug)] enum foo { - a(uint), + a(usize), b(String), c, } -#[derive(Show)] +#[derive(Debug)] enum bar { d, e, f } pub fn main() { - assert_eq!("a(22u)".to_string(), format!("{:?}", foo::a(22u))); + assert_eq!("a(22)".to_string(), format!("{:?}", foo::a(22))); assert_eq!("c".to_string(), format!("{:?}", foo::c)); assert_eq!("d".to_string(), format!("{:?}", bar::d)); } diff --git a/src/test/compile-fail/view-items-at-top.rs b/src/test/run-pass/macro_with_super_2.rs similarity index 69% rename from src/test/compile-fail/view-items-at-top.rs rename to src/test/run-pass/macro_with_super_2.rs index 7b78a8d932b3..5c681b8e6e76 100644 --- a/src/test/compile-fail/view-items-at-top.rs +++ b/src/test/run-pass/macro_with_super_2.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -8,12 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern crate test; +// aux-build:macro_with_super_1.rs -fn f() { -} +#[macro_use] +extern crate macro_with_super_1; -use test::net; //~ ERROR `use` and `extern crate` declarations must precede items +declare!(); fn main() { + bbb::ccc(); } diff --git a/src/test/run-pass/multidispatch1.rs b/src/test/run-pass/multidispatch1.rs index 87d188418bdd..15df67e14882 100644 --- a/src/test/run-pass/multidispatch1.rs +++ b/src/test/run-pass/multidispatch1.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::fmt::Show; +use std::fmt::Debug; trait MyTrait<T> { fn get(&self) -> T; @@ -29,7 +29,7 @@ impl MyTrait<u8> for MyType { } fn test_eq<T,M>(m: M, v: T) -where T : Eq + Show, +where T : Eq + Debug, M : MyTrait<T> { assert_eq!(m.get(), v); diff --git a/src/test/run-pass/multidispatch2.rs b/src/test/run-pass/multidispatch2.rs index 1aa15cc59834..0c2652e6a7cb 100644 --- a/src/test/run-pass/multidispatch2.rs +++ b/src/test/run-pass/multidispatch2.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::fmt::Show; +use std::fmt::Debug; use std::default::Default; trait MyTrait<T> { @@ -34,7 +34,7 @@ impl MyTrait<uint> for MyType { } fn test_eq<T,M>(m: M, v: T) -where T : Eq + Show, +where T : Eq + Debug, M : MyTrait<T> { assert_eq!(m.get(), v); diff --git a/src/test/run-pass/no-landing-pads.rs b/src/test/run-pass/no-landing-pads.rs index 64e78c3483bb..c90c6ce87f09 100644 --- a/src/test/run-pass/no-landing-pads.rs +++ b/src/test/run-pass/no-landing-pads.rs @@ -26,6 +26,6 @@ fn main() { Thread::scoped(move|| -> () { let _a = A; panic!(); - }).join().unwrap_err(); + }).join().err().unwrap(); assert!(unsafe { !HIT }); } diff --git a/src/test/run-pass/overloaded-index-assoc-list.rs b/src/test/run-pass/overloaded-index-assoc-list.rs index 2e044227eb13..5e0523d70418 100644 --- a/src/test/run-pass/overloaded-index-assoc-list.rs +++ b/src/test/run-pass/overloaded-index-assoc-list.rs @@ -28,7 +28,7 @@ impl<K,V> AssociationList<K,V> { } } -impl<K: PartialEq + std::fmt::Show, V:Clone> Index<K> for AssociationList<K,V> { +impl<K: PartialEq + std::fmt::Debug, V:Clone> Index<K> for AssociationList<K,V> { type Output = V; fn index<'a>(&'a self, index: &K) -> &'a V { diff --git a/src/test/run-pass/ranges-precedence.rs b/src/test/run-pass/ranges-precedence.rs index f678eed8775c..c947220f1f85 100644 --- a/src/test/run-pass/ranges-precedence.rs +++ b/src/test/run-pass/ranges-precedence.rs @@ -48,5 +48,12 @@ fn main() { assert!(x == &a[3..]); for _i in 2+4..10-3 {} + + let i = 42; + for _ in 1..i {} + for _ in 1.. { break; } + + let x = [1]..[2]; + assert!(x == (([1])..([2]))); } diff --git a/src/test/run-pass/rec-align-u32.rs b/src/test/run-pass/rec-align-u32.rs index 5b91d5e930f9..05643b0b56ba 100644 --- a/src/test/run-pass/rec-align-u32.rs +++ b/src/test/run-pass/rec-align-u32.rs @@ -22,14 +22,14 @@ mod rusti { } // This is the type with the questionable alignment -#[derive(Show)] +#[derive(Debug)] struct Inner { c64: u32 } // This is the type that contains the type with the // questionable alignment, for testing -#[derive(Show)] +#[derive(Debug)] struct Outer { c8: u8, t: Inner @@ -66,6 +66,6 @@ pub fn main() { // because `inner`s alignment was 4. assert_eq!(mem::size_of::<Outer>(), m::size()); - assert_eq!(y, "Outer { c8: 22u8, t: Inner { c64: 44u32 } }".to_string()); + assert_eq!(y, "Outer { c8: 22, t: Inner { c64: 44 } }".to_string()); } } diff --git a/src/test/run-pass/rec-align-u64.rs b/src/test/run-pass/rec-align-u64.rs index 27941542d000..eaf76ef5714a 100644 --- a/src/test/run-pass/rec-align-u64.rs +++ b/src/test/run-pass/rec-align-u64.rs @@ -22,14 +22,14 @@ mod rusti { } // This is the type with the questionable alignment -#[derive(Show)] +#[derive(Debug)] struct Inner { c64: u64 } // This is the type that contains the type with the // questionable alignment, for testing -#[derive(Show)] +#[derive(Debug)] struct Outer { c8: u8, t: Inner @@ -95,6 +95,6 @@ pub fn main() { // because `Inner`s alignment was 4. assert_eq!(mem::size_of::<Outer>(), m::m::size()); - assert_eq!(y, "Outer { c8: 22u8, t: Inner { c64: 44u64 } }".to_string()); + assert_eq!(y, "Outer { c8: 22, t: Inner { c64: 44 } }".to_string()); } } diff --git a/src/test/run-pass/regions-assoc-type-region-bound.rs b/src/test/run-pass/regions-assoc-type-region-bound.rs new file mode 100644 index 000000000000..77e1a2147645 --- /dev/null +++ b/src/test/run-pass/regions-assoc-type-region-bound.rs @@ -0,0 +1,28 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that the compiler considers the 'a bound declared in the +// trait. Issue #20890. + +trait Foo<'a> { + type Value: 'a; + + fn get(&self) -> &'a Self::Value; +} + +fn takes_foo<'a,F: Foo<'a>>(f: &'a F) { + // This call would be illegal, because it results in &'a F::Value, + // and the only way we know that `F::Value : 'a` is because of the + // trait declaration. + + f.get(); +} + +fn main() { } diff --git a/src/test/run-pass/regions-assoc-type-static-bound.rs b/src/test/run-pass/regions-assoc-type-static-bound.rs new file mode 100644 index 000000000000..6b629a9035db --- /dev/null +++ b/src/test/run-pass/regions-assoc-type-static-bound.rs @@ -0,0 +1,22 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that the compiler considers the 'static bound declared in the +// trait. Issue #20890. + +trait Foo { type Value: 'static; } + +fn require_static<T: 'static>() {} + +fn takes_foo<F: Foo>() { + require_static::<F::Value>() +} + +fn main() { } diff --git a/src/test/run-pass/rust-log-filter.rs b/src/test/run-pass/rust-log-filter.rs index 28d47f7aa9be..f7fa204d4539 100644 --- a/src/test/run-pass/rust-log-filter.rs +++ b/src/test/run-pass/rust-log-filter.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// exec-env:RUST_LOG=rust-log-filter/f.o +// exec-env:RUST_LOG=rust-log-filter/foo #![allow(unknown_features)] #![feature(box_syntax)] @@ -42,18 +42,14 @@ pub fn main() { let _t = Thread::spawn(move|| { log::set_logger(logger); - // our regex is "f.o" - // ensure it is a regex, and isn't anchored info!("foo"); info!("bar"); info!("foo bar"); info!("bar foo"); - info!("f1o"); }); assert_eq!(rx.recv().unwrap().as_slice(), "foo"); assert_eq!(rx.recv().unwrap().as_slice(), "foo bar"); assert_eq!(rx.recv().unwrap().as_slice(), "bar foo"); - assert_eq!(rx.recv().unwrap().as_slice(), "f1o"); assert!(rx.recv().is_err()); } diff --git a/src/test/run-pass/sepcomp-unwind.rs b/src/test/run-pass/sepcomp-unwind.rs index b8bb3b4e7f8c..f68dea04a087 100644 --- a/src/test/run-pass/sepcomp-unwind.rs +++ b/src/test/run-pass/sepcomp-unwind.rs @@ -36,5 +36,5 @@ mod b { } fn main() { - Thread::scoped(move|| { ::b::g() }).join().unwrap_err(); + Thread::scoped(move|| { ::b::g() }).join().err().unwrap(); } diff --git a/src/test/run-pass/show-boxed-slice.rs b/src/test/run-pass/show-boxed-slice.rs index fc0b501e9c52..f496765edca9 100644 --- a/src/test/run-pass/show-boxed-slice.rs +++ b/src/test/run-pass/show-boxed-slice.rs @@ -11,7 +11,7 @@ #![allow(unknown_features)] #![feature(box_syntax)] -#[derive(Show)] +#[derive(Debug)] struct Foo(Box<[u8]>); pub fn main() { diff --git a/src/test/run-pass/small-enums-with-fields.rs b/src/test/run-pass/small-enums-with-fields.rs index c793deaae2b2..fc45e107bb0e 100644 --- a/src/test/run-pass/small-enums-with-fields.rs +++ b/src/test/run-pass/small-enums-with-fields.rs @@ -10,7 +10,7 @@ use std::mem::size_of; -#[derive(PartialEq, Show)] +#[derive(PartialEq, Debug)] enum Either<T, U> { Left(T), Right(U) } macro_rules! check { @@ -29,14 +29,14 @@ macro_rules! check { pub fn main() { check!(Option<u8>, 2, None, "None", - Some(129u8), "Some(129u8)"); + Some(129u8), "Some(129)"); check!(Option<i16>, 4, None, "None", - Some(-20000i16), "Some(-20000i16)"); + Some(-20000i16), "Some(-20000)"); check!(Either<u8, i8>, 2, - Either::Left(132u8), "Left(132u8)", - Either::Right(-32i8), "Right(-32i8)"); + Either::Left(132u8), "Left(132)", + Either::Right(-32i8), "Right(-32)"); check!(Either<u8, i16>, 4, - Either::Left(132u8), "Left(132u8)", - Either::Right(-20000i16), "Right(-20000i16)"); + Either::Left(132u8), "Left(132)", + Either::Right(-20000i16), "Right(-20000)"); } diff --git a/src/test/run-pass/tag-align-shape.rs b/src/test/run-pass/tag-align-shape.rs index b88357252d8e..cc0a75181db9 100644 --- a/src/test/run-pass/tag-align-shape.rs +++ b/src/test/run-pass/tag-align-shape.rs @@ -8,12 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[derive(Show)] +#[derive(Debug)] enum a_tag { a_tag_var(u64) } -#[derive(Show)] +#[derive(Debug)] struct t_rec { c8: u8, t: a_tag @@ -23,5 +23,5 @@ pub fn main() { let x = t_rec {c8: 22u8, t: a_tag::a_tag_var(44u64)}; let y = format!("{:?}", x); println!("y = {:?}", y); - assert_eq!(y, "t_rec { c8: 22u8, t: a_tag_var(44u64) }".to_string()); + assert_eq!(y, "t_rec { c8: 22, t: a_tag_var(44) }".to_string()); } diff --git a/src/test/run-pass/unit-like-struct-drop-run.rs b/src/test/run-pass/unit-like-struct-drop-run.rs index 4c8665032828..3c50712b4647 100644 --- a/src/test/run-pass/unit-like-struct-drop-run.rs +++ b/src/test/run-pass/unit-like-struct-drop-run.rs @@ -26,6 +26,6 @@ pub fn main() { let _b = Foo; }).join(); - let s = x.unwrap_err().downcast::<&'static str>().unwrap(); + let s = x.err().unwrap().downcast::<&'static str>().ok().unwrap(); assert_eq!(s.as_slice(), "This panic should happen."); } diff --git a/src/test/run-pass/vec-macro-rvalue-scope.rs b/src/test/run-pass/vec-macro-rvalue-scope.rs new file mode 100644 index 000000000000..68dedfc6a2e6 --- /dev/null +++ b/src/test/run-pass/vec-macro-rvalue-scope.rs @@ -0,0 +1,18 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn one() -> i32 { 1 } + +// Make sure the vec![...] macro doesn't introduce hidden rvalue +// scopes (such as blocks) around the element expressions. +pub fn main() { + assert_eq!(vec![&one(), &one(), &2], vec![&1, &1, &(one()+one())]); + assert_eq!(vec![&one(); 2], vec![&1, &one()]); +} diff --git a/src/test/run-pass/vec-to_str.rs b/src/test/run-pass/vec-to_str.rs index 97c12d0954e4..31f261262420 100644 --- a/src/test/run-pass/vec-to_str.rs +++ b/src/test/run-pass/vec-to_str.rs @@ -9,11 +9,11 @@ // except according to those terms. pub fn main() { - assert_eq!(format!("{:?}", vec!(0i, 1)), "[0i, 1i]".to_string()); + assert_eq!(format!("{:?}", vec!(0i, 1)), "[0, 1]".to_string()); let foo = vec!(3i, 4); let bar: &[int] = &[4, 5]; - assert_eq!(format!("{:?}", foo), "[3i, 4i]"); - assert_eq!(format!("{:?}", bar), "[4i, 5i]"); + assert_eq!(format!("{:?}", foo), "[3, 4]"); + assert_eq!(format!("{:?}", bar), "[4, 5]"); } diff --git a/src/test/run-pass/wait-forked-but-failed-child.rs b/src/test/run-pass/wait-forked-but-failed-child.rs index eb7205b5e0a8..ffeb4be349a6 100644 --- a/src/test/run-pass/wait-forked-but-failed-child.rs +++ b/src/test/run-pass/wait-forked-but-failed-child.rs @@ -58,7 +58,7 @@ fn main() { let _failures = range(0, 100).map(|_| { let cmd = Command::new(too_long.as_slice()); let failed = cmd.spawn(); - assert!(failed.is_err(), "Make sure the command fails to spawn(): {}", cmd); + assert!(failed.is_err(), "Make sure the command fails to spawn(): {:?}", cmd); failed }).collect::<Vec<_>>(); diff --git a/src/test/run-pass/warn-ctypes-inhibit.rs b/src/test/run-pass/warn-ctypes-inhibit.rs index 93112e3e7ec9..73121918259a 100644 --- a/src/test/run-pass/warn-ctypes-inhibit.rs +++ b/src/test/run-pass/warn-ctypes-inhibit.rs @@ -8,9 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags:-D ctypes +// compile-flags:-D improper-ctypes -#![allow(ctypes)] +#![allow(improper_ctypes)] mod libc { extern {