]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #34743 - badboy:llvm-upgrade, r=eddyb
authorbors <bors@rust-lang.org>
Mon, 1 Aug 2016 11:47:48 +0000 (04:47 -0700)
committerGitHub <noreply@github.com>
Mon, 1 Aug 2016 11:47:48 +0000 (04:47 -0700)
LLVM upgrade

As discussed in https://internals.rust-lang.org/t/need-help-with-emscripten-port/3154/46 I'm trying to update the used LLVM checkout in Rust.

I basically took @shepmaster's code and applied it on top (though I did the commits manually, the [original commits have better descriptions](https://github.com/rust-lang/rust/compare/master...avr-rust:avr-support).

With these changes I was able to build rustc. `make check` throws one last error on `run-pass/issue-28950.rs`. Output: https://gist.github.com/badboy/bcdd3bbde260860b6159aa49070a9052

I took the metadata changes as is and they seem to work, though it now uses the module in another step. I'm not sure if this is the best and correct way.

Things to do:

* [x] ~~Make `run-pass/issue-28950.rs` pass~~ unrelated
* [x] Find out how the `PositionIndependentExecutable` setting is now used
* [x] Is the `llvm::legacy` still the right way to do these things?

cc @brson @alexcrichton

182 files changed:
configure
mk/cfg/arm-unknown-linux-musleabi.mk [new file with mode: 0644]
mk/cfg/arm-unknown-linux-musleabihf.mk [new file with mode: 0644]
mk/cfg/armv7-unknown-linux-musleabihf.mk [new file with mode: 0644]
mk/rt.mk
src/bootstrap/Cargo.lock
src/bootstrap/compile.rs
src/bootstrap/config.rs
src/bootstrap/config.toml.example
src/bootstrap/lib.rs
src/bootstrap/native.rs
src/bootstrap/sanity.rs
src/doc/book/closures.md
src/doc/book/ffi.md
src/etc/local_stage0.sh
src/liballoc_jemalloc/Cargo.toml
src/liballoc_jemalloc/build.rs
src/libcollections/fmt.rs
src/libcollections/linked_list.rs
src/libcollectionstest/string.rs
src/libcore/macros.rs
src/libcore/num/mod.rs
src/libcore/str/mod.rs
src/libflate/Cargo.toml
src/liblibc
src/libpanic_unwind/dwarf/eh.rs
src/libpanic_unwind/gcc.rs
src/libpanic_unwind/seh64_gnu.rs
src/librustc/hir/intravisit.rs
src/librustc/hir/map/collector.rs
src/librustc/hir/mod.rs
src/librustc/lint/context.rs
src/librustc/middle/cstore.rs
src/librustc/middle/effect.rs
src/librustc/middle/expr_use_visitor.rs
src/librustc/middle/lang_items.rs
src/librustc/middle/liveness.rs
src/librustc/middle/mem_categorization.rs
src/librustc/session/config.rs
src/librustc/ty/util.rs
src/librustc/util/ppaux.rs
src/librustc_back/target/aarch64_apple_ios.rs
src/librustc_back/target/aarch64_linux_android.rs
src/librustc_back/target/aarch64_unknown_linux_gnu.rs
src/librustc_back/target/apple_ios_base.rs
src/librustc_back/target/arm_linux_androideabi.rs
src/librustc_back/target/arm_unknown_linux_gnueabi.rs
src/librustc_back/target/arm_unknown_linux_gnueabihf.rs
src/librustc_back/target/arm_unknown_linux_musleabi.rs [new file with mode: 0644]
src/librustc_back/target/arm_unknown_linux_musleabihf.rs [new file with mode: 0644]
src/librustc_back/target/armv7_apple_ios.rs
src/librustc_back/target/armv7_linux_androideabi.rs
src/librustc_back/target/armv7_unknown_linux_gnueabihf.rs
src/librustc_back/target/armv7_unknown_linux_musleabihf.rs [new file with mode: 0644]
src/librustc_back/target/armv7s_apple_ios.rs
src/librustc_back/target/asmjs_unknown_emscripten.rs
src/librustc_back/target/i386_apple_ios.rs
src/librustc_back/target/i586_pc_windows_msvc.rs
src/librustc_back/target/i586_unknown_linux_gnu.rs
src/librustc_back/target/i686_apple_darwin.rs
src/librustc_back/target/i686_linux_android.rs
src/librustc_back/target/i686_pc_windows_gnu.rs
src/librustc_back/target/i686_pc_windows_msvc.rs
src/librustc_back/target/i686_unknown_dragonfly.rs
src/librustc_back/target/i686_unknown_freebsd.rs
src/librustc_back/target/i686_unknown_linux_gnu.rs
src/librustc_back/target/i686_unknown_linux_musl.rs
src/librustc_back/target/le32_unknown_nacl.rs
src/librustc_back/target/mips_unknown_linux_gnu.rs
src/librustc_back/target/mips_unknown_linux_musl.rs
src/librustc_back/target/mipsel_unknown_linux_gnu.rs
src/librustc_back/target/mipsel_unknown_linux_musl.rs
src/librustc_back/target/mod.rs
src/librustc_back/target/powerpc64_unknown_linux_gnu.rs
src/librustc_back/target/powerpc64le_unknown_linux_gnu.rs
src/librustc_back/target/powerpc_unknown_linux_gnu.rs
src/librustc_back/target/windows_base.rs
src/librustc_back/target/x86_64_apple_darwin.rs
src/librustc_back/target/x86_64_apple_ios.rs
src/librustc_back/target/x86_64_pc_windows_gnu.rs
src/librustc_back/target/x86_64_pc_windows_msvc.rs
src/librustc_back/target/x86_64_rumprun_netbsd.rs
src/librustc_back/target/x86_64_sun_solaris.rs
src/librustc_back/target/x86_64_unknown_bitrig.rs
src/librustc_back/target/x86_64_unknown_dragonfly.rs
src/librustc_back/target/x86_64_unknown_freebsd.rs
src/librustc_back/target/x86_64_unknown_linux_gnu.rs
src/librustc_back/target/x86_64_unknown_linux_musl.rs
src/librustc_back/target/x86_64_unknown_netbsd.rs
src/librustc_back/target/x86_64_unknown_openbsd.rs
src/librustc_borrowck/borrowck/mod.rs
src/librustc_const_eval/check_match.rs
src/librustc_driver/lib.rs
src/librustc_incremental/assert_dep_graph.rs
src/librustc_incremental/calculate_svh.rs
src/librustc_lint/builtin.rs
src/librustc_llvm/Cargo.toml
src/librustc_metadata/astencode.rs
src/librustc_metadata/decoder.rs
src/librustc_metadata/encoder.rs
src/librustc_metadata/macro_import.rs
src/librustc_mir/mir_map.rs
src/librustc_passes/consts.rs
src/librustc_passes/rvalues.rs
src/librustc_privacy/lib.rs
src/librustc_resolve/lib.rs
src/librustc_resolve/resolve_imports.rs
src/librustc_trans/closure.rs
src/librustc_trans/intrinsic.rs
src/librustc_trans/mir/constant.rs
src/librustc_trans/mir/rvalue.rs
src/librustc_typeck/check/upvar.rs
src/librustc_typeck/check/wfcheck.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/constrained_type_params.rs
src/librustdoc/Cargo.toml
src/librustdoc/clean/mod.rs
src/libstd/Cargo.toml
src/libstd/build.rs
src/libstd/fs.rs
src/libstd/panicking.rs
src/libstd/sys/common/mod.rs
src/libstd/sys/unix/ext/fs.rs
src/libstd/sys/unix/mod.rs
src/libsyntax/attr.rs
src/libsyntax/ext/build.rs
src/libsyntax/ext/expand.rs
src/libsyntax/feature_gate.rs
src/libsyntax_ext/deriving/mod.rs
src/libsyntax_ext/format.rs
src/libsyntax_pos/lib.rs
src/libunwind/build.rs
src/libunwind/libunwind.rs
src/rustc/std_shim/Cargo.lock
src/rustc/std_shim/Cargo.toml
src/test/compile-fail-fulldeps/lint-plugin-forbid-attrs.rs
src/test/compile-fail/E0045.rs
src/test/compile-fail/array-not-vector.rs
src/test/compile-fail/bad-const-type.rs
src/test/compile-fail/coerce-mut.rs
src/test/compile-fail/coercion-slice.rs
src/test/compile-fail/feature-gate-abi-vectorcall.rs [deleted file]
src/test/compile-fail/feature-gate-abi.rs [new file with mode: 0644]
src/test/compile-fail/feature-gate-rust-call.rs [deleted file]
src/test/compile-fail/fully-qualified-type-name1.rs
src/test/compile-fail/if-let-arm-types.rs
src/test/compile-fail/ifmt-bad-arg.rs
src/test/compile-fail/indexing-requires-a-uint.rs
src/test/compile-fail/integral-variable-unification-error.rs
src/test/compile-fail/issue-13466.rs
src/test/compile-fail/issue-17651.rs
src/test/compile-fail/issue-19991.rs
src/test/compile-fail/issue-26237.rs
src/test/compile-fail/issue-34349.rs [new file with mode: 0644]
src/test/compile-fail/issue-35075.rs [new file with mode: 0644]
src/test/compile-fail/issue-35139.rs [new file with mode: 0644]
src/test/compile-fail/issue-4201.rs
src/test/compile-fail/issue-4968.rs
src/test/compile-fail/issue-7867.rs
src/test/compile-fail/kindck-impl-type-params-2.rs
src/test/compile-fail/lint-forbid-attr.rs
src/test/compile-fail/match-range-fail.rs
src/test/compile-fail/match-vec-mismatch.rs
src/test/compile-fail/method-self-arg-1.rs
src/test/compile-fail/mut-pattern-mismatched.rs
src/test/compile-fail/no_send-rc.rs
src/test/compile-fail/privacy-ns2.rs
src/test/compile-fail/range-1.rs
src/test/compile-fail/repeat_count.rs
src/test/compile-fail/resolve-type-param-in-item-in-trait.rs
src/test/compile-fail/slightly-nice-generic-literal-messages.rs
src/test/compile-fail/str-idx.rs
src/test/compile-fail/struct-base-wrong-type-2.rs
src/test/compile-fail/struct-base-wrong-type.rs
src/test/compile-fail/traits-inductive-overflow-simultaneous.rs
src/test/compile-fail/tuple-arity-mismatch.rs
src/test/compile-fail/tuple-index-out-of-bounds.rs
src/test/compile-fail/type-mismatch-multiple.rs
src/test/compile-fail/typeck-unsafe-always-share.rs
src/test/compile-fail/vtable-res-trait-param.rs
src/test/run-pass/myriad-closures.rs [new file with mode: 0644]
src/test/ui/mismatched_types/issue-26480.stderr

index 3e2cbcbe3644253d10d3698e28c3e12932593191..d4bd16167d35cba350c1e042b12e1b189a8a720a 100755 (executable)
--- a/configure
+++ b/configure
@@ -1198,7 +1198,7 @@ do
             ;;
 
 
-        x86_64-*-musl)
+        x86_64-*-musl | arm-*-musleabi)
             if [ ! -f $CFG_MUSL_ROOT/lib/libc.a ]
             then
                 err "musl libc $CFG_MUSL_ROOT/lib/libc.a not found"
diff --git a/mk/cfg/arm-unknown-linux-musleabi.mk b/mk/cfg/arm-unknown-linux-musleabi.mk
new file mode 100644 (file)
index 0000000..8120250
--- /dev/null
@@ -0,0 +1,3 @@
+# This file is intentially left empty to indicate that, while this target is
+# supported, it's not supported using plain GNU Make builds. Use a --rustbuild
+# instead.
\ No newline at end of file
diff --git a/mk/cfg/arm-unknown-linux-musleabihf.mk b/mk/cfg/arm-unknown-linux-musleabihf.mk
new file mode 100644 (file)
index 0000000..8120250
--- /dev/null
@@ -0,0 +1,3 @@
+# This file is intentially left empty to indicate that, while this target is
+# supported, it's not supported using plain GNU Make builds. Use a --rustbuild
+# instead.
\ No newline at end of file
diff --git a/mk/cfg/armv7-unknown-linux-musleabihf.mk b/mk/cfg/armv7-unknown-linux-musleabihf.mk
new file mode 100644 (file)
index 0000000..8120250
--- /dev/null
@@ -0,0 +1,3 @@
+# This file is intentially left empty to indicate that, while this target is
+# supported, it's not supported using plain GNU Make builds. Use a --rustbuild
+# instead.
\ No newline at end of file
index 067721fab4fa8353101c7f42aeafad01e8475197..e86aec60893e9f42c03836d6be379d864230da11 100644 (file)
--- a/mk/rt.mk
+++ b/mk/rt.mk
@@ -384,7 +384,11 @@ COMPRT_OBJS_$(1) += emutls.o
 endif
 
 ifeq ($$(findstring msvc,$(1)),)
+
+ifeq ($$(findstring freebsd,$(1)),)
 COMPRT_OBJS_$(1) += gcc_personality_v0.o
+endif
+
 COMPRT_OBJS_$(1) += emutls.o
 
 ifeq ($$(findstring x86_64,$(1)),x86_64)
