diff --git a/configure b/configure index b14eac4b77e13..b2f8c33380ce7 100755 --- a/configure +++ b/configure @@ -509,7 +509,6 @@ opt optimize-tests 1 "build tests with optimizations" opt libcpp 1 "build with llvm with libc++ instead of libstdc++ when using clang" opt llvm-assertions 1 "build LLVM with assertions" opt debug 1 "build with extra debug fun" -opt ratchet-bench 0 "ratchet benchmarks" opt fast-make 0 "use .gitmodules as timestamp for submodule deps" opt ccache 0 "invoke gcc/clang via ccache to reuse object files between builds" opt local-rust 0 "use an installed rustc rather than downloading a snapshot" diff --git a/mk/cfg/aarch64-linux-android.mk b/mk/cfg/aarch64-linux-android.mk new file mode 100644 index 0000000000000..a6f7f2ba1d66e --- /dev/null +++ b/mk/cfg/aarch64-linux-android.mk @@ -0,0 +1,30 @@ +# aarch64-linux-android configuration +# CROSS_PREFIX_aarch64-linux-android- +CC_aarch64-linux-android=$(CFG_ANDROID_CROSS_PATH)/bin/aarch64-linux-android-gcc +CXX_aarch64-linux-android=$(CFG_ANDROID_CROSS_PATH)/bin/aarch64-linux-android-g++ +CPP_aarch64-linux-android=$(CFG_ANDROID_CROSS_PATH)/bin/aarch64-linux-android-gcc -E +AR_aarch64-linux-android=$(CFG_ANDROID_CROSS_PATH)/bin/aarch64-linux-android-ar +CFG_LIB_NAME_aarch64-linux-android=lib$(1).so +CFG_STATIC_LIB_NAME_aarch64-linux-android=lib$(1).a +CFG_LIB_GLOB_aarch64-linux-android=lib$(1)-*.so +CFG_LIB_DSYM_GLOB_aarch64-linux-android=lib$(1)-*.dylib.dSYM +CFG_JEMALLOC_CFLAGS_aarch64-linux-android := -D__aarch64__ -DANDROID -D__ANDROID__ $(CFLAGS) +CFG_GCCISH_CFLAGS_aarch64-linux-android := -Wall -g -fPIC -D__aarch64__ -DANDROID -D__ANDROID__ $(CFLAGS) +CFG_GCCISH_CXXFLAGS_aarch64-linux-android := -fno-rtti $(CXXFLAGS) +CFG_GCCISH_LINK_FLAGS_aarch64-linux-android := -shared -fPIC -ldl -g -lm -lsupc++ +CFG_GCCISH_DEF_FLAG_aarch64-linux-android := -Wl,--export-dynamic,--dynamic-list= +CFG_GCCISH_PRE_LIB_FLAGS_aarch64-linux-android := -Wl,-whole-archive +CFG_GCCISH_POST_LIB_FLAGS_aarch64-linux-android := -Wl,-no-whole-archive +CFG_DEF_SUFFIX_aarch64-linux-android := .android.def +CFG_LLC_FLAGS_aarch64-linux-android := +CFG_INSTALL_NAME_aarch64-linux-android = +CFG_EXE_SUFFIX_aarch64-linux-android := +CFG_WINDOWSY_aarch64-linux-android := +CFG_UNIXY_aarch64-linux-android := 1 +CFG_PATH_MUNGE_aarch64-linux-android := true +CFG_LDPATH_aarch64-linux-android := +CFG_RUN_aarch64-linux-android= +CFG_RUN_TARG_aarch64-linux-android= +RUSTC_FLAGS_aarch64-linux-android := +RUSTC_CROSS_FLAGS_aarch64-linux-android := +CFG_GNU_TRIPLE_aarch64-linux-android := aarch64-linux-android diff --git a/mk/rt.mk b/mk/rt.mk index 6a7be26c7a686..a8bbeb4151701 100644 --- a/mk/rt.mk +++ b/mk/rt.mk @@ -141,6 +141,8 @@ else ifeq ($(OSTYPE_$(1)), apple-ios) JEMALLOC_ARGS_$(1) := --disable-tls else ifeq ($(OSTYPE_$(1)), linux-androideabi) JEMALLOC_ARGS_$(1) := --disable-tls +else ifeq ($(OSTYPE_$(1)), linux-android) + JEMALLOC_ARGS_$(1) := --disable-tls endif ################################################################################ diff --git a/mk/tests.mk b/mk/tests.mk index 02cc745803fea..32d4d178e6b8c 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -300,6 +300,7 @@ tidy: | grep '^$(S)src/libbacktrace' -v \ | grep '^$(S)src/rust-installer' -v \ | xargs $(CFG_PYTHON) $(S)src/etc/check-binaries.py + $(Q) $(CFG_PYTHON) $(S)src/etc/errorck.py $(S)src/ endif diff --git a/src/compiletest/common.rs b/src/compiletest/common.rs index c29f74d741810..c21785c45a3ac 100644 --- a/src/compiletest/common.rs +++ b/src/compiletest/common.rs @@ -13,7 +13,7 @@ use std::fmt; use std::str::FromStr; use regex::Regex; -#[derive(Clone, PartialEq)] +#[derive(Clone, PartialEq, Debug)] pub enum Mode { CompileFail, RunFail, @@ -43,9 +43,9 @@ impl FromStr for Mode { } } -impl fmt::String for Mode { +impl fmt::Display for Mode { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::String::fmt(match *self { + fmt::Display::fmt(match *self { CompileFail => "compile-fail", RunFail => "run-fail", RunPass => "run-pass", @@ -58,12 +58,6 @@ impl fmt::String for Mode { } } -impl fmt::Show for Mode { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::String::fmt(self, f) - } -} - #[derive(Clone)] pub struct Config { // The library paths required for running the compiler @@ -115,20 +109,6 @@ pub struct Config { // Write out a parseable log of tests that were run pub logfile: Option, - // Write out a json file containing any metrics of the run - pub save_metrics: Option, - - // Write and ratchet a metrics file - pub ratchet_metrics: Option, - - // Percent change in metrics to consider noise - pub ratchet_noise_percent: Option, - - // "Shard" of the testsuite to pub run: this has the form of - // two numbers (a,b), and causes only those tests with - // positional order equal to a mod b to run. - pub test_shard: Option<(uint,uint)>, - // A command line to prefix program execution with, // for running under valgrind pub runtool: Option, diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs index f3514c6e7bc82..b3f0034ca894f 100644 --- a/src/compiletest/compiletest.rs +++ b/src/compiletest/compiletest.rs @@ -77,10 +77,6 @@ pub fn parse_config(args: Vec ) -> Config { optopt("", "target-rustcflags", "flags to pass to rustc for target", "FLAGS"), optflag("", "verbose", "run tests verbosely, showing all output"), optopt("", "logfile", "file to log test execution to", "FILE"), - optopt("", "save-metrics", "file to save metrics to", "FILE"), - optopt("", "ratchet-metrics", "file to ratchet metrics against", "FILE"), - optopt("", "ratchet-noise-percent", - "percent change in metrics to consider noise", "N"), optflag("", "jit", "run tests under the JIT"), optopt("", "target", "the target to build for", "TARGET"), optopt("", "host", "the host to build for", "HOST"), @@ -90,7 +86,6 @@ pub fn parse_config(args: Vec ) -> Config { optopt("", "adb-path", "path to the android debugger", "PATH"), optopt("", "adb-test-dir", "path to tests for the android debugger", "PATH"), optopt("", "lldb-python-dir", "directory containing LLDB's python module", "PATH"), - optopt("", "test-shard", "run shard A, of B shards, worth of the testsuite", "A.B"), optflag("h", "help", "show this message")); assert!(!args.is_empty()); @@ -152,12 +147,6 @@ pub fn parse_config(args: Vec ) -> Config { filter: filter, cfail_regex: Regex::new(errors::EXPECTED_PATTERN).unwrap(), logfile: matches.opt_str("logfile").map(|s| Path::new(s)), - save_metrics: matches.opt_str("save-metrics").map(|s| Path::new(s)), - ratchet_metrics: - matches.opt_str("ratchet-metrics").map(|s| Path::new(s)), - ratchet_noise_percent: - matches.opt_str("ratchet-noise-percent") - .and_then(|s| s.as_slice().parse::()), runtool: matches.opt_str("runtool"), host_rustcflags: matches.opt_str("host-rustcflags"), target_rustcflags: matches.opt_str("target-rustcflags"), @@ -176,7 +165,6 @@ pub fn parse_config(args: Vec ) -> Config { opt_str2(matches.opt_str("adb-test-dir")).as_slice() && !opt_str2(matches.opt_str("adb-test-dir")).is_empty(), lldb_python_dir: matches.opt_str("lldb-python-dir"), - test_shard: test::opt_shard(matches.opt_str("test-shard")), verbose: matches.opt_present("verbose"), } } @@ -210,10 +198,6 @@ pub fn log_config(config: &Config) { logv(c, format!("adb_test_dir: {:?}", config.adb_test_dir)); logv(c, format!("adb_device_status: {}", config.adb_device_status)); - match config.test_shard { - None => logv(c, "test_shard: (all)".to_string()), - Some((a,b)) => logv(c, format!("test_shard: {}.{}", a, b)) - } logv(c, format!("verbose: {}", config.verbose)); logv(c, format!("\n")); } @@ -264,6 +248,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) => {} @@ -284,15 +271,8 @@ pub fn test_opts(config: &Config) -> test::TestOpts { logfile: config.logfile.clone(), run_tests: true, run_benchmarks: true, - ratchet_metrics: config.ratchet_metrics.clone(), - ratchet_noise_percent: config.ratchet_noise_percent.clone(), - save_metrics: config.save_metrics.clone(), - test_shard: config.test_shard.clone(), nocapture: false, color: test::AutoColor, - show_boxplot: false, - boxplot_width: 50, - show_all_stats: false, } } diff --git a/src/compiletest/header.rs b/src/compiletest/header.rs index 2413a001ee805..d7af767688e81 100644 --- a/src/compiletest/header.rs +++ b/src/compiletest/header.rs @@ -332,8 +332,7 @@ pub fn parse_name_value_directive(line: &str, directive: &str) let keycolon = format!("{}:", directive); match line.find_str(keycolon.as_slice()) { Some(colon) => { - let value = line.slice(colon + keycolon.len(), - line.len()).to_string(); + let value = line[(colon + keycolon.len()) .. line.len()].to_string(); debug!("{}: {}", directive, value); Some(value) } diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs index 5579479c5e5ac..f075cff769fba 100644 --- a/src/compiletest/runtest.rs +++ b/src/compiletest/runtest.rs @@ -294,6 +294,7 @@ fn run_pretty_test(config: &Config, props: &TestProps, testfile: &Path) { let aux_dir = aux_output_dir_name(config, testfile); // FIXME (#9639): This needs to handle non-utf8 paths let mut args = vec!("-".to_string(), + "-Zunstable-options".to_string(), "--pretty".to_string(), pretty_type, format!("--target={}", config.target), @@ -340,7 +341,7 @@ actual:\n\ }; // FIXME (#9639): This needs to handle non-utf8 paths let mut args = vec!("-".to_string(), - "--no-trans".to_string(), + "-Zno-trans".to_string(), "--crate-type=lib".to_string(), format!("--target={}", target), "-L".to_string(), @@ -547,7 +548,7 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) { // Add line breakpoints for line in breakpoint_lines.iter() { - script_str.push_str(&format!("break '{:?}':{}\n", + script_str.push_str(&format!("break '{}':{}\n", testfile.filename_display(), *line)[]); } @@ -750,7 +751,7 @@ fn run_debuginfo_lldb_test(config: &Config, props: &TestProps, testfile: &Path) status: status, stdout: out, stderr: err, - cmdline: format!("{}", cmd) + cmdline: format!("{:?}", cmd) }; } } @@ -862,7 +863,7 @@ fn check_debugger_output(debugger_run_result: &ProcRes, check_lines: &[String]) break; } Some(i) => { - rest = rest.slice_from(i + frag.len()); + rest = &rest[(i + frag.len())..]; } } first = false; @@ -953,7 +954,7 @@ fn check_expected_errors(expected_errors: Vec , } let prefixes = expected_errors.iter().map(|ee| { - format!("{:?}:{}:", testfile.display(), ee.line) + format!("{}:{}:", testfile.display(), ee.line) }).collect:: >(); #[cfg(windows)] @@ -1045,7 +1046,7 @@ fn scan_until_char(haystack: &str, needle: char, idx: &mut uint) -> bool { if *idx >= haystack.len() { return false; } - let opt = haystack.slice_from(*idx).find(needle); + let opt = haystack[(*idx)..].find(needle); if opt.is_none() { return false; } diff --git a/src/doc/intro.md b/src/doc/intro.md index 3487738467fbc..b92d38215c29b 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 be5efaae92804..1bcb5a7b4a0c0 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -812,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 @@ -827,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) @@ -863,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 @@ -927,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} @@ -2389,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` @@ -2903,13 +2886,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. diff --git a/src/doc/rustdoc.md b/src/doc/rustdoc.md index 0b686eb76dbfb..d4a25efec17f6 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 aab03add905bb..6131e1b8a7070 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 51a0bb69a7ce9..bfb1494efc785 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 25870d84a754f..efeb201efe847 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 0000000000000..0b686eb76dbfb --- /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 ea1da167458ab..a350df67b1759 100644 --- a/src/doc/trpl/if.md +++ b/src/doc/trpl/if.md @@ -1,4 +1,4 @@ -% `if` +% If Rust's take on `if` is not particularly complex, but it's much more like the `if` you'll find in a dynamically typed language than in a more traditional diff --git a/src/doc/trpl/looping.md b/src/doc/trpl/looping.md index 28f02b1ffe152..4301149d1f8b3 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 0000000000000..07b49751b10a0 --- /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 8b7e37dd4c2fd..56cb5b1de699c 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 d74c10b814507..29986d7f23577 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 1bad09b4b6e55..a801a1ab0e921 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 2a66b4a01f7a9..3acd1eefe89d0 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 f25a59015fcdb..dae685f3a540a 100644 --- a/src/etc/emacs/rust-mode.el +++ b/src/etc/emacs/rust-mode.el @@ -54,6 +54,11 @@ :type 'integer :group 'rust-mode) +(defcustom rust-indent-method-chain nil + "Indent Rust method chains, aligned by the '.' operators" + :type 'boolean + :group 'rust-mode) + (defun rust-paren-level () (nth 0 (syntax-ppss))) (defun rust-in-str-or-cmnt () (nth 8 (syntax-ppss))) (defun rust-rewind-past-str-cmnt () (goto-char (nth 8 (syntax-ppss)))) @@ -73,10 +78,19 @@ ;; open bracket ends the line (when (not (looking-at "[[:blank:]]*\\(?://.*\\)?$")) (when (looking-at "[[:space:]]") - (forward-word 1) - (backward-word 1)) + (forward-word 1) + (backward-word 1)) (current-column)))) +(defun rust-align-to-method-chain () + (save-excursion + (previous-line) + (end-of-line) + (backward-word 1) + (backward-char) + (when (looking-at "\\..+\(.*\)\n") + (- (current-column) rust-indent-offset)))) + (defun rust-rewind-to-beginning-of-current-level-expr () (let ((current-level (rust-paren-level))) (back-to-indentation) @@ -99,10 +113,13 @@ ;; the inside of it correctly relative to the outside. (if (= 0 level) 0 + (or + (when rust-indent-method-chain + (rust-align-to-method-chain)) (save-excursion (backward-up-list) (rust-rewind-to-beginning-of-current-level-expr) - (+ (current-column) rust-indent-offset))))) + (+ (current-column) rust-indent-offset)))))) (cond ;; A function return type is indented to the corresponding function arguments ((looking-at "->") @@ -114,6 +131,16 @@ ;; A closing brace is 1 level unindended ((looking-at "}") (- baseline rust-indent-offset)) + ;;Line up method chains by their .'s + ((when (and rust-indent-method-chain + (looking-at "\..+\(.*\);?\n")) + (or + (let ((method-indent (rust-align-to-method-chain))) + (when method-indent + (+ method-indent rust-indent-offset))) + (+ baseline rust-indent-offset)))) + + ;; Doc comments in /** style with leading * indent to line up the *s ((and (nth 4 (syntax-ppss)) (looking-at "*")) (+ 1 baseline)) diff --git a/src/etc/errorck.py b/src/etc/errorck.py new file mode 100644 index 0000000000000..17659309d3b0d --- /dev/null +++ b/src/etc/errorck.py @@ -0,0 +1,70 @@ +# Copyright 2015 The Rust Project Developers. See the COPYRIGHT +# file at the top-level directory of this distribution and at +# http://rust-lang.org/COPYRIGHT. +# +# Licensed under the Apache License, Version 2.0 or the MIT license +# , at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + +# Digs error codes out of files named 'diagnostics.rs' across +# the tree, and ensures thare are no duplicates. + +import sys, os, re + +src_dir = sys.argv[1] + +errcode_map = { } + +for (dirpath, dirnames, filenames) in os.walk(src_dir): + + if "src/test" in dirpath or "src/llvm" in dirpath: + # Short circuit for fast + continue + + for filename in filenames: + if filename != "diagnostics.rs": + continue + + path = os.path.join(dirpath, filename) + line_num = 1 + with open(path, 'r') as f: + for line in f: + + p = re.compile("(E\d\d\d\d)") + m = p.search(line) + if not m is None: + errcode = m.group(1) + + new_record = [(errcode, path, line_num, line)] + existing = errcode_map.get(errcode) + if existing is not None: + # This is a dupe + errcode_map[errcode] = existing + new_record + else: + errcode_map[errcode] = new_record + + line_num += 1 + +errors = False +all_errors = [] +for errcode in errcode_map: + entries = errcode_map[errcode] + all_errors += [entries[0][0]] + if len(entries) > 1: + print "error: duplicate error code " + errcode + for entry in entries: + print entry[1] + ": " + str(entry[2]) + print entry[3] + errors = True + +print str(len(errcode_map)) + " error codes" + +all_errors.sort() +all_errors.reverse() + +print "highest error code: " + all_errors[0] + +if errors: + sys.exit(1) diff --git a/src/etc/rustup.sh b/src/etc/rustup.sh index 749d9eaa173e8..07e832d317adb 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/liballoc/arc.rs b/src/liballoc/arc.rs index c0cd034abfa4a..5f8cd6baf9a74 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}; @@ -578,16 +578,17 @@ impl Ord for Arc { #[stable] impl Eq for Arc {} -impl fmt::Show for Arc { +#[stable] +impl fmt::Display for Arc { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "Arc({:?})", (**self)) + fmt::Display::fmt(&**self, f) } } #[stable] -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) } } @@ -806,7 +807,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 a2cc98c7d0129..c4abedf3fe89a 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] @@ -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,23 +72,29 @@ 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"] #[unstable = "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] 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] pub fn new(x: T) -> Box { box x @@ -74,11 +115,29 @@ impl Default for Box<[T]> { #[stable] 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)); @@ -156,20 +215,22 @@ impl BoxAny for Box { } } -impl fmt::Show for Box { +#[stable] +impl fmt::Display for Box { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "Box({:?})", &**self) + fmt::Display::fmt(&**self, f) } } #[stable] -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] +impl fmt::Debug for Box { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("Box") } @@ -187,56 +248,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); - } - - #[test] - fn any_move() { - let a = Box::new(8u) as Box; - let b = Box::new(Test) as Box; +// FIXME(#21363) remove `old_impl_check` when bug is fixed +#[old_impl_check] +impl<'a, T> Iterator for Box + 'a> { + type Item = T; - 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()); + fn next(&mut self) -> Option { + (**self).next() } - #[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"); + fn size_hint(&self) -> (usize, Option) { + (**self).size_hint() } +} - #[test] - fn deref() { - fn homura>(_: T) { } - homura(Box::new(765i32)); +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 0000000000000..c47a771f60d09 --- /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 bd5b43b782e8d..a2643f4d0f79b 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 811e32e747dfd..231ef6e7e74da 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)] #[macro_use] @@ -91,6 +93,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 7191a7af346b0..5e82c4f1adea9 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -174,61 +174,17 @@ struct RcBox { /// See the [module level documentation](../index.html) for more details. #[unsafe_no_drop_flag] #[stable] -#[cfg(stage0)] // NOTE remove impl 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>, - _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] -#[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 { - /// Constructs a new `Rc`. - /// - /// # Examples - /// - /// ``` - /// use std::rc::Rc; - /// - /// let five = Rc::new(5i); - /// ``` - #[stable] - #[cfg(stage0)] // NOTE remove after next snapshot - 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`. /// @@ -240,7 +196,6 @@ impl Rc { /// let five = Rc::new(5i); /// ``` #[stable] - #[cfg(not(stage0))] // NOTE remove cfg after next snapshot pub fn new(value: T) -> Rc { unsafe { Rc { @@ -267,29 +222,6 @@ impl Rc { /// /// let weak_five = five.downgrade(); /// ``` - #[cfg(stage0)] // NOTE remove after next snapshot - #[unstable = "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 = "Weak pointers may not belong in this module"] pub fn downgrade(&self) -> Weak { self.inc_weak(); @@ -483,25 +415,6 @@ impl Drop for Rc { #[stable] 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`. /// @@ -517,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 } @@ -693,17 +605,17 @@ impl> Hash for Rc { } } -#[unstable = "Show is experimental."] -impl fmt::Show for Rc { +#[stable] +impl fmt::Display for Rc { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "Rc({:?})", **self) + fmt::Display::fmt(&**self, f) } } #[stable] -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) } } @@ -714,66 +626,21 @@ impl fmt::String for Rc { /// See the [module level documentation](../index.html) for more. #[unsafe_no_drop_flag] #[unstable = "Weak pointers may not belong in this module."] -#[cfg(stage0)] // NOTE remove impl 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>, - _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 = "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 #[allow(unstable)] impl !marker::Send for Weak {} -#[cfg(not(stage0))] // NOTE remove cfg after next snapshot #[allow(unstable)] impl !marker::Sync for Weak {} #[unstable = "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. /// @@ -792,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 @@ -849,25 +715,6 @@ impl Drop for Weak { #[unstable = "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`. /// @@ -883,15 +730,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 = "Show is experimental."] -impl fmt::Show for Weak { +#[stable] +impl fmt::Debug for Weak { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "(Weak)") } @@ -1134,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 efd056b0d66a5..4c07f5b31e64d 100644 --- a/src/libcollections/bit.rs +++ b/src/libcollections/bit.rs @@ -330,7 +330,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); @@ -972,7 +972,7 @@ impl Ord for Bitv { } #[stable] -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 })); @@ -1727,7 +1727,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; @@ -2622,7 +2622,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 c56592177b49a..8c2f00a569514 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}; @@ -871,7 +871,7 @@ impl Ord for BTreeMap { } #[stable] -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 fa8906430894f..50857c78469cf 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 4d71f9dbea8be..d307b7dbde75d 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}; @@ -592,7 +589,7 @@ impl<'a, 'b, T: Ord + Clone> BitOr<&'b BTreeSet> for &'a BTreeSet { } #[stable] -impl Show for BTreeSet { +impl Debug for BTreeSet { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { try!(write!(f, "BTreeSet {{")); @@ -892,7 +889,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 cce8cf398e12e..73fd806c9070b 100644 --- a/src/libcollections/dlist.rs +++ b/src/libcollections/dlist.rs @@ -874,7 +874,7 @@ impl Clone for DList { } #[stable] -impl fmt::Show for DList { +impl fmt::Debug for DList { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { try!(write!(f, "DList [")); @@ -1333,7 +1333,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 1b852d0ba680d..a40a590c51ace 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 c078db7d46fb7..85aedaeb010f1 100644 --- a/src/libcollections/macros.rs +++ b/src/libcollections/macros.rs @@ -12,13 +12,13 @@ #[macro_export] #[stable] 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 b9cb4be7c1891..338166c2f0b74 100644 --- a/src/libcollections/ring_buf.rs +++ b/src/libcollections/ring_buf.rs @@ -578,7 +578,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); @@ -1611,7 +1611,7 @@ impl Extend for RingBuf { } #[stable] -impl fmt::Show for RingBuf { +impl fmt::Debug for RingBuf { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { try!(write!(f, "RingBuf [")); @@ -1630,7 +1630,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; @@ -1678,7 +1678,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()); @@ -2302,7 +2302,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 988ec4c661faa..f65802de5ac6e 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -169,29 +169,16 @@ pub trait SliceExt { #[unstable = "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. - #[unstable = "will be replaced by slice syntax"] + /// Deprecated: use `&s[start .. end]` notation instead. + #[deprecated = "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. - #[unstable = "will be replaced by slice syntax"] + /// Deprecated: use `&s[start..]` notation instead. + #[deprecated = "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. - #[unstable = "will be replaced by slice syntax"] + /// Deprecated: use `&s[..end]` notation instead. + #[deprecated = "use &s[..end] instead"] fn slice_to(&self, end: uint) -> &[Self::Item]; /// Divides one slice into two at an index. @@ -378,29 +365,16 @@ pub trait SliceExt { #[stable] 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. - #[unstable = "will be replaced by slice syntax"] + /// Deprecated: use `&mut s[start .. end]` instead. + #[deprecated = "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. - #[unstable = "will be replaced by slice syntax"] + /// Deprecated: use `&mut s[start ..]` instead. + #[deprecated = "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. - #[unstable = "will be replaced by slice syntax"] + /// Deprecated: use `&mut s[.. end]` instead. + #[deprecated = "use &mut s[.. end] instead"] fn slice_to_mut(&mut self, end: uint) -> &mut [Self::Item]; /// Returns an iterator that allows modifying each value @@ -712,7 +686,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) @@ -720,17 +694,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] @@ -834,17 +808,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] @@ -993,11 +967,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] 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] fn connect(&self, sep: &T) -> U; } @@ -2409,8 +2402,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]]; @@ -2476,19 +2473,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] @@ -2675,7 +2672,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 f7668930660b0..6608d0ee9a7ec 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -750,67 +750,17 @@ 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); - /// ``` - #[unstable = "use slice notation [a..b] instead"] - fn slice(&self, begin: uint, end: uint) -> &str { - core_str::StrExt::slice(&self[], begin, end) - } + /// Deprecated: use `s[a .. b]` instead. + #[deprecated = "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`. - #[unstable = "use slice notation [a..] instead"] - fn slice_from(&self, begin: uint) -> &str { - core_str::StrExt::slice_from(&self[], begin) - } + /// Deprecated: use `s[a..]` instead. + #[deprecated = "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`. - #[unstable = "use slice notation [..a] instead"] - fn slice_to(&self, end: uint) -> &str { - core_str::StrExt::slice_to(&self[], end) - } + /// Deprecated: use `s[..a]` instead. + #[deprecated = "use slice notation [..a] instead"] + fn slice_to(&self, end: uint) -> &str; /// Returns a slice of the string from the character range /// [`begin`..`end`). @@ -1348,7 +1298,19 @@ pub trait StrExt: Index { } #[stable] -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 5d35d8a86795a..c965aedbc5d2f 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] +#[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] #[allow(missing_copy_implementations)] +#[derive(Show)] pub struct FromUtf16Error(()); impl String { @@ -680,30 +683,28 @@ impl FromUtf8Error { pub fn utf8_error(&self) -> Utf8Error { self.error } } -impl fmt::Show for FromUtf8Error { +#[stable] +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] -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] +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] -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] @@ -814,18 +815,18 @@ impl Default for String { } #[stable] -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 = "waiting on fmt stabilization"] -impl fmt::Show for String { +#[stable] +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) } } @@ -848,6 +849,7 @@ impl<'a> Add<&'a str> for String { } } +#[stable] impl ops::Index> for String { type Output = str; #[inline] @@ -855,6 +857,7 @@ impl ops::Index> for String { &self[][*index] } } +#[stable] impl ops::Index> for String { type Output = str; #[inline] @@ -862,6 +865,7 @@ impl ops::Index> for String { &self[][*index] } } +#[stable] impl ops::Index> for String { type Output = str; #[inline] @@ -869,6 +873,7 @@ impl ops::Index> for String { &self[][*index] } } +#[stable] impl ops::Index for String { type Output = str; #[inline] @@ -934,7 +939,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; @@ -1295,10 +1300,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 4ddab8c533aab..52590297a6afa 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -1229,7 +1229,7 @@ impl> Hash for Vec { } } -#[unstable = "waiting on Index stability"] +#[stable] impl Index for Vec { type Output = T; @@ -1239,6 +1239,7 @@ impl Index for Vec { } } +#[stable] impl IndexMut for Vec { type Output = T; @@ -1249,6 +1250,7 @@ impl IndexMut for Vec { } +#[stable] impl ops::Index> for Vec { type Output = [T]; #[inline] @@ -1256,6 +1258,7 @@ impl ops::Index> for Vec { self.as_slice().index(index) } } +#[stable] impl ops::Index> for Vec { type Output = [T]; #[inline] @@ -1263,6 +1266,7 @@ impl ops::Index> for Vec { self.as_slice().index(index) } } +#[stable] impl ops::Index> for Vec { type Output = [T]; #[inline] @@ -1270,6 +1274,7 @@ impl ops::Index> for Vec { self.as_slice().index(index) } } +#[stable] impl ops::Index for Vec { type Output = [T]; #[inline] @@ -1278,6 +1283,7 @@ impl ops::Index for Vec { } } +#[stable] impl ops::IndexMut> for Vec { type Output = [T]; #[inline] @@ -1285,6 +1291,7 @@ impl ops::IndexMut> for Vec { self.as_mut_slice().index_mut(index) } } +#[stable] impl ops::IndexMut> for Vec { type Output = [T]; #[inline] @@ -1292,6 +1299,7 @@ impl ops::IndexMut> for Vec { self.as_mut_slice().index_mut(index) } } +#[stable] impl ops::IndexMut> for Vec { type Output = [T]; #[inline] @@ -1299,6 +1307,7 @@ impl ops::IndexMut> for Vec { self.as_mut_slice().index_mut(index) } } +#[stable] impl ops::IndexMut for Vec { type Output = [T]; #[inline] @@ -1307,7 +1316,6 @@ impl ops::IndexMut for Vec { } } - #[stable] impl ops::Deref for Vec { type Target = [T]; @@ -1486,10 +1494,10 @@ impl Default for Vec { } } -#[unstable = "waiting on Show stability"] -impl fmt::Show for Vec { +#[stable] +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) } } @@ -2158,7 +2166,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] @@ -2172,7 +2180,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 7ff2e9535886c..f178d5bc7e9ed 100644 --- a/src/libcollections/vec_map.rs +++ b/src/libcollections/vec_map.rs @@ -513,7 +513,7 @@ impl Ord for VecMap { } #[stable] -impl fmt::Show for VecMap { +impl fmt::Debug for VecMap { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { try!(write!(f, "VecMap {{")); @@ -990,7 +990,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 20ed2253861ce..9966f0d4bf7d0 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 @@ -175,17 +175,10 @@ pub struct TypeId { impl TypeId { /// Returns the `TypeId` of the type this generic function has been /// instantiated with - #[cfg(not(stage0))] #[unstable = "may grow a `Reflect` bound soon via marker traits"] pub fn of() -> TypeId { 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 0cc31bf70dee6..a83537e12f7a9 100644 --- a/src/libcore/array.rs +++ b/src/libcore/array.rs @@ -39,10 +39,10 @@ macro_rules! array_impls { } } - #[unstable = "waiting for Show to stabilize"] - impl fmt::Show for [T; $N] { + #[stable] + 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 4363a0a444113..63614aaa46335 100644 --- a/src/libcore/borrow.rs +++ b/src/libcore/borrow.rs @@ -133,7 +133,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), @@ -239,14 +238,27 @@ impl<'a, T, B: ?Sized> PartialOrd for Cow<'a, T, B> where B: PartialOrd + ToOwne } #[stable] -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] +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 963cb48db0701..7f73be9eb5f4d 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 77% rename from src/libstd/error.rs rename to src/libcore/error.rs index ff12846197806..9ff38028df9f3 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,20 +81,15 @@ #![stable] -use prelude::v1::*; - -use str::Utf8Error; -use string::{FromUtf8Error, FromUtf16Error}; +use prelude::*; +use fmt::Display; /// Base functionality for all errors in Rust. #[unstable = "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 } } @@ -112,26 +108,3 @@ impl FromError for E { err } } - -#[stable] -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] -impl Error for FromUtf8Error { - fn description(&self) -> &str { "invalid utf-8" } - fn detail(&self) -> Option { Some(self.to_string()) } -} - -#[stable] -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 f1b9ebe6d905d..245dc00d83824 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 535722f93bfd6..0e8d31a62eed9 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; @@ -46,7 +49,7 @@ pub type Result = result::Result<(), Error>; /// occurred. Any extra information must be arranged to be transmitted through /// some other means. #[unstable = "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. @@ -133,7 +136,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> { @@ -214,14 +217,15 @@ pub struct Arguments<'a> { args: &'a [Argument<'a>], } -impl<'a> Show for Arguments<'a> { +#[stable] +impl<'a> Debug for Arguments<'a> { fn fmt(&self, fmt: &mut Formatter) -> Result { - String::fmt(self, fmt) + Display::fmt(self, fmt) } } #[stable] -impl<'a> String for Arguments<'a> { +impl<'a> Display for Arguments<'a> { fn fmt(&self, fmt: &mut Formatter) -> Result { write(fmt.buf, *self) } @@ -229,20 +233,49 @@ impl<'a> String for Arguments<'a> { /// Format trait for the `:?` format. Useful for debugging, most all types /// should implement this. -#[unstable = "I/O and core have yet to be reconciled"] +#[deprecated = "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 = "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, `{}`. +#[deprecated = "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 = "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 = "I/O and core have yet to be reconciled"] @@ -583,9 +616,10 @@ impl<'a> Formatter<'a> { pub fn precision(&self) -> Option { self.precision } } -impl Show for Error { +#[stable] +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) } } @@ -611,9 +645,11 @@ pub fn argumentuint<'a>(s: &'a uint) -> Argument<'a> { macro_rules! fmt_refs { ($($tr:ident),*) => { $( + #[stable] impl<'a, T: ?Sized + $tr> $tr for &'a T { fn fmt(&self, f: &mut Formatter) -> Result { $tr::fmt(&**self, f) } } + #[stable] impl<'a, T: ?Sized + $tr> $tr for &'a mut T { fn fmt(&self, f: &mut Formatter) -> Result { $tr::fmt(&**self, f) } } @@ -621,22 +657,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] +impl Debug for bool { fn fmt(&self, f: &mut Formatter) -> Result { - String::fmt(self, f) + Display::fmt(self, f) } } #[stable] -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] +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()) { @@ -647,13 +685,14 @@ impl Show for str { } #[stable] -impl String for str { +impl Display for str { fn fmt(&self, f: &mut Formatter) -> Result { f.pad(self) } } -impl Show for char { +#[stable] +impl Debug for char { fn fmt(&self, f: &mut Formatter) -> Result { use char::CharExt; try!(write!(f, "'")); @@ -665,15 +704,16 @@ impl Show for char { } #[stable] -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] impl Pointer for *const T { fn fmt(&self, f: &mut Formatter) -> Result { f.flags |= 1 << (rt::FlagAlternate as uint); @@ -683,18 +723,21 @@ impl Pointer for *const T { } } +#[stable] impl Pointer for *mut T { fn fmt(&self, f: &mut Formatter) -> Result { Pointer::fmt(&(*self as *const T), f) } } +#[stable] impl<'a, T> Pointer for &'a T { fn fmt(&self, f: &mut Formatter) -> Result { Pointer::fmt(&(*self as *const T), f) } } +#[stable] impl<'a, T> Pointer for &'a mut T { fn fmt(&self, f: &mut Formatter) -> Result { Pointer::fmt(&(&**self as *const T), f) @@ -703,15 +746,15 @@ impl<'a, T> Pointer for &'a mut T { macro_rules! floating { ($ty:ident) => { - impl Show for $ty { + #[stable] + 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] - impl String for $ty { + impl Display for $ty { fn fmt(&self, fmt: &mut Formatter) -> Result { use num::Float; @@ -732,6 +775,7 @@ macro_rules! floating { ($ty:ident) => { } } + #[stable] impl LowerExp for $ty { fn fmt(&self, fmt: &mut Formatter) -> Result { use num::Float; @@ -753,6 +797,7 @@ macro_rules! floating { ($ty:ident) => { } } + #[stable] impl UpperExp for $ty { fn fmt(&self, fmt: &mut Formatter) -> Result { use num::Float; @@ -777,12 +822,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] +impl Debug for *const T { fn fmt(&self, f: &mut Formatter) -> Result { Pointer::fmt(self, f) } } -impl Show for *mut T { +#[stable] +impl Debug for *mut T { fn fmt(&self, f: &mut Formatter) -> Result { Pointer::fmt(self, f) } } @@ -793,7 +840,8 @@ macro_rules! peel { macro_rules! tuple { () => (); ( $($name:ident,)+ ) => ( - impl<$($name:Show),*> Show for ($($name,)*) { + #[stable] + impl<$($name:Debug),*> Debug for ($($name,)*) { #[allow(non_snake_case, unused_assignments)] fn fmt(&self, f: &mut Formatter) -> Result { try!(write!(f, "(")); @@ -818,11 +866,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] +impl<'a> Debug for &'a (any::Any+'a) { fn fmt(&self, f: &mut Formatter) -> Result { f.pad("&Any") } } -impl Show for [T] { +#[stable] +impl Debug for [T] { fn fmt(&self, f: &mut Formatter) -> Result { if f.flags & (1 << (rt::FlagAlternate as uint)) == 0 { try!(write!(f, "[")); @@ -843,20 +893,22 @@ impl Show for [T] { } } -impl Show for () { +#[stable] +impl Debug for () { fn fmt(&self, f: &mut Formatter) -> Result { f.pad("()") } } -impl Show for Cell { +#[stable] +impl Debug for Cell { fn fmt(&self, f: &mut Formatter) -> Result { write!(f, "Cell {{ value: {:?} }}", self.get()) } } -#[unstable] -impl Show for RefCell { +#[stable] +impl Debug for RefCell { fn fmt(&self, f: &mut Formatter) -> Result { match self.try_borrow() { Some(val) => write!(f, "RefCell {{ value: {:?} }}", val), @@ -865,29 +917,17 @@ impl Show for RefCell { } } -impl<'b, T: Show> Show for Ref<'b, T> { - fn fmt(&self, f: &mut Formatter) -> Result { - Show::fmt(&**self, f) - } -} - -impl<'b, T: Show> Show for RefMut<'b, T> { +#[stable] +impl<'b, T: Debug> Debug for Ref<'b, T> { fn fmt(&self, f: &mut Formatter) -> Result { - Show::fmt(&*(self.deref()), f) + Debug::fmt(&**self, f) } } #[stable] -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 1df6f8452258b..c456b3379e8d3 100644 --- a/src/libcore/fmt/num.rs +++ b/src/libcore/fmt/num.rs @@ -154,13 +154,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] + 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] + 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) } } @@ -169,6 +170,7 @@ macro_rules! radix_fmt { } macro_rules! int_base { ($Trait:ident for $T:ident as $U:ident -> $Radix:ident) => { + #[stable] impl fmt::$Trait for $T { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { $Radix.fmt_int(*self as $U, f) @@ -179,10 +181,10 @@ macro_rules! int_base { macro_rules! show { ($T:ident with $S:expr) => { - impl fmt::Show for $T { + #[stable] + 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) } } } @@ -192,7 +194,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 } @@ -200,7 +202,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 73be68289c9b7..dd488a74216eb 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 0005db36c278a..773ac99b0dee2 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -99,6 +99,20 @@ pub trait Iterator { fn size_hint(&self) -> (uint, 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` #[stable] #[rustc_on_unimplemented="a collection of type `{Self}` cannot be \ @@ -2701,63 +2715,93 @@ impl Iterator for RangeStepInclusive { } } +macro_rules! range_impl { + ($($t:ty)*) => ($( + #[stable] + impl Iterator for ::ops::Range<$t> { + type Item = $t; + + #[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) -> (uint, Option) { + debug_assert!(self.end >= self.start); + let hint = (self.end - self.start) as uint; + (hint, Some(hint)) + } + } -/// 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 = "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; + #[stable] + impl ExactSizeIterator for ::ops::Range<$t> {} + )*) } -macro_rules! step_impl { +macro_rules! range_impl_no_hint { ($($t:ty)*) => ($( - #[unstable = "Trait is unstable."] - impl Step for $t { - #[inline] - fn step(&mut self) { *self += 1; } - #[inline] - fn step_back(&mut self) { *self -= 1; } + #[stable] + impl Iterator for ::ops::Range<$t> { + type Item = $t; + #[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 = "Trait is unstable."] - impl Step for $t { - #[inline] - fn step(&mut self) { *self += 1; } + #[stable] + impl DoubleEndedIterator for ::ops::Range<$t> { #[inline] - fn step_back(&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] + impl Iterator for ::ops::RangeFrom<$t> { + type Item = $t; + #[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!(uint u8 u16 u32 int 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!(uint u8 u16 u32 u64 int i8 i16 i32 i64); /// An iterator that repeats an element endlessly #[derive(Clone)] diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 0b150d1ecf90b..1e271f972b131 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -63,6 +63,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] @@ -136,6 +138,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 99ba9666cd296..a987a0a5068a8 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -376,16 +376,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 = "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. @@ -395,15 +385,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 = "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 = "likely to change with new variance strategy"] diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs index 905de9ef615dc..372596cdd44ec 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] -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 @@ -164,8 +159,6 @@ macro_rules! forward_ref_binop { /// calling `add`, and therefore, `main` prints `Adding!`. /// /// ```rust -/// #![feature(associated_types)] -/// /// use std::ops::Add; /// /// #[derive(Copy)] @@ -219,8 +212,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)] @@ -274,8 +265,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)] @@ -329,8 +318,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)] @@ -384,8 +371,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)] @@ -458,8 +443,6 @@ rem_float_impl! { f64, fmod } /// `neg`, and therefore, `main` prints `Negating!`. /// /// ``` -/// #![feature(associated_types)] -/// /// use std::ops::Neg; /// /// struct Foo; @@ -537,8 +520,6 @@ neg_uint_impl! { u64, i64 } /// `not`, and therefore, `main` prints `Not-ing!`. /// /// ``` -/// #![feature(associated_types)] -/// /// use std::ops::Not; /// /// struct Foo; @@ -593,8 +574,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)] @@ -648,8 +627,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)] @@ -703,8 +680,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)] @@ -758,8 +733,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)] @@ -831,8 +804,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)] @@ -924,10 +895,12 @@ shr_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize } /// } /// ``` #[lang="index"] +#[stable] pub trait Index { type Output: ?Sized; /// The method for the indexing (`Foo[Bar]`) operation + #[stable] fn index<'a>(&'a self, index: &Index) -> &'a Self::Output; } @@ -960,30 +933,32 @@ pub trait Index { /// } /// ``` #[lang="index_mut"] +#[stable] pub trait IndexMut { type Output: ?Sized; /// The method for the indexing (`Foo[Bar]`) operation + #[stable] 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 = "API still in development"] +#[unstable = "may be renamed to RangeFull"] pub struct FullRange; -#[unstable = "API still in development"] -impl fmt::Show for FullRange { +#[stable] +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 = "API still in development"] +#[stable] pub struct Range { /// The lower bound of the range (inclusive). pub start: Idx, @@ -991,49 +966,8 @@ pub struct Range { pub end: Idx, } -#[unstable = "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 = "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 = "API still in development"] -impl ExactSizeIterator for Range {} - -#[unstable = "API still in development"] -impl fmt::Show for Range { +#[stable] +impl fmt::Debug for Range { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { write!(fmt, "{:?}..{:?}", self.start, self.end) } @@ -1042,27 +976,16 @@ impl fmt::Show for Range { /// A range which is only bounded below. #[derive(Copy, Clone, PartialEq, Eq)] #[lang="range_from"] -#[unstable = "API still in development"] +#[stable] pub struct RangeFrom { /// The lower bound of the range (inclusive). pub start: Idx, } -#[unstable = "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 = "API still in development"] -impl fmt::Show for RangeFrom { +#[stable] +impl fmt::Debug for RangeFrom { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { write!(fmt, "{:?}..", self.start) } @@ -1071,14 +994,14 @@ impl fmt::Show for RangeFrom { /// A range which is only bounded above. #[derive(Copy, Clone, PartialEq, Eq)] #[lang="range_to"] -#[unstable = "API still in development"] +#[stable] pub struct RangeTo { /// The upper bound of the range (exclusive). pub end: Idx, } -#[unstable = "API still in development"] -impl fmt::Show for RangeTo { +#[stable] +impl fmt::Debug for RangeTo { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { write!(fmt, "..{:?}", self.end) } @@ -1094,8 +1017,6 @@ impl fmt::Show for RangeTo { /// struct. /// /// ``` -/// #![feature(associated_types)] -/// /// use std::ops::Deref; /// /// struct DerefExample { @@ -1149,8 +1070,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 1ab810f937de9..c3d49e2497845 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}; @@ -714,7 +714,7 @@ impl Result { } #[stable] -impl Result { +impl Result { /// Unwraps a result, yielding the content of an `Ok`. /// /// # Panics @@ -739,13 +739,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] -impl Result { +impl Result { /// Unwraps a result, yielding the content of an `Err`. /// /// # Panics @@ -769,7 +769,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 50cbb7a61dce3..ec43a35248e2e 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] @@ -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] impl ops::Index for [T] { type Output = T; @@ -541,6 +500,7 @@ impl ops::Index for [T] { } } +#[stable] impl ops::IndexMut for [T] { type Output = T; @@ -551,6 +511,7 @@ impl ops::IndexMut for [T] { } } +#[stable] impl ops::Index> for [T] { type Output = [T]; #[inline] @@ -565,6 +526,7 @@ impl ops::Index> for [T] { } } } +#[stable] 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] 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] impl ops::Index for [T] { type Output = [T]; #[inline] @@ -587,6 +551,7 @@ impl ops::Index for [T] { } } +#[stable] impl ops::IndexMut> for [T] { type Output = [T]; #[inline] @@ -601,6 +566,7 @@ impl ops::IndexMut> for [T] { } } } +#[stable] 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] 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] impl ops::IndexMut for [T] { type Output = [T]; #[inline] @@ -973,7 +941,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 } } @@ -998,7 +966,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 } @@ -1051,7 +1019,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) } } @@ -1087,7 +1055,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..]) } } } @@ -1269,6 +1237,9 @@ impl<'a, T> DoubleEndedIterator for Chunks<'a, T> { } } +#[stable] +impl<'a, T> ExactSizeIterator for Chunks<'a, T> {} + #[unstable = "trait is experimental"] impl<'a, T> RandomAccessIterator for Chunks<'a, T> { #[inline] @@ -1347,6 +1318,8 @@ impl<'a, T> DoubleEndedIterator for ChunksMut<'a, T> { } } +#[stable] +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 6a542b2c45882..bdac686cb66bd 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; @@ -242,6 +244,30 @@ impl<'a> CharEq for &'a [char] { } } +#[stable] +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] +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 */ @@ -902,13 +928,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()]) } } } @@ -1115,27 +1141,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] 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] 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] 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] impl ops::Index for str { type Output = str; #[inline] @@ -1147,7 +1236,7 @@ mod traits { /// Any string that can be represented as a slice #[unstable = "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. @@ -1208,9 +1297,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; @@ -1332,7 +1418,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 } } @@ -1343,38 +1429,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; @@ -1415,7 +1469,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 979ddaecb4ae3..6ec87203e0030 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/num.rs b/src/libcoretest/fmt/num.rs index c259e4cbb686d..eb278d2cc9044 100644 --- a/src/libcoretest/fmt/num.rs +++ b/src/libcoretest/fmt/num.rs @@ -26,11 +26,11 @@ fn test_format_int() { 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!("{:?}", 1i) == "1"); + assert!(format!("{:?}", 1i8) == "1"); + assert!(format!("{:?}", 1i16) == "1"); + assert!(format!("{:?}", 1i32) == "1"); + assert!(format!("{:?}", 1i64) == "1"); assert!(format!("{:b}", 1i) == "1"); assert!(format!("{:b}", 1i8) == "1"); assert!(format!("{:b}", 1i16) == "1"); @@ -57,11 +57,11 @@ fn test_format_int() { 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!("{:?}", 1u) == "1"); + assert!(format!("{:?}", 1u8) == "1"); + assert!(format!("{:?}", 1u16) == "1"); + assert!(format!("{:?}", 1u32) == "1"); + assert!(format!("{:?}", 1u64) == "1"); assert!(format!("{:b}", 1u) == "1"); assert!(format!("{:b}", 1u8) == "1"); assert!(format!("{:b}", 1u16) == "1"); @@ -94,14 +94,14 @@ fn test_format_int() { #[test] fn test_format_int_zero() { assert!(format!("{}", 0i) == "0"); - assert!(format!("{:?}", 0i) == "0i"); + assert!(format!("{:?}", 0i) == "0"); assert!(format!("{:b}", 0i) == "0"); assert!(format!("{:o}", 0i) == "0"); assert!(format!("{:x}", 0i) == "0"); assert!(format!("{:X}", 0i) == "0"); assert!(format!("{}", 0u) == "0"); - assert!(format!("{:?}", 0u) == "0u"); + assert!(format!("{:?}", 0u) == "0"); assert!(format!("{:b}", 0u) == "0"); assert!(format!("{:o}", 0u) == "0"); assert!(format!("{:x}", 0u) == "0"); diff --git a/src/libcoretest/iter.rs b/src/libcoretest/iter.rs index 26819bf920986..4bbbde6b48ced 100644 --- a/src/libcoretest/iter.rs +++ b/src/libcoretest/iter.rs @@ -585,7 +585,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); diff --git a/src/libcoretest/num/mod.rs b/src/libcoretest/num/mod.rs index 8186a4f0904af..e0623bade5c0e 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 485549cc552ac..daccb709890e1 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 62eb9f4ad3480..e524d8de05693 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 c2114d4c6df6d..70f2429282b9a 100644 --- a/src/libgetopts/lib.rs +++ b/src/libgetopts/lib.rs @@ -544,7 +544,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) => { @@ -893,7 +893,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 2d7d88f0f35e0..0ed32b7bf4f32 100644 --- a/src/libgraphviz/lib.rs +++ b/src/libgraphviz/lib.rs @@ -358,19 +358,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 == '_' @@ -874,8 +874,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") } } @@ -883,8 +883,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 567fe04c5afbc..4e6437a5e761f 100644 --- a/src/libgraphviz/maybe_owned_vec.rs +++ b/src/libgraphviz/maybe_owned_vec.rs @@ -124,7 +124,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 fa6468517e699..a07fd61cd8c34 100644 --- a/src/liblibc/lib.rs +++ b/src/liblibc/lib.rs @@ -555,7 +555,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}; @@ -646,8 +647,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}; @@ -2491,7 +2491,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; @@ -2704,8 +2705,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; @@ -3002,7 +3002,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; @@ -3050,8 +3051,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; @@ -3099,7 +3099,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; @@ -3127,8 +3128,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; @@ -4648,13 +4648,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/lib.rs b/src/liblog/lib.rs index dbd8843412785..4da07c50c595e 100644 --- a/src/liblog/lib.rs +++ b/src/liblog/lib.rs @@ -180,6 +180,7 @@ 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}; @@ -239,21 +240,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) } } } @@ -437,11 +432,11 @@ 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); - FILTER = 0 as *const _; + FILTER = ptr::null(); } }); } diff --git a/src/librand/chacha.rs b/src/librand/chacha.rs index 815fc0e7ec7ad..3332e06e19e74 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 f39860c8695c9..9c746c69baafc 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 25279796c03c0..50fe56ff5c073 100644 --- a/src/librbml/lib.rs +++ b/src/librbml/lib.rs @@ -38,6 +38,7 @@ pub use self::EbmlEncoderTag::*; pub use self::Error::*; use std::str; +use std::fmt; pub mod io; @@ -113,6 +114,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/parse.rs b/src/libregex/parse.rs index 1cc2b271e9ccd..c2186a0ec241c 100644 --- a/src/libregex/parse.rs +++ b/src/libregex/parse.rs @@ -30,6 +30,7 @@ static MAX_REPEAT: uint = 1000; /// /// (Once an expression is compiled, it is not possible to produce an error /// via searching, splitting or replacing.) +#[derive(Show)] pub struct Error { /// The *approximate* character index of where the error occurred. pub pos: uint, @@ -37,7 +38,7 @@ pub struct Error { pub msg: String, } -impl fmt::Show for Error { +impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Regex syntax error near position {}: {:?}", self.pos, self.msg) @@ -518,7 +519,7 @@ impl<'a> Parser<'a> { }; self.chari = closer; let greed = try!(self.get_next_greedy()); - let inner = self.chars[(start+1)..closer].iter().cloned() + let inner = self.chars[start+1..closer].iter().cloned() .collect::(); // Parse the min and max values from the regex. diff --git a/src/libregex/re.rs b/src/libregex/re.rs index abc51d6240409..1b68ad500caa5 100644 --- a/src/libregex/re.rs +++ b/src/libregex/re.rs @@ -90,10 +90,10 @@ impl Clone for ExNative { } } -impl fmt::String for Regex { +impl fmt::Display for Regex { /// Shows the original regular expression. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::String::fmt(self.as_str(), f) + fmt::Display::fmt(self.as_str(), f) } } @@ -459,7 +459,7 @@ impl<'t> Captures<'t> { pub fn at(&self, i: uint) -> Option<&'t str> { match self.pos(i) { None => None, - Some((s, e)) => Some(self.text.slice(s, e)) + Some((s, e)) => Some(&self.text[s.. e]) } } diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 1ea79bdf606da..b48df36a67931 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 628690645514a..377e5dd39ff57 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -54,7 +54,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; @@ -132,8 +134,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 8a27cfc510f4a..fef1017b78285 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -1202,17 +1202,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[]); }, _ => () @@ -1329,7 +1329,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); }, } @@ -1709,22 +1709,6 @@ impl LintPass for Stability { } } - fn check_view_item(&mut self, cx: &Context, item: &ast::ViewItem) { - // compiler-generated `extern crate` statements 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 cx.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 }; - self.lint(cx, id, item.span); - } - fn check_expr(&mut self, cx: &Context, e: &ast::Expr) { if self.is_internal(cx, e.span) { return; } @@ -1776,6 +1760,17 @@ impl LintPass for Stability { if self.is_internal(cx, item.span) { return } match item.node { + ast::ItemExternCrate(_) => { + // compiler-generated `extern crate` items have a dummy span. + if item.span == DUMMY_SP { return } + + let cnum = match cx.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 }; + self.lint(cx, id, item.span); + } ast::ItemTrait(_, _, ref supertraits, _) => { for t in supertraits.iter() { if let ast::TraitTyParamBound(ref t, _) = *t { diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index de4efe09f2725..4cbfcf7e91ad1 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"); } @@ -603,14 +580,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 826a35e3bb529..a4a3f485af1d1 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 5de683f8a4f07..7b71120ba64a6 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 a928d1c902285..7b7159da4385d 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 6bf1798d246a4..1197276b9908f 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 70b6ddf23fd8d..b1043a4152cfc 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 5aacaa04e46d0..943be282103a7 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 bdd08ad6c4952..9aead5bf4e7f8 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 550c0f34cafec..537a2b3f545a2 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 a1ac25a5650ef..1a2162b3076ec 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 1f779acac2503..623f3525d4a90 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 a1a90395b3b78..aa803d9d8aea5 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 86a58dae45aa4..4280b7fe3f096 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 2b9bd1cd09fdb..a172786981031 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 30e0ce33018d0..affeef330c454 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 4a4328fa98baf..3280769ff0386 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 1b9d6ec6c33b6..18c36f870b5bc 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 0f487fffe5cb9..9339f435d8fa0 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 4fa8e07ddd4f1..ed11cafdca9b5 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 ff79ace992409..2c0de9d163486 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 27a0324a3c413..43989d0aadc8a 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 d6e652f16c654..b93cde4bf6464 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 017641bd3b71a..81cbdf13c5189 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 90ba442ee394e..b4b2e1b63e80c 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 eff0018becc01..030bf26699fb2 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/subst.rs b/src/librustc/middle/subst.rs index 9ad2dd499cc9d..889d8b4052f0f 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 6d0e60ec495a7..7ccb5e6e71160 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 42624555ae475..568286e39d597 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 425765edf870c..89459f95b879f 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 62649653a6972..e8d82150ade4b 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 fe8362223e3cd..bdf9b16f13960 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 be6c6b9d34f37..83bbdf14e4a74 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 37886b4a1e1f6..b4e6cff954bcc 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 892a8004fec1c..25cca98c5fb47 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 ef8a89c40fb5a..c420d1f15b43b 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 d9bb1d769bfbe..a2bba313cca87 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 5424b1c8cae50..4150335abc3d3 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -69,65 +69,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 +243,62 @@ 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 = 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); + + 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 0cf04fe0a006a..dfc27d3ae684d 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 c505e9e311256..8915d55e2063e 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 fb44d0cadfa6c..c5aced4eb86f5 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 7ea192b8d6bc8..fa754b4a3018c 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 e376ac50dcdf5..0228098b8f838 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 b71e465b938f5..ebeaf3e6e22d7 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 0000000000000..313c0dc2a6ea7 --- /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 f8eabb4375fb3..4626f2dc48339 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 d5ad201eabfaa..0ade916f6390a 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 889a359b019cd..b1cc3a651200c 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_driver/lib.rs b/src/librustc_driver/lib.rs index 50ff4546c3783..0e940b85bd84d 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -61,7 +61,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; @@ -98,7 +97,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[]) { @@ -154,10 +153,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| { @@ -659,8 +662,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 279442891bec0..582e10323248c 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 f68c76f4c4424..cd28a27f9886b 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 464f9f98e7ffc..db2a569cdeffa 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 4c9a25f42fb77..eded88bb62e74 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -53,7 +53,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, @@ -2262,19 +2262,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 e12c195a3afbc..414dbb9626347 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -830,6 +830,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; @@ -926,42 +958,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 @@ -1069,23 +1065,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> { @@ -1162,7 +1141,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(..) => {} } } @@ -1219,6 +1198,7 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> { } } + ast::ItemExternCrate(_) | ast::ItemUse(_) | ast::ItemStatic(..) | ast::ItemConst(..) | ast::ItemFn(..) | ast::ItemMod(..) | ast::ItemTy(..) | ast::ItemMac(..) => {} @@ -1521,11 +1501,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 21eec383df465..65bd83d7937fb 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 18066a7b94bd8..97370112ab40f 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 0000000000000..dd9ccfbda7ca6 --- /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 31999faa6dfea..94801545c2f03 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -65,10 +65,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}; @@ -97,6 +97,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; @@ -536,7 +540,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, @@ -1139,7 +1143,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) @@ -1718,7 +1722,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(), @@ -1748,10 +1752,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()); @@ -1765,7 +1765,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 => {} } @@ -1780,7 +1780,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[]); } } @@ -1791,10 +1791,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() @@ -1805,7 +1801,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 => {} } @@ -1827,7 +1823,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"); @@ -1845,7 +1841,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") @@ -1858,7 +1854,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") } @@ -1867,7 +1863,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") @@ -1888,16 +1884,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()); } } @@ -1906,17 +1897,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()); } } @@ -1965,7 +1951,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) { @@ -2083,8 +2069,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 => { @@ -2760,7 +2746,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. @@ -2982,9 +2968,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { }); } - ItemMac(..) => { + ItemExternCrate(_) | ItemUse(_) | ItemMac(..) => { // do nothing, these are just around to be encoded - } + } } } @@ -3525,6 +3511,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 dacf620cbd1d0..eedfc9407515c 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 c0b1492a78450..590354ab54e0a 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 aa51b0c5ee248..b07c2060e692f 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 b12903c814cbf..4aec53711ad8a 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 77343612ac88b..97b3cda006bf7 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 9f3c55d4f687e..dcb0b0ef4ea37 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 92883371ec9db..c98515cff6857 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 eed61ae59a259..572dfd165eeda 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 1f77f625c9db3..7acac5a12ebd2 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 980a70256e936..3c0530bbb9a64 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 11006f37531d2..7ed4727404e10 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 5658889aaf368..a25f4f778ab7a 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 8989dfd493236..7a6c0c50dd1ff 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 312fd33ef1ff0..3bc851c559537 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 5dc939dc2025b..bea8a75997152 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 8b52732f4ee97..cba12babb9b10 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 2f01f0328e28c..39413d6348249 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 11d1c7e679681..4ebaf91d11173 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 d3f3f34b76bbb..fb2ee55940d09 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 771c51d629fb4..9bee2c5bbc61c 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 0fb0dffe930fa..c2f19670e4f15 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 f52e7c0ec94c0..93076260349ab 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 f8b01ebf4ccad..06bc19f45a47e 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 07eb17e6300cd..9640443f4f7a6 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 42b12c158664a..921ed505fa3af 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 bfe43086aab10..ffec1421f9289 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 27d4b2055d4cd..e3e5d67869fa4 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 2a89a1d28bfc6..3cf9a1a945668 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 f610456f73cf1..5f8ae09b5bd6f 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 3b5027dbb9e69..56b700663d419 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 3940092eb7291..41b63830279a8 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 e6390212c6002..60284433ffe45 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 82da22eab9837..52e81585875ab 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 2719a09f4f570..e535b86a7bfd1 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 350cee99f6a3f..7d59c3f9d3ff5 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 77d71e740d681..60b1fa5f4cf5d 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 ce7ba9ac11e65..a7bad3dc789aa 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 e30d0a29938aa..867dea9588568 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 80c0a72db8387..8158b8da86dfd 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 c9e15b93ad4c5..3627fa4116060 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 47b5cd4b11e0f..78007f3552ece 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -111,6 +111,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; @@ -158,7 +162,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") } } } @@ -202,11 +206,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 86447e76a898b..6ed18368738e0 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 ccaefadc1fcd9..6e79bd9bebda1 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 7342c9f3e81de..203d9758c579d 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::*; @@ -45,7 +44,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; @@ -116,7 +114,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, @@ -127,6 +125,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))); @@ -134,8 +134,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. @@ -188,9 +188,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, @@ -198,7 +203,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, @@ -231,7 +236,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, @@ -307,8 +312,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), @@ -318,8 +325,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), @@ -336,7 +341,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, @@ -349,27 +354,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. @@ -395,9 +394,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 }) } } @@ -938,7 +935,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, @@ -977,7 +974,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, @@ -1015,7 +1012,7 @@ impl Clean for ast::TypeMethod { } } -#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq)] +#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Show)] pub enum SelfTy { SelfStatic, SelfValue, @@ -1036,7 +1033,7 @@ impl Clean for ast::ExplicitSelf_ { } } -#[derive(Clone, RustcEncodable, RustcDecodable)] +#[derive(Clone, RustcEncodable, RustcDecodable, Show)] pub struct Function { pub decl: FnDecl, pub generics: Generics, @@ -1155,7 +1152,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, @@ -1199,11 +1196,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 { @@ -1244,7 +1241,7 @@ impl Clean for ast::TraitItem { } } -#[derive(Clone, RustcEncodable, RustcDecodable)] +#[derive(Clone, RustcEncodable, RustcDecodable, Show)] pub enum ImplMethod { MethodImplItem(Item), TypeImplItem(Item), @@ -1380,7 +1377,7 @@ pub enum PrimitiveType { PrimitiveTuple, } -#[derive(Clone, RustcEncodable, RustcDecodable, Copy)] +#[derive(Clone, RustcEncodable, RustcDecodable, Copy, Show)] pub enum TypeKind { TypeEnum, TypeFunction, @@ -1623,7 +1620,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), @@ -1682,7 +1679,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, @@ -1712,7 +1709,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, @@ -1729,7 +1726,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, @@ -1754,7 +1751,7 @@ impl Clean for doctree::Enum { } } -#[derive(Clone, RustcEncodable, RustcDecodable)] +#[derive(Clone, RustcEncodable, RustcDecodable, Show)] pub struct Variant { pub kind: VariantKind, } @@ -1822,7 +1819,7 @@ impl<'tcx> Clean for ty::VariantInfo<'tcx> { } } -#[derive(Clone, RustcEncodable, RustcDecodable)] +#[derive(Clone, RustcEncodable, RustcDecodable, Show)] pub enum VariantKind { CLikeVariant, TupleVariant(Vec), @@ -1872,9 +1869,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(), } } } @@ -1969,7 +1966,7 @@ impl Clean for ast::Name { } } -#[derive(Clone, RustcEncodable, RustcDecodable)] +#[derive(Clone, RustcEncodable, RustcDecodable, Show)] pub struct Typedef { pub type_: Type, pub generics: Generics, @@ -2082,13 +2079,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 { @@ -2115,17 +2128,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 @@ -2136,81 +2159,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)), } } - } - } - ref n => ret.push(convert(n)), - } - return 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()), + remaining + } else { + list.clean(cx) }; - ExternCrate(i.clean(cx), string, *id) + if remaining.is_empty() { + return ret; + } + (ret, ImportList(resolve_use_source(cx, p.clean(cx), self.id), + remaining)) } - &ast::ViewItemUse(ref vp) => { - Import(vp.clean(cx)) + 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))) } - } + }; + 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 ViewPath { +#[derive(Clone, RustcEncodable, RustcDecodable, Show)] +pub enum Import { // use source as str; SimpleImport(String, ImportSource), // use source::*; @@ -2219,28 +2224,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, @@ -2459,7 +2449,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, } @@ -2480,7 +2470,7 @@ impl Clean for doctree::Macro { } } -#[derive(Clone, RustcEncodable, RustcDecodable)] +#[derive(Clone, RustcEncodable, RustcDecodable, Show)] pub struct Stability { pub level: attr::StabilityLevel, pub text: String @@ -2516,14 +2506,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, }), @@ -2555,6 +2545,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 5bef0195874b6..04947e41663ec 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 99afef4173fdd..0e8ab594c20c1 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 6fb78d9a8334b..fe8ac3fde5fcc 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 57b8d666c95b7..b713032bc0577 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 db3319eb7659c..356be2ffeb04c 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 f75ab3f431c2a..e3bd2b4e27f00 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 0dbd13b4616bb..6f19519ee7cb2 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -146,7 +146,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 } @@ -426,7 +426,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,7 +435,7 @@ 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) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index ab9700d966aa5..cd2ed5f0a974b 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; @@ -404,7 +404,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 +559,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 +749,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 +842,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 +853,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 +1185,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("/"); } @@ -1351,7 +1351,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,7 +1469,7 @@ 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 => "" @@ -1497,18 +1497,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 +1519,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 +1530,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 +1550,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 +1565,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 +1610,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 +2069,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 +2176,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; @@ -2243,7 +2231,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 5951ac2bae71a..0914f93efd802 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 f27f0cd70f4ef..1b0c3b0064099 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", diff --git a/src/librustdoc/html/toc.rs b/src/librustdoc/html/toc.rs index 8d94e1857c417..aca6e5bb10ed1 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, "