index 1290f2a404b22cff42df43f162c667a5ac456cd3..02698d6f7a1237cdbd014173bd1a0b52a6ac3eb0 100644 (file)
@@ -7,8 +7,8 @@ dependencies = [
  "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "gcc 0.3.31 (git+https://github.com/alexcrichton/gcc-rs)",
  "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
- "kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "md5 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -33,7 +33,7 @@ name = "filetime"
 version = "0.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -53,7 +53,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "kernel32-sys"
-version = "0.2.1"
+version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -62,7 +62,7 @@ dependencies = [
 
 [[package]]
 name = "libc"
-version = "0.2.9"
+version = "0.2.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -75,7 +75,7 @@ name = "num_cpus"
 version = "0.2.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
index 8ec9c7f0109f3f18c5035008d4751dd955473a6b..061192ebd1340b318aedbea2441339eebb4282fe 100644 (file)
@@ -92,8 +92,7 @@ pub fn std_link(build: &Build,
     }
     add_to_sysroot(&out_dir, &libdir);
 
-    if target.contains("musl") &&
-       (target.contains("x86_64") || target.contains("i686")) {
+    if target.contains("musl") && !target.contains("mips") {
         copy_third_party_objects(build, target, &libdir);
     }
 }
index e64d7e5a437e6103b13f7b5a471c90fa1f9b7c5b..aafbf68d1b7b60b712fac8ba7a6b091b2266c98d 100644 (file)
@@ -72,6 +72,7 @@ pub struct Config {
     // libstd features
     pub debug_jemalloc: bool,
     pub use_jemalloc: bool,
+    pub backtrace: bool, // support for RUST_BACKTRACE
 
     // misc
     pub channel: String,
@@ -134,6 +135,7 @@ struct Rust {
     debuginfo: Option<bool>,
     debug_jemalloc: Option<bool>,
     use_jemalloc: Option<bool>,
+    backtrace: Option<bool>,
     default_linker: Option<String>,
     default_ar: Option<String>,
     channel: Option<String>,
@@ -158,6 +160,7 @@ pub fn parse(build: &str, file: Option<PathBuf>) -> Config {
         let mut config = Config::default();
         config.llvm_optimize = true;
         config.use_jemalloc = true;
+        config.backtrace = true;
         config.rust_optimize = true;
         config.rust_optimize_tests = true;
         config.submodules = true;
@@ -230,6 +233,7 @@ pub fn parse(build: &str, file: Option<PathBuf>) -> Config {
             set(&mut config.rust_rpath, rust.rpath);
             set(&mut config.debug_jemalloc, rust.debug_jemalloc);
             set(&mut config.use_jemalloc, rust.use_jemalloc);
+            set(&mut config.backtrace, rust.backtrace);
             set(&mut config.channel, rust.channel.clone());
             config.rustc_default_linker = rust.default_linker.clone();
             config.rustc_default_ar = rust.default_ar.clone();
index 6f0658423283be3c61f9377c0f04dcc8f0b24f49..2894adafef622dab873f3595bd264aaac1cfb004 100644 (file)
@@ -99,6 +99,9 @@
 # Whether or not jemalloc is built with its debug option set
 #debug-jemalloc = false
 
+# Whether or not `panic!`s generate backtraces (RUST_BACKTRACE)
+#backtrace = true
+
 # The default linker that will be used by the generated compiler. Note that this
 # is not the linker used to link said compiler.
 #default-linker = "cc"
index 367322e8816465d6f298c1e4a8fec8edcb7fd035..25356b86221c1975e4b59ee6d31901611852752c 100644 (file)
@@ -652,6 +652,9 @@ fn std_features(&self) -> String {
         if self.config.use_jemalloc {
             features.push_str(" jemalloc");
         }
+        if self.config.backtrace {
+            features.push_str(" backtrace");
+        }
         return features
     }
 
index 05ecbc0cadaa9ab25113e8ce3bca2ca33e98696f..a78cef4f409b43e1001b209459eb4604e0ff3a5c 100644 (file)
@@ -348,7 +348,9 @@ pub fn compiler_rt(build: &Build, target: &str) {
             ]);
         }
     } else {
-        sources.push("gcc_personality_v0.c");
+        if !target.contains("freebsd") {
+            sources.push("gcc_personality_v0.c");
+        }
 
         if target.contains("x86_64") {
             sources.extend(vec![
index 7c0f09c322f24cffa5bd39a0d515bc873a77a22f..09f96782e7184a9af4a9564430164224fcfb6fb2 100644 (file)
 pub fn check(build: &mut Build) {
     let mut checked = HashSet::new();
     let path = env::var_os("PATH").unwrap_or(OsString::new());
+    // On Windows, quotes are invalid characters for filename paths, and if
+    // one is present as part of the PATH then that can lead to the system
+    // being unable to identify the files properly. See
+    // https://github.com/rust-lang/rust/issues/34959 for more details.
+    if cfg!(windows) {
+        if path.to_string_lossy().contains("\"") {
+            panic!("PATH contains invalid character '\"'");
+        }
+    }
     let mut need_cmd = |cmd: &OsStr| {
         if !checked.insert(cmd.to_owned()) {
             return
@@ -100,7 +109,7 @@ pub fn check(build: &mut Build) {
         }
 
         // Make sure musl-root is valid if specified
-        if target.contains("musl") && (target.contains("x86_64") || target.contains("i686")) {
+        if target.contains("musl") && !target.contains("mips") {
             match build.config.musl_root {
                 Some(ref root) => {
                     if fs::metadata(root.join("lib/libc.a")).is_err() {
index 666d0946ecc80a3eac3e25a9764bb34b097bd85b..1470eac98295e8860c02464d7e445e68e2593aeb 100644 (file)
@@ -223,6 +223,7 @@ trait system to overload operators. Calling functions is no different. We have
 three separate traits to overload with:
 
 ```rust
+# #![feature(unboxed_closures)]
 # mod foo {
 pub trait Fn<Args> : FnMut<Args> {
     extern "rust-call" fn call(&self, args: Args) -> Self::Output;
@@ -291,9 +292,9 @@ isn’t interesting. The next part is:
 #   some_closure(1) }
 ```
 
-Because `Fn` is a trait, we can bound our generic with it. In this case, our
-closure takes a `i32` as an argument and returns an `i32`, and so the generic
-bound we use is `Fn(i32) -> i32`.
+Because `Fn` is a trait, we can use it as a bound for our generic type. In
+this case, our closure takes a `i32` as an argument and returns an `i32`, and
+so the generic bound we use is `Fn(i32) -> i32`.
 
 There’s one other key point here: because we’re bounding a generic with a
 trait, this will get monomorphized, and therefore, we’ll be doing static
index 3cbe5d6026774abca897db24797882d4065a95f6..ca104ff29ace3377c7ccb9efb5d53b7c350963a8 100644 (file)
@@ -575,16 +575,69 @@ against `libc` and `libm` by default.
 
 # The "nullable pointer optimization"
 
-Certain types are defined to not be NULL. This includes references (`&T`,
-`&mut T`), boxes (`Box<T>`), and function pointers (`extern "abi" fn()`).
-When interfacing with C, pointers that might be NULL are often used.
-As a special case, a generic `enum` that contains exactly two variants, one of
-which contains no data and the other containing a single field, is eligible
-for the "nullable pointer optimization". When such an enum is instantiated
-with one of the non-nullable types, it is represented as a single pointer,
-and the non-data variant is represented as the NULL pointer. So
-`Option<extern "C" fn(c_int) -> c_int>` is how one represents a nullable
-function pointer using the C ABI.
+Certain Rust types are defined to never be `null`. This includes references (`&T`,
+`&mut T`), boxes (`Box<T>`), and function pointers (`extern "abi" fn()`). When
+interfacing with C, pointers that might be `null` are often used, which would seem to
+require some messy `transmute`s and/or unsafe code to handle conversions to/from Rust types.
+However, the language provides a workaround.
+
+As a special case, an `enum` is eligible for the "nullable pointer optimization" if it contains
+exactly two variants, one of which contains no data and the other contains a field of one of the
+non-nullable types listed above.  This means no extra space is required for a discriminant; rather,
+the empty variant is represented by putting a `null` value into the non-nullable field. This is
+called an "optimization", but unlike other optimizations it is guaranteed to apply to eligible
+types.
+
+The most common type that takes advantage of the nullable pointer optimization is `Option<T>`,
+where `None` corresponds to `null`. So `Option<extern "C" fn(c_int) -> c_int>` is a correct way
+to represent a nullable function pointer using the C ABI (corresponding to the C type
+`int (*)(int)`).
+
+Here is a contrived example. Let's say some C library has a facility for registering a
+callback, which gets called in certain situations. The callback is passed a function pointer
+and an integer and it is supposed to run the function with the integer as a parameter. So
+we have function pointers flying across the FFI boundary in both directions.
+
+```rust
+# #![feature(libc)]
+extern crate libc;
+use libc::c_int;
+
+# #[cfg(hidden)]
+extern "C" {
+    /// Register the callback.
+    fn register(cb: Option<extern "C" fn(Option<extern "C" fn(c_int) -> c_int>, c_int) -> c_int>);
+}
+# unsafe fn register(_: Option<extern "C" fn(Option<extern "C" fn(c_int) -> c_int>,
+#                                            c_int) -> c_int>)
+# {}
+
+/// This fairly useless function receives a function pointer and an integer
+/// from C, and returns the result of calling the function with the integer.
+/// In case no function is provided, it squares the integer by default.
+extern "C" fn apply(process: Option<extern "C" fn(c_int) -> c_int>, int: c_int) -> c_int {
+    match process {
+        Some(f) => f(int),
+        None    => int * int
+    }
+}
+
+fn main() {
+    unsafe {
+        register(Some(apply));
+    }
+}
+```
+
+And the code on the C side looks like this:
+
+```c
+void register(void (*f)(void (*)(int), int)) {
+    ...
+}
+```
+
+No `transmute` required!
 
 # Calling Rust code from C
 
index 354be34b6a2950efe920bd2e44e57efe77e2bf74..f5f39d264a6b0a2f1cb7704aacabbbfc721522d9 100755 (executable)
@@ -58,6 +58,7 @@ case "$TARG_DIR" in
 
 cp ${PREFIX}/bin/rustc${BIN_SUF} ${TARG_DIR}/stage0/bin/
 cp ${PREFIX}/${LIB_DIR}/${RUSTLIBDIR}/${TARG_DIR}/${LIB_DIR}/* ${TARG_DIR}/stage0/${LIB_DIR}/
+cp ${PREFIX}/${LIB_DIR}/${LIB_PREFIX}arena*${LIB_SUF} ${TARG_DIR}/stage0/${LIB_DIR}/
 cp ${PREFIX}/${LIB_DIR}/${LIB_PREFIX}extra*${LIB_SUF} ${TARG_DIR}/stage0/${LIB_DIR}/
 cp ${PREFIX}/${LIB_DIR}/${LIB_PREFIX}rust*${LIB_SUF} ${TARG_DIR}/stage0/${LIB_DIR}/
 cp ${PREFIX}/${LIB_DIR}/${LIB_PREFIX}std*${LIB_SUF} ${TARG_DIR}/stage0/${LIB_DIR}/
index 768a0c2c0a54deb93a7bc178a25110ca1b6001f6..25b3c8a3a0a8355a89888a305ddb9c373cd04f05 100644 (file)
@@ -16,7 +16,7 @@ libc = { path = "../rustc/libc_shim" }
 
 [build-dependencies]
 build_helper = { path = "../build_helper" }
-gcc = "0.3.17"
+gcc = "0.3.27"
 
 [features]
 debug = []
index d1b3583d256b6e11bc6136c6ea364a5216b33a2e..dc1b8d6ea983509ef7b91dfb2f9867552e718f20 100644 (file)
@@ -73,7 +73,16 @@ fn main() {
                    .replace("\\", "/"))
        .current_dir(&build_dir)
        .env("CC", compiler.path())
-       .env("EXTRA_CFLAGS", cflags)
+       .env("EXTRA_CFLAGS", cflags.clone())
+       // jemalloc generates Makefile deps using GCC's "-MM" flag. This means
+       // that GCC will run the preprocessor, and only the preprocessor, over
+       // jemalloc's source files. If we don't specify CPPFLAGS, then at least
+       // on ARM that step fails with a "Missing implementation for 32-bit
+       // atomic operations" error. This is because no "-march" flag will be
+       // passed to GCC, and then GCC won't define the
+       // "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4" macro that jemalloc needs to
+       // select an atomic operation implementation.
+       .env("CPPFLAGS", cflags.clone())
        .env("AR", &ar)
        .env("RANLIB", format!("{} s", ar.display()));
 
index c5312d0d9bbd9ad27ee68432f46e40f8ff146842..be0ef85d6b114aad2c2c975774bc209af7311fac 100644 (file)
 //!    in this case, if one uses the format string `{<arg>:<spec>.*}`, then the `<arg>` part refers
 //!    to the *value* to print, and the `precision` must come in the input preceding `<arg>`.
 //!
-//! For example, these:
+//! For example, the following calls all print the same thing `Hello x is 0.01000`:
 //!
 //! ```
-//! // Hello {arg 0 (x)} is {arg 1 (0.01) with precision specified inline (5)}
+//! // Hello {arg 0 ("x")} is {arg 1 (0.01) with precision specified inline (5)}
 //! println!("Hello {0} is {1:.5}", "x", 0.01);
 //!
-//! // Hello {arg 1 (x)} is {arg 2 (0.01) with precision specified in arg 0 (5)}
+//! // Hello {arg 1 ("x")} is {arg 2 (0.01) with precision specified in arg 0 (5)}
 //! println!("Hello {1} is {2:.0$}", 5, "x", 0.01);
 //!
-//! // Hello {arg 0 (x)} is {arg 2 (0.01) with precision specified in arg 1 (5)}
+//! // Hello {arg 0 ("x")} is {arg 2 (0.01) with precision specified in arg 1 (5)}
 //! println!("Hello {0} is {2:.1$}", "x", 5, 0.01);
 //!
-//! // Hello {next arg (x)} is {second of next two args (0.01) with precision
+//! // Hello {next arg ("x")} is {second of next two args (0.01) with precision
 //! //                          specified in first of next two args (5)}
 //! println!("Hello {} is {:.*}",    "x", 5, 0.01);
 //!
-//! // Hello {next arg (x)} is {arg 2 (0.01) with precision
+//! // Hello {next arg ("x")} is {arg 2 (0.01) with precision
 //! //                          specified in its predecessor (5)}
 //! println!("Hello {} is {2:.*}",   "x", 5, 0.01);
 //!
-//! // Hello {next arg (x)} is {arg "number" (0.01) with precision specified
+//! // Hello {next arg ("x")} is {arg "number" (0.01) with precision specified
 //! //                          in arg "prec" (5)}
 //! println!("Hello {} is {number:.prec$}", "x", prec = 5, number = 0.01);
 //! ```
 //!
-//! All print the same thing:
-//!
-//! ```text
-//! Hello x is 0.01000
-//! ```
-//!
 //! While these:
 //!
 //! ```
index 3d5c3125fae2489c460f1352aa4776a1017fdf33..6842f02e0e19b1732d3ded4cc9a169f09c46b5c0 100644 (file)
@@ -203,19 +203,22 @@ pub fn new() -> Self {
     /// ```
     /// use std::collections::LinkedList;
     ///
-    /// let mut a = LinkedList::new();
-    /// let mut b = LinkedList::new();
-    /// a.push_back(1);
-    /// a.push_back(2);
-    /// b.push_back(3);
-    /// b.push_back(4);
+    /// let mut list1 = LinkedList::new();
+    /// list1.push_back('a');
     ///
-    /// a.append(&mut b);
+    /// let mut list2 = LinkedList::new();
+    /// list2.push_back('b');
+    /// list2.push_back('c');
     ///
-    /// for e in &a {
-    ///     println!("{}", e); // prints 1, then 2, then 3, then 4
-    /// }
-    /// println!("{}", b.len()); // prints 0
+    /// list1.append(&mut list2);
+    ///
+    /// let mut iter = list1.iter();
+    /// assert_eq!(iter.next(), Some(&'a'));
+    /// assert_eq!(iter.next(), Some(&'b'));
+    /// assert_eq!(iter.next(), Some(&'c'));
+    /// assert!(iter.next().is_none());
+    ///
+    /// assert!(list2.is_empty());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn append(&mut self, other: &mut Self) {
index 7f0fd282ae5e943f32b7f281a7c2f9137f2f50d7..1652fb5a88d80dc46d1089adbb277cf9fa330ba7 100644 (file)
@@ -192,6 +192,17 @@ fn test_push_str() {
     assert_eq!(&s[0..], "abcประเทศไทย中华Việt Nam");
 }
 
+#[test]
+fn test_add_assign() {
+    let mut s = String::new();
+    s += "";
+    assert_eq!(s.as_str(), "");
+    s += "abc";
+    assert_eq!(s.as_str(), "abc");
+    s += "ประเทศไทย中华Việt Nam";
+    assert_eq!(s.as_str(), "abcประเทศไทย中华Việt Nam");
+}
+
 #[test]
 fn test_push() {
     let mut data = String::from("ประเทศไทย中");
index 43868d124a22e00c69ac67e781e0d7b0c84ba114..b0c79a3a88547b0551436df2d562bc4ea6d0c6d9 100644 (file)
@@ -35,6 +35,17 @@ macro_rules! panic {
 /// This will invoke the `panic!` macro if the provided expression cannot be
 /// evaluated to `true` at runtime.
 ///
+/// Assertions are always checked in both debug and release builds, and cannot
+/// be disabled. See `debug_assert!` for assertions that are not enabled in
+/// release builds by default.
+///
+/// Unsafe code relies on `assert!` to enforce run-time invariants that, if
+/// violated could lead to unsafety.
+///
+/// Other use-cases of `assert!` include
+/// [testing](https://doc.rust-lang.org/book/testing.html) and enforcing
+/// run-time invariants in safe code (whose violation cannot result in unsafety).
+///
 /// This macro has a second version, where a custom panic message can be provided.
 ///
 /// # Examples
@@ -123,6 +134,13 @@ macro_rules! assert_eq {
 /// expensive to be present in a release build but may be helpful during
 /// development.
 ///
+/// An unchecked assertion allows a program in an inconsistent state to keep
+/// running, which might have unexpected consequences but does not introduce
+/// unsafety as long as this only happens in safe code. The performance cost
+/// of assertions, is however, not measurable in general. Replacing `assert!`
+/// with `debug_assert!` is thus only encouraged after thorough profiling, and
+/// more importantly, only in safe code!
+///
 /// # Examples
 ///
 /// ```
index 97648cc34699a9dc6baaf133fa8a28893b2fe74a..4636811aa46da2c95f96d6c87bf9cdd3a06a09b6 100644 (file)
@@ -611,6 +611,31 @@ pub fn checked_shr(self, rhs: u32) -> Option<Self> {
             if b {None} else {Some(a)}
         }
 
+        /// Checked absolute value. Computes `self.abs()`, returning `None` if
+        /// `self == MIN`.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        /// # #![feature(no_panic_abs)]
+        ///
+        /// use std::i32;
+        ///
+        /// assert_eq!((-5i32).checked_abs(), Some(5));
+        /// assert_eq!(i32::MIN.checked_abs(), None);
+        /// ```
+        #[unstable(feature = "no_panic_abs", issue = "35057")]
+        #[inline]
+        pub fn checked_abs(self) -> Option<Self> {
+            if self.is_negative() {
+                self.checked_neg()
+            } else {
+                Some(self)
+            }
+        }
+
         /// Saturating integer addition. Computes `self + other`, saturating at
         /// the numeric bounds instead of overflowing.
         ///
@@ -863,6 +888,36 @@ pub fn wrapping_shr(self, rhs: u32) -> Self {
             self.overflowing_shr(rhs).0
         }
 
+        /// Wrapping (modular) absolute value. Computes `self.abs()`,
+        /// wrapping around at the boundary of the type.
+        ///
+        /// The only case where such wrapping can occur is when one takes
+        /// the absolute value of the negative minimal value for the type
+        /// this is a positive value that is too large to represent in the
+        /// type. In such a case, this function returns `MIN` itself.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        /// # #![feature(no_panic_abs)]
+        ///
+        /// assert_eq!(100i8.wrapping_abs(), 100);
+        /// assert_eq!((-100i8).wrapping_abs(), 100);
+        /// assert_eq!((-128i8).wrapping_abs(), -128);
+        /// assert_eq!((-128i8).wrapping_abs() as u8, 128);
+        /// ```
+        #[unstable(feature = "no_panic_abs", issue = "35057")]
+        #[inline(always)]
+        pub fn wrapping_abs(self) -> Self {
+            if self.is_negative() {
+                self.wrapping_neg()
+            } else {
+                self
+            }
+        }
+
         /// Calculates `self` + `rhs`
         ///
         /// Returns a tuple of the addition along with a boolean indicating
@@ -1071,6 +1126,35 @@ pub fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
             (self >> (rhs & ($BITS - 1)), (rhs > ($BITS - 1)))
         }
 
+        /// Computes the absolute value of `self`.
+        ///
+        /// Returns a tuple of the absolute version of self along with a
+        /// boolean indicating whether an overflow happened. If self is the
+        /// minimum value (e.g. i32::MIN for values of type i32), then the
+        /// minimum value will be returned again and true will be returned for
+        /// an overflow happening.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        /// # #![feature(no_panic_abs)]
+        ///
+        /// assert_eq!(10i8.overflowing_abs(), (10,false));
+        /// assert_eq!((-10i8).overflowing_abs(), (10,false));
+        /// assert_eq!((-128i8).overflowing_abs(), (-128,true));
+        /// ```
+        #[unstable(feature = "no_panic_abs", issue = "35057")]
+        #[inline]
+        pub fn overflowing_abs(self) -> (Self, bool) {
+            if self.is_negative() {
+                self.overflowing_neg()
+            } else {
+                (self, false)
+            }
+        }
+
         /// Raises self to the power of `exp`, using exponentiation by squaring.
         ///
         /// # Examples
index a32c9da9815ffc0a19d0cfdeec1138ccd6097b3d..fdcadd43a0fb64deeda403b43c42ebf3a74c4277 100644 (file)
@@ -459,6 +459,19 @@ impl<'a> Chars<'a> {
     ///
     /// This has the same lifetime as the original slice, and so the
     /// iterator can continue to be used while this exists.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let mut chars = "abc".chars();
+    ///
+    /// assert_eq!(chars.as_str(), "abc");
+    /// chars.next();
+    /// assert_eq!(chars.as_str(), "bc");
+    /// chars.next();
+    /// chars.next();
+    /// assert_eq!(chars.as_str(), "");
+    /// ```
     #[stable(feature = "iter_to_slice", since = "1.4.0")]
     #[inline]
     pub fn as_str(&self) -> &'a str {
index 52aa6bb86ef903637d4c60cc347561ed4339e487..5423da9c81c02880c991871943c00b6442751fe6 100644 (file)
@@ -11,4 +11,4 @@ crate-type = ["dylib"]
 
 [build-dependencies]
 build_helper = { path = "../build_helper" }
-gcc = "0.3"
+gcc = "0.3.27"
index b0d62534d48b711c8978d1bbe8cca0558ae7b1cb..5066b7dcab7e700844b0e2ba71b8af9dc627a59b 160000 (submodule)
@@ -1 +1 @@
-Subproject commit b0d62534d48b711c8978d1bbe8cca0558ae7b1cb
+Subproject commit 5066b7dcab7e700844b0e2ba71b8af9dc627a59b
index 1e9e9e30f5cfe08df94cebfce04b840e9f23fca5..2284a9bbb73e124bcc32db89160180acf3def2c3 100644 (file)
@@ -108,7 +108,7 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext) -> EHAction {
                 }
             }
         }
-        // Ip is not present in the table.  This should not hapen... but it does: issie #35011.
+        // Ip is not present in the table.  This should not happen... but it does: issue #35011.
         // So rather than returning EHAction::Terminate, we do this.
         EHAction::None
     } else {
index cdf772ad3b825481231305ff6ae887bbb9048566..fdae8f69a9c0ef31f49fca61b919c7e17cfa0244 100644 (file)
@@ -61,6 +61,8 @@
 use alloc::boxed::Box;
 
 use unwind as uw;
+use libc::{c_int, uintptr_t};
+use dwarf::eh::{self, EHContext, EHAction};
 
 #[repr(C)]
 struct Exception {
@@ -106,139 +108,184 @@ fn rust_exception_class() -> uw::_Unwind_Exception_Class {
     0x4d4f5a_00_52555354
 }
 
-// All targets, except ARM which uses a slightly different ABI (however, iOS goes here as it uses
-// SjLj unwinding).  Also, 64-bit Windows implementation lives in seh64_gnu.rs
-#[cfg(all(any(target_os = "ios", not(target_arch = "arm"))))]
-pub mod eabi {
-    use unwind as uw;
-    use libc::{c_int, uintptr_t};
-    use dwarf::eh::{EHContext, EHAction, find_eh_action};
 
-    // Register ids were lifted from LLVM's TargetLowering::getExceptionPointerRegister()
-    // and TargetLowering::getExceptionSelectorRegister() for each architecture,
-    // then mapped to DWARF register numbers via register definition tables
-    // (typically <arch>RegisterInfo.td, search for "DwarfRegNum").
-    // See also http://llvm.org/docs/WritingAnLLVMBackend.html#defining-a-register.
+// Register ids were lifted from LLVM's TargetLowering::getExceptionPointerRegister()
+// and TargetLowering::getExceptionSelectorRegister() for each architecture,
+// then mapped to DWARF register numbers via register definition tables
+// (typically <arch>RegisterInfo.td, search for "DwarfRegNum").
+// See also http://llvm.org/docs/WritingAnLLVMBackend.html#defining-a-register.
 
-    #[cfg(target_arch = "x86")]
-    const UNWIND_DATA_REG: (i32, i32) = (0, 2); // EAX, EDX
+#[cfg(target_arch = "x86")]
+const UNWIND_DATA_REG: (i32, i32) = (0, 2); // EAX, EDX
 
-    #[cfg(target_arch = "x86_64")]
-    const UNWIND_DATA_REG: (i32, i32) = (0, 1); // RAX, RDX
+#[cfg(target_arch = "x86_64")]
+const UNWIND_DATA_REG: (i32, i32) = (0, 1); // RAX, RDX
 
-    #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
-    const UNWIND_DATA_REG: (i32, i32) = (0, 1); // R0, R1 / X0, X1
+#[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
+const UNWIND_DATA_REG: (i32, i32) = (0, 1); // R0, R1 / X0, X1
 
-    #[cfg(any(target_arch = "mips", target_arch = "mipsel"))]
-    const UNWIND_DATA_REG: (i32, i32) = (4, 5); // A0, A1
+#[cfg(any(target_arch = "mips", target_arch = "mipsel"))]
+const UNWIND_DATA_REG: (i32, i32) = (4, 5); // A0, A1
 
-    #[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
-    const UNWIND_DATA_REG: (i32, i32) = (3, 4); // R3, R4 / X3, X4
+#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
+const UNWIND_DATA_REG: (i32, i32) = (3, 4); // R3, R4 / X3, X4
 
-    // Based on GCC's C and C++ personality routines.  For reference, see:
-    // https://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/libsupc++/eh_personality.cc
-    // https://github.com/gcc-mirror/gcc/blob/trunk/libgcc/unwind-c.c
-    #[lang = "eh_personality"]
-    #[no_mangle]
-    #[allow(unused)]
-    unsafe extern "C" fn rust_eh_personality(version: c_int,
-                                             actions: uw::_Unwind_Action,
-                                             exception_class: uw::_Unwind_Exception_Class,
-                                             exception_object: *mut uw::_Unwind_Exception,
-                                             context: *mut uw::_Unwind_Context)
-                                             -> uw::_Unwind_Reason_Code {
-        if version != 1 {
-            return uw::_URC_FATAL_PHASE1_ERROR;
-        }
-        let lsda = uw::_Unwind_GetLanguageSpecificData(context) as *const u8;
-        let mut ip_before_instr: c_int = 0;
-        let ip = uw::_Unwind_GetIPInfo(context, &mut ip_before_instr);
-        let eh_context = EHContext {
-            // The return address points 1 byte past the call instruction,
-            // which could be in the next IP range in LSDA range table.
-            ip: if ip_before_instr != 0 { ip } else { ip - 1 },
-            func_start: uw::_Unwind_GetRegionStart(context),
-            get_text_start: &|| uw::_Unwind_GetTextRelBase(context),
-            get_data_start: &|| uw::_Unwind_GetDataRelBase(context),
-        };
-        let eh_action = find_eh_action(lsda, &eh_context);
+// The following code is based on GCC's C and C++ personality routines.  For reference, see:
+// https://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/libsupc++/eh_personality.cc
+// https://github.com/gcc-mirror/gcc/blob/trunk/libgcc/unwind-c.c
 
-        if actions as i32 & uw::_UA_SEARCH_PHASE as i32 != 0 {
-            match eh_action {
-                EHAction::None | EHAction::Cleanup(_) => return uw::_URC_CONTINUE_UNWIND,
-                EHAction::Catch(_) => return uw::_URC_HANDLER_FOUND,
-                EHAction::Terminate => return uw::_URC_FATAL_PHASE1_ERROR,
-            }
-        } else {
-            match eh_action {
-                EHAction::None => return uw::_URC_CONTINUE_UNWIND,
-                EHAction::Cleanup(lpad) | EHAction::Catch(lpad) => {
-                    uw::_Unwind_SetGR(context, UNWIND_DATA_REG.0, exception_object as uintptr_t);
-                    uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, 0);
-                    uw::_Unwind_SetIP(context, lpad);
-                    return uw::_URC_INSTALL_CONTEXT;
-                }
-                EHAction::Terminate => return uw::_URC_FATAL_PHASE2_ERROR,
+// The personality routine for most of our targets, except ARM, which has a slightly different ABI
+// (however, iOS goes here as it uses SjLj unwinding).  Also, the 64-bit Windows implementation
+// lives in seh64_gnu.rs
+#[cfg(all(any(target_os = "ios", not(target_arch = "arm"))))]
+#[lang = "eh_personality"]
+#[no_mangle]
+#[allow(unused)]
+unsafe extern "C" fn rust_eh_personality(version: c_int,
+                                         actions: uw::_Unwind_Action,
+                                         exception_class: uw::_Unwind_Exception_Class,
+                                         exception_object: *mut uw::_Unwind_Exception,
+                                         context: *mut uw::_Unwind_Context)
+                                         -> uw::_Unwind_Reason_Code {
+    if version != 1 {
+        return uw::_URC_FATAL_PHASE1_ERROR;
+    }
+    let eh_action = find_eh_action(context);
+    if actions as i32 & uw::_UA_SEARCH_PHASE as i32 != 0 {
+        match eh_action {
+            EHAction::None | EHAction::Cleanup(_) => return uw::_URC_CONTINUE_UNWIND,
+            EHAction::Catch(_) => return uw::_URC_HANDLER_FOUND,
+            EHAction::Terminate => return uw::_URC_FATAL_PHASE1_ERROR,
+        }
+    } else {
+        match eh_action {
+            EHAction::None => return uw::_URC_CONTINUE_UNWIND,
+            EHAction::Cleanup(lpad) | EHAction::Catch(lpad) => {
+                uw::_Unwind_SetGR(context, UNWIND_DATA_REG.0, exception_object as uintptr_t);
+                uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, 0);
+                uw::_Unwind_SetIP(context, lpad);
+                return uw::_URC_INSTALL_CONTEXT;
             }
+            EHAction::Terminate => return uw::_URC_FATAL_PHASE2_ERROR,
         }
     }
-
-    #[cfg(stage0)]
-    #[lang = "eh_personality_catch"]
-    #[no_mangle]
-    pub unsafe extern "C" fn rust_eh_personality_catch(version: c_int,
-                                                       actions: uw::_Unwind_Action,
-                                                       exception_class: uw::_Unwind_Exception_Class,
-                                                       ue_header: *mut uw::_Unwind_Exception,
-                                                       context: *mut uw::_Unwind_Context)
-                                                       -> uw::_Unwind_Reason_Code {
-        rust_eh_personality(version, actions, exception_class, ue_header, context)
-    }
 }
 
-// ARM EHABI uses a slightly different personality routine signature,
-// but otherwise works the same.
+// ARM EHABI personality routine.
+// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0038b/IHI0038B_ehabi.pdf
 #[cfg(all(target_arch = "arm", not(target_os = "ios")))]
-pub mod eabi {
-    use unwind as uw;
-    use libc::c_int;
+#[lang = "eh_personality"]
+#[no_mangle]
+unsafe extern "C" fn rust_eh_personality(state: uw::_Unwind_State,
+                                         exception_object: *mut uw::_Unwind_Exception,
+                                         context: *mut uw::_Unwind_Context)
+                                        -> uw::_Unwind_Reason_Code {
+    let state = state as c_int;
+    let action = state & uw::_US_ACTION_MASK as c_int;
+    let search_phase = if action == uw::_US_VIRTUAL_UNWIND_FRAME as c_int {
+        // Backtraces on ARM will call the personality routine with
+        // state == _US_VIRTUAL_UNWIND_FRAME | _US_FORCE_UNWIND. In those cases
+        // we want to continue unwinding the stack, otherwise all our backtraces
+        // would end at __rust_try
+        if state & uw::_US_FORCE_UNWIND as c_int != 0 {
+            return continue_unwind(exception_object, context)
+        }
+        true
+    } else if action == uw::_US_UNWIND_FRAME_STARTING as c_int {
+        false
+    } else if action == uw::_US_UNWIND_FRAME_RESUME as c_int {
+        return continue_unwind(exception_object, context);
+    } else {
+        return uw::_URC_FAILURE;
+    };
 
-    extern "C" {
-        fn __gcc_personality_v0(state: uw::_Unwind_State,
-                                ue_header: *mut uw::_Unwind_Exception,
-                                context: *mut uw::_Unwind_Context)
-                                -> uw::_Unwind_Reason_Code;
-    }
+    // The DWARF unwinder assumes that _Unwind_Context holds things like the function
+    // and LSDA pointers, however ARM EHABI places them into the exception object.
+    // To preserve signatures of functions like _Unwind_GetLanguageSpecificData(), which
+    // take only the context pointer, GCC personality routines stash a pointer to exception_object
+    // in the context, using location reserved for ARM's "scratch register" (r12).
+    uw::_Unwind_SetGR(context, uw::UNWIND_POINTER_REG, exception_object as uw::_Unwind_Ptr);
+    // ...A more principled approach would be to provide the full definition of ARM's
+    // _Unwind_Context in our libunwind bindings and fetch the required data from there directly,
+    // bypassing DWARF compatibility functions.
 
-    #[lang = "eh_personality"]
-    #[no_mangle]
-    extern "C" fn rust_eh_personality(state: uw::_Unwind_State,
-                                      ue_header: *mut uw::_Unwind_Exception,
-                                      context: *mut uw::_Unwind_Context)
-                                      -> uw::_Unwind_Reason_Code {
-        unsafe { __gcc_personality_v0(state, ue_header, context) }
+    let eh_action = find_eh_action(context);
+    if search_phase {
+        match eh_action {
+            EHAction::None |
+            EHAction::Cleanup(_) => return continue_unwind(exception_object, context),
+            EHAction::Catch(_) => return uw::_URC_HANDLER_FOUND,
+            EHAction::Terminate => return uw::_URC_FAILURE,
+        }
+    } else {
+        match eh_action {
+            EHAction::None => return continue_unwind(exception_object, context),
+            EHAction::Cleanup(lpad) | EHAction::Catch(lpad) => {
+                uw::_Unwind_SetGR(context, UNWIND_DATA_REG.0, exception_object as uintptr_t);
+                uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, 0);
+                uw::_Unwind_SetIP(context, lpad);
+                return uw::_URC_INSTALL_CONTEXT;
+            }
+            EHAction::Terminate => return uw::_URC_FAILURE,
+        }
     }
 
-    #[lang = "eh_personality_catch"]
-    #[no_mangle]
-    pub extern "C" fn rust_eh_personality_catch(state: uw::_Unwind_State,
-                                                ue_header: *mut uw::_Unwind_Exception,
-                                                context: *mut uw::_Unwind_Context)
-                                                -> uw::_Unwind_Reason_Code {
-        // Backtraces on ARM will call the personality routine with
-        // state == _US_VIRTUAL_UNWIND_FRAME | _US_FORCE_UNWIND. In those cases
-        // we want to continue unwinding the stack, otherwise all our backtraces
-        // would end at __rust_try.
-        if (state as c_int & uw::_US_ACTION_MASK as c_int) ==
-           uw::_US_VIRTUAL_UNWIND_FRAME as c_int &&
-           (state as c_int & uw::_US_FORCE_UNWIND as c_int) == 0 {
-            // search phase
-            uw::_URC_HANDLER_FOUND // catch!
+    // On ARM EHABI the personality routine is responsible for actually
+    // unwinding a single stack frame before returning (ARM EHABI Sec. 6.1).
+    unsafe fn continue_unwind(exception_object: *mut uw::_Unwind_Exception,
+                              context: *mut uw::_Unwind_Context)
+                              -> uw::_Unwind_Reason_Code {
+        if __gnu_unwind_frame(exception_object, context) == uw::_URC_NO_REASON {
+            uw::_URC_CONTINUE_UNWIND
         } else {
-            // cleanup phase
-            unsafe { __gcc_personality_v0(state, ue_header, context) }
+            uw::_URC_FAILURE
         }
     }
+    // defined in libgcc
+    extern "C" {
+        fn __gnu_unwind_frame(exception_object: *mut uw::_Unwind_Exception,
+                                context: *mut uw::_Unwind_Context)
+                                -> uw::_Unwind_Reason_Code;
+    }
+}
+
+unsafe fn find_eh_action(context: *mut uw::_Unwind_Context) -> EHAction {
+    let lsda = uw::_Unwind_GetLanguageSpecificData(context) as *const u8;
+    let mut ip_before_instr: c_int = 0;
+    let ip = uw::_Unwind_GetIPInfo(context, &mut ip_before_instr);
+    let eh_context = EHContext {
+        // The return address points 1 byte past the call instruction,
+        // which could be in the next IP range in LSDA range table.
+        ip: if ip_before_instr != 0 { ip } else { ip - 1 },
+        func_start: uw::_Unwind_GetRegionStart(context),
+        get_text_start: &|| uw::_Unwind_GetTextRelBase(context),
+        get_data_start: &|| uw::_Unwind_GetDataRelBase(context),
+    };
+    eh::find_eh_action(lsda, &eh_context)
+}
+
+// *** Delete after a new snapshot ***
+#[cfg(all(stage0, any(target_os = "ios", not(target_arch = "arm"))))]
+#[lang = "eh_personality_catch"]
+#[no_mangle]
+pub unsafe extern "C" fn rust_eh_personality_catch(version: c_int,
+                                                    actions: uw::_Unwind_Action,
+                                                    exception_class: uw::_Unwind_Exception_Class,
+                                                    ue_header: *mut uw::_Unwind_Exception,
+                                                    context: *mut uw::_Unwind_Context)
+                                                    -> uw::_Unwind_Reason_Code {
+    rust_eh_personality(version, actions, exception_class, ue_header, context)
+}
+
+// *** Delete after a new snapshot ***
+#[cfg(all(stage0, target_arch = "arm", not(target_os = "ios")))]
+#[lang = "eh_personality_catch"]
+#[no_mangle]
+pub unsafe extern "C" fn rust_eh_personality_catch(state: uw::_Unwind_State,
+                                                    ue_header: *mut uw::_Unwind_Exception,
+                                                    context: *mut uw::_Unwind_Context)
+                                                    -> uw::_Unwind_Reason_Code {
+    rust_eh_personality(state, ue_header, context)
 }
 
 // See docs in the `unwind` module.
index 7dc428871b387f2e83792d468706fa8b6c99675f..3642e2488958e921fa8b1efd6a514858873a5de8 100644 (file)
@@ -81,6 +81,7 @@ pub unsafe fn cleanup(ptr: *mut u8) -> Box<Any + Send> {
 // This is considered acceptable, because the behavior of throwing exceptions
 // through a C ABI boundary is undefined.
 
+// *** Delete after a new snapshot ***
 #[cfg(stage0)]
 #[lang = "eh_personality_catch"]
 #[cfg(not(test))]
index 442c85af22a262967f707484de232e8b06c443ef..a06fc21764de4c068287c65320ae8ff984ef00a4 100644 (file)
@@ -94,11 +94,14 @@ fn visit_item(&mut self, i: &'v Item) {
 
     ///////////////////////////////////////////////////////////////////////////
 
+    fn visit_id(&mut self, _node_id: NodeId) {
+        // Nothing to do.
+    }
     fn visit_name(&mut self, _span: Span, _name: Name) {
         // Nothing to do.
     }
-    fn visit_mod(&mut self, m: &'v Mod, _s: Span, _n: NodeId) {
-        walk_mod(self, m)
+    fn visit_mod(&mut self, m: &'v Mod, _s: Span, n: NodeId) {
+        walk_mod(self, m, n)
     }
     fn visit_foreign_item(&mut self, i: &'v ForeignItem) {
         walk_foreign_item(self, i)
@@ -135,8 +138,8 @@ fn visit_generics(&mut self, g: &'v Generics) {
     fn visit_where_predicate(&mut self, predicate: &'v WherePredicate) {
         walk_where_predicate(self, predicate)
     }
-    fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl, b: &'v Block, s: Span, _: NodeId) {
-        walk_fn(self, fk, fd, b, s)
+    fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl, b: &'v Block, s: Span, id: NodeId) {
+        walk_fn(self, fk, fd, b, s, id)
     }
     fn visit_trait_item(&mut self, ti: &'v TraitItem) {
         walk_trait_item(self, ti)
@@ -157,7 +160,7 @@ fn visit_variant_data(&mut self,
                           s: &'v VariantData,
                           _: Name,
                           _: &'v Generics,
-                          _: NodeId,
+                          _parent_id: NodeId,
                           _: Span) {
         walk_struct_def(self, s)
     }
@@ -225,24 +228,28 @@ pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate) {
 }
 
 pub fn walk_macro_def<'v, V: Visitor<'v>>(visitor: &mut V, macro_def: &'v MacroDef) {
+    visitor.visit_id(macro_def.id);
     visitor.visit_name(macro_def.span, macro_def.name);
     walk_opt_name(visitor, macro_def.span, macro_def.imported_from);
     walk_list!(visitor, visit_attribute, &macro_def.attrs);
 }
 
-pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod) {
+pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod, mod_node_id: NodeId) {
+    visitor.visit_id(mod_node_id);
     for &item_id in &module.item_ids {
         visitor.visit_nested_item(item_id);
     }
 }
 
 pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local) {
+    visitor.visit_id(local.id);
     visitor.visit_pat(&local.pat);
     walk_list!(visitor, visit_ty, &local.ty);
     walk_list!(visitor, visit_expr, &local.init);
 }
 
 pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime) {
+    visitor.visit_id(lifetime.id);
     visitor.visit_name(lifetime.span, lifetime.name);
 }
 
@@ -263,6 +270,7 @@ pub fn walk_poly_trait_ref<'v, V>(visitor: &mut V,
 pub fn walk_trait_ref<'v, V>(visitor: &mut V, trait_ref: &'v TraitRef)
     where V: Visitor<'v>
 {
+    visitor.visit_id(trait_ref.ref_id);
     visitor.visit_path(&trait_ref.path, trait_ref.ref_id)
 }
 
@@ -271,9 +279,11 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
     visitor.visit_name(item.span, item.name);
     match item.node {
         ItemExternCrate(opt_name) => {
+            visitor.visit_id(item.id);
             walk_opt_name(visitor, item.span, opt_name)
         }
         ItemUse(ref vp) => {
+            visitor.visit_id(item.id);
             match vp.node {
                 ViewPathSimple(name, ref path) => {
                     visitor.visit_name(vp.span, name);
@@ -292,6 +302,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
         }
         ItemStatic(ref typ, _, ref expr) |
         ItemConst(ref typ, ref expr) => {
+            visitor.visit_id(item.id);
             visitor.visit_ty(typ);
             visitor.visit_expr(expr);
         }
@@ -309,23 +320,29 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
                              item.id)
         }
         ItemMod(ref module) => {
+            // visit_mod() takes care of visiting the Item's NodeId
             visitor.visit_mod(module, item.span, item.id)
         }
         ItemForeignMod(ref foreign_module) => {
+            visitor.visit_id(item.id);
             walk_list!(visitor, visit_foreign_item, &foreign_module.items);
         }
         ItemTy(ref typ, ref type_parameters) => {
+            visitor.visit_id(item.id);
             visitor.visit_ty(typ);
             visitor.visit_generics(type_parameters)
         }
         ItemEnum(ref enum_definition, ref type_parameters) => {
             visitor.visit_generics(type_parameters);
+            // visit_enum_def() takes care of visiting the Item's NodeId
             visitor.visit_enum_def(enum_definition, type_parameters, item.id, item.span)
         }
         ItemDefaultImpl(_, ref trait_ref) => {
+            visitor.visit_id(item.id);
             visitor.visit_trait_ref(trait_ref)
         }
         ItemImpl(_, _, ref type_parameters, ref opt_trait_reference, ref typ, ref impl_items) => {
+            visitor.visit_id(item.id);
             visitor.visit_generics(type_parameters);
             walk_list!(visitor, visit_trait_ref, opt_trait_reference);
             visitor.visit_ty(typ);
@@ -333,9 +350,11 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
         }
         ItemStruct(ref struct_definition, ref generics) => {
             visitor.visit_generics(generics);
+            visitor.visit_id(item.id);
             visitor.visit_variant_data(struct_definition, item.name, generics, item.id, item.span);
         }
         ItemTrait(_, ref generics, ref bounds, ref methods) => {
+            visitor.visit_id(item.id);
             visitor.visit_generics(generics);
             walk_list!(visitor, visit_ty_param_bound, bounds);
             walk_list!(visitor, visit_trait_item, methods);
@@ -348,6 +367,7 @@ pub fn walk_enum_def<'v, V: Visitor<'v>>(visitor: &mut V,
                                          enum_definition: &'v EnumDef,
                                          generics: &'v Generics,
                                          item_id: NodeId) {
+    visitor.visit_id(item_id);
     walk_list!(visitor,
                visit_variant,
                &enum_definition.variants,
@@ -358,18 +378,20 @@ pub fn walk_enum_def<'v, V: Visitor<'v>>(visitor: &mut V,
 pub fn walk_variant<'v, V: Visitor<'v>>(visitor: &mut V,
                                         variant: &'v Variant,
                                         generics: &'v Generics,
-                                        item_id: NodeId) {
+                                        parent_item_id: NodeId) {
     visitor.visit_name(variant.span, variant.node.name);
     visitor.visit_variant_data(&variant.node.data,
                                variant.node.name,
                                generics,
-                               item_id,
+                               parent_item_id,
                                variant.span);
     walk_list!(visitor, visit_expr, &variant.node.disr_expr);
     walk_list!(visitor, visit_attribute, &variant.node.attrs);
 }
 
 pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
+    visitor.visit_id(typ.id);
+
     match typ.node {
         TyVec(ref ty) => {
             visitor.visit_ty(ty)
@@ -421,6 +443,7 @@ pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path) {
 pub fn walk_path_list_item<'v, V: Visitor<'v>>(visitor: &mut V,
                                                _prefix: &'v Path,
                                                item: &'v PathListItem) {
+    visitor.visit_id(item.node.id());
     walk_opt_name(visitor, item.span, item.node.name());
     walk_opt_name(visitor, item.span, item.node.rename());
 }
@@ -450,11 +473,13 @@ pub fn walk_path_parameters<'v, V: Visitor<'v>>(visitor: &mut V,
 
 pub fn walk_assoc_type_binding<'v, V: Visitor<'v>>(visitor: &mut V,
                                                    type_binding: &'v TypeBinding) {
+    visitor.visit_id(type_binding.id);
     visitor.visit_name(type_binding.span, type_binding.name);
     visitor.visit_ty(&type_binding.ty);
 }
 
 pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) {
+    visitor.visit_id(pattern.id);
     match pattern.node {
         PatKind::TupleStruct(ref path, ref children, _) => {
             visitor.visit_path(path, pattern.id);
@@ -499,6 +524,7 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) {
 }
 
 pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V, foreign_item: &'v ForeignItem) {
+    visitor.visit_id(foreign_item.id);
     visitor.visit_vis(&foreign_item.vis);
     visitor.visit_name(foreign_item.span, foreign_item.name);
 
@@ -526,11 +552,13 @@ pub fn walk_ty_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, bound: &'v TyPar
 
 pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics) {
     for param in &generics.ty_params {
+        visitor.visit_id(param.id);
         visitor.visit_name(param.span, param.name);
         walk_list!(visitor, visit_ty_param_bound, &param.bounds);
         walk_list!(visitor, visit_ty, &param.default);
     }
     walk_list!(visitor, visit_lifetime_def, &generics.lifetimes);
+    visitor.visit_id(generics.where_clause.id);
     walk_list!(visitor, visit_where_predicate, &generics.where_clause.predicates);
 }
 
@@ -557,6 +585,7 @@ pub fn walk_where_predicate<'v, V: Visitor<'v>>(
                                                       ref path,
                                                       ref ty,
                                                       ..}) => {
+            visitor.visit_id(id);
             visitor.visit_path(path, id);
             visitor.visit_ty(ty);
         }
@@ -571,6 +600,7 @@ pub fn walk_fn_ret_ty<'v, V: Visitor<'v>>(visitor: &mut V, ret_ty: &'v FunctionR
 
 pub fn walk_fn_decl<'v, V: Visitor<'v>>(visitor: &mut V, function_declaration: &'v FnDecl) {
     for argument in &function_declaration.inputs {
+        visitor.visit_id(argument.id);
         visitor.visit_pat(&argument.pat);
         visitor.visit_ty(&argument.ty)
     }
@@ -579,6 +609,7 @@ pub fn walk_fn_decl<'v, V: Visitor<'v>>(visitor: &mut V, function_declaration: &
 
 pub fn walk_fn_decl_nopat<'v, V: Visitor<'v>>(visitor: &mut V, function_declaration: &'v FnDecl) {
     for argument in &function_declaration.inputs {
+        visitor.visit_id(argument.id);
         visitor.visit_ty(&argument.ty)
     }
     walk_fn_ret_ty(visitor, &function_declaration.output)
@@ -600,7 +631,9 @@ pub fn walk_fn<'v, V: Visitor<'v>>(visitor: &mut V,
                                    function_kind: FnKind<'v>,
                                    function_declaration: &'v FnDecl,
                                    function_body: &'v Block,
-                                   _span: Span) {
+                                   _span: Span,
+                                   id: NodeId) {
+    visitor.visit_id(id);
     walk_fn_decl(visitor, function_declaration);
     walk_fn_kind(visitor, function_kind);
     visitor.visit_block(function_body)
@@ -611,10 +644,12 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai
     walk_list!(visitor, visit_attribute, &trait_item.attrs);
     match trait_item.node {
         ConstTraitItem(ref ty, ref default) => {
+            visitor.visit_id(trait_item.id);
             visitor.visit_ty(ty);
             walk_list!(visitor, visit_expr, default);
         }
         MethodTraitItem(ref sig, None) => {
+            visitor.visit_id(trait_item.id);
             visitor.visit_generics(&sig.generics);
             walk_fn_decl(visitor, &sig.decl);
         }
@@ -629,6 +664,7 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai
                              trait_item.id);
         }
         TypeTraitItem(ref bounds, ref default) => {
+            visitor.visit_id(trait_item.id);
             walk_list!(visitor, visit_ty_param_bound, bounds);
             walk_list!(visitor, visit_ty, default);
         }
@@ -641,6 +677,7 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt
     walk_list!(visitor, visit_attribute, &impl_item.attrs);
     match impl_item.node {
         ImplItemKind::Const(ref ty, ref expr) => {
+            visitor.visit_id(impl_item.id);
             visitor.visit_ty(ty);
             visitor.visit_expr(expr);
         }
@@ -655,16 +692,19 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt
                              impl_item.id);
         }
         ImplItemKind::Type(ref ty) => {
+            visitor.visit_id(impl_item.id);
             visitor.visit_ty(ty);
         }
     }
 }
 
 pub fn walk_struct_def<'v, V: Visitor<'v>>(visitor: &mut V, struct_definition: &'v VariantData) {
+    visitor.visit_id(struct_definition.id());
     walk_list!(visitor, visit_struct_field, struct_definition.fields());
 }
 
 pub fn walk_struct_field<'v, V: Visitor<'v>>(visitor: &mut V, struct_field: &'v StructField) {
+    visitor.visit_id(struct_field.id);
     visitor.visit_vis(&struct_field.vis);
     visitor.visit_name(struct_field.span, struct_field.name);
     visitor.visit_ty(&struct_field.ty);
@@ -672,14 +712,20 @@ pub fn walk_struct_field<'v, V: Visitor<'v>>(visitor: &mut V, struct_field: &'v
 }
 
 pub fn walk_block<'v, V: Visitor<'v>>(visitor: &mut V, block: &'v Block) {
+    visitor.visit_id(block.id);
     walk_list!(visitor, visit_stmt, &block.stmts);
     walk_list!(visitor, visit_expr, &block.expr);
 }
 
 pub fn walk_stmt<'v, V: Visitor<'v>>(visitor: &mut V, statement: &'v Stmt) {
     match statement.node {
-        StmtDecl(ref declaration, _) => visitor.visit_decl(declaration),
-        StmtExpr(ref expression, _) | StmtSemi(ref expression, _) => {
+        StmtDecl(ref declaration, id) => {
+            visitor.visit_id(id);
+            visitor.visit_decl(declaration)
+        }
+        StmtExpr(ref expression, id) |
+        StmtSemi(ref expression, id) => {
+            visitor.visit_id(id);
             visitor.visit_expr(expression)
         }
     }
@@ -693,6 +739,7 @@ pub fn walk_decl<'v, V: Visitor<'v>>(visitor: &mut V, declaration: &'v Decl) {
 }
 
 pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
+    visitor.visit_id(expression.id);
     match expression.node {
         ExprBox(ref subexpression) => {
             visitor.visit_expr(subexpression)
@@ -815,6 +862,7 @@ pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm) {
 
 pub fn walk_vis<'v, V: Visitor<'v>>(visitor: &mut V, vis: &'v Visibility) {
     if let Visibility::Restricted { ref path, id } = *vis {
+        visitor.visit_id(id);
         visitor.visit_path(path, id)
     }
 }
@@ -837,15 +885,16 @@ pub fn empty(&self) -> bool {
         self.min >= self.max
     }
 
+    pub fn contains(&self, id: NodeId) -> bool {
+        id >= self.min && id < self.max
+    }
+
     pub fn add(&mut self, id: NodeId) {
         self.min = cmp::min(self.min, id);
         self.max = cmp::max(self.max, id + 1);
     }
 }
 
-pub trait IdVisitingOperation {
-    fn visit_id(&mut self, node_id: NodeId);
-}
 
 pub struct IdRangeComputingVisitor {
     pub result: IdRange,
@@ -861,181 +910,12 @@ pub fn result(&self) -> IdRange {
     }
 }
 
-impl IdVisitingOperation for IdRangeComputingVisitor {
+impl<'v> Visitor<'v> for IdRangeComputingVisitor {
     fn visit_id(&mut self, id: NodeId) {
         self.result.add(id);
     }
 }
 
-pub struct IdVisitor<'a, O: 'a> {
-    operation: &'a mut O,
-
-    // In general, the id visitor visits the contents of an item, but
-    // not including nested trait/impl items, nor other nested items.
-    // The base visitor itself always skips nested items, but not
-    // trait/impl items. This means in particular that if you start by
-    // visiting a trait or an impl, you should not visit the
-    // trait/impl items respectively.  This is handled by setting
-    // `skip_members` to true when `visit_item` is on the stack. This
-    // way, if the user begins by calling `visit_trait_item`, we will
-    // visit the trait item, but if they begin with `visit_item`, we
-    // won't visit the (nested) trait items.
-    skip_members: bool,
-}
-
-impl<'a, O: IdVisitingOperation> IdVisitor<'a, O> {
-    pub fn new(operation: &'a mut O) -> IdVisitor<'a, O> {
-        IdVisitor { operation: operation, skip_members: false }
-    }
-
-    fn visit_generics_helper(&mut self, generics: &Generics) {
-        for type_parameter in generics.ty_params.iter() {
-            self.operation.visit_id(type_parameter.id)
-        }
-        for lifetime in &generics.lifetimes {
-            self.operation.visit_id(lifetime.lifetime.id)
-        }
-    }
-}
-
-impl<'a, 'v, O: IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O> {
-    fn visit_mod(&mut self, module: &Mod, _: Span, node_id: NodeId) {
-        self.operation.visit_id(node_id);
-        walk_mod(self, module)
-    }
-
-    fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) {
-        self.operation.visit_id(foreign_item.id);
-        walk_foreign_item(self, foreign_item)
-    }
-
-    fn visit_item(&mut self, item: &Item) {
-        assert!(!self.skip_members);
-        self.skip_members = true;
-
-        self.operation.visit_id(item.id);
-        match item.node {
-            ItemUse(ref view_path) => {
-                match view_path.node {
-                    ViewPathSimple(_, _) |
-                    ViewPathGlob(_) => {}
-                    ViewPathList(_, ref paths) => {
-                        for path in paths {
-                            self.operation.visit_id(path.node.id())
-                        }
-                    }
-                }
-            }
-            _ => {}
-        }
-        walk_item(self, item);
-
-        self.skip_members = false;
-    }
-
-    fn visit_local(&mut self, local: &Local) {
-        self.operation.visit_id(local.id);
-        walk_local(self, local)
-    }
-
-    fn visit_block(&mut self, block: &Block) {
-        self.operation.visit_id(block.id);
-        walk_block(self, block)
-    }
-
-    fn visit_stmt(&mut self, statement: &Stmt) {
-        self.operation.visit_id(statement.node.id());
-        walk_stmt(self, statement)
-    }
-
-    fn visit_pat(&mut self, pattern: &Pat) {
-        self.operation.visit_id(pattern.id);
-        walk_pat(self, pattern)
-    }
-
-    fn visit_expr(&mut self, expression: &Expr) {
-        self.operation.visit_id(expression.id);
-        walk_expr(self, expression)
-    }
-
-    fn visit_ty(&mut self, typ: &Ty) {
-        self.operation.visit_id(typ.id);
-        walk_ty(self, typ)
-    }
-
-    fn visit_generics(&mut self, generics: &Generics) {
-        self.visit_generics_helper(generics);
-        walk_generics(self, generics)
-    }
-
-    fn visit_fn(&mut self,
-                function_kind: FnKind<'v>,
-                function_declaration: &'v FnDecl,
-                block: &'v Block,
-                span: Span,
-                node_id: NodeId) {
-        self.operation.visit_id(node_id);
-
-        match function_kind {
-            FnKind::ItemFn(_, generics, _, _, _, _, _) => {
-                self.visit_generics_helper(generics)
-            }
-            FnKind::Method(_, sig, _, _) => {
-                self.visit_generics_helper(&sig.generics)
-            }
-            FnKind::Closure(_) => {}
-        }
-
-        for argument in &function_declaration.inputs {
-            self.operation.visit_id(argument.id)
-        }
-
-        walk_fn(self, function_kind, function_declaration, block, span);
-    }
-
-    fn visit_struct_field(&mut self, struct_field: &StructField) {
-        self.operation.visit_id(struct_field.id);
-        walk_struct_field(self, struct_field)
-    }
-
-    fn visit_variant_data(&mut self,
-                          struct_def: &VariantData,
-                          _: Name,
-                          _: &Generics,
-                          _: NodeId,
-                          _: Span) {
-        self.operation.visit_id(struct_def.id());
-        walk_struct_def(self, struct_def);
-    }
-
-    fn visit_trait_item(&mut self, ti: &TraitItem) {
-        if !self.skip_members {
-            self.operation.visit_id(ti.id);
-            walk_trait_item(self, ti);
-        }
-    }
-
-    fn visit_impl_item(&mut self, ii: &ImplItem) {
-        if !self.skip_members {
-            self.operation.visit_id(ii.id);
-            walk_impl_item(self, ii);
-        }
-    }
-
-    fn visit_lifetime(&mut self, lifetime: &Lifetime) {
-        self.operation.visit_id(lifetime.id);
-    }
-
-    fn visit_lifetime_def(&mut self, def: &LifetimeDef) {
-        self.visit_lifetime(&def.lifetime);
-    }
-
-    fn visit_trait_ref(&mut self, trait_ref: &TraitRef) {
-        self.operation.visit_id(trait_ref.ref_id);
-        walk_trait_ref(self, trait_ref);
-    }
-}
-
 /// Computes the id range for a single fn body, ignoring nested items.
 pub fn compute_id_range_for_fn_body(fk: FnKind,
                                     decl: &FnDecl,
@@ -1043,8 +923,7 @@ pub fn compute_id_range_for_fn_body(fk: FnKind,
                                     sp: Span,
                                     id: NodeId)
                                     -> IdRange {
-    let mut visitor = IdRangeComputingVisitor { result: IdRange::max() };
-    let mut id_visitor = IdVisitor::new(&mut visitor);
-    id_visitor.visit_fn(fk, decl, body, sp, id);
-    id_visitor.operation.result
+    let mut visitor = IdRangeComputingVisitor::new();
+    visitor.visit_fn(fk, decl, body, sp, id);
+    visitor.result()
 }
index 693d7a2edfca5cf726d366d74b3e8255bd6bdb2b..b3f222b22e8915314c1b1d7883b00a22aa8ac935 100644 (file)
@@ -197,7 +197,7 @@ fn visit_stmt(&mut self, stmt: &'ast Stmt) {
     fn visit_fn(&mut self, fk: intravisit::FnKind<'ast>, fd: &'ast FnDecl,
                 b: &'ast Block, s: Span, id: NodeId) {
         assert_eq!(self.parent_node, id);
-        intravisit::walk_fn(self, fk, fd, b, s);
+        intravisit::walk_fn(self, fk, fd, b, s, id);
     }
 
     fn visit_block(&mut self, block: &'ast Block) {
index 655f80ec07238ff9ba97fdb99057415fd6dec35b..20bf4f7d3edbb68dc88517338e2be124937d8642 100644 (file)
@@ -1362,9 +1362,9 @@ pub enum ViewPath_ {
 /// TraitRef's appear in impls.
 ///
 /// resolve maps each TraitRef's ref_id to its defining trait; that's all
-/// that the ref_id is for. The impl_id maps to the "self type" of this impl.
-/// If this impl is an ItemImpl, the impl_id is redundant (it could be the
-/// same as the impl's node id).
+/// that the ref_id is for. Note that ref_id's value is not the NodeId of the
+/// trait being referred to but just a unique NodeId that serves as a key
+/// within the DefMap.
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct TraitRef {
     pub path: Path,
index ce3d72de9ae99a5378cfbbf598833ae4e7cda408..daac315e14def73aed895377000e610242272a72 100644 (file)
@@ -29,7 +29,7 @@
 use middle::privacy::AccessLevels;
 use ty::TyCtxt;
 use session::{config, early_error, Session};
-use lint::{Level, LevelSource, Lint, LintId, LintPass};
+use lint::{Level, LevelSource, Lint, LintId, LintPass, LintSource};
 use lint::{EarlyLintPassObject, LateLintPassObject};
 use lint::{Default, CommandLine, Node, Allow, Warn, Deny, Forbid};
 use lint::builtin;
@@ -45,7 +45,6 @@
 use errors::DiagnosticBuilder;
 use hir;
 use hir::intravisit as hir_visit;
-use hir::intravisit::{IdVisitor, IdVisitingOperation};
 use syntax::visit as ast_visit;
 
 /// Information about the registered lints.
@@ -366,18 +365,18 @@ pub fn gather_attr(attr: &ast::Attribute)
     attr::mark_used(attr);
 
     let meta = &attr.node.value;
-    let metas = match meta.node {
-        ast::MetaItemKind::List(_, ref metas) => metas,
-        _ => {
-            out.push(Err(meta.span));
-            return out;
-        }
+    let metas = if let Some(metas) = meta.meta_item_list() {
+        metas
+    } else {
+        out.push(Err(meta.span));
+        return out;
     };
 
     for meta in metas {
-        out.push(match meta.node {
-            ast::MetaItemKind::Word(ref lint_name) => Ok((lint_name.clone(), level, meta.span)),
-            _ => Err(meta.span),
+        out.push(if meta.is_word() {
+            Ok((meta.name().clone(), level, meta.span))
+        } else {
+            Err(meta.span)
         });
     }
 
@@ -600,13 +599,23 @@ fn with_lint_attrs<F>(&mut self,
             };
 
             for (lint_id, level, span) in v {
-                let now = self.lints().get_level_source(lint_id).0;
+                let (now, now_source) = self.lints().get_level_source(lint_id);
                 if now == Forbid && level != Forbid {
                     let lint_name = lint_id.as_str();
-                    span_err!(self.sess(), span, E0453,
-                              "{}({}) overruled by outer forbid({})",
-                              level.as_str(), lint_name,
-                              lint_name);
+                    let mut diag_builder = struct_span_err!(self.sess(), span, E0453,
+                                                            "{}({}) overruled by outer forbid({})",
+                                                            level.as_str(), lint_name,
+                                                            lint_name);
+                    match now_source {
+                        LintSource::Default => &mut diag_builder,
+                        LintSource::Node(forbid_source_span) => {
+                            diag_builder.span_note(forbid_source_span,
+                                                   "`forbid` lint level set here")
+                        },
+                        LintSource::CommandLine => {
+                            diag_builder.note("`forbid` lint level was set on command line")
+                        }
+                    }.emit()
                 } else if now != level {
                     let src = self.lints().get_level_source(lint_id).1;
                     self.level_stack().push((lint_id, (now, src)));
@@ -663,9 +672,11 @@ fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     }
 
     fn visit_ids<F>(&mut self, f: F)
-        where F: FnOnce(&mut IdVisitor<LateContext>)
+        where F: FnOnce(&mut IdVisitor)
     {
-        let mut v = IdVisitor::new(self);
+        let mut v = IdVisitor {
+            cx: self
+        };
         f(&mut v);
     }
 }
@@ -779,7 +790,7 @@ fn visit_stmt(&mut self, s: &hir::Stmt) {
     fn visit_fn(&mut self, fk: hir_visit::FnKind<'v>, decl: &'v hir::FnDecl,
                 body: &'v hir::Block, span: Span, id: ast::NodeId) {
         run_lints!(self, check_fn, late_passes, fk, decl, body, span, id);
-        hir_visit::walk_fn(self, fk, decl, body, span);
+        hir_visit::walk_fn(self, fk, decl, body, span, id);
         run_lints!(self, check_fn_post, late_passes, fk, decl, body, span, id);
     }
 
@@ -820,7 +831,7 @@ fn visit_name(&mut self, sp: Span, name: ast::Name) {
 
     fn visit_mod(&mut self, m: &hir::Mod, s: Span, n: ast::NodeId) {
         run_lints!(self, check_mod, late_passes, m, s, n);
-        hir_visit::walk_mod(self, m);
+        hir_visit::walk_mod(self, m, n);
         run_lints!(self, check_mod_post, late_passes, m, s, n);
     }
 
@@ -859,7 +870,7 @@ fn visit_generics(&mut self, g: &hir::Generics) {
     fn visit_trait_item(&mut self, trait_item: &hir::TraitItem) {
         self.with_lint_attrs(&trait_item.attrs, |cx| {
             run_lints!(cx, check_trait_item, late_passes, trait_item);
-            cx.visit_ids(|v| v.visit_trait_item(trait_item));
+            cx.visit_ids(|v| hir_visit::walk_trait_item(v, trait_item));
             hir_visit::walk_trait_item(cx, trait_item);
             run_lints!(cx, check_trait_item_post, late_passes, trait_item);
         });
@@ -868,7 +879,7 @@ fn visit_trait_item(&mut self, trait_item: &hir::TraitItem) {
     fn visit_impl_item(&mut self, impl_item: &hir::ImplItem) {
         self.with_lint_attrs(&impl_item.attrs, |cx| {
             run_lints!(cx, check_impl_item, late_passes, impl_item);
-            cx.visit_ids(|v| v.visit_impl_item(impl_item));
+            cx.visit_ids(|v| hir_visit::walk_impl_item(v, impl_item));
             hir_visit::walk_impl_item(cx, impl_item);
             run_lints!(cx, check_impl_item_post, late_passes, impl_item);
         });
@@ -1046,16 +1057,30 @@ fn visit_attribute(&mut self, attr: &ast::Attribute) {
     }
 }
 
+struct IdVisitor<'a, 'b: 'a, 'tcx: 'a+'b> {
+    cx: &'a mut LateContext<'b, 'tcx>
+}
+
 // Output any lints that were previously added to the session.
-impl<'a, 'tcx> IdVisitingOperation for LateContext<'a, 'tcx> {
+impl<'a, 'b, 'tcx, 'v> hir_visit::Visitor<'v> for IdVisitor<'a, 'b, 'tcx> {
+
     fn visit_id(&mut self, id: ast::NodeId) {
-        if let Some(lints) = self.sess().lints.borrow_mut().remove(&id) {
+        if let Some(lints) = self.cx.sess().lints.borrow_mut().remove(&id) {
             debug!("LateContext::visit_id: id={:?} lints={:?}", id, lints);
             for (lint_id, span, msg) in lints {
-                self.span_lint(lint_id.lint, span, &msg[..])
+                self.cx.span_lint(lint_id.lint, span, &msg[..])
             }
         }
     }
+
+    fn visit_trait_item(&mut self, _ti: &hir::TraitItem) {
+        // Do not recurse into trait or impl items automatically. These are
+        // processed separately by calling hir_visit::walk_trait_item()
+    }
+
+    fn visit_impl_item(&mut self, _ii: &hir::ImplItem) {
+        // See visit_trait_item()
+    }
 }
 
 enum CheckLintNameResult {
@@ -1172,7 +1197,6 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     // Visit the whole crate.
     cx.with_lint_attrs(&krate.attrs, |cx| {
-        cx.visit_id(ast::CRATE_NODE_ID);
         cx.visit_ids(|v| {
             hir_visit::walk_crate(v, krate);
         });
index fd9463b13c055143eb208e4238b719a30ea4514f..484aacfd9ecc01f22747d3db740c4821fc678556 100644 (file)
@@ -44,7 +44,7 @@
 use syntax_pos::Span;
 use rustc_back::target::Target;
 use hir;
-use hir::intravisit::{IdVisitor, IdVisitingOperation, Visitor};
+use hir::intravisit::Visitor;
 
 pub use self::DefLike::{DlDef, DlField, DlImpl};
 pub use self::NativeLibraryKind::{NativeStatic, NativeFramework, NativeUnknown};
@@ -292,11 +292,6 @@ pub fn visit<'ast,V>(&'ast self, visitor: &mut V)
             InlinedItem::ImplItem(_, ref ii) => visitor.visit_impl_item(ii),
         }
     }
-
-    pub fn visit_ids<O: IdVisitingOperation>(&self, operation: &mut O) {
-        let mut id_visitor = IdVisitor::new(operation);
-        self.visit(&mut id_visitor);
-    }
 }
 
 // FIXME: find a better place for this?
index 6fe98119c706088f2d68b2a645237e7d7abafe5e..446767ecbcaba1e1cb1daf08da4c0602b2826fff 100644 (file)
@@ -79,7 +79,7 @@ fn require_unsafe(&mut self, span: Span, description: &str) {
 
 impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> {
     fn visit_fn(&mut self, fn_kind: FnKind<'v>, fn_decl: &'v hir::FnDecl,
-                block: &'v hir::Block, span: Span, _: ast::NodeId) {
+                block: &'v hir::Block, span: Span, id: ast::NodeId) {
 
         let (is_item_fn, is_unsafe_fn) = match fn_kind {
             FnKind::ItemFn(_, _, unsafety, _, _, _, _) =>
@@ -96,7 +96,7 @@ fn visit_fn(&mut self, fn_kind: FnKind<'v>, fn_decl: &'v hir::FnDecl,
             self.unsafe_context = UnsafeContext::new(SafeContext)
         }
 
-        intravisit::walk_fn(self, fn_kind, fn_decl, block, span);
+        intravisit::walk_fn(self, fn_kind, fn_decl, block, span, id);
 
         self.unsafe_context = old_unsafe_context
     }
index 6551e0129f88493dacffff9044ca34b10ea112db..18b80a9636b45e0c2d91a605167bb4b127f2df96 100644 (file)
@@ -271,10 +271,19 @@ enum PassArgs {
 
 impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
     pub fn new(delegate: &'a mut (Delegate<'tcx>+'a),
-               infcx: &'a InferCtxt<'a, 'gcx, 'tcx>) -> Self
+               infcx: &'a InferCtxt<'a, 'gcx, 'tcx>)
+               -> Self
+    {
+        ExprUseVisitor::with_options(delegate, infcx, mc::MemCategorizationOptions::default())
+    }
+
+    pub fn with_options(delegate: &'a mut (Delegate<'tcx>+'a),
+                        infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
+                        options: mc::MemCategorizationOptions)
+               -> Self
     {
         ExprUseVisitor {
-            mc: mc::MemCategorizationContext::new(infcx),
+            mc: mc::MemCategorizationContext::with_options(infcx, options),
             delegate: delegate
         }
     }
index 960305e10488d2fbd6f64fdfb529e9b5444ef2e6..a209b1d1abd7c6e320fbf0e129a59a2f992f4bce 100644 (file)
@@ -359,7 +359,6 @@ pub fn collect_language_items(session: &Session,
     StartFnLangItem,                 "start",                   start_fn;
 
     EhPersonalityLangItem,           "eh_personality",          eh_personality;
-    EhPersonalityCatchLangItem,      "eh_personality_catch",    eh_personality_catch;
     EhUnwindResumeLangItem,          "eh_unwind_resume",        eh_unwind_resume;
     MSVCTryFilterLangItem,           "msvc_try_filter",         msvc_try_filter;
 
index ea3765c76f89b2ec425fb845286e69338d7e685d..1222b5f42a19f6aeca5de5d471cadc434a05f1a9 100644 (file)
@@ -390,7 +390,7 @@ fn visit_fn(ir: &mut IrMaps,
 
     // gather up the various local variables, significant expressions,
     // and so forth:
-    intravisit::walk_fn(&mut fn_maps, fk, decl, body, sp);
+    intravisit::walk_fn(&mut fn_maps, fk, decl, body, sp, id);
 
     // Special nodes and variables:
     // - exit_ln represents the end of the fn, either by return or panic
index 28bfb460a14faf75c9fdbbe10fb5a195cfc3e600..0bc3c1ae899dd267d235e507c18eaded12278d50 100644 (file)
@@ -259,6 +259,18 @@ fn span(&self) -> Span { self.span }
 #[derive(Copy, Clone)]
 pub struct MemCategorizationContext<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     pub infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
+    options: MemCategorizationOptions,
+}
+
+#[derive(Copy, Clone, Default)]
+pub struct MemCategorizationOptions {
+    // If true, then when analyzing a closure upvar, if the closure
+    // has a missing kind, we treat it like a Fn closure. When false,
+    // we ICE if the closure has a missing kind. Should be false
+    // except during closure kind inference. It is used by the
+    // mem-categorization code to be able to have stricter assertions
+    // (which are always true except during upvar inference).
+    pub during_closure_kind_inference: bool,
 }
 
 pub type McResult<T> = Result<T, ()>;
@@ -362,7 +374,16 @@ pub fn to_user_str(&self) -> &'static str {
 impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
     pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>)
                -> MemCategorizationContext<'a, 'gcx, 'tcx> {
-        MemCategorizationContext { infcx: infcx }
+        MemCategorizationContext::with_options(infcx, MemCategorizationOptions::default())
+    }
+
+    pub fn with_options(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
+                        options: MemCategorizationOptions)
+                        -> MemCategorizationContext<'a, 'gcx, 'tcx> {
+        MemCategorizationContext {
+            infcx: infcx,
+            options: options,
+        }
     }
 
     fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> {
@@ -584,10 +605,20 @@ pub fn cat_def(&self,
                               self.cat_upvar(id, span, var_id, fn_node_id, kind)
                           }
                           None => {
-                              span_bug!(
-                                  span,
-                                  "No closure kind for {:?}",
-                                  closure_id);
+                              if !self.options.during_closure_kind_inference {
+                                  span_bug!(
+                                      span,
+                                      "No closure kind for {:?}",
+                                      closure_id);
+                              }
+
+                              // during closure kind inference, we
+                              // don't know the closure kind yet, but
+                              // it's ok because we detect that we are
+                              // accessing an upvar and handle that
+                              // case specially anyhow. Use Fn
+                              // arbitrarily.
+                              self.cat_upvar(id, span, var_id, fn_node_id, ty::ClosureKind::Fn)
                           }
                       }
                   }
index 690395399efa166cd1bf244415a60a7f894151a6..cdde6d6f63ddd1c3dcdb911251c799a673164b68 100644 (file)
@@ -30,7 +30,7 @@
 use syntax::parse::token::InternedString;
 use syntax::feature_gate::UnstableFeatures;
 
-use errors::{ColorConfig, Handler};
+use errors::{ColorConfig, FatalError, Handler};
 
 use getopts;
 use std::collections::HashMap;
@@ -330,6 +330,11 @@ pub fn build_dep_graph(&self) -> bool {
             self.debugging_opts.dump_dep_graph ||
             self.debugging_opts.query_dep_graph
     }
+
+    pub fn single_codegen_unit(&self) -> bool {
+        self.incremental.is_none() ||
+        self.cg.codegen_units == 1
+    }
 }
 
 // The type of entry function, so
@@ -655,7 +660,6 @@ fn parse_panic_strategy(slot: &mut PanicStrategy, v: Option<&str>) -> bool {
         "panic strategy to compile crate with"),
 }
 
-
 options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
          build_debugging_options, "Z", "debugging",
          DB_OPTIONS, db_type_desc, dbsetters,
@@ -836,7 +840,10 @@ pub fn build_target_config(opts: &Options, sp: &Handler) -> Config {
     let target = match Target::search(&opts.target_triple) {
         Ok(t) => t,
         Err(e) => {
-            panic!(sp.fatal(&format!("Error loading target specification: {}", e)));
+            sp.struct_fatal(&format!("Error loading target specification: {}", e))
+                .help("Use `--print target-list` for a list of built-in targets")
+                .emit();
+            panic!(FatalError);
         }
     };
 
index 21c14e6fe4c3b16c2d39eac6769274bcb445c47b..fadf36471555b7f83a151bffd55c7c6fa020a915 100644 (file)
@@ -182,6 +182,21 @@ pub fn arm_contains_ref_binding(self, arm: &hir::Arm) -> Option<hir::Mutability>
         pat_util::arm_contains_ref_binding(arm)
     }
 
+    pub fn has_error_field(self, ty: Ty<'tcx>) -> bool {
+        match ty.sty {
+            ty::TyStruct(def, substs) | ty::TyEnum(def, substs) => {
+                for field in def.all_fields() {
+                    let field_ty = field.ty(self, substs);
+                    if let TyError = field_ty.sty {
+                        return true;
+                    }
+                }
+            }
+            _ => ()
+        }
+        false
+    }
+
     /// Returns the type of element at index `i` in tuple or tuple-like type `t`.
     /// For an enum `t`, `variant` is None only if `t` is a univariant enum.
     pub fn positional_element_ty(self,
index 0bfb7c1ed55321da22e6c9fe412b2dedcbc04686..60977a80946ff6e23950ef024d739eb4764a45a1 100644 (file)
@@ -974,7 +974,9 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
             ty::TyVar(ref vid) if print_var_ids => write!(f, "{:?}", vid),
             ty::IntVar(ref vid) if print_var_ids => write!(f, "{:?}", vid),
             ty::FloatVar(ref vid) if print_var_ids => write!(f, "{:?}", vid),
-            ty::TyVar(_) | ty::IntVar(_) | ty::FloatVar(_) => write!(f, "_"),
+            ty::TyVar(_) => write!(f, "_"),
+            ty::IntVar(_) => write!(f, "{}", "{integer}"),
+            ty::FloatVar(_) => write!(f, "{}", "{float}"),
             ty::FreshTy(v) => write!(f, "FreshTy({})", v),
             ty::FreshIntTy(v) => write!(f, "FreshIntTy({})", v),
             ty::FreshFloatTy(v) => write!(f, "FreshFloatTy({})", v)
index 481338d1cee562fe05eb3fe3c6fefa6fe4e640dd..6530ccb0630db0342729b6f1892c9a560e39e007 100644 (file)
@@ -8,11 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::{Target, TargetOptions};
+use target::{Target, TargetOptions, TargetResult};
 use super::apple_ios_base::{opts, Arch};
 
-pub fn target() -> Target {
-    Target {
+pub fn target() -> TargetResult {
+    let base = try!(opts(Arch::Arm64));
+    Ok(Target {
         llvm_target: "arm64-apple-ios".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
@@ -25,7 +26,7 @@ pub fn target() -> Target {
             features: "+neon,+fp-armv8,+cyclone".to_string(),
             eliminate_frame_pointer: false,
             max_atomic_width: 128,
-            .. opts(Arch::Arm64)
+            .. base
         },
-    }
+    })
 }
index a5be1a227f1eafbc21dd92c422125fe9075e5342..7f54dab5b5385faa87e0185ab446712dec3cdcbc 100644 (file)
@@ -8,15 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::android_base::opts();
     base.max_atomic_width = 128;
     // As documented in http://developer.android.com/ndk/guides/cpu-features.html
     // the neon (ASIMD) and FP must exist on all android aarch64 targets.
     base.features = "+neon,+fp-armv8".to_string();
-    Target {
+    Ok(Target {
         llvm_target: "aarch64-linux-android".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
@@ -26,5 +26,5 @@ pub fn target() -> Target {
         target_env: "".to_string(),
         target_vendor: "unknown".to_string(),
         options: base,
-    }
+    })
 }
index 2dc9355e22f0d9a1d6d3e94efab1bb184267bdc8..cca965f9d4ff16c0c52d40f16c781c12171f953b 100644 (file)
@@ -8,12 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::linux_base::opts();
     base.max_atomic_width = 128;
-    Target {
+    Ok(Target {
         llvm_target: "aarch64-unknown-linux-gnu".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
@@ -23,5 +23,5 @@ pub fn target() -> Target {
         target_os: "linux".to_string(),
         target_vendor: "unknown".to_string(),
         options: base,
-    }
+    })
 }
index d182fd9605640677322f9d1d425a6732d6bdb488..8bd9feabdbebe2a37e4bd099ef669c4659886b00 100644 (file)
@@ -36,7 +36,7 @@ pub fn to_string(&self) -> &'static str {
     }
 }
 
-pub fn get_sdk_root(sdk_name: &str) -> String {
+pub fn get_sdk_root(sdk_name: &str) -> Result<String, String> {
     let res = Command::new("xcrun")
                       .arg("--show-sdk-path")
                       .arg("-sdk")
@@ -55,12 +55,12 @@ pub fn get_sdk_root(sdk_name: &str) -> String {
                       });
 
     match res {
-        Ok(output) => output.trim().to_string(),
-        Err(e) => panic!("failed to get {} SDK path: {}", sdk_name, e)
+        Ok(output) => Ok(output.trim().to_string()),
+        Err(e) => Err(format!("failed to get {} SDK path: {}", sdk_name, e))
     }
 }
 
-fn pre_link_args(arch: Arch) -> Vec<String> {
+fn build_pre_link_args(arch: Arch) -> Result<Vec<String>, String> {
     let sdk_name = match arch {
         Armv7 | Armv7s | Arm64 => "iphoneos",
         I386 | X86_64 => "iphonesimulator"
@@ -68,8 +68,10 @@ fn pre_link_args(arch: Arch) -> Vec<String> {
 
     let arch_name = arch.to_string();
 
-    vec!["-arch".to_string(), arch_name.to_string(),
-         "-Wl,-syslibroot".to_string(), get_sdk_root(sdk_name)]
+    let sdk_root = try!(get_sdk_root(sdk_name));
+
+    Ok(vec!["-arch".to_string(), arch_name.to_string(),
+         "-Wl,-syslibroot".to_string(), sdk_root])
 }
 
 fn target_cpu(arch: Arch) -> String {
@@ -82,13 +84,14 @@ fn target_cpu(arch: Arch) -> String {
     }.to_string()
 }
 
-pub fn opts(arch: Arch) -> TargetOptions {
-    TargetOptions {
+pub fn opts(arch: Arch) -> Result<TargetOptions, String> {
+    let pre_link_args = try!(build_pre_link_args(arch));
+    Ok(TargetOptions {
         cpu: target_cpu(arch),
         dynamic_linking: false,
         executables: true,
-        pre_link_args: pre_link_args(arch),
+        pre_link_args: pre_link_args,
         has_elf_tls: false,
         .. super::apple_base::opts()
-    }
+    })
 }
index e1b170422c60d4122c88a1d8e96743714fcf1e6b..f3a18b13c6783b35cfd879e22b5b5fdbd0e605db 100644 (file)
@@ -8,14 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::android_base::opts();
     base.features = "+v7,+vfp3,+d16".to_string();
     base.max_atomic_width = 64;
 
-    Target {
+    Ok(Target {
         llvm_target: "arm-linux-androideabi".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
@@ -25,5 +25,5 @@ pub fn target() -> Target {
         target_env: "".to_string(),
         target_vendor: "unknown".to_string(),
         options: base,
-    }
+    })
 }
index 60c4a7c3c90ce4356fecb378e41f7b7d2ee8516e..e666a8460e5ea85d4ec626a6b7fa2ae9d000a189 100644 (file)
@@ -8,12 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::{Target, TargetOptions};
+use target::{Target, TargetOptions, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::linux_base::opts();
     base.max_atomic_width = 64;
-    Target {
+    Ok(Target {
         llvm_target: "arm-unknown-linux-gnueabi".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
@@ -27,5 +27,5 @@ pub fn target() -> Target {
             features: "+v6".to_string(),
             .. base
         },
-    }
+    })
 }
index 72128e30641c61da73e658fa83c1c37a803b9b2a..d65c89abc206496002f0194466e6969dfa62c7c3 100644 (file)
@@ -8,12 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::{Target, TargetOptions};
+use target::{Target, TargetOptions, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::linux_base::opts();
     base.max_atomic_width = 64;
-    Target {
+    Ok(Target {
         llvm_target: "arm-unknown-linux-gnueabihf".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
@@ -27,5 +27,5 @@ pub fn target() -> Target {
             features: "+v6,+vfp2".to_string(),
             .. base
         }
-    }
+    })
 }
diff --git a/src/librustc_back/target/arm_unknown_linux_musleabi.rs b/src/librustc_back/target/arm_unknown_linux_musleabi.rs
new file mode 100644 (file)
index 0000000..028c91e
--- /dev/null
@@ -0,0 +1,34 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use target::{Target, TargetResult};
+
+pub fn target() -> TargetResult {
+    let mut base = super::linux_musl_base::opts();
+
+    // Most of these settings are copied from the arm_unknown_linux_gnueabi
+    // target.
+    base.features = "+v6".to_string();
+    base.max_atomic_width = 64;
+    Ok(Target {
+        // It's important we use "gnueabi" and not "musleabi" here. LLVM uses it
+        // to determine the calling convention and float ABI, and it doesn't
+        // support the "musleabi" value.
+        llvm_target: "arm-unknown-linux-gnueabi".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "32".to_string(),
+        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        arch: "arm".to_string(),
+        target_os: "linux".to_string(),
+        target_env: "musl".to_string(),
+        target_vendor: "unknown".to_string(),
+        options: base,
+    })
+}
diff --git a/src/librustc_back/target/arm_unknown_linux_musleabihf.rs b/src/librustc_back/target/arm_unknown_linux_musleabihf.rs
new file mode 100644 (file)
index 0000000..c7dda18
--- /dev/null
@@ -0,0 +1,34 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use target::{Target, TargetResult};
+
+pub fn target() -> TargetResult {
+    let mut base = super::linux_musl_base::opts();
+
+    // Most of these settings are copied from the arm_unknown_linux_gnueabihf
+    // target.
+    base.features = "+v6,+vfp2".to_string();
+    base.max_atomic_width = 64;
+    Ok(Target {
+        // It's important we use "gnueabihf" and not "musleabihf" here. LLVM
+        // uses it to determine the calling convention and float ABI, and it
+        // doesn't support the "musleabihf" value.
+        llvm_target: "arm-unknown-linux-gnueabihf".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "32".to_string(),
+        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        arch: "arm".to_string(),
+        target_os: "linux".to_string(),
+        target_env: "musl".to_string(),
+        target_vendor: "unknown".to_string(),
+        options: base,
+    })
+}
index a2486a1330a53da4f2d9fa728e4b39093f7812e7..a806204d0a6bcb6064bfd46bc7b2862a0e88b5bb 100644 (file)
@@ -8,11 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::{Target, TargetOptions};
+use target::{Target, TargetOptions, TargetResult};
 use super::apple_ios_base::{opts, Arch};
 
-pub fn target() -> Target {
-    Target {
+pub fn target() -> TargetResult {
+    let base = try!(opts(Arch::Armv7));
+    Ok(Target {
         llvm_target: "armv7-apple-ios".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
@@ -24,7 +25,7 @@ pub fn target() -> Target {
         options: TargetOptions {
             features: "+v7,+vfp3,+neon".to_string(),
             max_atomic_width: 64,
-            .. opts(Arch::Armv7)
+            .. base
         }
-    }
+    })
 }
index fd8f35da16f61a1820aeea9c161fe23a09b3bdff..1c59262e04198b519cec108b2d81ff1c122d77f8 100644 (file)
@@ -8,14 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::android_base::opts();
     base.features = "+v7,+thumb2,+vfp3,+d16".to_string();
     base.max_atomic_width = 64;
 
-    Target {
+    Ok(Target {
         llvm_target: "armv7-none-linux-android".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
@@ -25,5 +25,5 @@ pub fn target() -> Target {
         target_env: "".to_string(),
         target_vendor: "unknown".to_string(),
         options: base,
-    }
+    })
 }
index 7bcca3a3934bed04d9e9d10b66a5cdb424a0976c..52269f0cd4a08788408745f8dbc202bd728e6992 100644 (file)
@@ -8,11 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::{Target, TargetOptions};
+use target::{Target, TargetOptions, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let base = super::linux_base::opts();
-    Target {
+    Ok(Target {
         llvm_target: "armv7-unknown-linux-gnueabihf".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
@@ -28,6 +28,6 @@ pub fn target() -> Target {
             max_atomic_width: 64,
             .. base
         }
-    }
+    })
 }
 
diff --git a/src/librustc_back/target/armv7_unknown_linux_musleabihf.rs b/src/librustc_back/target/armv7_unknown_linux_musleabihf.rs
new file mode 100644 (file)
index 0000000..e40704e
--- /dev/null
@@ -0,0 +1,35 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use target::{Target, TargetResult};
+
+pub fn target() -> TargetResult {
+    let mut base = super::linux_musl_base::opts();
+
+    // Most of these settings are copied from the armv7_unknown_linux_gnueabihf
+    // target.
+    base.features = "+v7,+vfp3,+neon".to_string();
+    base.cpu = "cortex-a8".to_string();
+    base.max_atomic_width = 64;
+    Ok(Target {
+        // It's important we use "gnueabihf" and not "musleabihf" here. LLVM
+        // uses it to determine the calling convention and float ABI, and LLVM
+        // doesn't support the "musleabihf" value.
+        llvm_target: "armv7-unknown-linux-gnueabihf".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "32".to_string(),
+        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        arch: "arm".to_string(),
+        target_os: "linux".to_string(),
+        target_env: "musl".to_string(),
+        target_vendor: "unknown".to_string(),
+        options: base,
+    })
+}
index e5379aa1b42cd74571df00799e8dc015f7729da9..aaa3570fa62ee6e2e01afad79b6a8b674557d570 100644 (file)
@@ -8,11 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::{Target, TargetOptions};
+use target::{Target, TargetOptions, TargetResult};
 use super::apple_ios_base::{opts, Arch};
 
-pub fn target() -> Target {
-    Target {
+pub fn target() -> TargetResult {
+    let base = try!(opts(Arch::Armv7s));
+    Ok(Target {
         llvm_target: "armv7s-apple-ios".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
@@ -24,7 +25,7 @@ pub fn target() -> Target {
         options: TargetOptions {
             features: "+v7,+vfp4,+neon".to_string(),
             max_atomic_width: 64,
-            .. opts(Arch::Armv7s)
+            .. base
         }
-    }
+    })
 }
index e6200177944bbbc6313b23c7ae5e848d32a6a9e7..07eb191471c46c58de2915ea70c32467377562bb 100644 (file)
@@ -10,7 +10,7 @@
 
 use super::{Target, TargetOptions};
 
-pub fn target() -> Target {
+pub fn target() -> Result<Target, String> {
     let opts = TargetOptions {
         linker: "emcc".to_string(),
         ar: "emar".to_string(),
@@ -25,7 +25,7 @@ pub fn target() -> Target {
         max_atomic_width: 32,
         .. Default::default()
     };
-    Target {
+    Ok(Target {
         llvm_target: "asmjs-unknown-emscripten".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
@@ -35,5 +35,5 @@ pub fn target() -> Target {
         data_layout: "e-p:32:32-i64:64-v128:32:128-n32-S128".to_string(),
         arch: "asmjs".to_string(),
         options: opts,
-    }
+    })
 }
index cf4020eeb587420d00f5f852dd457bc9028fc146..f391d4118ea74c6fc6b0a09cb67cc66e618d10b2 100644 (file)
@@ -8,11 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::{Target, TargetOptions};
+use target::{Target, TargetOptions, TargetResult};
 use super::apple_ios_base::{opts, Arch};
 
-pub fn target() -> Target {
-    Target {
+pub fn target() -> TargetResult {
+    let base = try!(opts(Arch::I386));
+    Ok(Target {
         llvm_target: "i386-apple-ios".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
@@ -23,7 +24,7 @@ pub fn target() -> Target {
         target_vendor: "apple".to_string(),
         options: TargetOptions {
             max_atomic_width: 64,
-            .. opts(Arch::I386)
+            .. base
         }
-    }
+    })
 }
index 12bed370eae94403a87a7253148790eeecfb8b6e..445ee6c412283ff009b86d5d6a6e7b809bbf8a7c 100644 (file)
@@ -8,11 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::TargetResult;
 
-pub fn target() -> Target {
-    let mut base = super::i686_pc_windows_msvc::target();
+pub fn target() -> TargetResult {
+    let mut base = try!(super::i686_pc_windows_msvc::target());
     base.options.cpu = "pentium".to_string();
     base.llvm_target = "i586-pc-windows-msvc".to_string();
-    return base
+    Ok(base)
 }
index 6eb64556381903de28a6a382e838bba0bca854c8..1ca8606149bff6adf54a19887ee9b5864840d710 100644 (file)
@@ -8,11 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::TargetResult;
 
-pub fn target() -> Target {
-    let mut base = super::i686_unknown_linux_gnu::target();
+pub fn target() -> TargetResult {
+    let mut base = try!(super::i686_unknown_linux_gnu::target());
     base.options.cpu = "pentium".to_string();
     base.llvm_target = "i586-unknown-linux-gnu".to_string();
-    return base
+    Ok(base)
 }
index 302691e9a5922462fa5b746a04845219d063cd46..4876a3489d4707a74cea0b21943421f4af44f62e 100644 (file)
@@ -8,15 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::apple_base::opts();
     base.cpu = "yonah".to_string();
     base.max_atomic_width = 64;
     base.pre_link_args.push("-m32".to_string());
 
-    Target {
+    Ok(Target {
         llvm_target: "i686-apple-darwin".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
@@ -26,5 +26,5 @@ pub fn target() -> Target {
         target_env: "".to_string(),
         target_vendor: "apple".to_string(),
         options: base,
-    }
+    })
 }
index 2376de123980b60a3bbb17f95fd548365f579dde..1de629238a13c7b54c33f5794c5d7a2dfe5ae7f3 100644 (file)
@@ -8,9 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::android_base::opts();
 
     base.max_atomic_width = 64;
@@ -19,7 +19,7 @@ pub fn target() -> Target {
     base.cpu = "pentiumpro".to_string();
     base.features = "+mmx,+sse,+sse2,+sse3,+ssse3".to_string();
 
-    Target {
+    Ok(Target {
         llvm_target: "i686-linux-android".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
@@ -29,5 +29,5 @@ pub fn target() -> Target {
         target_env: "".to_string(),
         target_vendor: "unknown".to_string(),
         options: base,
-    }
+    })
 }
index c2cc624c9f9e65f344b81039e39481cf9c15a9aa..2c19b8109c36214db01be556fafb07efda981cd5 100644 (file)
@@ -8,9 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::windows_base::opts();
     base.cpu = "pentium4".to_string();
     base.max_atomic_width = 64;
@@ -19,7 +19,7 @@ pub fn target() -> Target {
     // space available to x86 Windows binaries on x86_64.
     base.pre_link_args.push("-Wl,--large-address-aware".to_string());
 
-    Target {
+    Ok(Target {
         llvm_target: "i686-pc-windows-gnu".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
@@ -29,5 +29,5 @@ pub fn target() -> Target {
         target_env: "gnu".to_string(),
         target_vendor: "pc".to_string(),
         options: base,
-    }
+    })
 }
index 8c1bacc2807677e39b53844382f0bc2336b4db40..cb02fcc308c2d8f71cbbd8dd7e54d2193aecae23 100644 (file)
@@ -8,9 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::windows_msvc_base::opts();
     base.cpu = "pentium4".to_string();
     base.max_atomic_width = 64;
@@ -24,7 +24,7 @@ pub fn target() -> Target {
     // https://msdn.microsoft.com/en-us/library/9a89h429.aspx
     base.pre_link_args.push("/SAFESEH".to_string());
 
-    Target {
+    Ok(Target {
         llvm_target: "i686-pc-windows-msvc".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
@@ -34,5 +34,5 @@ pub fn target() -> Target {
         target_env: "msvc".to_string(),
         target_vendor: "pc".to_string(),
         options: base,
-    }
+    })
 }
index 6446ac45f7d6e92b8174231a09f6860f3cb29ab8..f96ec004b481eaf98fb908a1191bb8a814768294 100644 (file)
@@ -8,15 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::dragonfly_base::opts();
     base.cpu = "pentium4".to_string();
     base.max_atomic_width = 64;
     base.pre_link_args.push("-m32".to_string());
 
-    Target {
+    Ok(Target {
         llvm_target: "i686-unknown-dragonfly".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
@@ -26,5 +26,5 @@ pub fn target() -> Target {
         target_env: "".to_string(),
         target_vendor: "unknown".to_string(),
         options: base,
-    }
+    })
 }
index a7903d5db64132856579ec1f949abf4b8c21e0b6..3489ecfe614d910a89901a686073f49307f9adac 100644 (file)
@@ -8,15 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::freebsd_base::opts();
     base.cpu = "pentium4".to_string();
     base.max_atomic_width = 64;
     base.pre_link_args.push("-m32".to_string());
 
-    Target {
+    Ok(Target {
         llvm_target: "i686-unknown-freebsd".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
@@ -26,5 +26,5 @@ pub fn target() -> Target {
         target_env: "".to_string(),
         target_vendor: "unknown".to_string(),
         options: base,
-    }
+    })
 }
index 7813d5570762def942934dc70140624d42732527..f2e865c015e353b8e7b3e070cbb0fa1af11e1e78 100644 (file)
@@ -8,15 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::linux_base::opts();
     base.cpu = "pentium4".to_string();
     base.max_atomic_width = 64;
     base.pre_link_args.push("-m32".to_string());
 
-    Target {
+    Ok(Target {
         llvm_target: "i686-unknown-linux-gnu".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
@@ -26,5 +26,5 @@ pub fn target() -> Target {
         target_env: "gnu".to_string(),
         target_vendor: "unknown".to_string(),
         options: base,
-    }
+    })
 }
index 527442958374236c4bea97272679bd1ea7faeab6..a0a8de46e2f59bd97eca8df993737cd26c5daef6 100644 (file)
@@ -8,16 +8,16 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::linux_musl_base::opts();
     base.cpu = "pentium4".to_string();
     base.max_atomic_width = 64;
     base.pre_link_args.push("-m32".to_string());
     base.pre_link_args.push("-Wl,-melf_i386".to_string());
 
-    Target {
+    Ok(Target {
         llvm_target: "i686-unknown-linux-musl".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
@@ -27,5 +27,5 @@ pub fn target() -> Target {
         target_env: "musl".to_string(),
         target_vendor: "unknown".to_string(),
         options: base,
-    }
+    })
 }
index f4f0262d476da75b3af893f37d96846622e56cea..25132f8a044d6faacba46c043699aa994166bcb5 100644 (file)
@@ -8,9 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use super::{Target, TargetOptions};
+use super::{Target, TargetOptions, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let opts = TargetOptions {
         linker: "pnacl-clang".to_string(),
         ar: "pnacl-ar".to_string(),
@@ -28,7 +28,7 @@ pub fn target() -> Target {
         max_atomic_width: 32,
         .. Default::default()
     };
-    Target {
+    Ok(Target {
         llvm_target: "le32-unknown-nacl".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
@@ -38,5 +38,5 @@ pub fn target() -> Target {
         data_layout: "e-i64:64:64-p:32:32:32-v128:32:32".to_string(),
         arch: "le32".to_string(),
         options: opts,
-    }
+    })
 }
index ceb17e53a5552e41540b94e3d850f72d4d08b07c..ab967f6b40fbead30c78c771d38b723b90eac6af 100644 (file)
@@ -8,10 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::{Target, TargetOptions};
+use target::{Target, TargetOptions, TargetResult};
 
-pub fn target() -> Target {
-    Target {
+pub fn target() -> TargetResult {
+    Ok(Target {
         llvm_target: "mips-unknown-linux-gnu".to_string(),
         target_endian: "big".to_string(),
         target_pointer_width: "32".to_string(),
@@ -26,5 +26,5 @@ pub fn target() -> Target {
             max_atomic_width: 32,
             ..super::linux_base::opts()
         },
-    }
+    })
 }
index 35366659d581ffa03e6fb5646b2d30b98d4be4dd..4a69bce53bc978a5a6c6b9a9ddbcf7f38ed4c107 100644 (file)
@@ -8,10 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::{Target, TargetOptions};
+use target::{Target, TargetOptions, TargetResult};
 
-pub fn target() -> Target {
-    Target {
+pub fn target() -> TargetResult {
+    Ok(Target {
         llvm_target: "mips-unknown-linux-musl".to_string(),
         target_endian: "big".to_string(),
         target_pointer_width: "32".to_string(),
@@ -26,5 +26,5 @@ pub fn target() -> Target {
             max_atomic_width: 32,
             ..super::linux_base::opts()
         }
-    }
+    })
 }
index ac1536b3d009b58950998e9de973538bfba0ee86..b66fb62cd591ecc97929f9547c930497c232867a 100644 (file)
@@ -8,10 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::{Target, TargetOptions};
+use target::{Target, TargetOptions, TargetResult};
 
-pub fn target() -> Target {
-    Target {
+pub fn target() -> TargetResult {
+    Ok(Target {
         llvm_target: "mipsel-unknown-linux-gnu".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
@@ -27,5 +27,5 @@ pub fn target() -> Target {
             max_atomic_width: 32,
             ..super::linux_base::opts()
         },
-    }
+    })
 }
index 6195ac5eadfce7ce7e9db032ae07649fa6b8e8b0..a0524e5e763895877cc62067bfcd0b0d6a1d8836 100644 (file)
@@ -8,10 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::{Target, TargetOptions};
+use target::{Target, TargetOptions, TargetResult};
 
-pub fn target() -> Target {
-    Target {
+pub fn target() -> TargetResult {
+    Ok(Target {
         llvm_target: "mipsel-unknown-linux-musl".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
@@ -26,5 +26,5 @@ pub fn target() -> Target {
             max_atomic_width: 32,
             ..super::linux_base::opts()
         }
-    }
+    })
 }
index 99bc26848025ec0ec030a28776c5b3634226a455..3d24fd8ab67e4a2d4b1bd1d1a25ff95f3336933b 100644 (file)
@@ -44,7 +44,8 @@
 //! the target's settings, though `target-feature` and `link-args` will *add*
 //! to the list specified by the target, rather than replace.
 
-use serialize::json::Json;
+use serialize::json::{Json, ToJson};
+use std::collections::BTreeMap;
 use std::default::Default;
 use std::io::prelude::*;
 use syntax::abi::Abi;
 mod windows_base;
 mod windows_msvc_base;
 
+pub type TargetResult = Result<Target, String>;
+
 macro_rules! supported_targets {
     ( $(($triple:expr, $module:ident)),+ ) => (
         $(mod $module;)*
 
         /// List of supported targets
-        pub const TARGETS: &'static [&'static str] = &[$($triple),*];
+        const TARGETS: &'static [&'static str] = &[$($triple),*];
 
-        fn load_specific(target: &str) -> Option<Target> {
+        fn load_specific(target: &str) -> TargetResult {
             match target {
                 $(
                     $triple => {
-                        let mut t = $module::target();
+                        let mut t = try!($module::target());
                         t.options.is_builtin = true;
+
+                        // round-trip through the JSON parser to ensure at
+                        // run-time that the parser works correctly
+                        t = try!(Target::from_json(t.to_json()));
                         debug!("Got builtin target: {:?}", t);
-                        Some(t)
+                        Ok(t)
                     },
                 )+
-                _ => None
+                _ => Err(format!("Unable to find target: {}", target))
             }
         }
+
+        pub fn get_targets() -> Box<Iterator<Item=String>> {
+            Box::new(TARGETS.iter().filter_map(|t| -> Option<String> {
+                load_specific(t)
+                    .map(|t| t.llvm_target)
+                    .ok()
+            }))
+        }
+
+        #[cfg(test)]
+        mod test_json_encode_decode {
+            use serialize::json::ToJson;
+            use super::Target;
+            $(use super::$module;)*
+
+            $(
+                #[test]
+                fn $module() {
+                    // Grab the TargetResult struct. If we successfully retrieved
+                    // a Target, then the test JSON encoding/decoding can run for this
+                    // Target on this testing platform (i.e., checking the iOS targets
+                    // only on a Mac test platform).
+                    let _ = $module::target().map(|original| {
+                        let as_json = original.to_json();
+                        let parsed = Target::from_json(as_json).unwrap();
+                        assert_eq!(original, parsed);
+                    });
+                }
+            )*
+        }
     )
 }
 
@@ -97,7 +134,10 @@ fn load_specific(target: &str) -> Option<Target> {
     ("powerpc64le-unknown-linux-gnu", powerpc64le_unknown_linux_gnu),
     ("arm-unknown-linux-gnueabi", arm_unknown_linux_gnueabi),
     ("arm-unknown-linux-gnueabihf", arm_unknown_linux_gnueabihf),
+    ("arm-unknown-linux-musleabi", arm_unknown_linux_musleabi),
+    ("arm-unknown-linux-musleabihf", arm_unknown_linux_musleabihf),
     ("armv7-unknown-linux-gnueabihf", armv7_unknown_linux_gnueabihf),
+    ("armv7-unknown-linux-musleabihf", armv7_unknown_linux_musleabihf),
     ("aarch64-unknown-linux-gnu", aarch64_unknown_linux_gnu),
     ("x86_64-unknown-linux-musl", x86_64_unknown_linux_musl),
     ("i686-unknown-linux-musl", i686_unknown_linux_musl),
@@ -145,7 +185,7 @@ fn load_specific(target: &str) -> Option<Target> {
 /// Everything `rustc` knows about how to compile for a specific target.
 ///
 /// Every field here must be specified, and has no default value.
-#[derive(Clone, Debug)]
+#[derive(PartialEq, Clone, Debug)]
 pub struct Target {
     /// Target triple to pass to LLVM.
     pub llvm_target: String,
@@ -172,7 +212,7 @@ pub struct Target {
 ///
 /// This has an implementation of `Default`, see each field for what the default is. In general,
 /// these try to take "minimal defaults" that don't assume anything about the runtime they run in.
-#[derive(Clone, Debug)]
+#[derive(PartialEq, Clone, Debug)]
 pub struct TargetOptions {
     /// Whether the target is built-in or loaded from a custom target specification.
     pub is_builtin: bool,
@@ -252,6 +292,13 @@ pub struct TargetOptions {
     pub is_like_android: bool,
     /// Whether the linker support GNU-like arguments such as -O. Defaults to false.
     pub linker_is_gnu: bool,
+    /// The MinGW toolchain has a known issue that prevents it from correctly
+    /// handling COFF object files with more than 2^15 sections. Since each weak
+    /// symbol needs its own COMDAT section, weak linkage implies a large
+    /// number sections that easily exceeds the given limit for larger
+    /// codebases. Consequently we want a way to disallow weak linkage on some
+    /// platforms.
+    pub allows_weak_linkage: bool,
     /// Whether the linker support rpaths or not. Defaults to false.
     pub has_rpath: bool,
     /// Whether to disable linking to compiler-rt. Defaults to false, as LLVM
@@ -327,6 +374,7 @@ fn default() -> TargetOptions {
             is_like_android: false,
             is_like_msvc: false,
             linker_is_gnu: false,
+            allows_weak_linkage: true,
             has_rpath: false,
             no_compiler_rt: false,
             no_default_libraries: true,
@@ -363,16 +411,21 @@ pub fn adjust_abi(&self, abi: Abi) -> Abi {
     }
 
     /// Load a target descriptor from a JSON object.
-    pub fn from_json(obj: Json) -> Target {
-        // this is 1. ugly, 2. error prone.
+    pub fn from_json(obj: Json) -> TargetResult {
+        // While ugly, this code must remain this way to retain
+        // compatibility with existing JSON fields and the internal
+        // expected naming of the Target and TargetOptions structs.
+        // To ensure compatibility is retained, the built-in targets
+        // are round-tripped through this code to catch cases where
+        // the JSON parser is not updated to match the structs.
 
         let get_req_field = |name: &str| {
             match obj.find(name)
                      .map(|s| s.as_string())
                      .and_then(|os| os.map(|s| s.to_string())) {
-                Some(val) => val,
+                Some(val) => Ok(val),
                 None => {
-                    panic!("Field {} in target specification is required", name)
+                    return Err(format!("Field {} in target specification is required", name))
                 }
             }
         };
@@ -384,12 +437,12 @@ pub fn from_json(obj: Json) -> Target {
         };
 
         let mut base = Target {
-            llvm_target: get_req_field("llvm-target"),
-            target_endian: get_req_field("target-endian"),
-            target_pointer_width: get_req_field("target-pointer-width"),
-            data_layout: get_req_field("data-layout"),
-            arch: get_req_field("arch"),
-            target_os: get_req_field("os"),
+            llvm_target: try!(get_req_field("llvm-target")),
+            target_endian: try!(get_req_field("target-endian")),
+            target_pointer_width: try!(get_req_field("target-pointer-width")),
+            data_layout: try!(get_req_field("data-layout")),
+            arch: try!(get_req_field("arch")),
+            target_os: try!(get_req_field("os")),
             target_env: get_opt_field("env", ""),
             target_vendor: get_opt_field("vendor", "unknown"),
             options: Default::default(),
@@ -434,38 +487,51 @@ macro_rules! key {
             } );
         }
 
-        key!(cpu);
-        key!(ar);
+        key!(is_builtin, bool);
         key!(linker);
+        key!(ar);
+        key!(pre_link_args, list);
+        key!(pre_link_objects_exe, list);
+        key!(pre_link_objects_dll, list);
+        key!(late_link_args, list);
+        key!(post_link_objects, list);
+        key!(post_link_args, list);
+        key!(cpu);
+        key!(features);
+        key!(dynamic_linking, bool);
+        key!(executables, bool);
         key!(relocation_model);
         key!(code_model);
+        key!(disable_redzone, bool);
+        key!(eliminate_frame_pointer, bool);
+        key!(function_sections, bool);
         key!(dll_prefix);
         key!(dll_suffix);
         key!(exe_suffix);
         key!(staticlib_prefix);
         key!(staticlib_suffix);
-        key!(features);
-        key!(dynamic_linking, bool);
-        key!(executables, bool);
-        key!(disable_redzone, bool);
-        key!(eliminate_frame_pointer, bool);
-        key!(function_sections, bool);
         key!(target_family, optional);
         key!(is_like_osx, bool);
+        key!(is_like_solaris, bool);
         key!(is_like_windows, bool);
         key!(is_like_msvc, bool);
+        key!(is_like_android, bool);
         key!(linker_is_gnu, bool);
+        key!(allows_weak_linkage, bool);
         key!(has_rpath, bool);
         key!(no_compiler_rt, bool);
         key!(no_default_libraries, bool);
-        key!(pre_link_args, list);
-        key!(post_link_args, list);
+        key!(position_independent_executables, bool);
         key!(archive_format);
         key!(allow_asm, bool);
         key!(custom_unwind_resume, bool);
+        key!(lib_allocation_crate);
+        key!(exe_allocation_crate);
+        key!(has_elf_tls, bool);
+        key!(obj_is_bitcode, bool);
         key!(max_atomic_width, u64);
 
-        base
+        Ok(base)
     }
 
     /// Search RUST_TARGET_PATH for a JSON file specifying the given target
@@ -488,10 +554,10 @@ fn load_file(path: &Path) -> Result<Target, String> {
             f.read_to_end(&mut contents).map_err(|e| e.to_string())?;
             let obj = json::from_reader(&mut &contents[..])
                            .map_err(|e| e.to_string())?;
-            Ok(Target::from_json(obj))
+            Target::from_json(obj)
         }
 
-        if let Some(t) = load_specific(target) {
+        if let Ok(t) = load_specific(target) {
             return Ok(t)
         }
 
@@ -523,6 +589,95 @@ fn load_file(path: &Path) -> Result<Target, String> {
     }
 }
 
+impl ToJson for Target {
+    fn to_json(&self) -> Json {
+        let mut d = BTreeMap::new();
+        let default: TargetOptions = Default::default();
+
+        macro_rules! target_val {
+            ($attr:ident) => ( {
+                let name = (stringify!($attr)).replace("_", "-");
+                d.insert(name.to_string(), self.$attr.to_json());
+            } );
+            ($attr:ident, $key_name:expr) => ( {
+                let name = $key_name;
+                d.insert(name.to_string(), self.$attr.to_json());
+            } );
+        }
+
+        macro_rules! target_option_val {
+            ($attr:ident) => ( {
+                let name = (stringify!($attr)).replace("_", "-");
+                if default.$attr != self.options.$attr {
+                    d.insert(name.to_string(), self.options.$attr.to_json());
+                }
+            } );
+            ($attr:ident, $key_name:expr) => ( {
+                let name = $key_name;
+                if default.$attr != self.options.$attr {
+                    d.insert(name.to_string(), self.options.$attr.to_json());
+                }
+            } );
+        }
+
+        target_val!(llvm_target);
+        target_val!(target_endian);
+        target_val!(target_pointer_width);
+        target_val!(arch);
+        target_val!(target_os, "os");
+        target_val!(target_env, "env");
+        target_val!(target_vendor, "vendor");
+        target_val!(arch);
+        target_val!(data_layout);
+
+        target_option_val!(is_builtin);
+        target_option_val!(linker);
+        target_option_val!(ar);
+        target_option_val!(pre_link_args);
+        target_option_val!(pre_link_objects_exe);
+        target_option_val!(pre_link_objects_dll);
+        target_option_val!(late_link_args);
+        target_option_val!(post_link_objects);
+        target_option_val!(post_link_args);
+        target_option_val!(cpu);
+        target_option_val!(features);
+        target_option_val!(dynamic_linking);
+        target_option_val!(executables);
+        target_option_val!(relocation_model);
+        target_option_val!(code_model);
+        target_option_val!(disable_redzone);
+        target_option_val!(eliminate_frame_pointer);
+        target_option_val!(function_sections);
+        target_option_val!(dll_prefix);
+        target_option_val!(dll_suffix);
+        target_option_val!(exe_suffix);
+        target_option_val!(staticlib_prefix);
+        target_option_val!(staticlib_suffix);
+        target_option_val!(target_family);
+        target_option_val!(is_like_osx);
+        target_option_val!(is_like_solaris);
+        target_option_val!(is_like_windows);
+        target_option_val!(is_like_msvc);
+        target_option_val!(is_like_android);
+        target_option_val!(linker_is_gnu);
+        target_option_val!(allows_weak_linkage);
+        target_option_val!(has_rpath);
+        target_option_val!(no_compiler_rt);
+        target_option_val!(no_default_libraries);
+        target_option_val!(position_independent_executables);
+        target_option_val!(archive_format);
+        target_option_val!(allow_asm);
+        target_option_val!(custom_unwind_resume);
+        target_option_val!(lib_allocation_crate);
+        target_option_val!(exe_allocation_crate);
+        target_option_val!(has_elf_tls);
+        target_option_val!(obj_is_bitcode);
+        target_option_val!(max_atomic_width);
+
+        Json::Object(d)
+    }
+}
+
 fn maybe_jemalloc() -> String {
     if cfg!(feature = "jemalloc") {
         "alloc_jemalloc".to_string()
index be4be8e6fc964f93e71e02c9c411bd891aab9481..1c04e763417c4b0574e6c043a9c8f2f0b1b7bdca 100644 (file)
@@ -8,15 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::linux_base::opts();
     base.cpu = "ppc64".to_string();
     base.pre_link_args.push("-m64".to_string());
     base.max_atomic_width = 64;
 
-    Target {
+    Ok(Target {
         llvm_target: "powerpc64-unknown-linux-gnu".to_string(),
         target_endian: "big".to_string(),
         target_pointer_width: "64".to_string(),
@@ -26,5 +26,5 @@ pub fn target() -> Target {
         target_env: "gnu".to_string(),
         target_vendor: "unknown".to_string(),
         options: base,
-    }
+    })
 }
index b0a81ce7ec5018162f0a3a023810671f1da4cdd8..906e28d2f20cb1d0c778f8ab9e455414deaac481 100644 (file)
@@ -8,15 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::linux_base::opts();
     base.cpu = "ppc64le".to_string();
     base.pre_link_args.push("-m64".to_string());
     base.max_atomic_width = 64;
 
-    Target {
+    Ok(Target {
         llvm_target: "powerpc64le-unknown-linux-gnu".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
@@ -26,5 +26,5 @@ pub fn target() -> Target {
         target_env: "gnu".to_string(),
         target_vendor: "unknown".to_string(),
         options: base,
-    }
+    })
 }
index aea57dc4b7f95404ddf26d41a75d07935b06a6b9..aebf9cd68717d18cc357114fbb99e122a8dbb13a 100644 (file)
@@ -8,14 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::linux_base::opts();
     base.pre_link_args.push("-m32".to_string());
     base.max_atomic_width = 32;
 
-    Target {
+    Ok(Target {
         llvm_target: "powerpc-unknown-linux-gnu".to_string(),
         target_endian: "big".to_string(),
         target_pointer_width: "32".to_string(),
@@ -25,5 +25,5 @@ pub fn target() -> Target {
         target_env: "gnu".to_string(),
         target_vendor: "unknown".to_string(),
         options: base,
-    }
+    })
 }
index 1e46f45bdcf4f2365da250926f8e2033365fd4b5..c398ee40f2f9790bfe5b4f310a8773baf79a982c 100644 (file)
@@ -25,6 +25,7 @@ pub fn opts() -> TargetOptions {
         staticlib_suffix: ".lib".to_string(),
         no_default_libraries: true,
         is_like_windows: true,
+        allows_weak_linkage: false,
         pre_link_args: vec!(
             // And here, we see obscure linker flags #45. On windows, it has been
             // found to be necessary to have this flag to compile liblibc.
index 5542c9120a4022f653004819f2d8edec23558dcb..65e4b1400fcf8a68171356f1418c48b7e9f9db08 100644 (file)
@@ -8,16 +8,16 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::apple_base::opts();
     base.cpu = "core2".to_string();
     base.max_atomic_width = 128; // core2 support cmpxchg16b
     base.eliminate_frame_pointer = false;
     base.pre_link_args.push("-m64".to_string());
 
-    Target {
+    Ok(Target {
         llvm_target: "x86_64-apple-darwin".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
@@ -27,5 +27,5 @@ pub fn target() -> Target {
         target_env: "".to_string(),
         target_vendor: "apple".to_string(),
         options: base,
-    }
+    })
 }
index 8638241f8610b0cb65851324f4d793e912ad5a57..4afc9bcb946c29da9b04cc13effaa140fcf17a50 100644 (file)
@@ -8,11 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::{Target, TargetOptions};
+use target::{Target, TargetOptions, TargetResult};
 use super::apple_ios_base::{opts, Arch};
 
-pub fn target() -> Target {
-    Target {
+pub fn target() -> TargetResult {
+    let base = try!(opts(Arch::X86_64));
+    Ok(Target {
         llvm_target: "x86_64-apple-ios".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
@@ -23,7 +24,7 @@ pub fn target() -> Target {
         target_vendor: "apple".to_string(),
         options: TargetOptions {
             max_atomic_width: 64,
-            .. opts(Arch::X86_64)
+            .. base
         }
-    }
+    })
 }
index e243054d0230e9ab8659ce22e31f8bc4437f3f44..086e0e6bf4fe7edc723082853fdd9e9ee71c12d7 100644 (file)
@@ -8,15 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::windows_base::opts();
     base.cpu = "x86-64".to_string();
     base.pre_link_args.push("-m64".to_string());
     base.max_atomic_width = 64;
 
-    Target {
+    Ok(Target {
         llvm_target: "x86_64-pc-windows-gnu".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
@@ -26,5 +26,5 @@ pub fn target() -> Target {
         target_env: "gnu".to_string(),
         target_vendor: "pc".to_string(),
         options: base,
-    }
+    })
 }
index a23a807a0257ed8ab88b019f4cba646ec2ed5ea3..064f06e9b31d6fbc1555cf0aa1ee3fe55a810ccb 100644 (file)
@@ -8,14 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::windows_msvc_base::opts();
     base.cpu = "x86-64".to_string();
     base.max_atomic_width = 64;
 
-    Target {
+    Ok(Target {
         llvm_target: "x86_64-pc-windows-msvc".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
@@ -25,5 +25,5 @@ pub fn target() -> Target {
         target_env: "msvc".to_string(),
         target_vendor: "pc".to_string(),
         options: base,
-    }
+    })
 }
index af5d21c4d93e45b92500927def98078d74621364..537d15f4603bb4f6c3fe6ebb8f0ce09f987e34f7 100644 (file)
@@ -8,9 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::netbsd_base::opts();
     base.pre_link_args.push("-m64".to_string());
     base.linker = "x86_64-rumprun-netbsd-gcc".to_string();
@@ -24,7 +24,7 @@ pub fn target() -> Target {
     base.no_default_libraries = false;
     base.exe_allocation_crate = "alloc_system".to_string();
 
-    Target {
+    Ok(Target {
         llvm_target: "x86_64-rumprun-netbsd".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
@@ -34,5 +34,5 @@ pub fn target() -> Target {
         target_env: "".to_string(),
         target_vendor: "rumprun".to_string(),
         options: base,
-    }
+    })
 }
index 8f2c905cf2ee4990bdc568a8db3098753c3fb52b..2a1feb937f742f3fc59a9fc2141701465af30737 100644 (file)
@@ -8,15 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::solaris_base::opts();
     base.pre_link_args.push("-m64".to_string());
     base.cpu = "x86-64".to_string();
     base.max_atomic_width = 64;
 
-    Target {
+    Ok(Target {
         llvm_target: "x86_64-pc-solaris".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
@@ -26,5 +26,5 @@ pub fn target() -> Target {
         target_env: "".to_string(),
         target_vendor: "sun".to_string(),
         options: base,
-    }
+    })
 }
index 87753da540a3646df48ac54bea6a4d873e268b7e..81710b99b80becfafb51c9aa009ad9601d5693de 100644 (file)
@@ -8,14 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::bitrig_base::opts();
     base.max_atomic_width = 64;
     base.pre_link_args.push("-m64".to_string());
 
-    Target {
+    Ok(Target {
         llvm_target: "x86_64-unknown-bitrig".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
@@ -25,5 +25,5 @@ pub fn target() -> Target {
         target_env: "".to_string(),
         target_vendor: "unknown".to_string(),
         options: base,
-    }
+    })
 }
index 2535071f3089c91c34ec82689a23d24f415417f8..7e40d49b870ade9d49c3d21faebd71f0ac6cd0d7 100644 (file)
@@ -8,15 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::dragonfly_base::opts();
     base.cpu = "x86-64".to_string();
     base.max_atomic_width = 64;
     base.pre_link_args.push("-m64".to_string());
 
-    Target {
+    Ok(Target {
         llvm_target: "x86_64-unknown-dragonfly".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
@@ -26,5 +26,5 @@ pub fn target() -> Target {
         target_env: "".to_string(),
         target_vendor: "unknown".to_string(),
         options: base,
-    }
+    })
 }
index d3ad0578aeb6e734b4c501799a0443c569732cc7..f38cdd4bec55f733be6955868e77949777bd0336 100644 (file)
@@ -8,15 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::freebsd_base::opts();
     base.cpu = "x86-64".to_string();
     base.max_atomic_width = 64;
     base.pre_link_args.push("-m64".to_string());
 
-    Target {
+    Ok(Target {
         llvm_target: "x86_64-unknown-freebsd".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
@@ -26,5 +26,5 @@ pub fn target() -> Target {
         target_env: "".to_string(),
         target_vendor: "unknown".to_string(),
         options: base,
-    }
+    })
 }
index 7908e0d581ba1aaa6bbc6ae596805390baf4a78d..ef81d397a8f1e9f9684721988a864261481c214d 100644 (file)
@@ -8,15 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::linux_base::opts();
     base.cpu = "x86-64".to_string();
     base.max_atomic_width = 64;
     base.pre_link_args.push("-m64".to_string());
 
-    Target {
+    Ok(Target {
         llvm_target: "x86_64-unknown-linux-gnu".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
@@ -26,5 +26,5 @@ pub fn target() -> Target {
         target_env: "gnu".to_string(),
         target_vendor: "unknown".to_string(),
         options: base,
-    }
+    })
 }
index 3301e0e0dc93f86d3b5ddd3b05752b1ae21ac0bd..4bad7754b3907d8b0ef51e108415c61267d2e64a 100644 (file)
@@ -8,15 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::linux_musl_base::opts();
     base.cpu = "x86-64".to_string();
     base.max_atomic_width = 64;
     base.pre_link_args.push("-m64".to_string());
 
-    Target {
+    Ok(Target {
         llvm_target: "x86_64-unknown-linux-musl".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
@@ -26,5 +26,5 @@ pub fn target() -> Target {
         target_env: "musl".to_string(),
         target_vendor: "unknown".to_string(),
         options: base,
-    }
+    })
 }
index 7e6d1b78469e27ccd3f37a1e85609f247cc360a0..5145e52d6b4c9800cace650860cbb5a39a1ddb34 100644 (file)
@@ -8,14 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::netbsd_base::opts();
     base.max_atomic_width = 64;
     base.pre_link_args.push("-m64".to_string());
 
-    Target {
+    Ok(Target {
         llvm_target: "x86_64-unknown-netbsd".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
@@ -25,5 +25,5 @@ pub fn target() -> Target {
         target_env: "".to_string(),
         target_vendor: "unknown".to_string(),
         options: base,
-    }
+    })
 }
index 823b0994b0a00d5cda917ceec7a79e97ac5a638a..339dbd591a02e21be8de7a9775260d37e1b63a09 100644 (file)
@@ -8,15 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::openbsd_base::opts();
     base.cpu = "x86-64".to_string();
     base.max_atomic_width = 64;
     base.pre_link_args.push("-m64".to_string());
 
-    Target {
+    Ok(Target {
         llvm_target: "x86_64-unknown-openbsd".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
@@ -26,5 +26,5 @@ pub fn target() -> Target {
         target_env: "".to_string(),
         target_vendor: "unknown".to_string(),
         options: base,
-    }
+    })
 }
index e86120b73bf97670bf59c2b7496ae76740bf4c2f..1fe47cd4853876ae544d568f32e65ac0481ffab2 100644 (file)
@@ -197,7 +197,7 @@ fn borrowck_fn(this: &mut BorrowckCtxt,
                              decl,
                              body);
 
-    intravisit::walk_fn(this, fk, decl, body, sp);
+    intravisit::walk_fn(this, fk, decl, body, sp, id);
 }
 
 fn build_borrowck_dataflow_data<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>,
index 915a0cf0bdc7301ecda143b9d51745a827453b37..d3952de2fbe30eb1088c6cbaf1df0515d5264419 100644 (file)
@@ -34,7 +34,7 @@
 
 use rustc::hir;
 use rustc::hir::{Pat, PatKind};
-use rustc::hir::intravisit::{self, IdVisitor, IdVisitingOperation, Visitor, FnKind};
+use rustc::hir::intravisit::{self, Visitor, FnKind};
 use rustc_back::slice;
 
 use syntax::ast::{self, DUMMY_NODE_ID, NodeId};
@@ -474,7 +474,7 @@ struct RenamingRecorder<'map> {
     renaming_map: &'map mut FnvHashMap<(NodeId, Span), NodeId>
 }
 
-impl<'map> IdVisitingOperation for RenamingRecorder<'map> {
+impl<'v, 'map> Visitor<'v> for RenamingRecorder<'map> {
     fn visit_id(&mut self, node_id: NodeId) {
         let key = (node_id, self.origin_span);
         self.renaming_map.insert(key, self.substituted_node_id);
@@ -529,9 +529,7 @@ fn record_renamings(const_expr: &hir::Expr,
                 renaming_map: renaming_map,
             };
 
-            let mut id_visitor = IdVisitor::new(&mut renaming_recorder);
-
-            id_visitor.visit_expr(const_expr);
+            renaming_recorder.visit_expr(const_expr);
         }
     }
 }
@@ -1049,7 +1047,7 @@ fn check_fn(cx: &mut MatchCheckCtxt,
         _ => cx.param_env = ParameterEnvironment::for_item(cx.tcx, fn_id),
     }
 
-    intravisit::walk_fn(cx, kind, decl, body, sp);
+    intravisit::walk_fn(cx, kind, decl, body, sp, fn_id);
 
     for input in &decl.inputs {
         check_irrefutable(cx, &input.pat, true);
index 0a8df923b846b90f2b4783a822fa7471f2497ef4..766e3883f2662ec33f07b4051bfebabc24a944cb 100644 (file)
@@ -95,6 +95,7 @@
 use rustc::session::early_error;
 
 use syntax::{ast, json};
+use syntax::attr::AttrMetaMethods;
 use syntax::codemap::{CodeMap, FileLoader, RealFileLoader};
 use syntax::feature_gate::{GatedCfg, UnstableFeatures};
 use syntax::parse::{self, PResult};
@@ -392,15 +393,12 @@ fn check_cfg(sopts: &config::Options,
 
     let mut saw_invalid_predicate = false;
     for item in sopts.cfg.iter() {
-        match item.node {
-            ast::MetaItemKind::List(ref pred, _) => {
-                saw_invalid_predicate = true;
-                handler.emit(&MultiSpan::new(),
-                             &format!("invalid predicate in --cfg command line argument: `{}`",
-                                      pred),
-                                errors::Level::Fatal);
-            }
-            _ => {},
+        if item.is_meta_item_list() {
+            saw_invalid_predicate = true;
+            handler.emit(&MultiSpan::new(),
+                         &format!("invalid predicate in --cfg command line argument: `{}`",
+                                  item.name()),
+                            errors::Level::Fatal);
         }
     }
 
@@ -609,7 +607,7 @@ fn print_crate_info(sess: &Session,
         for req in &sess.opts.prints {
             match *req {
                 PrintRequest::TargetList => {
-                    let mut targets = rustc_back::target::TARGETS.to_vec();
+                    let mut targets = rustc_back::target::get_targets().collect::<Vec<String>>();
                     targets.sort();
                     println!("{}", targets.join("\n"));
                 },
@@ -649,20 +647,17 @@ fn print_crate_info(sess: &Session,
                         if !allow_unstable_cfg && GatedCfg::gate(&*cfg).is_some() {
                             continue;
                         }
-                        match cfg.node {
-                            ast::MetaItemKind::Word(ref word) => println!("{}", word),
-                            ast::MetaItemKind::NameValue(ref name, ref value) => {
-                                println!("{}=\"{}\"", name, match value.node {
-                                    ast::LitKind::Str(ref s, _) => s,
-                                    _ => continue,
-                                });
+                        if cfg.is_word() {
+                            println!("{}", cfg.name());
+                        } else if cfg.is_value_str() {
+                            if let Some(s) = cfg.value_str() {
+                                println!("{}=\"{}\"", cfg.name(), s);
                             }
+                        } else if cfg.is_meta_item_list() {
                             // Right now there are not and should not be any
                             // MetaItemKind::List items in the configuration returned by
                             // `build_configuration`.
-                            ast::MetaItemKind::List(..) => {
-                                panic!("MetaItemKind::List encountered in default cfg")
-                            }
+                            panic!("MetaItemKind::List encountered in default cfg")
                         }
                     }
                 }
index d38f979e33c5ac154b5277ecb0bee115dc234cc4..774c5ca6d6b239a75b8a72ad583f23248e698280 100644 (file)
@@ -110,13 +110,11 @@ fn process_attrs(&mut self, node_id: ast::NodeId, def_id: DefId) {
             if attr.check_name(IF_THIS_CHANGED) {
                 let mut id = None;
                 for meta_item in attr.meta_item_list().unwrap_or_default() {
-                    match meta_item.node {
-                        ast::MetaItemKind::Word(ref s) if id.is_none() => id = Some(s.clone()),
-                        _ => {
-                            self.tcx.sess.span_err(
-                                meta_item.span,
-                                &format!("unexpected meta-item {:?}", meta_item.node));
-                        }
+                    if meta_item.is_word() && id.is_none() {
+                        id = Some(meta_item.name().clone());
+                    } else {
+                        // FIXME better-encapsulate meta_item (don't directly access `node`)
+                        span_bug!(meta_item.span(), "unexpected meta-item {:?}", meta_item.node)
                     }
                 }
                 let id = id.unwrap_or(InternedString::new(ID));
@@ -127,16 +125,13 @@ fn process_attrs(&mut self, node_id: ast::NodeId, def_id: DefId) {
                 let mut dep_node_interned = None;
                 let mut id = None;
                 for meta_item in attr.meta_item_list().unwrap_or_default() {
-                    match meta_item.node {
-                        ast::MetaItemKind::Word(ref s) if dep_node_interned.is_none() =>
-                            dep_node_interned = Some(s.clone()),
-                        ast::MetaItemKind::Word(ref s) if id.is_none() =>
-                            id = Some(s.clone()),
-                        _ => {
-                            self.tcx.sess.span_err(
-                                meta_item.span,
-                                &format!("unexpected meta-item {:?}", meta_item.node));
-                        }
+                    if meta_item.is_word() && dep_node_interned.is_none() {
+                        dep_node_interned = Some(meta_item.name().clone());
+                    } else if meta_item.is_word() && id.is_none() {
+                        id = Some(meta_item.name().clone());
+                    } else {
+                        // FIXME better-encapsulate meta_item (don't directly access `node`)
+                        span_bug!(meta_item.span(), "unexpected meta-item {:?}", meta_item.node)
                     }
                 }
                 let dep_node = match dep_node_interned {
index 7b1e0d2d0c8b676fb9e84832b13cab9981fef2f5..bea6b7e28344e01e08d60337d81c102d80228ef1 100644 (file)
@@ -11,6 +11,7 @@
 //! Calculation of a Strict Version Hash for crates.  For a length
 //! comment explaining the general idea, see `librustc/middle/svh.rs`.
 
+use syntax::attr::AttributeMethods;
 use std::hash::{Hash, SipHasher, Hasher};
 use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
 use rustc::hir::svh::Svh;
@@ -69,7 +70,7 @@ fn calculate_krate_hash(self) -> Svh {
         // to avoid hashing the AttrId
         for attr in &krate.attrs {
             debug!("krate attr {:?}", attr);
-            attr.node.value.hash(&mut state);
+            attr.meta().hash(&mut state);
         }
 
         Svh::new(state.finish())
@@ -384,9 +385,9 @@ fn visit_item(&mut self, i: &'a Item) {
             SawItem.hash(self.st); visit::walk_item(self, i)
         }
 
-        fn visit_mod(&mut self, m: &'a Mod, _s: Span, _n: NodeId) {
+        fn visit_mod(&mut self, m: &'a Mod, _s: Span, n: NodeId) {
             debug!("visit_mod: st={:?}", self.st);
-            SawMod.hash(self.st); visit::walk_mod(self, m)
+            SawMod.hash(self.st); visit::walk_mod(self, m, n)
         }
 
         fn visit_decl(&mut self, d: &'a Decl) {
@@ -405,9 +406,9 @@ fn visit_generics(&mut self, g: &'a Generics) {
         }
 
         fn visit_fn(&mut self, fk: FnKind<'a>, fd: &'a FnDecl,
-                    b: &'a Block, s: Span, _: NodeId) {
+                    b: &'a Block, s: Span, n: NodeId) {
             debug!("visit_fn: st={:?}", self.st);
-            SawFn.hash(self.st); visit::walk_fn(self, fk, fd, b, s)
+            SawFn.hash(self.st); visit::walk_fn(self, fk, fd, b, s, n)
         }
 
         fn visit_trait_item(&mut self, ti: &'a TraitItem) {
index 18f9733040e0f46b8e6f6449efb76e2efbe6f2ef..7547e28625c18eae079f660280d0950e971728c6 100644 (file)
@@ -44,7 +44,7 @@
 use std::collections::HashSet;
 
 use syntax::{ast};
-use syntax::attr::{self, AttrMetaMethods};
+use syntax::attr::{self, AttrMetaMethods, AttributeMethods};
 use syntax_pos::{self, Span};
 
 use rustc::hir::{self, PatKind};
@@ -298,12 +298,7 @@ fn check_missing_docs_attrs(&self,
             }
         }
 
-        let has_doc = attrs.iter().any(|a| {
-            match a.node.value.node {
-                ast::MetaItemKind::NameValue(ref name, _) if *name == "doc" => true,
-                _ => false
-            }
-        });
+        let has_doc = attrs.iter().any(|a| a.is_value_str() && a.name() == "doc");
         if !has_doc {
             cx.span_lint(MISSING_DOCS, sp,
                          &format!("missing documentation for {}", desc));
@@ -1094,10 +1089,10 @@ fn get_lints(&self) -> LintArray {
 
 impl LateLintPass for UnstableFeatures {
     fn check_attribute(&mut self, ctx: &LateContext, attr: &ast::Attribute) {
-        if attr::contains_name(&[attr.node.value.clone()], "feature") {
-            if let Some(items) = attr.node.value.meta_item_list() {
+        if attr::contains_name(&[attr.meta().clone()], "feature") {
+            if let Some(items) = attr.meta().meta_item_list() {
                 for item in items {
-                    ctx.span_lint(UNSTABLE_FEATURES, item.span, "unstable feature");
+                    ctx.span_lint(UNSTABLE_FEATURES, item.span(), "unstable feature");
                 }
             }
         }
index 05d20911a5dc3cd26495350b82ca8f5bf938287c..f97daa22ff6624c26487dfe8b9a5e1d1a1c43fb0 100644 (file)
@@ -17,4 +17,4 @@ rustc_bitflags = { path = "../librustc_bitflags" }
 
 [build-dependencies]
 build_helper = { path = "../build_helper" }
-gcc = "0.3"
+gcc = "0.3.27"
index 2e8c5a7c23418ba137017befcbd86b4a57613481..454c805ab577e233ea8659a112bbd572b3cdddd8 100644 (file)
@@ -18,7 +18,7 @@
 use rustc::hir;
 use rustc::hir::fold;
 use rustc::hir::fold::Folder;
-use rustc::hir::intravisit::{IdRange, IdRangeComputingVisitor, IdVisitingOperation};
+use rustc::hir::intravisit::{Visitor, IdRangeComputingVisitor, IdRange};
 
 use common as c;
 use cstore;
@@ -693,7 +693,7 @@ struct SideTableEncodingIdVisitor<'a, 'b:'a, 'c:'a, 'tcx:'c> {
     rbml_w: &'a mut Encoder<'b>,
 }
 
-impl<'a, 'b, 'c, 'tcx> IdVisitingOperation for
+impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for
         SideTableEncodingIdVisitor<'a, 'b, 'c, 'tcx> {
     fn visit_id(&mut self, id: ast::NodeId) {
         encode_side_tables_for_id(self.ecx, self.rbml_w, id)
@@ -704,7 +704,7 @@ fn encode_side_tables_for_ii(ecx: &e::EncodeContext,
                              rbml_w: &mut Encoder,
                              ii: &InlinedItem) {
     rbml_w.start_tag(c::tag_table as usize);
-    ii.visit_ids(&mut SideTableEncodingIdVisitor {
+    ii.visit(&mut SideTableEncodingIdVisitor {
         ecx: ecx,
         rbml_w: rbml_w
     });
@@ -1242,9 +1242,9 @@ fn copy_item_type(dcx: &DecodeContext,
     }
 }
 
-fn inlined_item_id_range(v: &InlinedItem) -> IdRange {
+fn inlined_item_id_range(ii: &InlinedItem) -> IdRange {
     let mut visitor = IdRangeComputingVisitor::new();
-    v.visit_ids(&mut visitor);
+    ii.visit(&mut visitor);
     visitor.result()
 }
 
index 409cec282bce93de82457834f12ad5e479c33d57..24e8b33f44c7539feaa1d60e77d135a0d0aabea6 100644 (file)
@@ -55,7 +55,6 @@
 use syntax::attr;
 use syntax::parse::token;
 use syntax::ast;
-use syntax::abi::Abi;
 use syntax::codemap;
 use syntax::print::pprust;
 use syntax::ptr::P;
@@ -1160,15 +1159,7 @@ fn get_attributes(md: rbml::Doc) -> Vec<ast::Attribute> {
                 // an attribute
                 assert_eq!(meta_items.len(), 1);
                 let meta_item = meta_items.into_iter().nth(0).unwrap();
-                codemap::Spanned {
-                    node: ast::Attribute_ {
-                        id: attr::mk_attr_id(),
-                        style: ast::AttrStyle::Outer,
-                        value: meta_item,
-                        is_sugared_doc: is_sugared_doc,
-                    },
-                    span: syntax_pos::DUMMY_SP
-                }
+                attr::mk_doc_attr_outer(attr::mk_attr_id(), meta_item, is_sugared_doc)
             }).collect()
         },
         None => vec![],
@@ -1542,13 +1533,9 @@ pub fn is_extern_item<'a, 'tcx>(cdata: Cmd,
     let applicable = match item_family(item_doc) {
         ImmStatic | MutStatic => true,
         Fn => {
-            let ty::TypeScheme { generics, ty } = get_type(cdata, id, tcx);
+            let ty::TypeScheme { generics, .. } = get_type(cdata, id, tcx);
             let no_generics = generics.types.is_empty();
-            match ty.sty {
-                ty::TyFnDef(_, _, fn_ty) | ty::TyFnPtr(fn_ty)
-                    if fn_ty.abi != Abi::Rust => return no_generics,
-                _ => no_generics,
-            }
+            no_generics
         },
         _ => false,
     };
index c896263de948ec295040a5e27b92c5a80fb3fd11..732c256a1910f18ca8e8b629d158d5476512f286 100644 (file)
@@ -44,7 +44,7 @@
 use std::u32;
 use syntax::abi::Abi;
 use syntax::ast::{self, NodeId, Name, CRATE_NODE_ID, CrateNum};
-use syntax::attr;
+use syntax::attr::{self,AttrMetaMethods,AttributeMethods};
 use errors::Handler;
 use syntax;
 use syntax_pos::BytePos;
@@ -1431,31 +1431,28 @@ fn encode_item_index(rbml_w: &mut Encoder, index: IndexData) {
 }
 
 fn encode_meta_item(rbml_w: &mut Encoder, mi: &ast::MetaItem) {
-    match mi.node {
-      ast::MetaItemKind::Word(ref name) => {
+    if mi.is_word() {
+        let name = mi.name();
         rbml_w.start_tag(tag_meta_item_word);
-        rbml_w.wr_tagged_str(tag_meta_item_name, name);
+        rbml_w.wr_tagged_str(tag_meta_item_name, &name);
         rbml_w.end_tag();
-      }
-      ast::MetaItemKind::NameValue(ref name, ref value) => {
-        match value.node {
-          ast::LitKind::Str(ref value, _) => {
-            rbml_w.start_tag(tag_meta_item_name_value);
-            rbml_w.wr_tagged_str(tag_meta_item_name, name);
-            rbml_w.wr_tagged_str(tag_meta_item_value, value);
-            rbml_w.end_tag();
-          }
-          _ => {/* FIXME (#623): encode other variants */ }
-        }
-      }
-      ast::MetaItemKind::List(ref name, ref items) => {
+    } else if mi.is_value_str() {
+        let name = mi.name();
+        /* FIXME (#623): support other literal kinds */
+        let value = mi.value_str().unwrap();
+        rbml_w.start_tag(tag_meta_item_name_value);
+        rbml_w.wr_tagged_str(tag_meta_item_name, &name);
+        rbml_w.wr_tagged_str(tag_meta_item_value, &value);
+        rbml_w.end_tag();
+    } else { // it must be a list
+        let name = mi.name();
+        let items = mi.meta_item_list().unwrap();
         rbml_w.start_tag(tag_meta_item_list);
-        rbml_w.wr_tagged_str(tag_meta_item_name, name);
+        rbml_w.wr_tagged_str(tag_meta_item_name, &name);
         for inner_item in items {
             encode_meta_item(rbml_w, &inner_item);
         }
         rbml_w.end_tag();
-      }
     }
 }
 
@@ -1464,7 +1461,7 @@ fn encode_attributes(rbml_w: &mut Encoder, attrs: &[ast::Attribute]) {
     for attr in attrs {
         rbml_w.start_tag(tag_attribute);
         rbml_w.wr_tagged_u8(tag_attribute_is_sugared_doc, attr.node.is_sugared_doc as u8);
-        encode_meta_item(rbml_w, &attr.node.value);
+        encode_meta_item(rbml_w, attr.meta());
         rbml_w.end_tag();
     }
     rbml_w.end_tag();
index 7dadf8d108a715f5e4dbf4c0b0e64499d5fc53d1..4be044c1df30720770e913e41b70d10328937a77 100644 (file)
@@ -60,10 +60,10 @@ fn load_crate(&mut self, extern_crate: &ast::Item, allows_macros: bool) -> Vec<a
                     }
                     if let (Some(sel), Some(names)) = (import.as_mut(), names) {
                         for attr in names {
-                            if let ast::MetaItemKind::Word(ref name) = attr.node {
-                                sel.insert(name.clone(), attr.span);
+                            if attr.is_word() {
+                                sel.insert(attr.name().clone(), attr.span());
                             } else {
-                                span_err!(self.sess, attr.span, E0466, "bad macro import");
+                                span_err!(self.sess, attr.span(), E0466, "bad macro import");
                             }
                         }
                     }
@@ -78,10 +78,10 @@ fn load_crate(&mut self, extern_crate: &ast::Item, allows_macros: bool) -> Vec<a
                     };
 
                     for attr in names {
-                        if let ast::MetaItemKind::Word(ref name) = attr.node {
-                            reexport.insert(name.clone(), attr.span);
+                        if attr.is_word() {
+                            reexport.insert(attr.name().clone(), attr.span());
                         } else {
-                            call_bad_macro_reexport(self.sess, attr.span);
+                            call_bad_macro_reexport(self.sess, attr.span());
                         }
                     }
                 }
index b7c5f35892b0b870c20df88a70913b5a9ca30e56..11d6b0779275ee40f6f6a56ae6728fdb9d0c687f 100644 (file)
@@ -250,7 +250,7 @@ fn visit_fn(&mut self,
             build::construct_fn(cx, id, arguments, fn_sig.output, body)
         });
 
-        intravisit::walk_fn(self, fk, decl, body, span);
+        intravisit::walk_fn(self, fk, decl, body, span, id);
     }
 }
 
index b0ba38f1db67322d33aa51dac8e0d5fd41f26492..1030a4b0116de5a07572ffa53fa974d909f4b6b7 100644 (file)
@@ -158,7 +158,7 @@ fn fn_like(&mut self,
 
         let qualif = self.with_mode(mode, |this| {
             this.with_euv(Some(fn_id), |euv| euv.walk_fn(fd, b));
-            intravisit::walk_fn(this, fk, fd, b, s);
+            intravisit::walk_fn(this, fk, fd, b, s, fn_id);
             this.qualif
         });
 
index 4684683f02501afe32eeb60b76cd2afbe0891827..2a5dc50cae92f4682044ffae57dc069e04ce409c 100644 (file)
@@ -49,7 +49,7 @@ fn visit_fn(&mut self,
             let mut euv = euv::ExprUseVisitor::new(&mut delegate, &infcx);
             euv.walk_fn(fd, b);
         });
-        intravisit::walk_fn(self, fk, fd, b, s)
+        intravisit::walk_fn(self, fk, fd, b, s, fn_id)
     }
 }
 
index acaf9b9b2faeed9d57b1b4da9a0cccd4b3b26238..793e52d37920354be1a9373fbdd672920c0eaba5 100644 (file)
@@ -291,7 +291,7 @@ fn visit_mod(&mut self, m: &hir::Mod, _sp: Span, id: ast::NodeId) {
             }
         }
 
-        intravisit::walk_mod(self, m);
+        intravisit::walk_mod(self, m, id);
     }
 
     fn visit_macro_def(&mut self, md: &'v hir::MacroDef) {
index 88cd29a3ccfa721b11e0dc0df3a1a988dbf09158..8c8cf1da467388cc98c3bec6d88c8cfda283e077 100644 (file)
@@ -825,8 +825,6 @@ enum NameBindingKind<'a> {
     Import {
         binding: &'a NameBinding<'a>,
         directive: &'a ImportDirective<'a>,
-        // Some(error) if using this imported name causes the import to be a privacy error
-        privacy_error: Option<Box<PrivacyError<'a>>>,
     },
 }
 
@@ -1206,16 +1204,11 @@ fn record_use(&mut self, name: Name, binding: &'a NameBinding<'a>) {
             self.used_crates.insert(krate);
         }
 
-        let (directive, privacy_error) = match binding.kind {
-            NameBindingKind::Import { directive, ref privacy_error, .. } =>
-                (directive, privacy_error),
+        let directive = match binding.kind {
+            NameBindingKind::Import { directive, .. } => directive,
             _ => return,
         };
 
-        if let Some(error) = privacy_error.as_ref() {
-            self.privacy_errors.push((**error).clone());
-        }
-
         if !self.make_glob_map {
             return;
         }
index 681d9ec735b4fd1f491cb6e5e508299be29ff2bd..fc5e2a48e876ccc2eaf5391dd85a4e399f7ec2ee 100644 (file)
@@ -73,13 +73,11 @@ pub struct ImportDirective<'a> {
 impl<'a> ImportDirective<'a> {
     // Given the binding to which this directive resolves in a particular namespace,
     // this returns the binding for the name this directive defines in that namespace.
-    fn import(&'a self, binding: &'a NameBinding<'a>, privacy_error: Option<Box<PrivacyError<'a>>>)
-              -> NameBinding<'a> {
+    fn import(&'a self, binding: &'a NameBinding<'a>) -> NameBinding<'a> {
         NameBinding {
             kind: NameBindingKind::Import {
                 binding: binding,
                 directive: self,
-                privacy_error: privacy_error,
             },
             span: self.span,
             vis: self.vis,
@@ -328,7 +326,7 @@ fn update_resolution<T, F>(&self, name: Name, ns: Namespace, update: F) -> T
     fn define_in_glob_importers(&self, name: Name, ns: Namespace, binding: &'a NameBinding<'a>) {
         if !binding.is_importable() || !binding.is_pseudo_public() { return }
         for &(importer, directive) in self.glob_importers.borrow_mut().iter() {
-            let _ = importer.try_define_child(name, ns, directive.import(binding, None));
+            let _ = importer.try_define_child(name, ns, directive.import(binding));
         }
     }
 }
@@ -409,7 +407,7 @@ fn import_dummy_binding(&self, source_module: Module<'b>, directive: &'b ImportD
                 span: DUMMY_SP,
                 vis: ty::Visibility::Public,
             });
-            let dummy_binding = directive.import(dummy_binding, None);
+            let dummy_binding = directive.import(dummy_binding);
 
             let _ = source_module.try_define_child(target, ValueNS, dummy_binding.clone());
             let _ = source_module.try_define_child(target, TypeNS, dummy_binding);
@@ -494,14 +492,17 @@ fn resolve_import(&mut self, directive: &'b ImportDirective<'b>) -> ResolveResul
             self.resolver.resolve_name_in_module(target_module, source, TypeNS, false, true);
 
         let module_ = self.resolver.current_module;
+        let mut privacy_error = true;
         for &(ns, result, determined) in &[(ValueNS, &value_result, value_determined),
                                            (TypeNS, &type_result, type_determined)] {
-            if determined.get() { continue }
-            if let Indeterminate = *result { continue }
-
-            determined.set(true);
-            if let Success(binding) = *result {
-                if !binding.is_importable() {
+            match *result {
+                Failed(..) if !determined.get() => {
+                    determined.set(true);
+                    module_.update_resolution(target, ns, |resolution| {
+                        resolution.single_imports.directive_failed()
+                    });
+                }
+                Success(binding) if !binding.is_importable() => {
                     let msg = format!("`{}` is not directly importable", target);
                     span_err!(self.resolver.session, directive.span, E0253, "{}", &msg);
                     // Do not import this illegal binding. Import a dummy binding and pretend
@@ -509,23 +510,19 @@ fn resolve_import(&mut self, directive: &'b ImportDirective<'b>) -> ResolveResul
                     self.import_dummy_binding(module_, directive);
                     return Success(());
                 }
-
-                let privacy_error = if !self.resolver.is_accessible(binding.vis) {
-                    Some(Box::new(PrivacyError(directive.span, source, binding)))
-                } else {
-                    None
-                };
-
-                let imported_binding = directive.import(binding, privacy_error);
-                let conflict = module_.try_define_child(target, ns, imported_binding);
-                if let Err(old_binding) = conflict {
-                    let binding = &directive.import(binding, None);
-                    self.resolver.report_conflict(module_, target, ns, binding, old_binding);
+                Success(binding) if !self.resolver.is_accessible(binding.vis) => {}
+                Success(binding) if !determined.get() => {
+                    determined.set(true);
+                    let imported_binding = directive.import(binding);
+                    let conflict = module_.try_define_child(target, ns, imported_binding);
+                    if let Err(old_binding) = conflict {
+                        let binding = &directive.import(binding);
+                        self.resolver.report_conflict(module_, target, ns, binding, old_binding);
+                    }
+                    privacy_error = false;
                 }
-            } else {
-                module_.update_resolution(target, ns, |resolution| {
-                    resolution.single_imports.directive_failed();
-                });
+                Success(_) => privacy_error = false,
+                _ => {}
             }
         }
 
@@ -556,6 +553,14 @@ fn resolve_import(&mut self, directive: &'b ImportDirective<'b>) -> ResolveResul
             _ => (),
         }
 
+        if privacy_error {
+            for &(ns, result) in &[(ValueNS, &value_result), (TypeNS, &type_result)] {
+                let binding = match *result { Success(binding) => binding, _ => continue };
+                self.resolver.privacy_errors.push(PrivacyError(directive.span, source, binding));
+                let _ = module_.try_define_child(target, ns, directive.import(binding));
+            }
+        }
+
         match (&value_result, &type_result) {
             (&Success(binding), _) if !binding.pseudo_vis()
                                               .is_at_least(directive.vis, self.resolver) &&
@@ -592,19 +597,6 @@ fn resolve_import(&mut self, directive: &'b ImportDirective<'b>) -> ResolveResul
             _ => {}
         }
 
-        // Report a privacy error here if all successful namespaces are privacy errors.
-        let mut privacy_error = None;
-        for &ns in &[ValueNS, TypeNS] {
-            privacy_error = match module_.resolve_name(target, ns, true) {
-                Success(&NameBinding {
-                    kind: NameBindingKind::Import { ref privacy_error, .. }, ..
-                }) => privacy_error.as_ref().map(|error| (**error).clone()),
-                _ => continue,
-            };
-            if privacy_error.is_none() { break }
-        }
-        privacy_error.map(|error| self.resolver.privacy_errors.push(error));
-
         // Record what this import resolves to for later uses in documentation,
         // this may resolve to either a value or a type, but for documentation
         // purposes it's good enough to just favor one over the other.
@@ -652,7 +644,7 @@ fn resolve_glob_import(&mut self, target_module: Module<'b>, directive: &'b Impo
         }).collect::<Vec<_>>();
         for ((name, ns), binding) in bindings {
             if binding.is_importable() && binding.is_pseudo_public() {
-                let _ = module_.try_define_child(name, ns, directive.import(binding, None));
+                let _ = module_.try_define_child(name, ns, directive.import(binding));
             }
         }
 
index 90443d9ec4f7067b0406ec02db37d4ab974e0f39..6b9de4a48786d4eddbff71ee5f3120b71d3ecac8 100644 (file)
@@ -181,6 +181,41 @@ fn get_or_create_closure_declaration<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     llfn
 }
 
+fn translating_closure_body_via_mir_will_fail(ccx: &CrateContext,
+                                              closure_def_id: DefId)
+                                              -> bool {
+    let default_to_mir = ccx.sess().opts.debugging_opts.orbit;
+    let invert = if default_to_mir { "rustc_no_mir" } else { "rustc_mir" };
+    let use_mir = default_to_mir ^ ccx.tcx().has_attr(closure_def_id, invert);
+
+    !use_mir
+}
+
+pub fn trans_closure_body_via_mir<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+                                            closure_def_id: DefId,
+                                            closure_substs: ty::ClosureSubsts<'tcx>) {
+    use syntax::ast::DUMMY_NODE_ID;
+    use syntax_pos::DUMMY_SP;
+    use syntax::ptr::P;
+
+    trans_closure_expr(Dest::Ignore(ccx),
+                       &hir::FnDecl {
+                           inputs: P::new(),
+                           output: hir::NoReturn(DUMMY_SP),
+                           variadic: false
+                       },
+                       &hir::Block {
+                           stmts: P::new(),
+                           expr: None,
+                           id: DUMMY_NODE_ID,
+                           rules: hir::DefaultBlock,
+                           span: DUMMY_SP
+                       },
+                       DUMMY_NODE_ID,
+                       closure_def_id,
+                       closure_substs);
+}
+
 pub enum Dest<'a, 'tcx: 'a> {
     SaveIn(Block<'a, 'tcx>, ValueRef),
     Ignore(&'a CrateContext<'a, 'tcx>)
@@ -213,8 +248,13 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
     // If we have not done so yet, translate this closure's body
     if  !ccx.instances().borrow().contains_key(&instance) {
         let llfn = get_or_create_closure_declaration(ccx, closure_def_id, closure_substs);
-        llvm::SetLinkage(llfn, llvm::WeakODRLinkage);
-        llvm::SetUniqueComdat(ccx.llmod(), llfn);
+
+        if ccx.sess().target.target.options.allows_weak_linkage {
+            llvm::SetLinkage(llfn, llvm::WeakODRLinkage);
+            llvm::SetUniqueComdat(ccx.llmod(), llfn);
+        } else {
+            llvm::SetLinkage(llfn, llvm::InternalLinkage);
+        }
 
         // set an inline hint for all closures
         attributes::inline(llfn, attributes::InlineAttr::Hint);
@@ -296,6 +336,39 @@ pub fn trans_closure_method<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>,
     // If this is a closure, redirect to it.
     let llfn = get_or_create_closure_declaration(ccx, closure_def_id, substs);
 
+    // If weak linkage is not allowed, we have to make sure that a local,
+    // private copy of the closure is available in this codegen unit
+    if !ccx.sess().target.target.options.allows_weak_linkage &&
+       !ccx.sess().opts.single_codegen_unit() {
+
+        if let Some(node_id) = ccx.tcx().map.as_local_node_id(closure_def_id) {
+            // If the closure is defined in the local crate, we can always just
+            // translate it.
+            let (decl, body) = match ccx.tcx().map.expect_expr(node_id).node {
+                hir::ExprClosure(_, ref decl, ref body, _) => (decl, body),
+                _ => { unreachable!() }
+            };
+
+            trans_closure_expr(Dest::Ignore(ccx),
+                               decl,
+                               body,
+                               node_id,
+                               closure_def_id,
+                               substs);
+        } else {
+            // If the closure is defined in an upstream crate, we can only
+            // translate it if MIR-trans is active.
+
+            if translating_closure_body_via_mir_will_fail(ccx, closure_def_id) {
+                ccx.sess().fatal("You have run into a known limitation of the \
+                                  MingW toolchain. Either compile with -Zorbit or \
+                                  with -Ccodegen-units=1 to work around it.");
+            }
+
+            trans_closure_body_via_mir(ccx, closure_def_id, substs);
+        }
+    }
+
     // If the closure is a Fn closure, but a FnOnce is needed (etc),
     // then adapt the self type
     let llfn_closure_kind = ccx.tcx().closure_kind(closure_def_id);
index e657a086581e2dadfff30deedc5c7a07288b6861..1e4a27481827dae8b84405efd1d4eb74696d0893 100644 (file)
@@ -19,7 +19,6 @@
 use rustc::ty::subst::FnSpace;
 use abi::{Abi, FnType};
 use adt;
-use attributes;
 use base::*;
 use build::*;
 use callee::{self, Callee};
@@ -37,7 +36,6 @@
 use type_::Type;
 use rustc::ty::{self, Ty};
 use Disr;
-use rustc::ty::subst::Substs;
 use rustc::hir;
 use syntax::ast;
 use syntax::ptr::P;
@@ -1173,7 +1171,6 @@ fn trans_gnu_try<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                              dloc: DebugLoc) -> Block<'blk, 'tcx> {
     let llfn = get_rust_try_fn(bcx.fcx, &mut |bcx| {
         let ccx = bcx.ccx();
-        let tcx = ccx.tcx();
         let dloc = DebugLoc::None;
 
         // Translates the shims described above:
@@ -1193,20 +1190,6 @@ fn trans_gnu_try<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         // expected to be `*mut *mut u8` for this to actually work, but that's
         // managed by the standard library.
 
-        attributes::emit_uwtable(bcx.fcx.llfn, true);
-        let target = &bcx.sess().target.target;
-        let catch_pers = if target.arch == "arm" && target.target_os != "ios" {
-            // Only ARM still uses a separate catch personality (for now)
-            match tcx.lang_items.eh_personality_catch() {
-                Some(did) => {
-                    Callee::def(ccx, did, tcx.mk_substs(Substs::empty())).reify(ccx).val
-                }
-                None => bug!("eh_personality_catch not defined"),
-            }
-        } else {
-            bcx.fcx.eh_personality()
-        };
-
         let then = bcx.fcx.new_temp_block("then");
         let catch = bcx.fcx.new_temp_block("catch");
 
@@ -1224,7 +1207,7 @@ fn trans_gnu_try<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         // rust_try ignores the selector.
         let lpad_ty = Type::struct_(ccx, &[Type::i8p(ccx), Type::i32(ccx)],
                                     false);
-        let vals = LandingPad(catch, lpad_ty, catch_pers, 1);
+        let vals = LandingPad(catch, lpad_ty, bcx.fcx.eh_personality(), 1);
         AddClause(catch, vals, C_null(Type::i8p(ccx)));
         let ptr = ExtractValue(catch, vals, 0);
         Store(catch, ptr, BitCast(catch, local_ptr, Type::i8p(ccx).ptr_to()));
index 1f3b13203163f7fbf6cbab2ea681e6fea84572f7..8dc5e5f993fbe5122deba33712eb99aed3bf52a6 100644 (file)
@@ -530,26 +530,10 @@ fn const_rvalue(&self, rvalue: &mir::Rvalue<'tcx>,
 
                 // FIXME Shouldn't need to manually trigger closure instantiations.
                 if let mir::AggregateKind::Closure(def_id, substs) = *kind {
-                    use rustc::hir;
-                    use syntax::ast::DUMMY_NODE_ID;
-                    use syntax::ptr::P;
                     use closure;
-
-                    closure::trans_closure_expr(closure::Dest::Ignore(self.ccx),
-                                                &hir::FnDecl {
-                                                    inputs: P::new(),
-                                                    output: hir::NoReturn(DUMMY_SP),
-                                                    variadic: false
-                                                },
-                                                &hir::Block {
-                                                    stmts: P::new(),
-                                                    expr: None,
-                                                    id: DUMMY_NODE_ID,
-                                                    rules: hir::DefaultBlock,
-                                                    span: DUMMY_SP
-                                                },
-                                                DUMMY_NODE_ID, def_id,
-                                                self.monomorphize(&substs));
+                    closure::trans_closure_body_via_mir(self.ccx,
+                                                        def_id,
+                                                        self.monomorphize(&substs));
                 }
 
                 let val = if let mir::AggregateKind::Adt(adt_def, index, _) = *kind {
index c3f2c4f2c8bfe5bf333550dbadc1ff6687690620..6ebc23884918976c19f4cfc1c220ed3ab3977a8f 100644 (file)
@@ -131,27 +131,11 @@ pub fn trans_rvalue(&mut self,
                     _ => {
                         // FIXME Shouldn't need to manually trigger closure instantiations.
                         if let mir::AggregateKind::Closure(def_id, substs) = *kind {
-                            use rustc::hir;
-                            use syntax::ast::DUMMY_NODE_ID;
-                            use syntax::ptr::P;
-                            use syntax_pos::DUMMY_SP;
                             use closure;
 
-                            closure::trans_closure_expr(closure::Dest::Ignore(bcx.ccx()),
-                                                        &hir::FnDecl {
-                                                            inputs: P::new(),
-                                                            output: hir::NoReturn(DUMMY_SP),
-                                                            variadic: false
-                                                        },
-                                                        &hir::Block {
-                                                            stmts: P::new(),
-                                                            expr: None,
-                                                            id: DUMMY_NODE_ID,
-                                                            rules: hir::DefaultBlock,
-                                                            span: DUMMY_SP
-                                                        },
-                                                        DUMMY_NODE_ID, def_id,
-                                                        bcx.monomorphize(&substs));
+                            closure::trans_closure_body_via_mir(bcx.ccx(),
+                                                                def_id,
+                                                                bcx.monomorphize(&substs));
                         }
 
                         for (i, operand) in operands.iter().enumerate() {
index 702dd5f8de58a3060cc3430206d119f6a7c09226..030491b521d95679e38b0f72cfdc975a7ba468ae 100644 (file)
 use middle::mem_categorization::Categorization;
 use rustc::ty::{self, Ty};
 use rustc::infer::UpvarRegion;
-use std::collections::HashSet;
 use syntax::ast;
 use syntax_pos::Span;
 use rustc::hir;
 use rustc::hir::intravisit::{self, Visitor};
+use rustc::util::nodemap::NodeMap;
 
 ///////////////////////////////////////////////////////////////////////////
 // PUBLIC ENTRY POINTS
@@ -60,9 +60,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     pub fn closure_analyze_fn(&self, body: &hir::Block) {
         let mut seed = SeedBorrowKind::new(self);
         seed.visit_block(body);
-        let closures_with_inferred_kinds = seed.closures_with_inferred_kinds;
 
-        let mut adjust = AdjustBorrowKind::new(self, &closures_with_inferred_kinds);
+        let mut adjust = AdjustBorrowKind::new(self, seed.temp_closure_kinds);
         adjust.visit_block(body);
 
         // it's our job to process these.
@@ -72,9 +71,8 @@ pub fn closure_analyze_fn(&self, body: &hir::Block) {
     pub fn closure_analyze_const(&self, body: &hir::Expr) {
         let mut seed = SeedBorrowKind::new(self);
         seed.visit_expr(body);
-        let closures_with_inferred_kinds = seed.closures_with_inferred_kinds;
 
-        let mut adjust = AdjustBorrowKind::new(self, &closures_with_inferred_kinds);
+        let mut adjust = AdjustBorrowKind::new(self, seed.temp_closure_kinds);
         adjust.visit_expr(body);
 
         // it's our job to process these.
@@ -87,7 +85,7 @@ pub fn closure_analyze_const(&self, body: &hir::Expr) {
 
 struct SeedBorrowKind<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
-    closures_with_inferred_kinds: HashSet<ast::NodeId>,
+    temp_closure_kinds: NodeMap<ty::ClosureKind>,
 }
 
 impl<'a, 'gcx, 'tcx, 'v> Visitor<'v> for SeedBorrowKind<'a, 'gcx, 'tcx> {
@@ -106,7 +104,7 @@ fn visit_expr(&mut self, expr: &hir::Expr) {
 
 impl<'a, 'gcx, 'tcx> SeedBorrowKind<'a, 'gcx, 'tcx> {
     fn new(fcx: &'a FnCtxt<'a, 'gcx, 'tcx>) -> SeedBorrowKind<'a, 'gcx, 'tcx> {
-        SeedBorrowKind { fcx: fcx, closures_with_inferred_kinds: HashSet::new() }
+        SeedBorrowKind { fcx: fcx, temp_closure_kinds: NodeMap() }
     }
 
     fn check_closure(&mut self,
@@ -116,11 +114,8 @@ fn check_closure(&mut self,
     {
         let closure_def_id = self.fcx.tcx.map.local_def_id(expr.id);
         if !self.fcx.tables.borrow().closure_kinds.contains_key(&closure_def_id) {
-            self.closures_with_inferred_kinds.insert(expr.id);
-            self.fcx.tables.borrow_mut().closure_kinds
-                                        .insert(closure_def_id, ty::ClosureKind::Fn);
-            debug!("check_closure: adding closure_id={:?} to closures_with_inferred_kinds",
-                   closure_def_id);
+            self.temp_closure_kinds.insert(expr.id, ty::ClosureKind::Fn);
+            debug!("check_closure: adding closure {:?} as Fn", expr.id);
         }
 
         self.fcx.tcx.with_freevars(expr.id, |freevars| {
@@ -154,14 +149,14 @@ fn check_closure(&mut self,
 
 struct AdjustBorrowKind<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
-    closures_with_inferred_kinds: &'a HashSet<ast::NodeId>,
+    temp_closure_kinds: NodeMap<ty::ClosureKind>,
 }
 
 impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
     fn new(fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
-           closures_with_inferred_kinds: &'a HashSet<ast::NodeId>)
+           temp_closure_kinds: NodeMap<ty::ClosureKind>)
            -> AdjustBorrowKind<'a, 'gcx, 'tcx> {
-        AdjustBorrowKind { fcx: fcx, closures_with_inferred_kinds: closures_with_inferred_kinds }
+        AdjustBorrowKind { fcx: fcx, temp_closure_kinds: temp_closure_kinds }
     }
 
     fn analyze_closure(&mut self,
@@ -176,7 +171,12 @@ fn analyze_closure(&mut self,
         debug!("analyze_closure(id={:?}, body.id={:?})", id, body.id);
 
         {
-            let mut euv = euv::ExprUseVisitor::new(self, self.fcx);
+            let mut euv =
+                euv::ExprUseVisitor::with_options(self,
+                                                  self.fcx,
+                                                  mc::MemCategorizationOptions {
+                                                      during_closure_kind_inference: true
+                                                  });
             euv.walk_fn(decl, body);
         }
 
@@ -211,10 +211,14 @@ fn analyze_closure(&mut self,
             self.fcx.demand_eqtype(span, final_upvar_ty, upvar_ty);
         }
 
-        // Now we must process and remove any deferred resolutions,
-        // since we have a concrete closure kind.
+        // If we are also inferred the closure kind here, update the
+        // main table and process any deferred resolutions.
         let closure_def_id = self.fcx.tcx.map.local_def_id(id);
-        if self.closures_with_inferred_kinds.contains(&id) {
+        if let Some(&kind) = self.temp_closure_kinds.get(&id) {
+            self.fcx.tables.borrow_mut().closure_kinds
+                                        .insert(closure_def_id, kind);
+            debug!("closure_kind({:?}) = {:?}", closure_def_id, kind);
+
             let mut deferred_call_resolutions =
                 self.fcx.remove_deferred_call_resolutions(closure_def_id);
             for deferred_call_resolution in &mut deferred_call_resolutions {
@@ -259,7 +263,7 @@ fn final_upvar_tys(&mut self, closure_id: ast::NodeId) -> Vec<Ty<'tcx>> {
             })
     }
 
-    fn adjust_upvar_borrow_kind_for_consume(&self,
+    fn adjust_upvar_borrow_kind_for_consume(&mut self,
                                             cmt: mc::cmt<'tcx>,
                                             mode: euv::ConsumeMode)
     {
@@ -350,7 +354,7 @@ fn adjust_upvar_borrow_kind_for_mut(&mut self, cmt: mc::cmt<'tcx>) {
         }
     }
 
-    fn adjust_upvar_borrow_kind_for_unique(&self, cmt: mc::cmt<'tcx>) {
+    fn adjust_upvar_borrow_kind_for_unique(&mut self, cmt: mc::cmt<'tcx>) {
         debug!("adjust_upvar_borrow_kind_for_unique(cmt={:?})",
                cmt);
 
@@ -381,7 +385,7 @@ fn adjust_upvar_borrow_kind_for_unique(&self, cmt: mc::cmt<'tcx>) {
         }
     }
 
-    fn try_adjust_upvar_deref(&self,
+    fn try_adjust_upvar_deref(&mut self,
                               note: &mc::Note,
                               borrow_kind: ty::BorrowKind)
                               -> bool
@@ -430,7 +434,7 @@ fn try_adjust_upvar_deref(&self,
     /// moving from left to right as needed (but never right to left).
     /// Here the argument `mutbl` is the borrow_kind that is required by
     /// some particular use.
-    fn adjust_upvar_borrow_kind(&self,
+    fn adjust_upvar_borrow_kind(&mut self,
                                 upvar_id: ty::UpvarId,
                                 upvar_capture: &mut ty::UpvarCapture,
                                 kind: ty::BorrowKind) {
@@ -460,36 +464,30 @@ fn adjust_upvar_borrow_kind(&self,
         }
     }
 
-    fn adjust_closure_kind(&self,
+    fn adjust_closure_kind(&mut self,
                            closure_id: ast::NodeId,
                            new_kind: ty::ClosureKind) {
         debug!("adjust_closure_kind(closure_id={}, new_kind={:?})",
                closure_id, new_kind);
 
-        if !self.closures_with_inferred_kinds.contains(&closure_id) {
-            return;
-        }
-
-        let closure_def_id = self.fcx.tcx.map.local_def_id(closure_id);
-        let closure_kinds = &mut self.fcx.tables.borrow_mut().closure_kinds;
-        let existing_kind = *closure_kinds.get(&closure_def_id).unwrap();
+        if let Some(&existing_kind) = self.temp_closure_kinds.get(&closure_id) {
+            debug!("adjust_closure_kind: closure_id={}, existing_kind={:?}, new_kind={:?}",
+                   closure_id, existing_kind, new_kind);
 
-        debug!("adjust_closure_kind: closure_id={}, existing_kind={:?}, new_kind={:?}",
-               closure_id, existing_kind, new_kind);
-
-        match (existing_kind, new_kind) {
-            (ty::ClosureKind::Fn, ty::ClosureKind::Fn) |
-            (ty::ClosureKind::FnMut, ty::ClosureKind::Fn) |
-            (ty::ClosureKind::FnMut, ty::ClosureKind::FnMut) |
-            (ty::ClosureKind::FnOnce, _) => {
-                // no change needed
-            }
+            match (existing_kind, new_kind) {
+                (ty::ClosureKind::Fn, ty::ClosureKind::Fn) |
+                (ty::ClosureKind::FnMut, ty::ClosureKind::Fn) |
+                (ty::ClosureKind::FnMut, ty::ClosureKind::FnMut) |
+                (ty::ClosureKind::FnOnce, _) => {
+                    // no change needed
+                }
 
-            (ty::ClosureKind::Fn, ty::ClosureKind::FnMut) |
-            (ty::ClosureKind::Fn, ty::ClosureKind::FnOnce) |
-            (ty::ClosureKind::FnMut, ty::ClosureKind::FnOnce) => {
-                // new kind is stronger than the old kind
-                closure_kinds.insert(closure_def_id, new_kind);
+                (ty::ClosureKind::Fn, ty::ClosureKind::FnMut) |
+                (ty::ClosureKind::Fn, ty::ClosureKind::FnOnce) |
+                (ty::ClosureKind::FnMut, ty::ClosureKind::FnOnce) => {
+                    // new kind is stronger than the old kind
+                    self.temp_closure_kinds.insert(closure_id, new_kind);
+                }
             }
         }
     }
@@ -503,7 +501,7 @@ fn visit_fn(&mut self,
                 span: Span,
                 id: ast::NodeId)
     {
-        intravisit::walk_fn(self, fn_kind, decl, body, span);
+        intravisit::walk_fn(self, fn_kind, decl, body, span, id);
         self.analyze_closure(id, span, decl, body);
     }
 }
index 907cb734c2ff9f00128641761e20eb9543b323fe..34a91b22981e15b298c5e8752f7710ecfe011c52 100644 (file)
@@ -454,6 +454,11 @@ fn check_variances_for_type_defn(&self,
                                      item: &hir::Item,
                                      ast_generics: &hir::Generics)
     {
+        let ty = self.tcx().node_id_to_type(item.id);
+        if self.tcx().has_error_field(ty) {
+            return;
+        }
+
         let item_def_id = self.tcx().map.local_def_id(item.id);
         let ty_predicates = self.tcx().lookup_predicates(item_def_id);
         let variances = self.tcx().item_variances(item_def_id);
index 57602b55cc96f10e5bb4110692cd481c361bdf95..ec95afe15bd518778b2556eec503c60fc8102973 100644 (file)
@@ -2237,9 +2237,9 @@ fn enforce_impl_params_are_constrained<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     // reachable from there, to start (if this is an inherent impl,
     // then just examine the self type).
     let mut input_parameters: HashSet<_> =
-        ctp::parameters_for_type(impl_scheme.ty, false).into_iter().collect();
+        ctp::parameters_for(&impl_scheme.ty, false).into_iter().collect();
     if let Some(ref trait_ref) = impl_trait_ref {
-        input_parameters.extend(ctp::parameters_for_trait_ref(trait_ref, false));
+        input_parameters.extend(ctp::parameters_for(trait_ref, false));
     }
 
     ctp::setup_constraining_predicates(impl_predicates.predicates.get_mut_slice(TypeSpace),
@@ -2267,9 +2267,9 @@ fn enforce_impl_lifetimes_are_constrained<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     let impl_trait_ref = ccx.tcx.impl_trait_ref(impl_def_id);
 
     let mut input_parameters: HashSet<_> =
-        ctp::parameters_for_type(impl_scheme.ty, false).into_iter().collect();
+        ctp::parameters_for(&impl_scheme.ty, false).into_iter().collect();
     if let Some(ref trait_ref) = impl_trait_ref {
-        input_parameters.extend(ctp::parameters_for_trait_ref(trait_ref, false));
+        input_parameters.extend(ctp::parameters_for(trait_ref, false));
     }
     ctp::identify_constrained_type_params(
         &impl_predicates.predicates.as_slice(), impl_trait_ref, &mut input_parameters);
@@ -2280,7 +2280,7 @@ fn enforce_impl_lifetimes_are_constrained<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
             ty::TypeTraitItem(ref assoc_ty) => assoc_ty.ty,
             ty::ConstTraitItem(..) | ty::MethodTraitItem(..) => None
         })
-        .flat_map(|ty| ctp::parameters_for_type(ty, true))
+        .flat_map(|ty| ctp::parameters_for(&ty, true))
         .filter_map(|p| match p {
             ctp::Parameter::Type(_) => None,
             ctp::Parameter::Region(r) => Some(r),
index 08c1b5fcc82c3dc9e72d7ec0f6d35e17f4dd2756..7909584bfabdf560b4c11ffe97b08f3133a2667d 100644 (file)
@@ -8,8 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use rustc::ty::{self, subst, Ty};
-
+use rustc::ty::{self, Ty};
+use rustc::ty::fold::{TypeFoldable, TypeVisitor};
 use std::collections::HashSet;
 
 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
@@ -19,77 +19,53 @@ pub enum Parameter {
 }
 
 /// If `include_projections` is false, returns the list of parameters that are
-/// constrained by the type `ty` - i.e. the value of each parameter in the list is
-/// uniquely determined by `ty` (see RFC 447). If it is true, return the list
+/// constrained by `t` - i.e. the value of each parameter in the list is
+/// uniquely determined by `t` (see RFC 447). If it is true, return the list
 /// of parameters whose values are needed in order to constrain `ty` - these
 /// differ, with the latter being a superset, in the presence of projections.
-pub fn parameters_for_type<'tcx>(ty: Ty<'tcx>,
-                                 include_projections: bool) -> Vec<Parameter> {
-    let mut result = vec![];
-    ty.maybe_walk(|t| match t.sty {
-        ty::TyProjection(..) if !include_projections => {
+pub fn parameters_for<'tcx, T>(t: &T,
+                               include_nonconstraining: bool)
+                               -> Vec<Parameter>
+    where T: TypeFoldable<'tcx>
+{
 
-            false // projections are not injective.
-        }
-        _ => {
-            result.append(&mut parameters_for_type_shallow(t));
-            // non-projection type constructors are injective.
-            true
-        }
-    });
-    result
+    let mut collector = ParameterCollector {
+        parameters: vec![],
+        include_nonconstraining: include_nonconstraining
+    };
+    t.visit_with(&mut collector);
+    collector.parameters
 }
 
-pub fn parameters_for_trait_ref<'tcx>(trait_ref: &ty::TraitRef<'tcx>,
-                                      include_projections: bool) -> Vec<Parameter> {
-    let mut region_parameters =
-        parameters_for_regions_in_substs(&trait_ref.substs);
-
-    let type_parameters =
-        trait_ref.substs
-                 .types
-                 .iter()
-                 .flat_map(|ty| parameters_for_type(ty, include_projections));
-
-    region_parameters.extend(type_parameters);
-
-    region_parameters
+struct ParameterCollector {
+    parameters: Vec<Parameter>,
+    include_nonconstraining: bool
 }
 
-fn parameters_for_type_shallow<'tcx>(ty: Ty<'tcx>) -> Vec<Parameter> {
-    match ty.sty {
-        ty::TyParam(ref d) =>
-            vec![Parameter::Type(d.clone())],
-        ty::TyRef(region, _) =>
-            parameters_for_region(region).into_iter().collect(),
-        ty::TyStruct(_, substs) |
-        ty::TyEnum(_, substs) =>
-            parameters_for_regions_in_substs(substs),
-        ty::TyTrait(ref data) =>
-            parameters_for_regions_in_substs(&data.principal.skip_binder().substs),
-        ty::TyProjection(ref pi) =>
-            parameters_for_regions_in_substs(&pi.trait_ref.substs),
-        ty::TyBool | ty::TyChar | ty::TyInt(..) | ty::TyUint(..) |
-        ty::TyFloat(..) | ty::TyBox(..) | ty::TyStr |
-        ty::TyArray(..) | ty::TySlice(..) |
-        ty::TyFnDef(..) | ty::TyFnPtr(_) |
-        ty::TyTuple(..) | ty::TyRawPtr(..) |
-        ty::TyInfer(..) | ty::TyClosure(..) | ty::TyError =>
-            vec![]
-    }
-}
+impl<'tcx> TypeVisitor<'tcx> for ParameterCollector {
+    fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
+        match t.sty {
+            ty::TyProjection(..) if !self.include_nonconstraining => {
+                // projections are not injective
+                return false;
+            }
+            ty::TyParam(ref d) => {
+                self.parameters.push(Parameter::Type(d.clone()));
+            }
+            _ => {}
+        }
 
-fn parameters_for_regions_in_substs(substs: &subst::Substs) -> Vec<Parameter> {
-    substs.regions
-          .iter()
-          .filter_map(|r| parameters_for_region(r))
-          .collect()
-}
+        t.super_visit_with(self)
+    }
 
-fn parameters_for_region(region: &ty::Region) -> Option<Parameter> {
-    match *region {
-        ty::ReEarlyBound(data) => Some(Parameter::Region(data)),
-        _ => None,
+    fn visit_region(&mut self, r: ty::Region) -> bool {
+        match r {
+            ty::ReEarlyBound(data) => {
+                self.parameters.push(Parameter::Region(data));
+            }
+            _ => {}
+        }
+        false
     }
 }
 
@@ -191,12 +167,12 @@ pub fn setup_constraining_predicates<'tcx>(predicates: &mut [ty::Predicate<'tcx>
                 // Then the projection only applies if `T` is known, but it still
                 // does not determine `U`.
 
-                let inputs = parameters_for_trait_ref(&projection.projection_ty.trait_ref, true);
+                let inputs = parameters_for(&projection.projection_ty.trait_ref, true);
                 let relies_only_on_inputs = inputs.iter().all(|p| input_parameters.contains(&p));
                 if !relies_only_on_inputs {
                     continue;
                 }
-                input_parameters.extend(parameters_for_type(projection.ty, false));
+                input_parameters.extend(parameters_for(&projection.ty, false));
             } else {
                 continue;
             }
index a41d3b0253a3668c794bb72e74fb02120de9c5d0..3e510bdc9002e2cbbc5b0089a1c53386a205d439 100644 (file)
@@ -28,4 +28,4 @@ log = { path = "../liblog" }
 
 [build-dependencies]
 build_helper = { path = "../build_helper" }
-gcc = "0.3"
+gcc = "0.3.27"
index 0211b2c9bc7ba5176c06cfd9d433bc0143264276..6883c22d67525e8cae4c5e28ad81b995caffe8fe 100644 (file)
@@ -498,21 +498,20 @@ pub enum Attribute {
 
 impl Clean<Attribute> for ast::MetaItem {
     fn clean(&self, cx: &DocContext) -> Attribute {
-        match self.node {
-            ast::MetaItemKind::Word(ref s) => Word(s.to_string()),
-            ast::MetaItemKind::List(ref s, ref l) => {
-                List(s.to_string(), l.clean(cx))
-            }
-            ast::MetaItemKind::NameValue(ref s, ref v) => {
-                NameValue(s.to_string(), lit_to_string(v))
-            }
-        }
+        if self.is_word() {
+            Word(self.name().to_string())
+        } else if let Some(v) = self.value_str() {
+            NameValue(self.name().to_string(), v.to_string())
+        } else { // must be a list
+            let l = self.meta_item_list().unwrap();
+            List(self.name().to_string(), l.clean(cx))
+       }
     }
 }
 
 impl Clean<Attribute> for ast::Attribute {
     fn clean(&self, cx: &DocContext) -> Attribute {
-        self.with_desugared_doc(|a| a.node.value.clean(cx))
+        self.with_desugared_doc(|a| a.meta().clean(cx))
     }
 }
 
@@ -535,6 +534,28 @@ fn value_str(&self) -> Option<InternedString> {
         }
     }
     fn meta_item_list<'a>(&'a self) -> Option<&'a [P<ast::MetaItem>]> { None }
+
+    fn is_word(&self) -> bool {
+      match *self {
+        Word(_) => true,
+        _ => false,
+      }
+    }
+
+    fn is_value_str(&self) -> bool {
+      match *self {
+        NameValue(..) => true,
+        _ => false,
+      }
+    }
+
+    fn is_meta_item_list(&self) -> bool {
+      match *self {
+        List(..) => true,
+        _ => false,
+      }
+    }
+
     fn span(&self) -> syntax_pos::Span { unimplemented!() }
 }
 
@@ -2568,26 +2589,6 @@ fn to_src(&self, cx: &DocContext) -> String {
     }
 }
 
-fn lit_to_string(lit: &ast::Lit) -> String {
-    match lit.node {
-        ast::LitKind::Str(ref st, _) => st.to_string(),
-        ast::LitKind::ByteStr(ref data) => format!("{:?}", data),
-        ast::LitKind::Byte(b) => {
-            let mut res = String::from("b'");
-            for c in (b as char).escape_default() {
-                res.push(c);
-            }
-            res.push('\'');
-            res
-        },
-        ast::LitKind::Char(c) => format!("'{}'", c),
-        ast::LitKind::Int(i, _t) => i.to_string(),
-        ast::LitKind::Float(ref f, _t) => f.to_string(),
-        ast::LitKind::FloatUnsuffixed(ref f) => f.to_string(),
-        ast::LitKind::Bool(b) => b.to_string(),
-    }
-}
-
 fn name_from_pat(p: &hir::Pat) -> String {
     use rustc::hir::*;
     debug!("Trying to get a name from pattern: {:?}", p);
index eded6e24f3ef5db2f6f0d2f06179c43b73f9ea8c..3ce6841fdd4c6a1d4d1448047e1b5848ee21f5df 100644 (file)
@@ -24,8 +24,9 @@ unwind = { path = "../libunwind" }
 
 [build-dependencies]
 build_helper = { path = "../build_helper" }
-gcc = "0.3"
+gcc = "0.3.27"
 
 [features]
+backtrace = []
 jemalloc = ["alloc_jemalloc"]
 debug-jemalloc = ["alloc_jemalloc/debug"]
index 9c408366f8b481d38e983d83f4bdcac9cdcfbbde..9018e48d06bd1a2da7b32bbad80b836643f00497 100644 (file)
@@ -25,7 +25,8 @@ fn main() {
 
     let target = env::var("TARGET").unwrap();
     let host = env::var("HOST").unwrap();
-    if !target.contains("apple") && !target.contains("msvc") && !target.contains("emscripten"){
+    if cfg!(feature = "backtrace") && !target.contains("apple") && !target.contains("msvc") &&
+        !target.contains("emscripten") {
         build_libbacktrace(&host, &target);
     }
 
index 48753ccf1c353cfe8ba172dbb347cf47c54f4f5e..38fd93501a528520f7b1ea951780f5209b966dba 100644 (file)
@@ -694,6 +694,23 @@ pub fn permissions(&self) -> Permissions {
     ///
     /// This field may not be available on all platforms, and will return an
     /// `Err` on platforms where it is not available.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # fn foo() -> std::io::Result<()> {
+    /// use std::fs;
+    ///
+    /// let metadata = try!(fs::metadata("foo.txt"));
+    ///
+    /// if let Ok(time) = metadata.modified() {
+    ///     println!("{:?}", time);
+    /// } else {
+    ///     println!("Not supported on this platform");
+    /// }
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "fs_time", since = "1.10.0")]
     pub fn modified(&self) -> io::Result<SystemTime> {
         self.0.modified().map(FromInner::from_inner)
@@ -712,6 +729,23 @@ pub fn modified(&self) -> io::Result<SystemTime> {
     ///
     /// This field may not be available on all platforms, and will return an
     /// `Err` on platforms where it is not available.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # fn foo() -> std::io::Result<()> {
+    /// use std::fs;
+    ///
+    /// let metadata = try!(fs::metadata("foo.txt"));
+    ///
+    /// if let Ok(time) = metadata.accessed() {
+    ///     println!("{:?}", time);
+    /// } else {
+    ///     println!("Not supported on this platform");
+    /// }
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "fs_time", since = "1.10.0")]
     pub fn accessed(&self) -> io::Result<SystemTime> {
         self.0.accessed().map(FromInner::from_inner)
@@ -726,6 +760,23 @@ pub fn accessed(&self) -> io::Result<SystemTime> {
     ///
     /// This field may not be available on all platforms, and will return an
     /// `Err` on platforms where it is not available.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # fn foo() -> std::io::Result<()> {
+    /// use std::fs;
+    ///
+    /// let metadata = try!(fs::metadata("foo.txt"));
+    ///
+    /// if let Ok(time) = metadata.created() {
+    ///     println!("{:?}", time);
+    /// } else {
+    ///     println!("Not supported on this platform");
+    /// }
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "fs_time", since = "1.10.0")]
     pub fn created(&self) -> io::Result<SystemTime> {
         self.0.created().map(FromInner::from_inner)
index d73e9542d21253e765958f4a1a1d51140a393dd5..57a4c3df70a476eeeb680233db6ab390a4c95490 100644 (file)
@@ -28,9 +28,7 @@
 use mem;
 use raw;
 use sys_common::rwlock::RWLock;
-use sync::atomic::{AtomicBool, Ordering};
 use sys::stdio::Stderr;
-use sys_common::backtrace;
 use sys_common::thread_info;
 use sys_common::util;
 use thread;
@@ -71,7 +69,6 @@ enum Hook {
 
 static HOOK_LOCK: RWLock = RWLock::new();
 static mut HOOK: Hook = Hook::Default;
-static FIRST_PANIC: AtomicBool = AtomicBool::new(true);
 
 /// Registers a custom panic hook, replacing any that was previously registered.
 ///
@@ -183,11 +180,17 @@ pub fn line(&self) -> u32 {
 }
 
 fn default_hook(info: &PanicInfo) {
-    let panics = PANIC_COUNT.with(|c| c.get());
+    #[cfg(any(not(cargobuild), feature = "backtrace"))]
+    use sys_common::backtrace;
 
     // If this is a double panic, make sure that we print a backtrace
     // for this panic. Otherwise only print it if logging is enabled.
-    let log_backtrace = panics >= 2 || backtrace::log_enabled();
+    #[cfg(any(not(cargobuild), feature = "backtrace"))]
+    let log_backtrace = {
+        let panics = PANIC_COUNT.with(|c| c.get());
+
+        panics >= 2 || backtrace::log_enabled()
+    };
 
     let file = info.location.file;
     let line = info.location.line;
@@ -207,10 +210,17 @@ fn default_hook(info: &PanicInfo) {
         let _ = writeln!(err, "thread '{}' panicked at '{}', {}:{}",
                          name, msg, file, line);
 
-        if log_backtrace {
-            let _ = backtrace::write(err);
-        } else if FIRST_PANIC.compare_and_swap(true, false, Ordering::SeqCst) {
-            let _ = writeln!(err, "note: Run with `RUST_BACKTRACE=1` for a backtrace.");
+        #[cfg(any(not(cargobuild), feature = "backtrace"))]
+        {
+            use sync::atomic::{AtomicBool, Ordering};
+
+            static FIRST_PANIC: AtomicBool = AtomicBool::new(true);
+
+            if log_backtrace {
+                let _ = backtrace::write(err);
+            } else if FIRST_PANIC.compare_and_swap(true, false, Ordering::SeqCst) {
+                let _ = writeln!(err, "note: Run with `RUST_BACKTRACE=1` for a backtrace.");
+            }
         }
     };
 
index c9279883ae59d8e2bb32c2a0d32bfee6c73b9800..a1f3f477b3ab7dfa4f64eadac9847bc8568d4f92 100644 (file)
@@ -28,6 +28,7 @@ macro_rules! rtassert {
 
 pub mod args;
 pub mod at_exit_imp;
+#[cfg(any(not(cargobuild), feature = "backtrace"))]
 pub mod backtrace;
 pub mod condvar;
 pub mod io;
@@ -42,6 +43,7 @@ macro_rules! rtassert {
 pub mod util;
 pub mod wtf8;
 
+#[cfg(any(not(cargobuild), feature = "backtrace"))]
 #[cfg(any(all(unix, not(any(target_os = "macos", target_os = "ios", target_os = "emscripten"))),
           all(windows, target_env = "gnu")))]
 pub mod gnu;
index 54340773a42b52e5bb672e41edde061cc487f769..77587918ac94b0e83d9edb6f912d3227c54f719c 100644 (file)
 pub trait PermissionsExt {
     /// Returns the underlying raw `mode_t` bits that are the standard Unix
     /// permissions for this file.
+    ///
+    /// # Examples
+    ///
+    /// ```rust,ignore
+    /// use std::fs::File;
+    /// use std::os::unix::fs::PermissionsExt;
+    ///
+    /// let f = try!(File::create("foo.txt"));
+    /// let metadata = try!(f.metadata());
+    /// let permissions = metadata.permissions();
+    ///
+    /// println!("permissions: {}", permissions.mode());
+    /// ```
     #[stable(feature = "fs_ext", since = "1.1.0")]
     fn mode(&self) -> u32;
 
     /// Sets the underlying raw bits for this set of permissions.
+    ///
+    /// # Examples
+    ///
+    /// ```rust,ignore
+    /// use std::fs::File;
+    /// use std::os::unix::fs::PermissionsExt;
+    ///
+    /// let f = try!(File::create("foo.txt"));
+    /// let metadata = try!(f.metadata());
+    /// let mut permissions = metadata.permissions();
+    ///
+    /// permissions.set_mode(0o644); // Read/write for owner and read for others.
+    /// assert_eq!(permissions.mode(), 0o644);
+    /// ```
     #[stable(feature = "fs_ext", since = "1.1.0")]
     fn set_mode(&mut self, mode: u32);
 
     /// Creates a new instance of `Permissions` from the given set of Unix
     /// permission bits.
+    ///
+    /// # Examples
+    ///
+    /// ```rust,ignore
+    /// use std::fs::Permissions;
+    /// use std::os::unix::fs::PermissionsExt;
+    ///
+    /// // Read/write for owner and read for others.
+    /// let permissions = Permissions::from_mode(0o644);
+    /// assert_eq!(permissions.mode(), 0o644);
+    /// ```
     #[stable(feature = "fs_ext", since = "1.1.0")]
     fn from_mode(mode: u32) -> Self;
 }
@@ -63,6 +101,18 @@ pub trait OpenOptionsExt {
     /// If no `mode` is set, the default of `0o666` will be used.
     /// The operating system masks out bits with the systems `umask`, to produce
     /// the final permissions.
+    ///
+    /// # Examples
+    ///
+    /// ```rust,ignore
+    /// extern crate libc;
+    /// use std::fs::OpenOptions;
+    /// use std::os::unix::fs::OpenOptionsExt;
+    ///
+    /// let mut options = OpenOptions::new();
+    /// options.mode(0o644); // Give read/write for owner and read for others.
+    /// let file = options.open("foo.txt");
+    /// ```
     #[stable(feature = "fs_ext", since = "1.1.0")]
     fn mode(&mut self, mode: u32) -> &mut Self;
 
index f0fd42fc99b806eadba0b261ddefe2ca61872980..1c25c8f77c196f444489178e37a471c67cdb3947 100644 (file)
@@ -30,6 +30,7 @@
 pub mod weak;
 
 pub mod android;
+#[cfg(any(not(cargobuild), feature = "backtrace"))]
 pub mod backtrace;
 pub mod condvar;
 pub mod ext;
index 67f73d4dd4f711e4798a42200002c5ddf50933a3..b622f6861b38379059ea23b23994b76792b9265c 100644 (file)
@@ -17,8 +17,8 @@
 use ast;
 use ast::{AttrId, Attribute, Attribute_, MetaItem, MetaItemKind};
 use ast::{Expr, Item, Local, Stmt, StmtKind};
-use codemap::{spanned, dummy_spanned, Spanned};
-use syntax_pos::{Span, BytePos};
+use codemap::{respan, spanned, dummy_spanned, Spanned};
+use syntax_pos::{Span, BytePos, DUMMY_SP};
 use errors::Handler;
 use feature_gate::{Features, GatedCfg};
 use parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration};
@@ -92,6 +92,19 @@ fn check_name(&self, name: &str) -> bool {
     /// Gets a list of inner meta items from a list MetaItem type.
     fn meta_item_list(&self) -> Option<&[P<MetaItem>]>;
 
+    /// Indicates if the attribute is a Word.
+    fn is_word(&self) -> bool;
+
+    /// Indicates if the attribute is a Value String.
+    fn is_value_str(&self) -> bool {
+        self.value_str().is_some()
+    }
+
+    /// Indicates if the attribute is a Meta-Item List.
+    fn is_meta_item_list(&self) -> bool {
+        self.meta_item_list().is_some()
+    }
+
     fn span(&self) -> Span;
 }
 
@@ -108,8 +121,11 @@ fn value_str(&self) -> Option<InternedString> {
         self.meta().value_str()
     }
     fn meta_item_list(&self) -> Option<&[P<MetaItem>]> {
-        self.node.value.meta_item_list()
+        self.meta().meta_item_list()
     }
+
+    fn is_word(&self) -> bool { self.meta().is_word() }
+
     fn span(&self) -> Span { self.meta().span }
 }
 
@@ -140,6 +156,14 @@ fn meta_item_list(&self) -> Option<&[P<MetaItem>]> {
             _ => None
         }
     }
+
+    fn is_word(&self) -> bool {
+        match self.node {
+            MetaItemKind::Word(_) => true,
+            _ => false,
+        }
+    }
+
     fn span(&self) -> Span { self.span }
 }
 
@@ -150,6 +174,9 @@ fn value_str(&self) -> Option<InternedString> { (**self).value_str() }
     fn meta_item_list(&self) -> Option<&[P<MetaItem>]> {
         (**self).meta_item_list()
     }
+    fn is_word(&self) -> bool { (**self).is_word() }
+    fn is_value_str(&self) -> bool { (**self).is_value_str() }
+    fn is_meta_item_list(&self) -> bool { (**self).is_meta_item_list() }
     fn span(&self) -> Span { (**self).span() }
 }
 
@@ -194,22 +221,38 @@ fn with_desugared_doc<T, F>(&self, f: F) -> T where
 pub fn mk_name_value_item_str(name: InternedString, value: InternedString)
                               -> P<MetaItem> {
     let value_lit = dummy_spanned(ast::LitKind::Str(value, ast::StrStyle::Cooked));
-    mk_name_value_item(name, value_lit)
+    mk_spanned_name_value_item(DUMMY_SP, name, value_lit)
 }
 
 pub fn mk_name_value_item(name: InternedString, value: ast::Lit)
                           -> P<MetaItem> {
-    P(dummy_spanned(MetaItemKind::NameValue(name, value)))
+    mk_spanned_name_value_item(DUMMY_SP, name, value)
 }
 
 pub fn mk_list_item(name: InternedString, items: Vec<P<MetaItem>>) -> P<MetaItem> {
-    P(dummy_spanned(MetaItemKind::List(name, items)))
+    mk_spanned_list_item(DUMMY_SP, name, items)
 }
 
 pub fn mk_word_item(name: InternedString) -> P<MetaItem> {
-    P(dummy_spanned(MetaItemKind::Word(name)))
+    mk_spanned_word_item(DUMMY_SP, name)
+}
+
+pub fn mk_spanned_name_value_item(sp: Span, name: InternedString, value: ast::Lit)
+                          -> P<MetaItem> {
+    P(respan(sp, MetaItemKind::NameValue(name, value)))
+}
+
+pub fn mk_spanned_list_item(sp: Span, name: InternedString, items: Vec<P<MetaItem>>)
+                            -> P<MetaItem> {
+    P(respan(sp, MetaItemKind::List(name, items)))
+}
+
+pub fn mk_spanned_word_item(sp: Span, name: InternedString) -> P<MetaItem> {
+    P(respan(sp, MetaItemKind::Word(name)))
 }
 
+
+
 thread_local! { static NEXT_ATTR_ID: Cell<usize> = Cell::new(0) }
 
 pub fn mk_attr_id() -> AttrId {
@@ -223,21 +266,43 @@ pub fn mk_attr_id() -> AttrId {
 
 /// Returns an inner attribute with the given value.
 pub fn mk_attr_inner(id: AttrId, item: P<MetaItem>) -> Attribute {
-    dummy_spanned(Attribute_ {
-        id: id,
-        style: ast::AttrStyle::Inner,
-        value: item,
-        is_sugared_doc: false,
-    })
+    mk_spanned_attr_inner(DUMMY_SP, id, item)
+}
+
+/// Returns an innter attribute with the given value and span.
+pub fn mk_spanned_attr_inner(sp: Span, id: AttrId, item: P<MetaItem>) -> Attribute {
+    respan(sp,
+           Attribute_ {
+            id: id,
+            style: ast::AttrStyle::Inner,
+            value: item,
+            is_sugared_doc: false,
+          })
 }
 
+
 /// Returns an outer attribute with the given value.
 pub fn mk_attr_outer(id: AttrId, item: P<MetaItem>) -> Attribute {
+    mk_spanned_attr_outer(DUMMY_SP, id, item)
+}
+
+/// Returns an outer attribute with the given value and span.
+pub fn mk_spanned_attr_outer(sp: Span, id: AttrId, item: P<MetaItem>) -> Attribute {
+    respan(sp,
+           Attribute_ {
+            id: id,
+            style: ast::AttrStyle::Outer,
+            value: item,
+            is_sugared_doc: false,
+          })
+}
+
+pub fn mk_doc_attr_outer(id: AttrId, item: P<MetaItem>, is_sugared_doc: bool) -> Attribute {
     dummy_spanned(Attribute_ {
         id: id,
         style: ast::AttrStyle::Outer,
         value: item,
-        is_sugared_doc: false,
+        is_sugared_doc: is_sugared_doc,
     })
 }
 
index 435241f426ec6f4329e90a2dc6dea8c093e3e723..5d6429f7bdfffa1bac2326fd821c5d664832b00a 100644 (file)
@@ -1135,30 +1135,19 @@ fn item_ty(&self, span: Span, name: Ident, ty: P<ast::Ty>) -> P<ast::Item> {
     }
 
     fn attribute(&self, sp: Span, mi: P<ast::MetaItem>) -> ast::Attribute {
-        respan(sp, ast::Attribute_ {
-            id: attr::mk_attr_id(),
-            style: ast::AttrStyle::Outer,
-            value: mi,
-            is_sugared_doc: false,
-        })
+        attr::mk_spanned_attr_outer(sp, attr::mk_attr_id(), mi)
     }
 
     fn meta_word(&self, sp: Span, w: InternedString) -> P<ast::MetaItem> {
-        P(respan(sp, ast::MetaItemKind::Word(w)))
+        attr::mk_spanned_word_item(sp, w)
     }
-    fn meta_list(&self,
-                 sp: Span,
-                 name: InternedString,
-                 mis: Vec<P<ast::MetaItem>> )
+    fn meta_list(&self, sp: Span, name: InternedString, mis: Vec<P<ast::MetaItem>>)
                  -> P<ast::MetaItem> {
-        P(respan(sp, ast::MetaItemKind::List(name, mis)))
+        attr::mk_spanned_list_item(sp, name, mis)
     }
-    fn meta_name_value(&self,
-                       sp: Span,
-                       name: InternedString,
-                       value: ast::LitKind)
+    fn meta_name_value(&self, sp: Span, name: InternedString, value: ast::LitKind)
                        -> P<ast::MetaItem> {
-        P(respan(sp, ast::MetaItemKind::NameValue(name, respan(sp, value))))
+        attr::mk_spanned_name_value_item(sp, name, respan(sp, value))
     }
 
     fn item_use(&self, sp: Span,
index 18342f2e38c1be8c51be9d662fed96c24ef83e7a..5293d2ab0001a5309587f1115481f6ceb1aeeb9a 100644 (file)
@@ -302,9 +302,8 @@ fn contains_macro_use(fld: &mut MacroExpander, attrs: &[ast::Attribute]) -> bool
         };
 
         if is_use {
-            match attr.node.value.node {
-                ast::MetaItemKind::Word(..) => (),
-                _ => fld.cx.span_err(attr.span, "arguments to macro_use are not allowed here"),
+            if !attr.is_word() {
+              fld.cx.span_err(attr.span, "arguments to macro_use are not allowed here");
             }
             return true;
         }
index f80f25a2e776d7c1521233542715417c33ed004b..29da0fb1a2735aa14c4ac71633ac9be97f9b9ebb 100644 (file)
@@ -810,6 +810,29 @@ macro_rules! gate_feature_post {
     }}
 }
 
+impl<'a> PostExpansionVisitor<'a> {
+    fn check_abi(&self, abi: Abi, span: Span) {
+        match abi {
+            Abi::RustIntrinsic =>
+                gate_feature_post!(&self, intrinsics, span,
+                                   "intrinsics are subject to change"),
+            Abi::PlatformIntrinsic => {
+                gate_feature_post!(&self, platform_intrinsics, span,
+                                   "platform intrinsics are experimental and possibly buggy")
+            },
+            Abi::Vectorcall => {
+                gate_feature_post!(&self, abi_vectorcall, span,
+                                   "vectorcall is experimental and subject to change")
+            }
+            Abi::RustCall => {
+                gate_feature_post!(&self, unboxed_closures, span,
+                                   "rust-call ABI is subject to change");
+            }
+            _ => {}
+        }
+    }
+}
+
 impl<'a> Visitor for PostExpansionVisitor<'a> {
     fn visit_attribute(&mut self, attr: &ast::Attribute) {
         if !self.context.cm.span_allows_unstable(attr.span) {
@@ -841,21 +864,7 @@ fn visit_item(&mut self, i: &ast::Item) {
                                        across platforms, it is recommended to \
                                        use `#[link(name = \"foo\")]` instead")
                 }
-                match foreign_module.abi {
-                    Abi::RustIntrinsic =>
-                        gate_feature_post!(&self, intrinsics, i.span,
-                                           "intrinsics are subject to change"),
-                    Abi::PlatformIntrinsic => {
-                        gate_feature_post!(&self, platform_intrinsics, i.span,
-                                           "platform intrinsics are experimental \
-                                            and possibly buggy")
-                    },
-                    Abi::Vectorcall => {
-                        gate_feature_post!(&self, abi_vectorcall, i.span,
-                                           "vectorcall is experimental and subject to change")
-                    }
-                    _ => ()
-                }
+                self.check_abi(foreign_module.abi, i.span);
             }
 
             ast::ItemKind::Fn(..) => {
@@ -938,6 +947,16 @@ fn visit_foreign_item(&mut self, i: &ast::ForeignItem) {
         visit::walk_foreign_item(self, i)
     }
 
+    fn visit_ty(&mut self, ty: &ast::Ty) {
+        match ty.node {
+            ast::TyKind::BareFn(ref bare_fn_ty) => {
+                self.check_abi(bare_fn_ty.abi, ty.span);
+            }
+            _ => {}
+        }
+        visit::walk_ty(self, ty)
+    }
+
     fn visit_expr(&mut self, e: &ast::Expr) {
         match e.node {
             ast::ExprKind::Box(_) => {
@@ -1025,23 +1044,10 @@ fn visit_fn(&mut self,
         }
 
         match fn_kind {
-            FnKind::ItemFn(_, _, _, _, abi, _) if abi == Abi::RustIntrinsic => {
-                gate_feature_post!(&self, intrinsics,
-                                  span,
-                                  "intrinsics are subject to change")
-            }
             FnKind::ItemFn(_, _, _, _, abi, _) |
-            FnKind::Method(_, &ast::MethodSig { abi, .. }, _) => match abi {
-                Abi::RustCall => {
-                    gate_feature_post!(&self, unboxed_closures, span,
-                        "rust-call ABI is subject to change");
-                },
-                Abi::Vectorcall => {
-                    gate_feature_post!(&self, abi_vectorcall, span,
-                        "vectorcall is experimental and subject to change");
-                },
-                _ => {}
-            },
+            FnKind::Method(_, &ast::MethodSig { abi, .. }, _) => {
+                self.check_abi(abi, span);
+            }
             _ => {}
         }
         visit::walk_fn(self, fn_kind, fn_decl, block, span);
@@ -1054,7 +1060,10 @@ fn visit_trait_item(&mut self, ti: &ast::TraitItem) {
                                   ti.span,
                                   "associated constants are experimental")
             }
-            ast::TraitItemKind::Method(ref sig, _) => {
+            ast::TraitItemKind::Method(ref sig, ref block) => {
+                if block.is_none() {
+                    self.check_abi(sig.abi, ti.span);
+                }
                 if sig.constness == ast::Constness::Const {
                     gate_feature_post!(&self, const_fn, ti.span, "const fn is unstable");
                 }
@@ -1118,14 +1127,13 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute]) -> F
             }
             Some(list) => {
                 for mi in list {
-                    let name = match mi.node {
-                        ast::MetaItemKind::Word(ref word) => (*word).clone(),
-                        _ => {
-                            span_err!(span_handler, mi.span, E0556,
-                                      "malformed feature, expected just one word");
-                            continue
-                        }
-                    };
+                    let name = if mi.is_word() {
+                                   mi.name()
+                               } else {
+                                   span_err!(span_handler, mi.span, E0556,
+                                             "malformed feature, expected just one word");
+                                   continue
+                               };
                     if let Some(&(_, _, _, setter)) = ACTIVE_FEATURES.iter()
                         .find(|& &(n, _, _, _)| name == n) {
                         *(setter(&mut features)) = true;
index 80e2a923e5569ef9693f5efd9742c17e46e1198c..e09a64e73449b1e371ad0c94b2746f26440f46af 100644 (file)
@@ -10,7 +10,7 @@
 
 //! The compiler code necessary to implement the `#[derive]` extensions.
 
-use syntax::ast::{self, MetaItem, MetaItemKind};
+use syntax::ast::{MetaItem, self};
 use syntax::attr::AttrMetaMethods;
 use syntax::ext::base::{Annotatable, ExtCtxt, SyntaxEnv};
 use syntax::ext::base::{MultiDecorator, MultiItemDecorator, MultiModifier};
@@ -98,15 +98,14 @@ fn expand_derive(cx: &mut ExtCtxt,
             let mut eq_span = None;
 
             for titem in traits.iter().rev() {
-                let tname = match titem.node {
-                    MetaItemKind::Word(ref tname) => tname,
-                    _ => {
-                        cx.span_err(titem.span, "malformed `derive` entry");
-                        continue;
-                    }
-                };
-
-                if !(is_builtin_trait(tname) || cx.ecfg.enable_custom_derive()) {
+                let tname = if titem.is_word() {
+                                titem.name() }
+                            else {
+                                cx.span_err(titem.span, "malformed `derive` entry");
+                                continue;
+                            };
+
+                if !(is_builtin_trait(&tname) || cx.ecfg.enable_custom_derive()) {
                     feature_gate::emit_feature_err(&cx.parse_sess.span_diagnostic,
                                                    "custom_derive",
                                                    titem.span,
index 94bb78edaacdb617110784fc50dad9c8c8c0ac6b..1f6f57c70f72f09dd6186c8eb49449aafdd5fe99 100644 (file)
@@ -406,7 +406,9 @@ fn trans_piece(&mut self,
                             let arg_idx = match arg_index_consumed.get_mut(i) {
                                 None => 0, // error already emitted elsewhere
                                 Some(offset) => {
-                                    let arg_idx = self.arg_index_map[i][*offset];
+                                    let ref idx_map = self.arg_index_map[i];
+                                    // unwrap_or branch: error already emitted elsewhere
+                                    let arg_idx = *idx_map.get(*offset).unwrap_or(&0);
                                     *offset += 1;
                                     arg_idx
                                 }
index c96be8fec2b02abb4ffffecddaa0884187641303..0f171805bb0a988fb95853932fa3619b46b37627 100644 (file)
@@ -193,6 +193,20 @@ pub fn new() -> MultiSpan {
         }
     }
 
+    pub fn from_span(primary_span: Span) -> MultiSpan {
+        MultiSpan {
+            primary_spans: vec![primary_span],
+            span_labels: vec![]
+        }
+    }
+
+    pub fn from_spans(vec: Vec<Span>) -> MultiSpan {
+        MultiSpan {
+            primary_spans: vec,
+            span_labels: vec![]
+        }
+    }
+
     pub fn push_span_label(&mut self, span: Span, label: String) {
         self.span_labels.push((span, label));
     }
@@ -240,10 +254,7 @@ pub fn span_labels(&self) -> Vec<SpanLabel> {
 
 impl From<Span> for MultiSpan {
     fn from(span: Span) -> MultiSpan {
-        MultiSpan {
-            primary_spans: vec![span],
-            span_labels: vec![]
-        }
+        MultiSpan::from_span(span)
     }
 }
 
@@ -254,6 +265,10 @@ fn from(span: Span) -> MultiSpan {
 // For code appearing from the command line
 pub const COMMAND_LINE_EXPN: ExpnId = ExpnId(!1);
 
+// For code generated by a procedural macro, without knowing which
+// Used in `qquote!`
+pub const PROC_EXPN: ExpnId = ExpnId(!2);
+
 impl ExpnId {
     pub fn from_u32(id: u32) -> ExpnId {
         ExpnId(id)
index ebe6fd54799ee47f4245b8cf6a6749a8615da27e..fd446f5a4f9428ff852097c4ecd25882bdb1b6ef 100644 (file)
@@ -16,7 +16,7 @@ fn main() {
     let target = env::var("TARGET").unwrap();
 
     if target.contains("linux") {
-        if target.contains("musl") && (target.contains("x86_64") || target.contains("i686")) {
+        if target.contains("musl") && !target.contains("mips") {
             println!("cargo:rustc-link-lib=static=unwind");
         } else if !target.contains("android") {
             println!("cargo:rustc-link-lib=gcc_s");
index d9b6c9ed74dd21b4fec9ec88ebbce37b27990ea3..5e242db0a888db8c1dbd41c6aafb58ef9d27c196 100644 (file)
 
 #![allow(bad_style)]
 
-use libc;
-
-#[cfg(any(not(target_arch = "arm"), target_os = "ios"))]
-pub use self::_Unwind_Action::*;
-#[cfg(target_arch = "arm")]
-pub use self::_Unwind_State::*;
-pub use self::_Unwind_Reason_Code::*;
-
-#[cfg(any(not(target_arch = "arm"), target_os = "ios"))]
-#[repr(C)]
-#[derive(Clone, Copy)]
-pub enum _Unwind_Action {
-    _UA_SEARCH_PHASE = 1,
-    _UA_CLEANUP_PHASE = 2,
-    _UA_HANDLER_FRAME = 4,
-    _UA_FORCE_UNWIND = 8,
-    _UA_END_OF_STACK = 16,
+macro_rules! cfg_if {
+    ( $( if #[cfg( $meta:meta )] { $($it1:item)* } else { $($it2:item)* } )* ) =>
+        ( $( $( #[cfg($meta)] $it1)* $( #[cfg(not($meta))] $it2)* )* )
 }
 
-#[cfg(target_arch = "arm")]
-#[repr(C)]
-#[derive(Clone, Copy)]
-pub enum _Unwind_State {
-    _US_VIRTUAL_UNWIND_FRAME = 0,
-    _US_UNWIND_FRAME_STARTING = 1,
-    _US_UNWIND_FRAME_RESUME = 2,
-    _US_ACTION_MASK = 3,
-    _US_FORCE_UNWIND = 8,
-    _US_END_OF_STACK = 16,
-}
+use libc::{c_int, c_void, uintptr_t};
 
 #[repr(C)]
+#[derive(Copy, Clone, PartialEq)]
 pub enum _Unwind_Reason_Code {
     _URC_NO_REASON = 0,
     _URC_FOREIGN_EXCEPTION_CAUGHT = 1,
@@ -52,17 +29,15 @@ pub enum _Unwind_Reason_Code {
     _URC_HANDLER_FOUND = 6,
     _URC_INSTALL_CONTEXT = 7,
     _URC_CONTINUE_UNWIND = 8,
-    _URC_FAILURE = 9, // used only by ARM EABI
+    _URC_FAILURE = 9, // used only by ARM EHABI
 }
+pub use self::_Unwind_Reason_Code::*;
 
 pub type _Unwind_Exception_Class = u64;
-
-pub type _Unwind_Word = libc::uintptr_t;
-pub type _Unwind_Ptr = libc::uintptr_t;
-
-pub type _Unwind_Trace_Fn = extern "C" fn(ctx: *mut _Unwind_Context, arg: *mut libc::c_void)
+pub type _Unwind_Word = uintptr_t;
+pub type _Unwind_Ptr = uintptr_t;
+pub type _Unwind_Trace_Fn = extern "C" fn(ctx: *mut _Unwind_Context, arg: *mut c_void)
                                           -> _Unwind_Reason_Code;
-
 #[cfg(target_arch = "x86")]
 pub const unwinder_private_data_size: usize = 5;
 
@@ -99,91 +74,55 @@ pub enum _Unwind_Context {}
 
 pub type _Unwind_Exception_Cleanup_Fn = extern "C" fn(unwind_code: _Unwind_Reason_Code,
                                                       exception: *mut _Unwind_Exception);
-
-#[cfg_attr(any(all(target_os = "linux", not(target_env = "musl")),
-               target_os = "freebsd",
-               target_os = "solaris",
-               all(target_os = "linux",
-                   target_env = "musl",
-                   not(target_arch = "x86"),
-                   not(target_arch = "x86_64"))),
-           link(name = "gcc_s"))]
-#[cfg_attr(all(target_os = "linux",
-               target_env = "musl",
-               any(target_arch = "x86", target_arch = "x86_64"),
-               not(test)),
-           link(name = "unwind", kind = "static"))]
-#[cfg_attr(any(target_os = "android", target_os = "openbsd"),
-           link(name = "gcc"))]
-#[cfg_attr(all(target_os = "netbsd", not(target_vendor = "rumprun")),
-           link(name = "gcc"))]
-#[cfg_attr(all(target_os = "netbsd", target_vendor = "rumprun"),
-           link(name = "unwind"))]
-#[cfg_attr(target_os = "dragonfly",
-           link(name = "gcc_pic"))]
-#[cfg_attr(target_os = "bitrig",
-           link(name = "c++abi"))]
-#[cfg_attr(all(target_os = "windows", target_env = "gnu"),
-           link(name = "gcc_eh"))]
-#[cfg(not(cargobuild))]
-extern "C" {}
-
 extern "C" {
-    // iOS on armv7 uses SjLj exceptions and requires to link
-    // against corresponding routine (..._SjLj_...)
-    #[cfg(not(all(target_os = "ios", target_arch = "arm")))]
-    #[unwind]
-    pub fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
-
-    #[cfg(all(target_os = "ios", target_arch = "arm"))]
-    #[unwind]
-    fn _Unwind_SjLj_RaiseException(e: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
-
-    pub fn _Unwind_DeleteException(exception: *mut _Unwind_Exception);
-
     #[unwind]
     pub fn _Unwind_Resume(exception: *mut _Unwind_Exception) -> !;
-
-    // No native _Unwind_Backtrace on iOS
-    #[cfg(not(all(target_os = "ios", target_arch = "arm")))]
-    pub fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn,
-                             trace_argument: *mut libc::c_void)
-                             -> _Unwind_Reason_Code;
-
-    // available since GCC 4.2.0, should be fine for our purpose
-    #[cfg(all(not(all(target_os = "android", target_arch = "arm")),
-              not(all(target_os = "linux", target_arch = "arm"))))]
-    pub fn _Unwind_GetIPInfo(ctx: *mut _Unwind_Context,
-                             ip_before_insn: *mut libc::c_int)
-                             -> libc::uintptr_t;
-
-    pub fn _Unwind_GetLanguageSpecificData(ctx: *mut _Unwind_Context) -> _Unwind_Ptr;
+    pub fn _Unwind_DeleteException(exception: *mut _Unwind_Exception);
+    pub fn _Unwind_GetLanguageSpecificData(ctx: *mut _Unwind_Context) -> *mut c_void;
     pub fn _Unwind_GetRegionStart(ctx: *mut _Unwind_Context) -> _Unwind_Ptr;
     pub fn _Unwind_GetTextRelBase(ctx: *mut _Unwind_Context) -> _Unwind_Ptr;
     pub fn _Unwind_GetDataRelBase(ctx: *mut _Unwind_Context) -> _Unwind_Ptr;
-    pub fn _Unwind_SetGR(ctx: *mut _Unwind_Context, reg_index: libc::c_int, value: _Unwind_Ptr);
-    pub fn _Unwind_SetIP(ctx: *mut _Unwind_Context, value: _Unwind_Ptr);
-
-    #[cfg(all(not(target_os = "android"),
-              not(all(target_os = "linux", target_arch = "arm"))))]
-    pub fn _Unwind_FindEnclosingFunction(pc: *mut libc::c_void) -> *mut libc::c_void;
 }
 
-// ... and now we just providing access to SjLj counterspart
-// through a standard name to hide those details from others
-// (see also comment above regarding _Unwind_RaiseException)
-#[cfg(all(target_os = "ios", target_arch = "arm"))]
-#[inline]
-pub unsafe fn _Unwind_RaiseException(exc: *mut _Unwind_Exception) -> _Unwind_Reason_Code {
-    _Unwind_SjLj_RaiseException(exc)
-}
+cfg_if! {
+if #[cfg(not(any(all(target_os = "android", target_arch = "arm"),
+                 all(target_os = "linux", target_arch = "arm"))))] {
+    // Not ARM EHABI
+    #[repr(C)]
+    #[derive(Copy, Clone, PartialEq)]
+    pub enum _Unwind_Action {
+        _UA_SEARCH_PHASE = 1,
+        _UA_CLEANUP_PHASE = 2,
+        _UA_HANDLER_FRAME = 4,
+        _UA_FORCE_UNWIND = 8,
+        _UA_END_OF_STACK = 16,
+    }
+    pub use self::_Unwind_Action::*;
+
+    extern "C" {
+        pub fn _Unwind_GetGR(ctx: *mut _Unwind_Context, reg_index: c_int) -> _Unwind_Word;
+        pub fn _Unwind_SetGR(ctx: *mut _Unwind_Context, reg_index: c_int, value: _Unwind_Word);
+        pub fn _Unwind_GetIP(ctx: *mut _Unwind_Context) -> _Unwind_Word;
+        pub fn _Unwind_SetIP(ctx: *mut _Unwind_Context, value: _Unwind_Word);
+        pub fn _Unwind_GetIPInfo(ctx: *mut _Unwind_Context, ip_before_insn: *mut c_int)
+                                 -> _Unwind_Word;
+        pub fn _Unwind_FindEnclosingFunction(pc: *mut c_void) -> *mut c_void;
+    }
+
+} else {
+    // ARM EHABI
+    #[repr(C)]
+    #[derive(Copy, Clone, PartialEq)]
+    pub enum _Unwind_State {
+        _US_VIRTUAL_UNWIND_FRAME = 0,
+        _US_UNWIND_FRAME_STARTING = 1,
+        _US_UNWIND_FRAME_RESUME = 2,
+        _US_ACTION_MASK = 3,
+        _US_FORCE_UNWIND = 8,
+        _US_END_OF_STACK = 16,
+    }
+    pub use self::_Unwind_State::*;
 
-// On android, the function _Unwind_GetIP is a macro, and this is the
-// expansion of the macro. This is all copy/pasted directly from the
-// header file with the definition of _Unwind_GetIP.
-#[cfg(any(all(target_os = "android", target_arch = "arm"),
-          all(target_os = "linux", target_arch = "arm")))]
-pub unsafe fn _Unwind_GetIP(ctx: *mut _Unwind_Context) -> libc::uintptr_t {
     #[repr(C)]
     enum _Unwind_VRS_Result {
         _UVRSR_OK = 0,
@@ -198,6 +137,7 @@ enum _Unwind_VRS_RegClass {
         _UVRSC_WMMXD = 3,
         _UVRSC_WMMXC = 4,
     }
+    use self::_Unwind_VRS_RegClass::*;
     #[repr(C)]
     enum _Unwind_VRS_DataRepresentation {
         _UVRSD_UINT32 = 0,
@@ -207,42 +147,116 @@ enum _Unwind_VRS_DataRepresentation {
         _UVRSD_FLOAT = 4,
         _UVRSD_DOUBLE = 5,
     }
+    use self::_Unwind_VRS_DataRepresentation::*;
+
+    pub const UNWIND_POINTER_REG: c_int = 12;
+    pub const UNWIND_IP_REG: c_int = 15;
 
-    type _Unwind_Word = libc::c_uint;
     extern "C" {
         fn _Unwind_VRS_Get(ctx: *mut _Unwind_Context,
-                           klass: _Unwind_VRS_RegClass,
-                           word: _Unwind_Word,
+                           regclass: _Unwind_VRS_RegClass,
+                           regno: _Unwind_Word,
+                           repr: _Unwind_VRS_DataRepresentation,
+                           data: *mut c_void)
+                           -> _Unwind_VRS_Result;
+
+        fn _Unwind_VRS_Set(ctx: *mut _Unwind_Context,
+                           regclass: _Unwind_VRS_RegClass,
+                           regno: _Unwind_Word,
                            repr: _Unwind_VRS_DataRepresentation,
-                           data: *mut libc::c_void)
+                           data: *mut c_void)
                            -> _Unwind_VRS_Result;
     }
 
-    let mut val: _Unwind_Word = 0;
-    let ptr = &mut val as *mut _Unwind_Word;
-    let _ = _Unwind_VRS_Get(ctx,
-                            _Unwind_VRS_RegClass::_UVRSC_CORE,
-                            15,
-                            _Unwind_VRS_DataRepresentation::_UVRSD_UINT32,
-                            ptr as *mut libc::c_void);
-    (val & !1) as libc::uintptr_t
-}
+    // On Android or ARM/Linux, these are implemented as macros:
+
+    pub unsafe fn _Unwind_GetGR(ctx: *mut _Unwind_Context, reg_index: c_int) -> _Unwind_Word {
+        let mut val: _Unwind_Word = 0;
+        _Unwind_VRS_Get(ctx, _UVRSC_CORE, reg_index as _Unwind_Word, _UVRSD_UINT32,
+                        &mut val as *mut _ as *mut c_void);
+        val
+    }
 
-// This function doesn't exist on Android or ARM/Linux, so make it same
-// to _Unwind_GetIP
-#[cfg(any(all(target_os = "android", target_arch = "arm"),
-          all(target_os = "linux", target_arch = "arm")))]
-pub unsafe fn _Unwind_GetIPInfo(ctx: *mut _Unwind_Context,
-                                ip_before_insn: *mut libc::c_int)
-                                -> libc::uintptr_t {
-    *ip_before_insn = 0;
-    _Unwind_GetIP(ctx)
+    pub unsafe fn _Unwind_SetGR(ctx: *mut _Unwind_Context, reg_index: c_int, value: _Unwind_Word) {
+        let mut value = value;
+        _Unwind_VRS_Set(ctx, _UVRSC_CORE, reg_index as _Unwind_Word, _UVRSD_UINT32,
+                        &mut value as *mut _ as *mut c_void);
+    }
+
+    pub unsafe fn _Unwind_GetIP(ctx: *mut _Unwind_Context)
+                                -> _Unwind_Word {
+        let val = _Unwind_GetGR(ctx, UNWIND_IP_REG);
+        (val & !1) as _Unwind_Word
+    }
+
+    pub unsafe fn _Unwind_SetIP(ctx: *mut _Unwind_Context,
+                                value: _Unwind_Word) {
+        // Propagate thumb bit to instruction pointer
+        let thumb_state = _Unwind_GetGR(ctx, UNWIND_IP_REG) & 1;
+        let value = value | thumb_state;
+        _Unwind_SetGR(ctx, UNWIND_IP_REG, value);
+    }
+
+    pub unsafe fn _Unwind_GetIPInfo(ctx: *mut _Unwind_Context,
+                                    ip_before_insn: *mut c_int)
+                                    -> _Unwind_Word {
+        *ip_before_insn = 0;
+        _Unwind_GetIP(ctx)
+    }
+
+    // This function also doesn't exist on Android or ARM/Linux, so make it a no-op
+    pub unsafe fn _Unwind_FindEnclosingFunction(pc: *mut c_void) -> *mut c_void {
+        pc
+    }
 }
 
-// This function also doesn't exist on Android or ARM/Linux, so make it
-// a no-op
-#[cfg(any(target_os = "android",
-          all(target_os = "linux", target_arch = "arm")))]
-pub unsafe fn _Unwind_FindEnclosingFunction(pc: *mut libc::c_void) -> *mut libc::c_void {
-    pc
+if #[cfg(not(all(target_os = "ios", target_arch = "arm")))] {
+    // Not 32-bit iOS
+    extern "C" {
+        #[unwind]
+        pub fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
+        pub fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn,
+                                 trace_argument: *mut c_void)
+                                 -> _Unwind_Reason_Code;
+    }
+} else {
+    // 32-bit iOS uses SjLj and does not provide _Unwind_Backtrace()
+    extern "C" {
+        #[unwind]
+        pub fn _Unwind_SjLj_RaiseException(e: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
+    }
+
+    #[inline]
+    pub unsafe fn _Unwind_RaiseException(exc: *mut _Unwind_Exception) -> _Unwind_Reason_Code {
+        _Unwind_SjLj_RaiseException(exc)
+    }
 }
+} // cfg_if!
+
+#[cfg_attr(any(all(target_os = "linux", not(target_env = "musl")),
+               target_os = "freebsd",
+               target_os = "solaris",
+               all(target_os = "linux",
+                   target_env = "musl",
+                   not(target_arch = "x86"),
+                   not(target_arch = "x86_64"))),
+           link(name = "gcc_s"))]
+#[cfg_attr(all(target_os = "linux",
+               target_env = "musl",
+               any(target_arch = "x86", target_arch = "x86_64"),
+               not(test)),
+           link(name = "unwind", kind = "static"))]
+#[cfg_attr(any(target_os = "android", target_os = "openbsd"),
+           link(name = "gcc"))]
+#[cfg_attr(all(target_os = "netbsd", not(target_vendor = "rumprun")),
+           link(name = "gcc"))]
+#[cfg_attr(all(target_os = "netbsd", target_vendor = "rumprun"),
+           link(name = "unwind"))]
+#[cfg_attr(target_os = "dragonfly",
+           link(name = "gcc_pic"))]
+#[cfg_attr(target_os = "bitrig",
+           link(name = "c++abi"))]
+#[cfg_attr(all(target_os = "windows", target_env = "gnu"),
+           link(name = "gcc_eh"))]
+#[cfg(not(cargobuild))]
+extern "C" {}
index bad46966ffa6bef5eed035363137dcc75c097e14..70aef55d799c114be7c0a975a7ba94af02a3b960 100644 (file)
@@ -18,7 +18,7 @@ version = "0.0.0"
 dependencies = [
  "build_helper 0.1.0",
  "core 0.0.0",
- "gcc 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.27 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.0.0",
 ]
 
@@ -49,7 +49,7 @@ version = "0.0.0"
 
 [[package]]
 name = "gcc"
-version = "0.3.26"
+version = "0.3.27"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -101,7 +101,7 @@ dependencies = [
  "build_helper 0.1.0",
  "collections 0.0.0",
  "core 0.0.0",
- "gcc 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.27 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.0.0",
  "panic_abort 0.0.0",
  "panic_unwind 0.0.0",
index 5602ef866b83ae800e44f877f026f16ef054d566..693cbe06ba987bcc4e60d6f1d9071d9bc5f5511c 100644 (file)
@@ -46,3 +46,4 @@ std = { path = "../../libstd" }
 [features]
 jemalloc = ["std/jemalloc"]
 debug-jemalloc = ["std/debug-jemalloc"]
+backtrace = ["std/backtrace"]
index 83c845bfdf96ef413adc5fc39ddcae2383ebc702..61a8ee88a70825e0c534447f51d151ea0055d5bf 100644 (file)
@@ -14,6 +14,8 @@
 #![feature(plugin)]
 #![plugin(lint_plugin_test)]
 #![forbid(test_lint)]
+//~^ NOTE lint level defined here
+//~| NOTE `forbid` lint level set here
 
 fn lintme() { } //~ ERROR item is named 'lintme'
 
index edec911d3c070e6b14eb0fbc5190af2bb84506a7..2a731596b4be8005c57ac9ba2ecdee156654b9d4 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-extern "rust-call" { fn foo(x: u8, ...); } //~ ERROR E0045
+extern "Rust" { fn foo(x: u8, ...); } //~ ERROR E0045
 
 fn main() {
 }
index 1bbccae53a44d6f755804790fe9d8b787025028f..47e1c09f380b89d6601257017e709657766ab559 100644 (file)
@@ -12,7 +12,7 @@ fn main() {
     let _x: i32 = [1, 2, 3];
     //~^ ERROR mismatched types
     //~| expected type `i32`
-    //~| found type `[_; 3]`
+    //~| found type `[{integer}; 3]`
     //~| expected i32, found array of 3 elements
 
     let x: &[i32] = &[1, 2, 3];
index ee6ac33072792a722202d7a1b82f7bbbcad19f6b..5547d19868d34e2340473e9fc480a8092a59e9ae 100644 (file)
@@ -11,6 +11,6 @@
 static i: String = 10;
 //~^ ERROR mismatched types
 //~| expected type `std::string::String`
-//~| found type `_`
+//~| found type `{integer}`
 //~| expected struct `std::string::String`, found integral variable
 fn main() { println!("{}", i); }
index 634d12441a12077c73bf3c5b62f63ff126d4d21b..86702a7463fd0872957e6f96f79c4462c512d3ec 100644 (file)
@@ -15,6 +15,6 @@ fn main() {
     f(&x);
     //~^ ERROR mismatched types
     //~| expected type `&mut i32`
-    //~| found type `&_`
+    //~| found type `&{integer}`
     //~| values differ in mutability
 }
index bd7e6c2a2131d36d0eb104be0864caabe72b9c40..a619f33468f4a94e068fe70d6a8aa26da03c6312 100644 (file)
@@ -14,6 +14,6 @@ fn main() {
     let _: &[i32] = [0];
     //~^ ERROR mismatched types
     //~| expected type `&[i32]`
-    //~| found type `[_; 1]`
+    //~| found type `[{integer}; 1]`
     //~| expected &-ptr, found array of 1 elements
 }
diff --git a/src/test/compile-fail/feature-gate-abi-vectorcall.rs b/src/test/compile-fail/feature-gate-abi-vectorcall.rs
deleted file mode 100644 (file)
index 79f3c8d..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-extern "vectorcall" {   //~ ERROR vectorcall is experimental and subject to change
-    fn bar();
-}
-
-extern "vectorcall" fn baz() {  //~ ERROR vectorcall is experimental and subject to change
-}
-
-fn main() {
-}
diff --git a/src/test/compile-fail/feature-gate-abi.rs b/src/test/compile-fail/feature-gate-abi.rs
new file mode 100644 (file)
index 0000000..0c01f95
--- /dev/null
@@ -0,0 +1,60 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Functions
+extern "rust-intrinsic" fn f1() {} //~ ERROR intrinsics are subject to change
+extern "platform-intrinsic" fn f2() {} //~ ERROR platform intrinsics are experimental
+extern "vectorcall" fn f3() {} //~ ERROR vectorcall is experimental and subject to change
+extern "rust-call" fn f4() {} //~ ERROR rust-call ABI is subject to change
+
+// Methods in trait definition
+trait Tr {
+    extern "rust-intrinsic" fn m1(); //~ ERROR intrinsics are subject to change
+    extern "platform-intrinsic" fn m2(); //~ ERROR platform intrinsics are experimental
+    extern "vectorcall" fn m3(); //~ ERROR vectorcall is experimental and subject to change
+    extern "rust-call" fn m4(); //~ ERROR rust-call ABI is subject to change
+
+    extern "rust-intrinsic" fn dm1() {} //~ ERROR intrinsics are subject to change
+    extern "platform-intrinsic" fn dm2() {} //~ ERROR platform intrinsics are experimental
+    extern "vectorcall" fn dm3() {} //~ ERROR vectorcall is experimental and subject to change
+    extern "rust-call" fn dm4() {} //~ ERROR rust-call ABI is subject to change
+}
+
+struct S;
+
+// Methods in trait impl
+impl Tr for S {
+    extern "rust-intrinsic" fn m1() {} //~ ERROR intrinsics are subject to change
+    extern "platform-intrinsic" fn m2() {} //~ ERROR platform intrinsics are experimental
+    extern "vectorcall" fn m3() {} //~ ERROR vectorcall is experimental and subject to change
+    extern "rust-call" fn m4() {} //~ ERROR rust-call ABI is subject to change
+}
+
+// Methods in inherent impl
+impl S {
+    extern "rust-intrinsic" fn im1() {} //~ ERROR intrinsics are subject to change
+    extern "platform-intrinsic" fn im2() {} //~ ERROR platform intrinsics are experimental
+    extern "vectorcall" fn im3() {} //~ ERROR vectorcall is experimental and subject to change
+    extern "rust-call" fn im4() {} //~ ERROR rust-call ABI is subject to change
+}
+
+// Function pointer types
+type A1 = extern "rust-intrinsic" fn(); //~ ERROR intrinsics are subject to change
+type A2 = extern "platform-intrinsic" fn(); //~ ERROR platform intrinsics are experimental
+type A3 = extern "vectorcall" fn(); //~ ERROR vectorcall is experimental and subject to change
+type A4 = extern "rust-call" fn(); //~ ERROR rust-call ABI is subject to change
+
+// Foreign modules
+extern "rust-intrinsic" {} //~ ERROR intrinsics are subject to change
+extern "platform-intrinsic" {} //~ ERROR platform intrinsics are experimental
+extern "vectorcall" {} //~ ERROR vectorcall is experimental and subject to change
+extern "rust-call" {} //~ ERROR rust-call ABI is subject to change
+
+fn main() {}
diff --git a/src/test/compile-fail/feature-gate-rust-call.rs b/src/test/compile-fail/feature-gate-rust-call.rs
deleted file mode 100644 (file)
index 029a9ca..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-extern "rust-call" fn foo() { } //~ ERROR rust-call ABI is subject to change
-
-trait Foo {
-    extern "rust-call" fn foo();
-}
-
-impl Foo for i32 {
-    extern "rust-call" fn foo() { } //~ ERROR rust-call ABI is subject to change
-}
-
-fn main() { }
index 5ea8ce226443836889e06866c287577af8a95f3a..1a7ceb2e7639e72392f34b352af61f0bd621e0c1 100644 (file)
@@ -15,6 +15,6 @@ fn main() {
     x = 5;
     //~^ ERROR mismatched types
     //~| expected type `std::option::Option<usize>`
-    //~| found type `_`
+    //~| found type `{integer}`
     //~| expected enum `std::option::Option`, found integral variable
 }
index c7b1e1a62c2097c4e87fdcbdec210f5aa8b7f9a3..40013a7ee43bb142495a317c1f5640b401209aa4 100644 (file)
@@ -12,7 +12,7 @@ fn main() {
     if let Some(b) = None { //~ ERROR: `if let` arms have incompatible types
         //~^ expected (), found integral variable
         //~| expected type `()`
-        //~| found type `_`
+        //~| found type `{integer}`
         ()
     } else {                //~ NOTE: `if let` arm with an incompatible type
         1
index 272ad980feb467c767f36088f10da6881dd3dade..59c61a42e077f22146391ed3a7eb62bb551c507e 100644 (file)
@@ -41,6 +41,12 @@ fn main() {
     //~^ ERROR invalid reference to argument `0` (no arguments given)
     //~^^ ERROR invalid reference to argument `1` (no arguments given)
 
+    // bad named arguments, #35082
+
+    format!("{valuea} {valueb}", valuea=5, valuec=7);
+    //~^ ERROR there is no argument named `valueb`
+    //~^^ ERROR named argument never used
+
     // bad syntax of the format string
 
     format!("{"); //~ ERROR: expected `'}'` but string was terminated
index 354d7b936485bd0505c02eb71758860d5400d5a4..61d54b3f8e4fdf407ce95120cc313d55d0dbc2ef 100644 (file)
@@ -13,7 +13,7 @@
 
 fn main() {
     fn bar<T>(_: T) {}
-    [0][0u8]; //~ ERROR: `[_]: std::ops::Index<u8>` is not satisfied
+    [0][0u8]; //~ ERROR: `[{integer}]: std::ops::Index<u8>` is not satisfied
 
     [0][0]; // should infer to be a usize
 
index 99f2d25166891b1a785f03c1e8098edf9c113d63..f2686ae4d196b432751df2d1abaffa2d7ab55b78 100644 (file)
@@ -12,7 +12,7 @@ fn main() {
     let mut x = 2;
     x = 5.0;
     //~^ ERROR mismatched types
-    //~| expected type `_`
-    //~| found type `_`
+    //~| expected type `{integer}`
+    //~| found type `{float}`
     //~| expected integral variable, found floating-point variable
 }
index 17b96411603ef3e3ce6ffd4981728f34fd98e686..abddf6ba7a38d4550392a514e56cc7d51e45820e 100644 (file)
@@ -17,13 +17,13 @@ pub fn main() {
     let _x: usize = match Some(1) {
         Ok(u) => u,
         //~^ ERROR mismatched types
-        //~| expected type `std::option::Option<_>`
+        //~| expected type `std::option::Option<{integer}>`
         //~| found type `std::result::Result<_, _>`
         //~| expected enum `std::option::Option`, found enum `std::result::Result`
 
         Err(e) => panic!(e)
         //~^ ERROR mismatched types
-        //~| expected type `std::option::Option<_>`
+        //~| expected type `std::option::Option<{integer}>`
         //~| found type `std::result::Result<_, _>`
         //~| expected enum `std::option::Option`, found enum `std::result::Result`
     };
index 0fe01ece558ee0d9a4b8f3fbdcc431252dc932d2..3ea136aca4becdc9da48b09ef452906a7377e5d9 100644 (file)
@@ -14,5 +14,5 @@
 fn main() {
     // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
     (|| Box::new(*(&[0][..])))();
-    //~^ ERROR `[_]: std::marker::Sized` is not satisfied
+    //~^ ERROR `[{integer}]: std::marker::Sized` is not satisfied
 }
index b368daaaf587c15cf874979d1a2ce9ec93c5d161..e07dfaf9fe59e1d7296c159925bd98f3ac7ed804 100644 (file)
@@ -14,7 +14,7 @@
 fn main() {
     if let Some(homura) = Some("madoka") { //~  ERROR missing an else clause
                                            //~| expected type `()`
-                                           //~| found type `_`
+                                           //~| found type `{integer}`
                                            //~| expected (), found integral variable
         765
     };
index 11e236d22126b3638504f4bb00019c4529d220bf..22772e596b19ec19a68c607ef399bc903502504b 100644 (file)
@@ -11,7 +11,7 @@
 macro_rules! macro_panic {
     ($not_a_function:expr, $some_argument:ident) => {
         $not_a_function($some_argument)
-        //~^ ERROR expected function, found `_`
+        //~^ ERROR expected function, found `{integer}`
     }
 }
 
diff --git a/src/test/compile-fail/issue-34349.rs b/src/test/compile-fail/issue-34349.rs
new file mode 100644 (file)
index 0000000..5917531
--- /dev/null
@@ -0,0 +1,32 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This is a regression test for a problem encountered around upvar
+// inference and trait caching: in particular, we were entering a
+// temporary closure kind during inference, and then caching results
+// based on that temporary kind, which led to no error being reported
+// in this particular test.
+
+fn main() {
+    let inc = || {};
+    inc();
+
+    fn apply<F>(f: F) where F: Fn() {
+        f()
+    }
+
+    let mut farewell = "goodbye".to_owned();
+    let diary = || { //~ ERROR E0525
+        farewell.push_str("!!!");
+        println!("Then I screamed {}.", farewell);
+    };
+
+    apply(diary);
+}
diff --git a/src/test/compile-fail/issue-35075.rs b/src/test/compile-fail/issue-35075.rs
new file mode 100644 (file)
index 0000000..a70452d
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct Bar<T> {
+    inner: Foo<T> //~ ERROR type name `Foo` is undefined or not in scope
+}
+
+enum Baz<T> {
+    Foo(Foo<T>) //~ ERROR type name `Foo` is undefined or not in scope
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/issue-35139.rs b/src/test/compile-fail/issue-35139.rs
new file mode 100644 (file)
index 0000000..67f0e7a
--- /dev/null
@@ -0,0 +1,36 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::fmt;
+
+pub trait MethodType {
+    type GetProp: ?Sized;
+}
+
+pub struct MTFn;
+
+impl<'a> MethodType for MTFn { //~ ERROR E0207
+    type GetProp = fmt::Debug + 'a;
+}
+
+fn bad(a: Box<<MTFn as MethodType>::GetProp>) -> Box<fmt::Debug+'static> {
+    a
+}
+
+fn dangling(a: &str) -> Box<fmt::Debug> {
+    bad(Box::new(a))
+}
+
+fn main() {
+    let mut s = "hello".to_string();
+    let x = dangling(&s);
+    s = String::new();
+    println!("{:?}", x);
+}
index 58423341cc6f0e88e283a338f69e8e8d367e1905..b1f668d9c5e217f8ac1b085ff8a1b3022be4842a 100644 (file)
@@ -14,7 +14,7 @@ fn main() {
     } else if false {
 //~^ ERROR if may be missing an else clause
 //~| expected type `()`
-//~| found type `_`
+//~| found type `{integer}`
 //~| expected (), found integral variable
         1
     };
index 7c0905873df8900f961438f2cc49cb9a841a77e3..77588e5c221fd38a554989388f01c1e028b83509 100644 (file)
@@ -14,7 +14,7 @@
 fn main() {
     match 42 { A => () }
     //~^ ERROR mismatched types
-    //~| expected type `_`
+    //~| expected type `{integer}`
     //~| found type `(isize, isize)`
     //~| expected integral variable, found tuple
 }
index e0de860b0eac30ef260b9bf75f1d3c678e27c813..ed465117344d407e682d5deabf14f9c70d9999ea 100644 (file)
@@ -25,12 +25,12 @@ fn main() {
     match &Some(42) {
         Some(x) => (),
         //~^ ERROR mismatched types
-        //~| expected type `&std::option::Option<_>`
+        //~| expected type `&std::option::Option<{integer}>`
         //~| found type `std::option::Option<_>`
         //~| expected &-ptr, found enum `std::option::Option`
         None => ()
         //~^ ERROR mismatched types
-        //~| expected type `&std::option::Option<_>`
+        //~| expected type `&std::option::Option<{integer}>`
         //~| found type `std::option::Option<_>`
         //~| expected &-ptr, found enum `std::option::Option`
     }
index 1cf970e150d7033da338ec5b79e80ec5a6056c8a..a455a7b2d5d0f7b190f06542bc91619c4cf919e4 100644 (file)
@@ -21,5 +21,5 @@ fn take_param<T:Foo>(foo: &T) { }
 fn main() {
     let x: Box<_> = box 3;
     take_param(&x);
-    //~^ ERROR `Box<_>: std::marker::Copy` is not satisfied
+    //~^ ERROR `Box<{integer}>: std::marker::Copy` is not satisfied
 }
index fcc8fb6f933bda47e52bf96a7e30f48a7bc7f5ae..fd2513c5a066daaa728aef75e6392a73ce588c6f 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 #![forbid(deprecated)]
+//~^ NOTE `forbid` lint level set here
 
 #[allow(deprecated)] //~ ERROR allow(deprecated) overruled by outer forbid(deprecated)
 fn main() {
index 2c4c2563021867ddbd6c305f1500b60c6971a5e4..f89b3e39390d31de8b22d29cbea8c112ede25b71 100644 (file)
@@ -20,7 +20,7 @@ fn main() {
         10 ... "what" => ()
     };
     //~^^ ERROR only char and numeric types are allowed in range
-    //~| start type: _
+    //~| start type: {integer}
     //~| end type: &'static str
 
     match 5 {
@@ -28,6 +28,6 @@ fn main() {
         _ => { }
     };
     //~^^^ ERROR mismatched types
-    //~| expected type `_`
+    //~| expected type `{integer}`
     //~| found type `char`
 }
index 3ac4958e7db0f6425b5a5d170574d967e1849bdf..596cec167c218ac2ce674d1c7366c571143f2ce2 100644 (file)
@@ -18,7 +18,7 @@ fn main() {
     };
 
     match &[0, 1, 2] {
-        [..] => {} //~ ERROR expected an array or slice, found `&[_; 3]`
+        [..] => {} //~ ERROR expected an array or slice, found `&[{integer}; 3]`
     };
 
     match &[0, 1, 2] {
index ffa5287d4b2c34d5ae5a770642ed2650ece23a4a..03816362d46c34860aef664661f0898315338108 100644 (file)
@@ -24,6 +24,6 @@ fn main() {
                  //~| expected &-ptr, found struct `Foo`
     Foo::bar(&42); //~  ERROR mismatched types
                       //~| expected type `&Foo`
-                      //~| found type `&_`
+                      //~| found type `&{integer}`
                       //~| expected struct `Foo`, found integral variable
 }
index 63e7dbd30def2fcf96fe647e0f55dc314646b4e7..318d121e4c2df45f20ceaecc3fd512f7b00ba203 100644 (file)
@@ -14,7 +14,7 @@ fn main() {
     // (separate lines to ensure the spans are accurate)
 
      let &_ //~  ERROR mismatched types
-            //~| expected type `&mut _`
+            //~| expected type `&mut {integer}`
             //~| found type `&_`
             //~| values differ in mutability
         = foo;
@@ -23,7 +23,7 @@ fn main() {
     let bar = &1;
     let &_ = bar;
     let &mut _ //~  ERROR mismatched types
-               //~| expected type `&_`
+               //~| expected type `&{integer}`
                //~| found type `&mut _`
                //~| values differ in mutability
          = bar;
index 69f6fcdc4afa6577b8a0cbeb232f7ea4b758ec7a..f31d3787334916bffb1565d63bd1eaf5df7067a8 100644 (file)
@@ -15,5 +15,5 @@ fn bar<T: Send>(_: T) {}
 fn main() {
     let x = Rc::new(5);
     bar(x);
-    //~^ ERROR `std::rc::Rc<_>: std::marker::Send` is not satisfied
+    //~^ ERROR `std::rc::Rc<{integer}>: std::marker::Send` is not satisfied
 }
index bf296220d2a2b601d2cb38bce3f6e5dba8621526..7accf0ca8201c27da5c21be4463c7fe765572dac 100644 (file)
@@ -25,15 +25,15 @@ fn Bar() { }
 }
 
 fn test_single1() {
-    use foo1::Bar;  //~ ERROR function `Bar` is private
+    use foo1::Bar;
 
-    Bar();
+    Bar(); //~ ERROR unresolved name `Bar`
 }
 
 fn test_list1() {
-    use foo1::{Bar,Baz};  //~ ERROR `Bar` is private
+    use foo1::{Bar,Baz};
 
-    Bar();
+    Bar(); //~ ERROR unresolved name `Bar`
 }
 
 // private type, public value
@@ -46,15 +46,15 @@ pub fn Bar() { }
 }
 
 fn test_single2() {
-    use foo2::Bar;  //~ ERROR trait `Bar` is private
+    use foo2::Bar;
 
-    let _x : Box<Bar>;
+    let _x : Box<Bar>; //~ ERROR type name `Bar` is undefined
 }
 
 fn test_list2() {
-    use foo2::{Bar,Baz};  //~ ERROR `Bar` is private
+    use foo2::{Bar,Baz};
 
-    let _x: Box<Bar>;
+    let _x: Box<Bar>; //~ ERROR type name `Bar` is undefined
 }
 
 // neither public
index c00be91a2d74daf067a0d99abb6251d0652239c9..dc6833163a478b4f6d2ae342da44ce03d548de93 100644 (file)
@@ -23,5 +23,5 @@ pub fn main() {
     // Unsized type.
     let arr: &[_] = &[1, 2, 3];
     let range = *arr..;
-    //~^ ERROR `[_]: std::marker::Sized` is not satisfied
+    //~^ ERROR `[{integer}]: std::marker::Sized` is not satisfied
 }
index 3a7e9cc4191ec2af4de80bacf0579705aefe9bd8..1758b28a32482555bb6911420f996ced91ed6330 100644 (file)
@@ -28,7 +28,7 @@ fn main() {
     let d = [0; 0.5];
     //~^ ERROR mismatched types
     //~| expected type `usize`
-    //~| found type `_`
+    //~| found type `{float}`
     //~| expected usize, found floating-point variable
     //~| ERROR expected usize for repeat count, found float [E0306]
     let e = [0; "foo"];
index 30ff1ed0e26f7a2a637a253e7512c7ac73a62048..a1572b85666424bc128f2f27b098757c96f6e80d 100644 (file)
@@ -13,9 +13,8 @@
 // scope (in this case, the enum).
 
 trait TraitA<A> {
-    fn outer(self) {
+    fn outer(&self) {
         enum Foo<B> {
-            //~^ ERROR parameter `B` is never used
             Variance(A)
                 //~^ ERROR can't use type parameters from outer function
         }
@@ -23,23 +22,21 @@ enum Foo<B> {
 }
 
 trait TraitB<A> {
-    fn outer(self) {
+    fn outer(&self) {
         struct Foo<B>(A);
                 //~^ ERROR can't use type parameters from outer function
-                //~^^ ERROR parameter `B` is never used
     }
 }
 
 trait TraitC<A> {
-    fn outer(self) {
+    fn outer(&self) {
         struct Foo<B> { a: A }
                 //~^ ERROR can't use type parameters from outer function
-                //~^^ ERROR parameter `B` is never used
     }
 }
 
 trait TraitD<A> {
-    fn outer(self) {
+    fn outer(&self) {
         fn foo<B>(a: A) { }
                 //~^ ERROR can't use type parameters from outer function
     }
index 3140bb6e5731d04d5822800e32fd00eb06dceb09..2eba7c2e534e15abc2458d34ae90644577c5d0cf 100644 (file)
@@ -16,8 +16,8 @@ fn main() {
     match Foo(1.1, marker::PhantomData) {
         1 => {}
     //~^ ERROR mismatched types
-    //~| expected type `Foo<_, _>`
-    //~| found type `_`
+    //~| expected type `Foo<{float}, _>`
+    //~| found type `{integer}`
     //~| expected struct `Foo`, found integral variable
     }
 
index b972a09b5c4908fa9e200d0888fbbb1f64fe33b3..2b2c23a3ce4e92c88fee61c0c242775e1a65cc7d 100644 (file)
@@ -10,5 +10,5 @@
 
 pub fn main() {
     let s: &str = "hello";
-    let c: u8 = s[4]; //~ ERROR `str: std::ops::Index<_>` is not satisfied
+    let c: u8 = s[4]; //~ ERROR `str: std::ops::Index<{integer}>` is not satisfied
 }
index 1250d0dabcd9a561e87db5a136d2cf65c6e89c76..7e5510edb2c3377707469ca08fe23b0021103be2 100644 (file)
@@ -24,6 +24,6 @@ fn main() {
                                //~| expected struct `Foo`, found struct `Bar`
     let f__isize = Foo { a: 2, ..4 }; //~  ERROR mismatched types
                                  //~| expected type `Foo`
-                                 //~| found type `_`
+                                 //~| found type `{integer}`
                                  //~| expected struct `Foo`, found integral variable
 }
index 4503e465840fe73bfb6f5b0364f52e0f72f82fb7..3703b15d4db836395e3407e816713d3a67ad4dc4 100644 (file)
@@ -23,7 +23,7 @@ struct Bar { x: isize }
                                        //~| expected struct `Foo`, found struct `Bar`
 static foo_i: Foo = Foo { a: 2, ..4 }; //~  ERROR mismatched types
                                        //~| expected type `Foo`
-                                       //~| found type `_`
+                                       //~| found type `{integer}`
                                        //~| expected struct `Foo`, found integral variable
 
 fn main() {
index 2968e8a7ca9968edaeb83f689ab50274800dded0..777746a189c5feee96df9857b887b4e1bb824472 100644 (file)
@@ -26,5 +26,5 @@ fn is_ee<T: Combo>(t: T) {
 
 fn main() {
     is_ee(4);
-    //~^ ERROR overflow evaluating the requirement `_: Tweedle
+    //~^ ERROR overflow evaluating the requirement `{integer}: Tweedle
 }
index e62255a4e77d4301756320a6cd13c25f5f5c69fa..a71f441029472229b37f3e0af7a09b5ea105a9a7 100644 (file)
@@ -16,7 +16,7 @@ fn main() {
     let y = first ((1,2.0,3));
     //~^ ERROR mismatched types
     //~| expected type `(isize, f64)`
-    //~| found type `(isize, f64, _)`
+    //~| found type `(isize, f64, {integer})`
     //~| expected a tuple with 2 elements, found one with 3 elements
 
     let y = first ((1,));
index c2c41fbbb2aaf16857a721a4a2dd90ec859dfafe..4597cf3d350c4167af32c3c32204cbd7ddaf9379 100644 (file)
@@ -20,5 +20,5 @@ fn main() {
     tuple.0;
     tuple.1;
     tuple.2;
-    //~^ ERROR attempted out-of-bounds tuple index `2` on type `(_, _)`
+    //~^ ERROR attempted out-of-bounds tuple index `2` on type `({integer}, {integer})`
 }
index 0f174d99fefcbe4b5d952776a7ec7d906dc7179a..9359c03595669a659160821689c8d16bd3f5b9e4 100644 (file)
@@ -13,7 +13,7 @@
 fn main() { let a: bool = 1; let b: i32 = true; }
 //~^ ERROR mismatched types
 //~| expected type `bool`
-//~| found type `_`
+//~| found type `{integer}`
 //~| expected bool, found integral variable
 //~| ERROR mismatched types
 //~| expected i32, found bool
index 6047f6770a7bdc17422c88bdb54f1e182f4ecc96..f0172777cdabb4e5828e6370afe614b5d5851390 100644 (file)
@@ -27,7 +27,7 @@ fn test<T: Sync>(s: T) {}
 fn main() {
     let us = UnsafeCell::new(MySync{u: UnsafeCell::new(0)});
     test(us);
-    //~^ ERROR `std::cell::UnsafeCell<MySync<_>>: std::marker::Sync` is not satisfied
+    //~^ ERROR `std::cell::UnsafeCell<MySync<{integer}>>: std::marker::Sync` is not satisfied
 
     let uns = UnsafeCell::new(NoSync);
     test(uns);
index eb0baff0005ddd53ce54853b1f31223495b7d2b2..8b3e9369ece46d12e19234da3379b039a6ad006f 100644 (file)
@@ -24,7 +24,7 @@ fn gimme_an_a<A:TraitA>(&self, a: A) -> isize {
 
 fn call_it<B:TraitB>(b: B)  -> isize {
     let y = 4;
-    b.gimme_an_a(y) //~ ERROR `_: TraitA` is not satisfied
+    b.gimme_an_a(y) //~ ERROR `{integer}: TraitA` is not satisfied
 }
 
 fn main() {
diff --git a/src/test/run-pass/myriad-closures.rs b/src/test/run-pass/myriad-closures.rs
new file mode 100644 (file)
index 0000000..d2c9a5d
--- /dev/null
@@ -0,0 +1,48 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This test case tests whether we can handle code bases that contain a high
+// number of closures, something that needs special handling in the MingGW
+// toolchain.
+// See https://github.com/rust-lang/rust/issues/34793 for more information.
+
+// Expand something exponentially
+macro_rules! go_bacterial {
+    ($mac:ident) => ($mac!());
+    ($mac:ident 1 $($t:tt)*) => (
+        go_bacterial!($mac $($t)*);
+        go_bacterial!($mac $($t)*);
+    )
+}
+
+macro_rules! mk_closure {
+    () => ({
+        let c = |a: u32| a + 4;
+        let _ = c(2);
+    })
+}
+
+macro_rules! mk_fn {
+    () => {
+        {
+            fn function() {
+                // Make 16 closures
+                go_bacterial!(mk_closure 1 1 1 1);
+            }
+            let _ = function();
+        }
+    }
+}
+
+fn main() {
+    // Make 2^12 functions, each containing 16 closures,
+    // resulting in 2^16 closures overall.
+    go_bacterial!(mk_fn 1 1 1 1  1 1 1 1  1 1 1 1);
+}
index ff6920d28ccf90a3647df517a6d4dae074feecdd..45638a65915c49901430f6a63d556b5aa0c13d28 100644 (file)
@@ -5,7 +5,7 @@ error[E0308]: mismatched types
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected u64, found usize
 $DIR/issue-26480.rs:38:5: 38:19 note: in this expansion of write! (defined in $DIR/issue-26480.rs)
 
-error: non-scalar cast: `_` as `()`
+error: non-scalar cast: `{integer}` as `()`
   --> $DIR/issue-26480.rs:33:19
    |
 33 |     ($x:expr) => ($x as ())