Auto merge of #35168 - scottcarr:deaggregation, r=nikomatsakis
[MIR] Deaggregate structs to enable further optimizations
Currently, we generate MIR like:
```
tmp0 = ...;
tmp1 = ...;
tmp3 = Foo { a: ..., b: ... };
```
This PR implements "deaggregation," i.e.:
```
tmp3.0 = ...
tmp3.1 = ...
```
Currently, the code only deaggregates structs, not enums. My understanding is that we do not have MIR to set the discriminant of an enum.
diff --git a/.travis.yml b/.travis.yml
index 87197a3..0abd858 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -7,6 +7,7 @@
# our configure script, so disable auto submodule management.
git:
submodules: false
+ depth: 1
before_install:
- docker build -t rust -f src/etc/Dockerfile src/etc
diff --git a/configure b/configure
index d2ec457..29f16da 100755
--- a/configure
+++ b/configure
@@ -609,7 +609,7 @@
opt inject-std-version 1 "inject the current compiler version of libstd into programs"
opt llvm-version-check 1 "check if the LLVM version is supported, build anyway"
opt rustbuild 0 "use the rust and cargo based build system"
-opt orbit 0 "get MIR where it belongs - everywhere; most importantly, in orbit"
+opt orbit 1 "get MIR where it belongs - everywhere; most importantly, in orbit"
opt codegen-tests 1 "run the src/test/codegen tests"
opt option-checking 1 "complain about unrecognized options in this configure script"
opt ninja 0 "build LLVM using the Ninja generator (for MSVC, requires building in the correct environment)"
@@ -733,7 +733,7 @@
if [ -n "$CFG_ENABLE_DEBUGINFO" ]; then putvar CFG_ENABLE_DEBUGINFO; fi
if [ -n "$CFG_ENABLE_DEBUG_JEMALLOC" ]; then putvar CFG_ENABLE_DEBUG_JEMALLOC; fi
-if [ -n "$CFG_ENABLE_ORBIT" ]; then putvar CFG_ENABLE_ORBIT; fi
+if [ -n "$CFG_DISABLE_ORBIT" ]; then putvar CFG_DISABLE_ORBIT; fi
step_msg "looking for build programs"
@@ -1020,6 +1020,12 @@
err "bad LLVM version: $LLVM_VERSION, need >=3.7"
;;
esac
+
+ if "$CFG_LLVM_ROOT/bin/llvm-mc" -help | grep -- "-relocation-model"; then
+ msg "found older llvm-mc"
+ CFG_LLVM_MC_HAS_RELOCATION_MODEL=1
+ putvar CFG_LLVM_MC_HAS_RELOCATION_MODEL
+ fi
fi
# Even when the user overrides the choice of CC, still try to detect
@@ -1192,7 +1198,7 @@
;;
- 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
index 0000000..8120250
--- /dev/null
+++ b/mk/cfg/arm-unknown-linux-musleabi.mk
@@ -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
index 0000000..8120250
--- /dev/null
+++ b/mk/cfg/arm-unknown-linux-musleabihf.mk
@@ -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
index 0000000..8120250
--- /dev/null
+++ b/mk/cfg/armv7-unknown-linux-musleabihf.mk
@@ -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/x86_64-unknown-linux-musl.mk b/mk/cfg/x86_64-unknown-linux-musl.mk
index 3a03b2a..6f707ac 100644
--- a/mk/cfg/x86_64-unknown-linux-musl.mk
+++ b/mk/cfg/x86_64-unknown-linux-musl.mk
@@ -7,8 +7,8 @@
CFG_LIB_NAME_x86_64-unknown-linux-musl=lib$(1).so
CFG_STATIC_LIB_NAME_x86_64-unknown-linux-musl=lib$(1).a
CFG_LIB_GLOB_x86_64-unknown-linux-musl=lib$(1)-*.so
-CFG_JEMALLOC_CFLAGS_x86_64-unknown-linux-musl := -m64
-CFG_GCCISH_CFLAGS_x86_64-unknown-linux-musl := -g -fPIC -m64
+CFG_JEMALLOC_CFLAGS_x86_64-unknown-linux-musl := -m64 -Wa,-mrelax-relocations=no
+CFG_GCCISH_CFLAGS_x86_64-unknown-linux-musl := -g -fPIC -m64 -Wa,-mrelax-relocations=no
CFG_GCCISH_CXXFLAGS_x86_64-unknown-linux-musl :=
CFG_GCCISH_LINK_FLAGS_x86_64-unknown-linux-musl :=
CFG_GCCISH_DEF_FLAG_x86_64-unknown-linux-musl :=
diff --git a/mk/main.mk b/mk/main.mk
index fd12bf2..c6c3e70 100644
--- a/mk/main.mk
+++ b/mk/main.mk
@@ -162,9 +162,10 @@
CFG_RUSTC_FLAGS += -g
endif
-ifdef CFG_ENABLE_ORBIT
- $(info cfg: launching MIR (CFG_ENABLE_ORBIT))
- CFG_RUSTC_FLAGS += -Z orbit
+ifdef CFG_DISABLE_ORBIT
+ $(info cfg: HOLD HOLD HOLD (CFG_DISABLE_ORBIT))
+ RUSTFLAGS_STAGE1 += -Z orbit=off
+ RUSTFLAGS_STAGE2 += -Z orbit=off
endif
ifdef SAVE_TEMPS
diff --git a/mk/platform.mk b/mk/platform.mk
index c264462..d601cab 100644
--- a/mk/platform.mk
+++ b/mk/platform.mk
@@ -221,12 +221,19 @@
LLVM_MC_RELOCATION_MODEL="default"
endif
+ # LLVM changed this flag in 3.9
+ ifdef CFG_LLVM_MC_HAS_RELOCATION_MODEL
+ LLVM_MC_RELOC_FLAG := -relocation-model=$$(LLVM_MC_RELOCATION_MODEL)
+ else
+ LLVM_MC_RELOC_FLAG := -position-independent
+ endif
+
# We're using llvm-mc as our assembler because it supports
# .cfi pseudo-ops on mac
CFG_ASSEMBLE_$(1)=$$(CPP_$(1)) -E $$(2) | \
$$(LLVM_MC_$$(CFG_BUILD)) \
-assemble \
- -relocation-model=$$(LLVM_MC_RELOCATION_MODEL) \
+ $$(LLVM_MC_RELOC_FLAG) \
-filetype=obj \
-triple=$(1) \
-o=$$(1)
diff --git a/mk/rt.mk b/mk/rt.mk
index 067721f..e86aec6 100644
--- a/mk/rt.mk
+++ b/mk/rt.mk
@@ -384,7 +384,11 @@
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)
diff --git a/mk/rustllvm.mk b/mk/rustllvm.mk
index 834a11d..b50dbd0 100644
--- a/mk/rustllvm.mk
+++ b/mk/rustllvm.mk
@@ -24,7 +24,7 @@
endif
RUSTLLVM_OBJS_CS_$(1) := $$(addprefix rustllvm/, \
- ExecutionEngineWrapper.cpp RustWrapper.cpp PassWrapper.cpp \
+ RustWrapper.cpp PassWrapper.cpp \
ArchiveWrapper.cpp)
RUSTLLVM_INCS_$(1) = $$(LLVM_EXTRA_INCDIRS_$(1)) \
diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock
index 1290f2a..02698d6 100644
--- a/src/bootstrap/Cargo.lock
+++ b/src/bootstrap/Cargo.lock
@@ -7,8 +7,8 @@
"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 @@
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 @@
[[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 @@
[[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 @@
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]]
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index 8ec9c7f..061192e 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -92,8 +92,7 @@
}
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);
}
}
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index e64d7e5..aafbf68 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -72,6 +72,7 @@
// 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 @@
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 @@
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 @@
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();
diff --git a/src/bootstrap/config.toml.example b/src/bootstrap/config.toml.example
index 6f06584..2894ada 100644
--- a/src/bootstrap/config.toml.example
+++ b/src/bootstrap/config.toml.example
@@ -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"
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index 367322e8..acb7e0f 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -652,6 +652,9 @@
if self.config.use_jemalloc {
features.push_str(" jemalloc");
}
+ if self.config.backtrace {
+ features.push_str(" backtrace");
+ }
return features
}
@@ -852,6 +855,12 @@
base.push("-stdlib=libc++".into());
base.push("-mmacosx-version-min=10.7".into());
}
+ // This is a hack, because newer binutils broke things on some vms/distros
+ // (i.e., linking against unknown relocs disabled by the following flag)
+ // See: https://github.com/rust-lang/rust/issues/34978
+ if target == "x86_64-unknown-linux-musl" {
+ base.push("-Wa,-mrelax-relocations=no".into());
+ }
return base
}
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index 05ecbc0..a78cef4 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -348,7 +348,9 @@
]);
}
} 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![
diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs
index 7c0f09c..09f9678 100644
--- a/src/bootstrap/sanity.rs
+++ b/src/bootstrap/sanity.rs
@@ -31,6 +31,15 @@
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 @@
}
// 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() {
diff --git a/src/compiler-rt b/src/compiler-rt
index ac3d1cd..8598065 160000
--- a/src/compiler-rt
+++ b/src/compiler-rt
@@ -1 +1 @@
-Subproject commit ac3d1cda612edccb6f1da53cbf7716e248405f3b
+Subproject commit 8598065bd965d9713bfafb6c1e766d63a7b17b89
diff --git a/src/doc/book/closures.md b/src/doc/book/closures.md
index 666d094..1470eac 100644
--- a/src/doc/book/closures.md
+++ b/src/doc/book/closures.md
@@ -223,6 +223,7 @@
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 @@
# 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
diff --git a/src/doc/book/ffi.md b/src/doc/book/ffi.md
index 3cbe5d6..ca104ff 100644
--- a/src/doc/book/ffi.md
+++ b/src/doc/book/ffi.md
@@ -575,16 +575,69 @@
# 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
diff --git a/src/doc/book/lang-items.md b/src/doc/book/lang-items.md
index b948567..72a3c08 100644
--- a/src/doc/book/lang-items.md
+++ b/src/doc/book/lang-items.md
@@ -15,7 +15,7 @@
and one for deallocation. A freestanding program that uses the `Box`
sugar for dynamic allocations via `malloc` and `free`:
-```rust
+```rust,ignore
#![feature(lang_items, box_syntax, start, libc)]
#![no_std]
diff --git a/src/etc/Dockerfile b/src/etc/Dockerfile
index 94be84a..83d5478 100644
--- a/src/etc/Dockerfile
+++ b/src/etc/Dockerfile
@@ -23,11 +23,5 @@
libedit-dev zlib1g-dev \
llvm-3.7-tools cmake
-# When we compile compiler-rt we pass it the llvm-config we just installed on
-# the system, but unfortunately it doesn't infer correctly where
-# LLVMConfig.cmake is so we need to coerce it a bit...
-RUN mkdir -p /usr/lib/llvm-3.7/build/share/llvm
-RUN ln -s /usr/share/llvm-3.7/cmake /usr/lib/llvm-3.7/build/share/llvm/cmake
-
RUN mkdir /build
WORKDIR /build
diff --git a/src/etc/char_private.py b/src/etc/char_private.py
new file mode 100644
index 0000000..3566d14
--- /dev/null
+++ b/src/etc/char_private.py
@@ -0,0 +1,154 @@
+#!/usr/bin/env python
+#
+# Copyright 2011-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 script uses the following Unicode tables:
+# - Categories.txt
+
+import os
+import subprocess
+
+def to_ranges(iter):
+ current = None
+ for i in iter:
+ if current is None or i != current[1] or i in (0x10000, 0x20000):
+ if current is not None:
+ yield tuple(current)
+ current = [i, i + 1]
+ else:
+ current[1] += 1
+ if current is not None:
+ yield tuple(current)
+
+def get_escaped(dictionary):
+ for i in range(0x110000):
+ if dictionary.get(i, "Cn") in "Cc Cf Cs Co Cn Zl Zp Zs".split() and i != ord(' '):
+ yield i
+
+def get_file(f):
+ try:
+ return open(os.path.basename(f))
+ except FileNotFoundError:
+ subprocess.run(["curl", "-O", f], check=True)
+ return open(os.path.basename(f))
+
+def main():
+ file = get_file("http://www.unicode.org/notes/tn36/Categories.txt")
+
+ dictionary = {int(line.split()[0], 16): line.split()[1] for line in file}
+
+ CUTOFF=0x10000
+ singletons0 = []
+ singletons1 = []
+ normal0 = []
+ normal1 = []
+ extra = []
+
+ for a, b in to_ranges(get_escaped(dictionary)):
+ if a > 2 * CUTOFF:
+ extra.append((a, b - a))
+ elif a == b - 1:
+ if a & CUTOFF:
+ singletons1.append(a & ~CUTOFF)
+ else:
+ singletons0.append(a)
+ elif a == b - 2:
+ if a & CUTOFF:
+ singletons1.append(a & ~CUTOFF)
+ singletons1.append((a + 1) & ~CUTOFF)
+ else:
+ singletons0.append(a)
+ singletons0.append(a + 1)
+ else:
+ if a >= 2 * CUTOFF:
+ extra.append((a, b - a))
+ elif a & CUTOFF:
+ normal1.append((a & ~CUTOFF, b - a))
+ else:
+ normal0.append((a, b - a))
+
+ print("""\
+// Copyright 2012-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.
+
+// NOTE: The following code was generated by "src/etc/char_private.py",
+// do not edit directly!
+
+use slice::SliceExt;
+
+fn check(x: u16, singletons: &[u16], normal: &[u16]) -> bool {
+ for &s in singletons {
+ if x == s {
+ return false;
+ } else if x < s {
+ break;
+ }
+ }
+ for w in normal.chunks(2) {
+ let start = w[0];
+ let len = w[1];
+ let difference = (x as i32) - (start as i32);
+ if 0 <= difference {
+ if difference < len as i32 {
+ return false;
+ }
+ } else {
+ break;
+ }
+ }
+ true
+}
+
+pub fn is_printable(x: char) -> bool {
+ let x = x as u32;
+ let lower = x as u16;
+ if x < 0x10000 {
+ check(lower, SINGLETONS0, NORMAL0)
+ } else if x < 0x20000 {
+ check(lower, SINGLETONS1, NORMAL1)
+ } else {\
+""")
+ for a, b in extra:
+ print(" if 0x{:x} <= x && x < 0x{:x} {{".format(a, a + b))
+ print(" return false;")
+ print(" }")
+ print("""\
+ true
+ }
+}\
+""")
+ print()
+ print("const SINGLETONS0: &'static [u16] = &[")
+ for s in singletons0:
+ print(" 0x{:x},".format(s))
+ print("];")
+ print("const SINGLETONS1: &'static [u16] = &[")
+ for s in singletons1:
+ print(" 0x{:x},".format(s))
+ print("];")
+ print("const NORMAL0: &'static [u16] = &[")
+ for a, b in normal0:
+ print(" 0x{:x}, 0x{:x},".format(a, b))
+ print("];")
+ print("const NORMAL1: &'static [u16] = &[")
+ for a, b in normal1:
+ print(" 0x{:x}, 0x{:x},".format(a, b))
+ print("];")
+
+if __name__ == '__main__':
+ main()
diff --git a/src/etc/local_stage0.sh b/src/etc/local_stage0.sh
index 354be34..f5f39d2 100755
--- a/src/etc/local_stage0.sh
+++ b/src/etc/local_stage0.sh
@@ -58,6 +58,7 @@
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}/
diff --git a/src/etc/mklldeps.py b/src/etc/mklldeps.py
index 8381e4f..24b0075 100644
--- a/src/etc/mklldeps.py
+++ b/src/etc/mklldeps.py
@@ -77,6 +77,13 @@
lib = lib.strip()[2:]
elif lib[0] == '-':
lib = lib.strip()[1:]
+ # If this actually points at a literal file then we're on MSVC which now
+ # prints full paths, so get just the name of the library and strip off the
+ # trailing ".lib"
+ elif os.path.exists(lib):
+ lib = os.path.basename(lib)[:-4]
+ elif lib[-4:] == '.lib':
+ lib = lib[:-4]
f.write("#[link(name = \"" + lib + "\"")
if not llvm_shared and 'LLVM' in lib:
f.write(", kind = \"static\"")
diff --git a/src/liballoc_jemalloc/Cargo.toml b/src/liballoc_jemalloc/Cargo.toml
index 768a0c2..25b3c8a 100644
--- a/src/liballoc_jemalloc/Cargo.toml
+++ b/src/liballoc_jemalloc/Cargo.toml
@@ -16,7 +16,7 @@
[build-dependencies]
build_helper = { path = "../build_helper" }
-gcc = "0.3.17"
+gcc = "0.3.27"
[features]
debug = []
diff --git a/src/liballoc_jemalloc/build.rs b/src/liballoc_jemalloc/build.rs
index d1b3583..dc1b8d6 100644
--- a/src/liballoc_jemalloc/build.rs
+++ b/src/liballoc_jemalloc/build.rs
@@ -73,7 +73,16 @@
.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()));
diff --git a/src/libcollections/fmt.rs b/src/libcollections/fmt.rs
index c5312d0..be0ef85 100644
--- a/src/libcollections/fmt.rs
+++ b/src/libcollections/fmt.rs
@@ -434,37 +434,31 @@
//! 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:
//!
//! ```
diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs
index f027d07..21387a1 100644
--- a/src/libcollections/lib.rs
+++ b/src/libcollections/lib.rs
@@ -33,6 +33,7 @@
#![feature(allow_internal_unstable)]
#![feature(box_patterns)]
#![feature(box_syntax)]
+#![cfg_attr(not(test), feature(char_escape_debug))]
#![feature(core_intrinsics)]
#![feature(dropck_parametricity)]
#![feature(fmt_internals)]
@@ -48,7 +49,6 @@
#![feature(specialization)]
#![feature(staged_api)]
#![feature(step_by)]
-#![feature(unboxed_closures)]
#![feature(unicode)]
#![feature(unique)]
#![feature(unsafe_no_drop_flag)]
diff --git a/src/libcollections/linked_list.rs b/src/libcollections/linked_list.rs
index 3d5c312..6842f02 100644
--- a/src/libcollections/linked_list.rs
+++ b/src/libcollections/linked_list.rs
@@ -203,19 +203,22 @@
/// ```
/// 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) {
diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs
index ccef6c0..ff2b8cd 100644
--- a/src/libcollections/slice.rs
+++ b/src/libcollections/slice.rs
@@ -577,15 +577,13 @@
///
/// # Example
///
- /// Print the slice two elements at a time (i.e. `[1,2]`,
- /// `[3,4]`, `[5]`):
- ///
- /// ```rust
- /// let v = &[1, 2, 3, 4, 5];
- ///
- /// for chunk in v.chunks(2) {
- /// println!("{:?}", chunk);
- /// }
+ /// ```
+ /// let slice = ['l', 'o', 'r', 'e', 'm'];
+ /// let mut iter = slice.chunks(2);
+ /// assert_eq!(iter.next().unwrap(), &['l', 'o']);
+ /// assert_eq!(iter.next().unwrap(), &['r', 'e']);
+ /// assert_eq!(iter.next().unwrap(), &['m']);
+ /// assert!(iter.next().is_none());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs
index 55308a4..4c64019 100644
--- a/src/libcollections/str.rs
+++ b/src/libcollections/str.rs
@@ -1697,6 +1697,14 @@
return s;
}
+ /// Escapes each char in `s` with `char::escape_debug`.
+ #[unstable(feature = "str_escape",
+ reason = "return type may change to be an iterator",
+ issue = "27791")]
+ pub fn escape_debug(&self) -> String {
+ self.chars().flat_map(|c| c.escape_debug()).collect()
+ }
+
/// Escapes each char in `s` with `char::escape_default`.
#[unstable(feature = "str_escape",
reason = "return type may change to be an iterator",
diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs
index f91d8a5..0695225 100644
--- a/src/libcollections/string.rs
+++ b/src/libcollections/string.rs
@@ -1881,6 +1881,26 @@
}
}
+#[stable(feature = "stringfromchars", since = "1.12.0")]
+impl<'a> From<&'a [char]> for String {
+ #[inline]
+ fn from(v: &'a [char]) -> String {
+ let mut s = String::with_capacity(v.len());
+ for c in v {
+ s.push(*c);
+ }
+ s
+ }
+}
+
+#[stable(feature = "stringfromchars", since = "1.12.0")]
+impl From<Vec<char>> for String {
+ #[inline]
+ fn from(v: Vec<char>) -> String {
+ String::from(v.as_slice())
+ }
+}
+
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Write for String {
#[inline]
diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs
index 967bacc..275f38b 100644
--- a/src/libcollections/vec.rs
+++ b/src/libcollections/vec.rs
@@ -73,6 +73,7 @@
use core::ops::{Index, IndexMut};
use core::ops;
use core::ptr;
+use core::ptr::Shared;
use core::slice;
use super::SpecExtend;
@@ -899,8 +900,8 @@
Drain {
tail_start: end,
tail_len: len - end,
- iter: range_slice.iter_mut(),
- vec: self as *mut _,
+ iter: range_slice.iter(),
+ vec: Shared::new(self as *mut _),
}
}
}
@@ -1806,8 +1807,8 @@
/// Length of tail
tail_len: usize,
/// Current remaining range to remove
- iter: slice::IterMut<'a, T>,
- vec: *mut Vec<T>,
+ iter: slice::Iter<'a, T>,
+ vec: Shared<Vec<T>>,
}
#[stable(feature = "drain", since = "1.6.0")]
@@ -1845,7 +1846,7 @@
if self.tail_len > 0 {
unsafe {
- let source_vec = &mut *self.vec;
+ let source_vec = &mut **self.vec;
// memmove back untouched tail, update to new length
let start = source_vec.len();
let tail = self.tail_start;
diff --git a/src/libcollectionstest/binary_heap.rs b/src/libcollectionstest/binary_heap.rs
index be933ab..e2a57bd 100644
--- a/src/libcollectionstest/binary_heap.rs
+++ b/src/libcollectionstest/binary_heap.rs
@@ -9,6 +9,7 @@
// except according to those terms.
use std::collections::BinaryHeap;
+use std::collections::binary_heap::Drain;
#[test]
fn test_iterator() {
@@ -292,3 +293,8 @@
assert_eq!(a.into_sorted_vec(), [-20, -10, 1, 2, 3, 3, 5, 43]);
}
+
+#[allow(dead_code)]
+fn assert_covariance() {
+ fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> { d }
+}
diff --git a/src/libcollectionstest/str.rs b/src/libcollectionstest/str.rs
index 07428f3f..a61925c 100644
--- a/src/libcollectionstest/str.rs
+++ b/src/libcollectionstest/str.rs
@@ -704,15 +704,31 @@
}
#[test]
+fn test_escape_debug() {
+ assert_eq!("abc".escape_debug(), "abc");
+ assert_eq!("a c".escape_debug(), "a c");
+ assert_eq!("éèê".escape_debug(), "éèê");
+ assert_eq!("\r\n\t".escape_debug(), "\\r\\n\\t");
+ assert_eq!("'\"\\".escape_debug(), "\\'\\\"\\\\");
+ assert_eq!("\u{7f}\u{ff}".escape_debug(), "\\u{7f}\u{ff}");
+ assert_eq!("\u{100}\u{ffff}".escape_debug(), "\u{100}\\u{ffff}");
+ assert_eq!("\u{10000}\u{10ffff}".escape_debug(), "\u{10000}\\u{10ffff}");
+ assert_eq!("ab\u{200b}".escape_debug(), "ab\\u{200b}");
+ assert_eq!("\u{10d4ea}\r".escape_debug(), "\\u{10d4ea}\\r");
+}
+
+#[test]
fn test_escape_default() {
assert_eq!("abc".escape_default(), "abc");
assert_eq!("a c".escape_default(), "a c");
+ assert_eq!("éèê".escape_default(), "\\u{e9}\\u{e8}\\u{ea}");
assert_eq!("\r\n\t".escape_default(), "\\r\\n\\t");
assert_eq!("'\"\\".escape_default(), "\\'\\\"\\\\");
+ assert_eq!("\u{7f}\u{ff}".escape_default(), "\\u{7f}\\u{ff}");
assert_eq!("\u{100}\u{ffff}".escape_default(), "\\u{100}\\u{ffff}");
assert_eq!("\u{10000}\u{10ffff}".escape_default(), "\\u{10000}\\u{10ffff}");
- assert_eq!("ab\u{fb00}".escape_default(), "ab\\u{fb00}");
- assert_eq!("\u{1d4ea}\r".escape_default(), "\\u{1d4ea}\\r");
+ assert_eq!("ab\u{200b}".escape_default(), "ab\\u{200b}");
+ assert_eq!("\u{10d4ea}\r".escape_default(), "\\u{10d4ea}\\r");
}
#[test]
diff --git a/src/libcollectionstest/string.rs b/src/libcollectionstest/string.rs
index 7f0fd28..1652fb5 100644
--- a/src/libcollectionstest/string.rs
+++ b/src/libcollectionstest/string.rs
@@ -193,6 +193,17 @@
}
#[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("ประเทศไทย中");
data.push('华');
diff --git a/src/libcollectionstest/vec.rs b/src/libcollectionstest/vec.rs
index cb99659..7a6bd95 100644
--- a/src/libcollectionstest/vec.rs
+++ b/src/libcollectionstest/vec.rs
@@ -11,6 +11,7 @@
use std::borrow::Cow;
use std::iter::{FromIterator, repeat};
use std::mem::size_of;
+use std::vec::Drain;
use test::Bencher;
@@ -510,6 +511,11 @@
}
}
+#[allow(dead_code)]
+fn assert_covariance() {
+ fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> { d }
+}
+
#[bench]
fn bench_new(b: &mut Bencher) {
b.iter(|| {
diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs
index 65cb1aa..06af200 100644
--- a/src/libcore/cell.rs
+++ b/src/libcore/cell.rs
@@ -847,6 +847,20 @@
/// The `UnsafeCell<T>` type is the only legal way to obtain aliasable data that is considered
/// mutable. In general, transmuting an `&T` type into an `&mut T` is considered undefined behavior.
///
+/// The compiler makes optimizations based on the knowledge that `&T` is not mutably aliased or
+/// mutated, and that `&mut T` is unique. When building abstractions like `Cell`, `RefCell`,
+/// `Mutex`, etc, you need to turn these optimizations off. `UnsafeCell` is the only legal way
+/// to do this. When `UnsafeCell<T>` is immutably aliased, it is still safe to obtain a mutable
+/// reference to its interior and/or to mutate it. However, it is up to the abstraction designer
+/// to ensure that no two mutable references obtained this way are active at the same time, and
+/// that there are no active mutable references or mutations when an immutable reference is obtained
+/// from the cell. This is often done via runtime checks.
+///
+/// Note that while mutating or mutably aliasing the contents of an `& UnsafeCell<T>` is
+/// okay (provided you enforce the invariants some other way); it is still undefined behavior
+/// to have multiple `&mut UnsafeCell<T>` aliases.
+///
+///
/// Types like `Cell<T>` and `RefCell<T>` use this type to wrap their internal data.
///
/// # Examples
@@ -916,6 +930,11 @@
impl<T: ?Sized> UnsafeCell<T> {
/// Gets a mutable pointer to the wrapped value.
///
+ /// This can be cast to a pointer of any kind.
+ /// Ensure that the access is unique when casting to
+ /// `&mut T`, and ensure that there are no mutations or mutable
+ /// aliases going on when casting to `&T`
+ ///
/// # Examples
///
/// ```
diff --git a/src/libcore/char.rs b/src/libcore/char.rs
index 0e7f04c..a3440fe 100644
--- a/src/libcore/char.rs
+++ b/src/libcore/char.rs
@@ -17,6 +17,7 @@
use prelude::v1::*;
+use char_private::is_printable;
use mem::transmute;
// UTF-8 ranges and tags for encoding characters
@@ -263,6 +264,8 @@
fn escape_unicode(self) -> EscapeUnicode;
#[stable(feature = "core", since = "1.6.0")]
fn escape_default(self) -> EscapeDefault;
+ #[unstable(feature = "char_escape_debug", issue = "35068")]
+ fn escape_debug(self) -> EscapeDebug;
#[stable(feature = "core", since = "1.6.0")]
fn len_utf8(self) -> usize;
#[stable(feature = "core", since = "1.6.0")]
@@ -327,6 +330,19 @@
}
#[inline]
+ fn escape_debug(self) -> EscapeDebug {
+ let init_state = match self {
+ '\t' => EscapeDefaultState::Backslash('t'),
+ '\r' => EscapeDefaultState::Backslash('r'),
+ '\n' => EscapeDefaultState::Backslash('n'),
+ '\\' | '\'' | '"' => EscapeDefaultState::Backslash(self),
+ c if is_printable(c) => EscapeDefaultState::Char(c),
+ c => EscapeDefaultState::Unicode(c.escape_unicode()),
+ };
+ EscapeDebug(EscapeDefault { state: init_state })
+ }
+
+ #[inline]
fn len_utf8(self) -> usize {
let code = self as u32;
if code < MAX_ONE_B {
@@ -600,6 +616,27 @@
}
}
+/// An iterator that yields the literal escape code of a `char`.
+///
+/// This `struct` is created by the [`escape_debug()`] method on [`char`]. See its
+/// documentation for more.
+///
+/// [`escape_debug()`]: ../../std/primitive.char.html#method.escape_debug
+/// [`char`]: ../../std/primitive.char.html
+#[unstable(feature = "char_escape_debug", issue = "35068")]
+#[derive(Clone, Debug)]
+pub struct EscapeDebug(EscapeDefault);
+
+#[unstable(feature = "char_escape_debug", issue = "35068")]
+impl Iterator for EscapeDebug {
+ type Item = char;
+ fn next(&mut self) -> Option<char> { self.0.next() }
+ fn size_hint(&self) -> (usize, Option<usize>) { self.0.size_hint() }
+}
+
+#[unstable(feature = "char_escape_debug", issue = "35068")]
+impl ExactSizeIterator for EscapeDebug { }
+
/// An iterator over `u8` entries represending the UTF-8 encoding of a `char`
/// value.
///
diff --git a/src/libcore/char_private.rs b/src/libcore/char_private.rs
new file mode 100644
index 0000000..1d8f95c
--- /dev/null
+++ b/src/libcore/char_private.rs
@@ -0,0 +1,695 @@
+// Copyright 2012-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.
+
+// NOTE: The following code was generated by "src/etc/char_private.py",
+// do not edit directly!
+
+use slice::SliceExt;
+
+fn check(x: u16, singletons: &[u16], normal: &[u16]) -> bool {
+ for &s in singletons {
+ if x == s {
+ return false;
+ } else if x < s {
+ break;
+ }
+ }
+ for w in normal.chunks(2) {
+ let start = w[0];
+ let len = w[1];
+ let difference = (x as i32) - (start as i32);
+ if 0 <= difference {
+ if difference < len as i32 {
+ return false;
+ }
+ } else {
+ break;
+ }
+ }
+ true
+}
+
+pub fn is_printable(x: char) -> bool {
+ let x = x as u32;
+ let lower = x as u16;
+ if x < 0x10000 {
+ check(lower, SINGLETONS0, NORMAL0)
+ } else if x < 0x20000 {
+ check(lower, SINGLETONS1, NORMAL1)
+ } else {
+ if 0x20000 <= x && x < 0x2f800 {
+ return false;
+ }
+ if 0x2fa1e <= x && x < 0xe0100 {
+ return false;
+ }
+ if 0xe01f0 <= x && x < 0x110000 {
+ return false;
+ }
+ true
+ }
+}
+
+const SINGLETONS0: &'static [u16] = &[
+ 0xad,
+ 0x378,
+ 0x379,
+ 0x38b,
+ 0x38d,
+ 0x3a2,
+ 0x557,
+ 0x558,
+ 0x560,
+ 0x588,
+ 0x590,
+ 0x61c,
+ 0x61d,
+ 0x6dd,
+ 0x70e,
+ 0x70f,
+ 0x74b,
+ 0x74c,
+ 0x82e,
+ 0x82f,
+ 0x83f,
+ 0x85c,
+ 0x85d,
+ 0x8a1,
+ 0x8ff,
+ 0x978,
+ 0x980,
+ 0x984,
+ 0x98d,
+ 0x98e,
+ 0x991,
+ 0x992,
+ 0x9a9,
+ 0x9b1,
+ 0x9ba,
+ 0x9bb,
+ 0x9c5,
+ 0x9c6,
+ 0x9c9,
+ 0x9ca,
+ 0x9de,
+ 0x9e4,
+ 0x9e5,
+ 0xa04,
+ 0xa11,
+ 0xa12,
+ 0xa29,
+ 0xa31,
+ 0xa34,
+ 0xa37,
+ 0xa3a,
+ 0xa3b,
+ 0xa3d,
+ 0xa49,
+ 0xa4a,
+ 0xa5d,
+ 0xa84,
+ 0xa8e,
+ 0xa92,
+ 0xaa9,
+ 0xab1,
+ 0xab4,
+ 0xaba,
+ 0xabb,
+ 0xac6,
+ 0xaca,
+ 0xace,
+ 0xacf,
+ 0xae4,
+ 0xae5,
+ 0xb04,
+ 0xb0d,
+ 0xb0e,
+ 0xb11,
+ 0xb12,
+ 0xb29,
+ 0xb31,
+ 0xb34,
+ 0xb3a,
+ 0xb3b,
+ 0xb45,
+ 0xb46,
+ 0xb49,
+ 0xb4a,
+ 0xb5e,
+ 0xb64,
+ 0xb65,
+ 0xb84,
+ 0xb91,
+ 0xb9b,
+ 0xb9d,
+ 0xbc9,
+ 0xbce,
+ 0xbcf,
+ 0xc04,
+ 0xc0d,
+ 0xc11,
+ 0xc29,
+ 0xc34,
+ 0xc45,
+ 0xc49,
+ 0xc57,
+ 0xc64,
+ 0xc65,
+ 0xc80,
+ 0xc81,
+ 0xc84,
+ 0xc8d,
+ 0xc91,
+ 0xca9,
+ 0xcb4,
+ 0xcba,
+ 0xcbb,
+ 0xcc5,
+ 0xcc9,
+ 0xcdf,
+ 0xce4,
+ 0xce5,
+ 0xcf0,
+ 0xd04,
+ 0xd0d,
+ 0xd11,
+ 0xd3b,
+ 0xd3c,
+ 0xd45,
+ 0xd49,
+ 0xd64,
+ 0xd65,
+ 0xd80,
+ 0xd81,
+ 0xd84,
+ 0xdb2,
+ 0xdbc,
+ 0xdbe,
+ 0xdbf,
+ 0xdd5,
+ 0xdd7,
+ 0xe83,
+ 0xe85,
+ 0xe86,
+ 0xe89,
+ 0xe8b,
+ 0xe8c,
+ 0xe98,
+ 0xea0,
+ 0xea4,
+ 0xea6,
+ 0xea8,
+ 0xea9,
+ 0xeac,
+ 0xeba,
+ 0xebe,
+ 0xebf,
+ 0xec5,
+ 0xec7,
+ 0xece,
+ 0xecf,
+ 0xeda,
+ 0xedb,
+ 0xf48,
+ 0xf98,
+ 0xfbd,
+ 0xfcd,
+ 0x10c6,
+ 0x10ce,
+ 0x10cf,
+ 0x1249,
+ 0x124e,
+ 0x124f,
+ 0x1257,
+ 0x1259,
+ 0x125e,
+ 0x125f,
+ 0x1289,
+ 0x128e,
+ 0x128f,
+ 0x12b1,
+ 0x12b6,
+ 0x12b7,
+ 0x12bf,
+ 0x12c1,
+ 0x12c6,
+ 0x12c7,
+ 0x12d7,
+ 0x1311,
+ 0x1316,
+ 0x1317,
+ 0x135b,
+ 0x135c,
+ 0x1680,
+ 0x170d,
+ 0x176d,
+ 0x1771,
+ 0x17de,
+ 0x17df,
+ 0x180e,
+ 0x180f,
+ 0x196e,
+ 0x196f,
+ 0x1a1c,
+ 0x1a1d,
+ 0x1a5f,
+ 0x1a7d,
+ 0x1a7e,
+ 0x1f16,
+ 0x1f17,
+ 0x1f1e,
+ 0x1f1f,
+ 0x1f46,
+ 0x1f47,
+ 0x1f4e,
+ 0x1f4f,
+ 0x1f58,
+ 0x1f5a,
+ 0x1f5c,
+ 0x1f5e,
+ 0x1f7e,
+ 0x1f7f,
+ 0x1fb5,
+ 0x1fc5,
+ 0x1fd4,
+ 0x1fd5,
+ 0x1fdc,
+ 0x1ff0,
+ 0x1ff1,
+ 0x1ff5,
+ 0x2072,
+ 0x2073,
+ 0x208f,
+ 0x2700,
+ 0x2c2f,
+ 0x2c5f,
+ 0x2d26,
+ 0x2d2e,
+ 0x2d2f,
+ 0x2da7,
+ 0x2daf,
+ 0x2db7,
+ 0x2dbf,
+ 0x2dc7,
+ 0x2dcf,
+ 0x2dd7,
+ 0x2ddf,
+ 0x2e9a,
+ 0x3040,
+ 0x3097,
+ 0x3098,
+ 0x318f,
+ 0x321f,
+ 0x32ff,
+ 0xa78f,
+ 0xa9ce,
+ 0xaa4e,
+ 0xaa4f,
+ 0xaa5a,
+ 0xaa5b,
+ 0xab07,
+ 0xab08,
+ 0xab0f,
+ 0xab10,
+ 0xab27,
+ 0xabee,
+ 0xabef,
+ 0xfa6e,
+ 0xfa6f,
+ 0xfb37,
+ 0xfb3d,
+ 0xfb3f,
+ 0xfb42,
+ 0xfb45,
+ 0xfd90,
+ 0xfd91,
+ 0xfdfe,
+ 0xfdff,
+ 0xfe53,
+ 0xfe67,
+ 0xfe75,
+ 0xffc8,
+ 0xffc9,
+ 0xffd0,
+ 0xffd1,
+ 0xffd8,
+ 0xffd9,
+ 0xffe7,
+ 0xfffe,
+ 0xffff,
+];
+const SINGLETONS1: &'static [u16] = &[
+ 0xc,
+ 0x27,
+ 0x3b,
+ 0x3e,
+ 0x4e,
+ 0x4f,
+ 0x31f,
+ 0x39e,
+ 0x49e,
+ 0x49f,
+ 0x806,
+ 0x807,
+ 0x809,
+ 0x836,
+ 0x83d,
+ 0x83e,
+ 0x856,
+ 0xa04,
+ 0xa14,
+ 0xa18,
+ 0xb56,
+ 0xb57,
+ 0x10bd,
+ 0x1135,
+ 0xd127,
+ 0xd128,
+ 0xd455,
+ 0xd49d,
+ 0xd4a0,
+ 0xd4a1,
+ 0xd4a3,
+ 0xd4a4,
+ 0xd4a7,
+ 0xd4a8,
+ 0xd4ad,
+ 0xd4ba,
+ 0xd4bc,
+ 0xd4c4,
+ 0xd506,
+ 0xd50b,
+ 0xd50c,
+ 0xd515,
+ 0xd51d,
+ 0xd53a,
+ 0xd53f,
+ 0xd545,
+ 0xd551,
+ 0xd6a6,
+ 0xd6a7,
+ 0xd7cc,
+ 0xd7cd,
+ 0xee04,
+ 0xee20,
+ 0xee23,
+ 0xee25,
+ 0xee26,
+ 0xee28,
+ 0xee33,
+ 0xee38,
+ 0xee3a,
+ 0xee48,
+ 0xee4a,
+ 0xee4c,
+ 0xee50,
+ 0xee53,
+ 0xee55,
+ 0xee56,
+ 0xee58,
+ 0xee5a,
+ 0xee5c,
+ 0xee5e,
+ 0xee60,
+ 0xee63,
+ 0xee65,
+ 0xee66,
+ 0xee6b,
+ 0xee73,
+ 0xee78,
+ 0xee7d,
+ 0xee7f,
+ 0xee8a,
+ 0xeea4,
+ 0xeeaa,
+ 0xf0af,
+ 0xf0b0,
+ 0xf0bf,
+ 0xf0c0,
+ 0xf0d0,
+ 0xf12f,
+ 0xf336,
+ 0xf3c5,
+ 0xf43f,
+ 0xf441,
+ 0xf4f8,
+ 0xf53e,
+ 0xf53f,
+];
+const NORMAL0: &'static [u16] = &[
+ 0x0, 0x20,
+ 0x7f, 0x22,
+ 0x37f, 0x5,
+ 0x528, 0x9,
+ 0x58b, 0x4,
+ 0x5c8, 0x8,
+ 0x5eb, 0x5,
+ 0x5f5, 0x11,
+ 0x7b2, 0xe,
+ 0x7fb, 0x5,
+ 0x85f, 0x41,
+ 0x8ad, 0x37,
+ 0x9b3, 0x3,
+ 0x9cf, 0x8,
+ 0x9d8, 0x4,
+ 0x9fc, 0x5,
+ 0xa0b, 0x4,
+ 0xa43, 0x4,
+ 0xa4e, 0x3,
+ 0xa52, 0x7,
+ 0xa5f, 0x7,
+ 0xa76, 0xb,
+ 0xad1, 0xf,
+ 0xaf2, 0xf,
+ 0xb4e, 0x8,
+ 0xb58, 0x4,
+ 0xb78, 0xa,
+ 0xb8b, 0x3,
+ 0xb96, 0x3,
+ 0xba0, 0x3,
+ 0xba5, 0x3,
+ 0xbab, 0x3,
+ 0xbba, 0x4,
+ 0xbc3, 0x3,
+ 0xbd1, 0x6,
+ 0xbd8, 0xe,
+ 0xbfb, 0x6,
+ 0xc3a, 0x3,
+ 0xc4e, 0x7,
+ 0xc5a, 0x6,
+ 0xc70, 0x8,
+ 0xcce, 0x7,
+ 0xcd7, 0x7,
+ 0xcf3, 0xf,
+ 0xd4f, 0x8,
+ 0xd58, 0x8,
+ 0xd76, 0x3,
+ 0xd97, 0x3,
+ 0xdc7, 0x3,
+ 0xdcb, 0x4,
+ 0xde0, 0x12,
+ 0xdf5, 0xc,
+ 0xe3b, 0x4,
+ 0xe5c, 0x25,
+ 0xe8e, 0x6,
+ 0xee0, 0x20,
+ 0xf6d, 0x4,
+ 0xfdb, 0x25,
+ 0x10c8, 0x5,
+ 0x137d, 0x3,
+ 0x139a, 0x6,
+ 0x13f5, 0xb,
+ 0x169d, 0x3,
+ 0x16f1, 0xf,
+ 0x1715, 0xb,
+ 0x1737, 0x9,
+ 0x1754, 0xc,
+ 0x1774, 0xc,
+ 0x17ea, 0x6,
+ 0x17fa, 0x6,
+ 0x181a, 0x6,
+ 0x1878, 0x8,
+ 0x18ab, 0x5,
+ 0x18f6, 0xa,
+ 0x191d, 0x3,
+ 0x192c, 0x4,
+ 0x193c, 0x4,
+ 0x1941, 0x3,
+ 0x1975, 0xb,
+ 0x19ac, 0x4,
+ 0x19ca, 0x6,
+ 0x19db, 0x3,
+ 0x1a8a, 0x6,
+ 0x1a9a, 0x6,
+ 0x1aae, 0x52,
+ 0x1b4c, 0x4,
+ 0x1b7d, 0x3,
+ 0x1bf4, 0x8,
+ 0x1c38, 0x3,
+ 0x1c4a, 0x3,
+ 0x1c80, 0x40,
+ 0x1cc8, 0x8,
+ 0x1cf7, 0x9,
+ 0x1de7, 0x15,
+ 0x1fff, 0x11,
+ 0x2028, 0x8,
+ 0x205f, 0x11,
+ 0x209d, 0x3,
+ 0x20ba, 0x16,
+ 0x20f1, 0xf,
+ 0x218a, 0x6,
+ 0x23f4, 0xc,
+ 0x2427, 0x19,
+ 0x244b, 0x15,
+ 0x2b4d, 0x3,
+ 0x2b5a, 0xa6,
+ 0x2cf4, 0x5,
+ 0x2d28, 0x5,
+ 0x2d68, 0x7,
+ 0x2d71, 0xe,
+ 0x2d97, 0x9,
+ 0x2e3c, 0x44,
+ 0x2ef4, 0xc,
+ 0x2fd6, 0x1a,
+ 0x2ffc, 0x5,
+ 0x3100, 0x5,
+ 0x312e, 0x3,
+ 0x31bb, 0x5,
+ 0x31e4, 0xc,
+ 0x3400, 0x19c0,
+ 0x4e00, 0x5200,
+ 0xa48d, 0x3,
+ 0xa4c7, 0x9,
+ 0xa62c, 0x14,
+ 0xa698, 0x7,
+ 0xa6f8, 0x8,
+ 0xa794, 0xc,
+ 0xa7ab, 0x4d,
+ 0xa82c, 0x4,
+ 0xa83a, 0x6,
+ 0xa878, 0x8,
+ 0xa8c5, 0x9,
+ 0xa8da, 0x6,
+ 0xa8fc, 0x4,
+ 0xa954, 0xb,
+ 0xa97d, 0x3,
+ 0xa9da, 0x4,
+ 0xa9e0, 0x20,
+ 0xaa37, 0x9,
+ 0xaa7c, 0x4,
+ 0xaac3, 0x18,
+ 0xaaf7, 0xa,
+ 0xab17, 0x9,
+ 0xab2f, 0x91,
+ 0xabfa, 0x2bb6,
+ 0xd7c7, 0x4,
+ 0xd7fc, 0x2104,
+ 0xfada, 0x26,
+ 0xfb07, 0xc,
+ 0xfb18, 0x5,
+ 0xfbc2, 0x11,
+ 0xfd40, 0x10,
+ 0xfdc8, 0x28,
+ 0xfe1a, 0x6,
+ 0xfe27, 0x9,
+ 0xfe6c, 0x4,
+ 0xfefd, 0x4,
+ 0xffbf, 0x3,
+ 0xffdd, 0x3,
+ 0xffef, 0xd,
+];
+const NORMAL1: &'static [u16] = &[
+ 0x5e, 0x22,
+ 0xfb, 0x5,
+ 0x103, 0x4,
+ 0x134, 0x3,
+ 0x18b, 0x5,
+ 0x19c, 0x34,
+ 0x1fe, 0x82,
+ 0x29d, 0x3,
+ 0x2d1, 0x2f,
+ 0x324, 0xc,
+ 0x34b, 0x35,
+ 0x3c4, 0x4,
+ 0x3d6, 0x2a,
+ 0x4aa, 0x356,
+ 0x839, 0x3,
+ 0x860, 0xa0,
+ 0x91c, 0x3,
+ 0x93a, 0x5,
+ 0x940, 0x40,
+ 0x9b8, 0x6,
+ 0x9c0, 0x40,
+ 0xa07, 0x5,
+ 0xa34, 0x4,
+ 0xa3b, 0x4,
+ 0xa48, 0x8,
+ 0xa59, 0x7,
+ 0xa80, 0x80,
+ 0xb36, 0x3,
+ 0xb73, 0x5,
+ 0xb80, 0x80,
+ 0xc49, 0x217,
+ 0xe7f, 0x181,
+ 0x104e, 0x4,
+ 0x1070, 0x10,
+ 0x10c2, 0xe,
+ 0x10e9, 0x7,
+ 0x10fa, 0x6,
+ 0x1144, 0x3c,
+ 0x11c9, 0x7,
+ 0x11da, 0x4a6,
+ 0x16b8, 0x8,
+ 0x16ca, 0x936,
+ 0x236f, 0x91,
+ 0x2463, 0xd,
+ 0x2474, 0xb8c,
+ 0x342f, 0x33d1,
+ 0x6a39, 0x4c7,
+ 0x6f45, 0xb,
+ 0x6f7f, 0x10,
+ 0x6fa0, 0x4060,
+ 0xb002, 0x1ffe,
+ 0xd0f6, 0xa,
+ 0xd173, 0x8,
+ 0xd1de, 0x22,
+ 0xd246, 0xba,
+ 0xd357, 0x9,
+ 0xd372, 0x8e,
+ 0xd547, 0x3,
+ 0xd800, 0x1600,
+ 0xee3c, 0x6,
+ 0xee43, 0x4,
+ 0xee9c, 0x5,
+ 0xeebc, 0x34,
+ 0xeef2, 0x10e,
+ 0xf02c, 0x4,
+ 0xf094, 0xc,
+ 0xf0e0, 0x20,
+ 0xf10b, 0x5,
+ 0xf16c, 0x4,
+ 0xf19b, 0x4b,
+ 0xf203, 0xd,
+ 0xf23b, 0x5,
+ 0xf249, 0x7,
+ 0xf252, 0xae,
+ 0xf321, 0xf,
+ 0xf37d, 0x3,
+ 0xf394, 0xc,
+ 0xf3cb, 0x15,
+ 0xf3f1, 0xf,
+ 0xf4fd, 0x3,
+ 0xf544, 0xc,
+ 0xf568, 0x93,
+ 0xf641, 0x4,
+ 0xf650, 0x30,
+ 0xf6c6, 0x3a,
+ 0xf774, 0x88c,
+];
diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs
index e5eb8f2..173c55e 100644
--- a/src/libcore/fmt/mod.rs
+++ b/src/libcore/fmt/mod.rs
@@ -1383,7 +1383,7 @@
f.write_char('"')?;
let mut from = 0;
for (i, c) in self.char_indices() {
- let esc = c.escape_default();
+ let esc = c.escape_debug();
// If char needs escaping, flush backlog so far and write, else skip
if esc.len() != 1 {
f.write_str(&self[from..i])?;
@@ -1409,7 +1409,7 @@
impl Debug for char {
fn fmt(&self, f: &mut Formatter) -> Result {
f.write_char('\'')?;
- for c in self.escape_default() {
+ for c in self.escape_debug() {
f.write_char(c)?
}
f.write_char('\'')
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index 0ad1f67..fabb390 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -103,17 +103,17 @@
#[macro_use]
mod uint_macros;
-#[path = "num/isize.rs"] pub mod isize;
-#[path = "num/i8.rs"] pub mod i8;
-#[path = "num/i16.rs"] pub mod i16;
-#[path = "num/i32.rs"] pub mod i32;
-#[path = "num/i64.rs"] pub mod i64;
+#[path = "num/isize.rs"] pub mod isize;
+#[path = "num/i8.rs"] pub mod i8;
+#[path = "num/i16.rs"] pub mod i16;
+#[path = "num/i32.rs"] pub mod i32;
+#[path = "num/i64.rs"] pub mod i64;
#[path = "num/usize.rs"] pub mod usize;
-#[path = "num/u8.rs"] pub mod u8;
-#[path = "num/u16.rs"] pub mod u16;
-#[path = "num/u32.rs"] pub mod u32;
-#[path = "num/u64.rs"] pub mod u64;
+#[path = "num/u8.rs"] pub mod u8;
+#[path = "num/u16.rs"] pub mod u16;
+#[path = "num/u32.rs"] pub mod u32;
+#[path = "num/u64.rs"] pub mod u64;
#[path = "num/f32.rs"] pub mod f32;
#[path = "num/f64.rs"] pub mod f64;
@@ -161,5 +161,6 @@
pub mod fmt;
// note: does not need to be public
+mod char_private;
mod iter_private;
mod tuple;
diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs
index 43868d1..b0c79a3 100644
--- a/src/libcore/macros.rs
+++ b/src/libcore/macros.rs
@@ -35,6 +35,17 @@
/// 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 @@
/// 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
///
/// ```
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index 97648cc..4636811 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -611,6 +611,31 @@
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 @@
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 @@
(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
diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index a32c9da..fdcadd4 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -459,6 +459,19 @@
///
/// 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 {
diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs
index 47d9deb..2a7a0b6 100644
--- a/src/libcore/sync/atomic.rs
+++ b/src/libcore/sync/atomic.rs
@@ -74,6 +74,8 @@
//! ```
#![stable(feature = "rust1", since = "1.0.0")]
+#![cfg_attr(not(target_has_atomic = "8"), allow(dead_code))]
+#![cfg_attr(not(target_has_atomic = "8"), allow(unused_imports))]
use self::Ordering::*;
diff --git a/src/libcoretest/char.rs b/src/libcoretest/char.rs
index c8906fe..4632419 100644
--- a/src/libcoretest/char.rs
+++ b/src/libcoretest/char.rs
@@ -124,6 +124,49 @@
}
#[test]
+fn test_escape_debug() {
+ fn string(c: char) -> String {
+ c.escape_debug().collect()
+ }
+ let s = string('\n');
+ assert_eq!(s, "\\n");
+ let s = string('\r');
+ assert_eq!(s, "\\r");
+ let s = string('\'');
+ assert_eq!(s, "\\'");
+ let s = string('"');
+ assert_eq!(s, "\\\"");
+ let s = string(' ');
+ assert_eq!(s, " ");
+ let s = string('a');
+ assert_eq!(s, "a");
+ let s = string('~');
+ assert_eq!(s, "~");
+ let s = string('é');
+ assert_eq!(s, "é");
+ let s = string('\x00');
+ assert_eq!(s, "\\u{0}");
+ let s = string('\x1f');
+ assert_eq!(s, "\\u{1f}");
+ let s = string('\x7f');
+ assert_eq!(s, "\\u{7f}");
+ let s = string('\u{80}');
+ assert_eq!(s, "\\u{80}");
+ let s = string('\u{ff}');
+ assert_eq!(s, "\u{ff}");
+ let s = string('\u{11b}');
+ assert_eq!(s, "\u{11b}");
+ let s = string('\u{1d4b6}');
+ assert_eq!(s, "\u{1d4b6}");
+ let s = string('\u{200b}'); // zero width space
+ assert_eq!(s, "\\u{200b}");
+ let s = string('\u{e000}'); // private use 1
+ assert_eq!(s, "\\u{e000}");
+ let s = string('\u{100000}'); // private use 2
+ assert_eq!(s, "\\u{100000}");
+}
+
+#[test]
fn test_escape_default() {
fn string(c: char) -> String {
c.escape_default().collect()
@@ -142,18 +185,28 @@
assert_eq!(s, "a");
let s = string('~');
assert_eq!(s, "~");
+ let s = string('é');
+ assert_eq!(s, "\\u{e9}");
let s = string('\x00');
assert_eq!(s, "\\u{0}");
let s = string('\x1f');
assert_eq!(s, "\\u{1f}");
let s = string('\x7f');
assert_eq!(s, "\\u{7f}");
+ let s = string('\u{80}');
+ assert_eq!(s, "\\u{80}");
let s = string('\u{ff}');
assert_eq!(s, "\\u{ff}");
let s = string('\u{11b}');
assert_eq!(s, "\\u{11b}");
let s = string('\u{1d4b6}');
assert_eq!(s, "\\u{1d4b6}");
+ let s = string('\u{200b}'); // zero width space
+ assert_eq!(s, "\\u{200b}");
+ let s = string('\u{e000}'); // private use 1
+ assert_eq!(s, "\\u{e000}");
+ let s = string('\u{100000}'); // private use 2
+ assert_eq!(s, "\\u{100000}");
}
#[test]
diff --git a/src/libcoretest/lib.rs b/src/libcoretest/lib.rs
index 1ef2b58..9428b40 100644
--- a/src/libcoretest/lib.rs
+++ b/src/libcoretest/lib.rs
@@ -14,6 +14,7 @@
#![feature(borrow_state)]
#![feature(box_syntax)]
#![feature(cell_extras)]
+#![feature(char_escape_debug)]
#![feature(const_fn)]
#![feature(core_private_bignum)]
#![feature(core_private_diy_float)]
@@ -29,10 +30,9 @@
#![feature(slice_patterns)]
#![feature(step_by)]
#![feature(test)]
-#![feature(unboxed_closures)]
+#![feature(try_from)]
#![feature(unicode)]
#![feature(unique)]
-#![feature(try_from)]
extern crate core;
extern crate test;
diff --git a/src/libflate/Cargo.toml b/src/libflate/Cargo.toml
index 52aa6bb..5423da9 100644
--- a/src/libflate/Cargo.toml
+++ b/src/libflate/Cargo.toml
@@ -11,4 +11,4 @@
[build-dependencies]
build_helper = { path = "../build_helper" }
-gcc = "0.3"
+gcc = "0.3.27"
diff --git a/src/liblibc b/src/liblibc
index b0d6253..5066b7d 160000
--- a/src/liblibc
+++ b/src/liblibc
@@ -1 +1 @@
-Subproject commit b0d62534d48b711c8978d1bbe8cca0558ae7b1cb
+Subproject commit 5066b7dcab7e700844b0e2ba71b8af9dc627a59b
diff --git a/src/libpanic_unwind/dwarf/eh.rs b/src/libpanic_unwind/dwarf/eh.rs
index 1e9e9e3..2284a9b 100644
--- a/src/libpanic_unwind/dwarf/eh.rs
+++ b/src/libpanic_unwind/dwarf/eh.rs
@@ -108,7 +108,7 @@
}
}
}
- // 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 {
diff --git a/src/libpanic_unwind/gcc.rs b/src/libpanic_unwind/gcc.rs
index cdf772a..fdae8f6 100644
--- a/src/libpanic_unwind/gcc.rs
+++ b/src/libpanic_unwind/gcc.rs
@@ -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 @@
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
+
+// 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_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 = "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
+
+// 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
+
+// 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"))))]
-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.
-
- #[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(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 = "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);
-
- 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,
- }
- }
+#[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;
}
-
- #[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)
+ 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,
+ }
}
}
-// 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;
-
- 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;
- }
-
- #[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) }
- }
-
- #[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 {
+#[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 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!
- } else {
- // cleanup phase
- unsafe { __gcc_personality_v0(state, ue_header, context) }
+ // 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;
+ };
+
+ // 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.
+
+ 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,
}
}
+
+ // 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 {
+ 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.
diff --git a/src/libpanic_unwind/seh64_gnu.rs b/src/libpanic_unwind/seh64_gnu.rs
index 7dc4288..3642e24 100644
--- a/src/libpanic_unwind/seh64_gnu.rs
+++ b/src/libpanic_unwind/seh64_gnu.rs
@@ -81,6 +81,7 @@
// 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))]
diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs
index 73b9665..c924753 100644
--- a/src/librustc/dep_graph/dep_node.rs
+++ b/src/librustc/dep_graph/dep_node.rs
@@ -9,6 +9,7 @@
// except according to those terms.
use std::fmt::Debug;
+use std::sync::Arc;
macro_rules! try_opt {
($e:expr) => (
@@ -45,6 +46,10 @@
// in an extern crate.
MetaData(D),
+ // Represents some artifact that we save to disk. Note that these
+ // do not have a def-id as part of their identifier.
+ WorkProduct(Arc<WorkProductId>),
+
// Represents different phases in the compiler.
CrateReader,
CollectLanguageItems,
@@ -189,6 +194,11 @@
TransCrate => Some(TransCrate),
TransWriteMetadata => Some(TransWriteMetadata),
LinkBinary => Some(LinkBinary),
+
+ // work product names do not need to be mapped, because
+ // they are always absolute.
+ WorkProduct(ref id) => Some(WorkProduct(id.clone())),
+
Hir(ref d) => op(d).map(Hir),
MetaData(ref d) => op(d).map(MetaData),
CollectItem(ref d) => op(d).map(CollectItem),
@@ -229,3 +239,12 @@
}
}
}
+
+/// A "work product" corresponds to a `.o` (or other) file that we
+/// save in between runs. These ids do not have a DefId but rather
+/// some independent path or string that persists between runs without
+/// the need to be mapped or unmapped. (This ensures we can serialize
+/// them even in the absence of a tcx.)
+#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
+pub struct WorkProductId(pub String);
+
diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs
index 741ad65..bb027b1 100644
--- a/src/librustc/dep_graph/graph.rs
+++ b/src/librustc/dep_graph/graph.rs
@@ -9,22 +9,45 @@
// except according to those terms.
use hir::def_id::DefId;
+use rustc_data_structures::fnv::FnvHashMap;
+use session::config::OutputType;
+use std::cell::{Ref, RefCell};
use std::rc::Rc;
+use std::sync::Arc;
-use super::dep_node::DepNode;
+use super::dep_node::{DepNode, WorkProductId};
use super::query::DepGraphQuery;
use super::raii;
use super::thread::{DepGraphThreadData, DepMessage};
#[derive(Clone)]
pub struct DepGraph {
- data: Rc<DepGraphThreadData>
+ data: Rc<DepGraphData>
+}
+
+struct DepGraphData {
+ /// We send messages to the thread to let it build up the dep-graph
+ /// from the current run.
+ thread: DepGraphThreadData,
+
+ /// When we load, there may be `.o` files, cached mir, or other such
+ /// things available to us. If we find that they are not dirty, we
+ /// load the path to the file storing those work-products here into
+ /// this map. We can later look for and extract that data.
+ previous_work_products: RefCell<FnvHashMap<Arc<WorkProductId>, WorkProduct>>,
+
+ /// Work-products that we generate in this run.
+ work_products: RefCell<FnvHashMap<Arc<WorkProductId>, WorkProduct>>,
}
impl DepGraph {
pub fn new(enabled: bool) -> DepGraph {
DepGraph {
- data: Rc::new(DepGraphThreadData::new(enabled))
+ data: Rc::new(DepGraphData {
+ thread: DepGraphThreadData::new(enabled),
+ previous_work_products: RefCell::new(FnvHashMap()),
+ work_products: RefCell::new(FnvHashMap())
+ })
}
}
@@ -32,19 +55,19 @@
/// then the other methods on this `DepGraph` will have no net effect.
#[inline]
pub fn enabled(&self) -> bool {
- self.data.enabled()
+ self.data.thread.enabled()
}
pub fn query(&self) -> DepGraphQuery<DefId> {
- self.data.query()
+ self.data.thread.query()
}
pub fn in_ignore<'graph>(&'graph self) -> raii::IgnoreTask<'graph> {
- raii::IgnoreTask::new(&self.data)
+ raii::IgnoreTask::new(&self.data.thread)
}
pub fn in_task<'graph>(&'graph self, key: DepNode<DefId>) -> raii::DepTask<'graph> {
- raii::DepTask::new(&self.data, key)
+ raii::DepTask::new(&self.data.thread, key)
}
pub fn with_ignore<OP,R>(&self, op: OP) -> R
@@ -62,10 +85,84 @@
}
pub fn read(&self, v: DepNode<DefId>) {
- self.data.enqueue(DepMessage::Read(v));
+ self.data.thread.enqueue(DepMessage::Read(v));
}
pub fn write(&self, v: DepNode<DefId>) {
- self.data.enqueue(DepMessage::Write(v));
+ self.data.thread.enqueue(DepMessage::Write(v));
}
+
+ /// Indicates that a previous work product exists for `v`. This is
+ /// invoked during initial start-up based on what nodes are clean
+ /// (and what files exist in the incr. directory).
+ pub fn insert_previous_work_product(&self, v: &Arc<WorkProductId>, data: WorkProduct) {
+ debug!("insert_previous_work_product({:?}, {:?})", v, data);
+ self.data.previous_work_products.borrow_mut()
+ .insert(v.clone(), data);
+ }
+
+ /// Indicates that we created the given work-product in this run
+ /// for `v`. This record will be preserved and loaded in the next
+ /// run.
+ pub fn insert_work_product(&self, v: &Arc<WorkProductId>, data: WorkProduct) {
+ debug!("insert_work_product({:?}, {:?})", v, data);
+ self.data.work_products.borrow_mut()
+ .insert(v.clone(), data);
+ }
+
+ /// Check whether a previous work product exists for `v` and, if
+ /// so, return the path that leads to it. Used to skip doing work.
+ pub fn previous_work_product(&self, v: &Arc<WorkProductId>) -> Option<WorkProduct> {
+ self.data.previous_work_products.borrow()
+ .get(v)
+ .cloned()
+ }
+
+ /// Access the map of work-products created during this run. Only
+ /// used during saving of the dep-graph.
+ pub fn work_products(&self) -> Ref<FnvHashMap<Arc<WorkProductId>, WorkProduct>> {
+ self.data.work_products.borrow()
+ }
+}
+
+/// A "work product" is an intermediate result that we save into the
+/// incremental directory for later re-use. The primary example are
+/// the object files that we save for each partition at code
+/// generation time.
+///
+/// Each work product is associated with a dep-node, representing the
+/// process that produced the work-product. If that dep-node is found
+/// to be dirty when we load up, then we will delete the work-product
+/// at load time. If the work-product is found to be clean, then we
+/// will keep a record in the `previous_work_products` list.
+///
+/// In addition, work products have an associated hash. This hash is
+/// an extra hash that can be used to decide if the work-product from
+/// a previous compilation can be re-used (in addition to the dirty
+/// edges check).
+///
+/// As the primary example, consider the object files we generate for
+/// each partition. In the first run, we create partitions based on
+/// the symbols that need to be compiled. For each partition P, we
+/// hash the symbols in P and create a `WorkProduct` record associated
+/// with `DepNode::TransPartition(P)`; the hash is the set of symbols
+/// in P.
+///
+/// The next time we compile, if the `DepNode::TransPartition(P)` is
+/// judged to be clean (which means none of the things we read to
+/// generate the partition were found to be dirty), it will be loaded
+/// into previous work products. We will then regenerate the set of
+/// symbols in the partition P and hash them (note that new symbols
+/// may be added -- for example, new monomorphizations -- even if
+/// nothing in P changed!). We will compare that hash against the
+/// previous hash. If it matches up, we can reuse the object file.
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
+pub struct WorkProduct {
+ /// Extra hash used to decide if work-product is still suitable;
+ /// note that this is *not* a hash of the work-product itself.
+ /// See documentation on `WorkProduct` type for an example.
+ pub input_hash: u64,
+
+ /// Saved files associated with this CGU
+ pub saved_files: Vec<(OutputType, String)>,
}
diff --git a/src/librustc/dep_graph/mod.rs b/src/librustc/dep_graph/mod.rs
index e65f6bb..a499cb1 100644
--- a/src/librustc/dep_graph/mod.rs
+++ b/src/librustc/dep_graph/mod.rs
@@ -20,7 +20,9 @@
pub use self::dep_tracking_map::{DepTrackingMap, DepTrackingMapConfig};
pub use self::dep_node::DepNode;
+pub use self::dep_node::WorkProductId;
pub use self::graph::DepGraph;
+pub use self::graph::WorkProduct;
pub use self::query::DepGraphQuery;
pub use self::visit::visit_all_items_in_krate;
pub use self::raii::DepTask;
diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs
index 442c85a..aded220 100644
--- a/src/librustc/hir/intravisit.rs
+++ b/src/librustc/hir/intravisit.rs
@@ -94,11 +94,14 @@
///////////////////////////////////////////////////////////////////////////
+ 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_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 @@
s: &'v VariantData,
_: Name,
_: &'v Generics,
- _: NodeId,
+ _parent_id: NodeId,
_: Span) {
walk_struct_def(self, s)
}
@@ -225,24 +228,28 @@
}
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, ¯o_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_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 @@
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 @@
}
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 @@
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 @@
}
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 @@
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_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_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_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_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_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, ¶m.bounds);
walk_list!(visitor, visit_ty, ¶m.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 @@
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_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_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 @@
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 @@
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 @@
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 @@
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 @@
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_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_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,11 +862,12 @@
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)
}
}
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, PartialEq, Eq)]
pub struct IdRange {
pub min: NodeId,
pub max: NodeId,
@@ -837,15 +885,17 @@
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 +911,12 @@
}
}
-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 +924,7 @@
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()
}
diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs
index 693d7a2..b3f222b 100644
--- a/src/librustc/hir/map/collector.rs
+++ b/src/librustc/hir/map/collector.rs
@@ -197,7 +197,7 @@
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) {
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index 960e32a..aed3613 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -32,6 +32,7 @@
use arena::TypedArena;
use std::cell::RefCell;
+use std::cmp;
use std::io;
use std::mem;
@@ -127,7 +128,10 @@
EntryStructCtor(id, _) => id,
EntryLifetime(id, _) => id,
EntryTyParam(id, _) => id,
- _ => return None
+
+ NotPresent |
+ RootCrate |
+ RootInlinedParent(_) => return None,
})
}
@@ -196,6 +200,10 @@
map: RefCell<Vec<MapEntry<'ast>>>,
definitions: RefCell<Definitions>,
+
+ /// All NodeIds that are numerically greater or equal to this value come
+ /// from inlined items.
+ local_node_id_watermark: NodeId,
}
impl<'ast> Map<'ast> {
@@ -550,6 +558,13 @@
}
}
+ pub fn expect_inlined_item(&self, id: NodeId) -> &'ast InlinedItem {
+ match self.find_entry(id) {
+ Some(RootInlinedParent(inlined_item)) => inlined_item,
+ _ => bug!("expected inlined item, found {}", self.node_to_string(id)),
+ }
+ }
+
/// Returns the name associated with the given NodeId's AST.
pub fn name(&self, id: NodeId) -> Name {
match self.get(id) {
@@ -649,6 +664,10 @@
pub fn node_to_user_string(&self, id: NodeId) -> String {
node_id_to_string(self, id, false)
}
+
+ pub fn is_inlined(&self, id: NodeId) -> bool {
+ id >= self.local_node_id_watermark
+ }
}
pub struct NodesMatchingSuffix<'a, 'ast:'a> {
@@ -765,13 +784,37 @@
}
/// A Folder that updates IDs and Span's according to fold_ops.
-struct IdAndSpanUpdater<F> {
- fold_ops: F
+pub struct IdAndSpanUpdater<F> {
+ fold_ops: F,
+ min_id_assigned: NodeId,
+ max_id_assigned: NodeId,
+}
+
+impl<F: FoldOps> IdAndSpanUpdater<F> {
+ pub fn new(fold_ops: F) -> IdAndSpanUpdater<F> {
+ IdAndSpanUpdater {
+ fold_ops: fold_ops,
+ min_id_assigned: ::std::u32::MAX,
+ max_id_assigned: ::std::u32::MIN,
+ }
+ }
+
+ pub fn id_range(&self) -> intravisit::IdRange {
+ intravisit::IdRange {
+ min: self.min_id_assigned,
+ max: self.max_id_assigned + 1,
+ }
+ }
}
impl<F: FoldOps> Folder for IdAndSpanUpdater<F> {
fn new_id(&mut self, id: NodeId) -> NodeId {
- self.fold_ops.new_id(id)
+ let id = self.fold_ops.new_id(id);
+
+ self.min_id_assigned = cmp::min(self.min_id_assigned, id);
+ self.max_id_assigned = cmp::max(self.max_id_assigned, id);
+
+ id
}
fn new_span(&mut self, span: Span) -> Span {
@@ -802,11 +845,14 @@
entries, vector_length, (entries as f64 / vector_length as f64) * 100.);
}
+ let local_node_id_watermark = map.len() as NodeId;
+
Map {
forest: forest,
dep_graph: forest.dep_graph.clone(),
map: RefCell::new(map),
definitions: RefCell::new(definitions),
+ local_node_id_watermark: local_node_id_watermark
}
}
@@ -818,7 +864,7 @@
ii: InlinedItem,
fold_ops: F)
-> &'ast InlinedItem {
- let mut fld = IdAndSpanUpdater { fold_ops: fold_ops };
+ let mut fld = IdAndSpanUpdater::new(fold_ops);
let ii = match ii {
II::Item(i) => II::Item(i.map(|i| fld.fold_item(i))),
II::TraitItem(d, ti) => {
@@ -835,6 +881,12 @@
let ii = map.forest.inlined_items.alloc(ii);
let ii_parent_id = fld.new_id(DUMMY_NODE_ID);
+ // Assert that the ii_parent_id is the last NodeId in our reserved range
+ assert!(ii_parent_id == fld.max_id_assigned);
+ // Assert that we did not violate the invariant that all inlined HIR items
+ // have NodeIds greater than or equal to `local_node_id_watermark`
+ assert!(fld.min_id_assigned >= map.local_node_id_watermark);
+
let defs = &mut *map.definitions.borrow_mut();
let mut def_collector = DefCollector::extend(ii_parent_id,
parent_def_path.clone(),
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index 655f80e..20bf4f7 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -1362,9 +1362,9 @@
/// 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,
diff --git a/src/librustc/infer/bivariate.rs b/src/librustc/infer/bivariate.rs
index 96b14a6..125f815 100644
--- a/src/librustc/infer/bivariate.rs
+++ b/src/librustc/infer/bivariate.rs
@@ -32,22 +32,27 @@
use ty::TyVar;
use ty::relate::{Relate, RelateResult, TypeRelation};
-pub struct Bivariate<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
- fields: CombineFields<'a, 'gcx, 'tcx>
+pub struct Bivariate<'combine, 'infcx: 'combine, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> {
+ fields: &'combine mut CombineFields<'infcx, 'gcx, 'tcx>,
+ a_is_expected: bool,
}
-impl<'a, 'gcx, 'tcx> Bivariate<'a, 'gcx, 'tcx> {
- pub fn new(fields: CombineFields<'a, 'gcx, 'tcx>) -> Bivariate<'a, 'gcx, 'tcx> {
- Bivariate { fields: fields }
+impl<'combine, 'infcx, 'gcx, 'tcx> Bivariate<'combine, 'infcx, 'gcx, 'tcx> {
+ pub fn new(fields: &'combine mut CombineFields<'infcx, 'gcx, 'tcx>, a_is_expected: bool)
+ -> Bivariate<'combine, 'infcx, 'gcx, 'tcx>
+ {
+ Bivariate { fields: fields, a_is_expected: a_is_expected }
}
}
-impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Bivariate<'a, 'gcx, 'tcx> {
+impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
+ for Bivariate<'combine, 'infcx, 'gcx, 'tcx>
+{
fn tag(&self) -> &'static str { "Bivariate" }
- fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> { self.fields.tcx() }
+ fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> { self.fields.tcx() }
- fn a_is_expected(&self) -> bool { self.fields.a_is_expected }
+ fn a_is_expected(&self) -> bool { self.a_is_expected }
fn relate_with_variance<T: Relate<'tcx>>(&mut self,
variance: ty::Variance,
@@ -86,12 +91,12 @@
}
(&ty::TyInfer(TyVar(a_id)), _) => {
- self.fields.instantiate(b, BiTo, a_id)?;
+ self.fields.instantiate(b, BiTo, a_id, self.a_is_expected)?;
Ok(a)
}
(_, &ty::TyInfer(TyVar(b_id))) => {
- self.fields.instantiate(a, BiTo, b_id)?;
+ self.fields.instantiate(a, BiTo, b_id, self.a_is_expected)?;
Ok(a)
}
diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs
index c9235d0..b4818f9 100644
--- a/src/librustc/infer/combine.rs
+++ b/src/librustc/infer/combine.rs
@@ -52,21 +52,20 @@
use syntax_pos::Span;
#[derive(Clone)]
-pub struct CombineFields<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
- pub infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
- pub a_is_expected: bool,
+pub struct CombineFields<'infcx, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> {
+ pub infcx: &'infcx InferCtxt<'infcx, 'gcx, 'tcx>,
pub trace: TypeTrace<'tcx>,
pub cause: Option<ty::relate::Cause>,
pub obligations: PredicateObligations<'tcx>,
}
-impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
+impl<'infcx, 'gcx, 'tcx> InferCtxt<'infcx, 'gcx, 'tcx> {
pub fn super_combine_tys<R>(&self,
relation: &mut R,
a: Ty<'tcx>,
b: Ty<'tcx>)
-> RelateResult<'tcx, Ty<'tcx>>
- where R: TypeRelation<'a, 'gcx, 'tcx>
+ where R: TypeRelation<'infcx, 'gcx, 'tcx>
{
let a_is_expected = relation.a_is_expected();
@@ -150,42 +149,36 @@
}
}
-impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
- pub fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> {
+impl<'infcx, 'gcx, 'tcx> CombineFields<'infcx, 'gcx, 'tcx> {
+ pub fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> {
self.infcx.tcx
}
- pub fn switch_expected(&self) -> CombineFields<'a, 'gcx, 'tcx> {
- CombineFields {
- a_is_expected: !self.a_is_expected,
- ..(*self).clone()
- }
+ pub fn equate<'a>(&'a mut self, a_is_expected: bool) -> Equate<'a, 'infcx, 'gcx, 'tcx> {
+ Equate::new(self, a_is_expected)
}
- pub fn equate(&self) -> Equate<'a, 'gcx, 'tcx> {
- Equate::new(self.clone())
+ pub fn bivariate<'a>(&'a mut self, a_is_expected: bool) -> Bivariate<'a, 'infcx, 'gcx, 'tcx> {
+ Bivariate::new(self, a_is_expected)
}
- pub fn bivariate(&self) -> Bivariate<'a, 'gcx, 'tcx> {
- Bivariate::new(self.clone())
+ pub fn sub<'a>(&'a mut self, a_is_expected: bool) -> Sub<'a, 'infcx, 'gcx, 'tcx> {
+ Sub::new(self, a_is_expected)
}
- pub fn sub(&self) -> Sub<'a, 'gcx, 'tcx> {
- Sub::new(self.clone())
+ pub fn lub<'a>(&'a mut self, a_is_expected: bool) -> Lub<'a, 'infcx, 'gcx, 'tcx> {
+ Lub::new(self, a_is_expected)
}
- pub fn lub(&self) -> Lub<'a, 'gcx, 'tcx> {
- Lub::new(self.clone())
+ pub fn glb<'a>(&'a mut self, a_is_expected: bool) -> Glb<'a, 'infcx, 'gcx, 'tcx> {
+ Glb::new(self, a_is_expected)
}
- pub fn glb(&self) -> Glb<'a, 'gcx, 'tcx> {
- Glb::new(self.clone())
- }
-
- pub fn instantiate(&self,
+ pub fn instantiate(&mut self,
a_ty: Ty<'tcx>,
dir: RelationDir,
- b_vid: ty::TyVid)
+ b_vid: ty::TyVid,
+ a_is_expected: bool)
-> RelateResult<'tcx, ()>
{
let mut stack = Vec::new();
@@ -255,10 +248,11 @@
// to associate causes/spans with each of the relations in
// the stack to get this right.
match dir {
- BiTo => self.bivariate().relate(&a_ty, &b_ty),
- EqTo => self.equate().relate(&a_ty, &b_ty),
- SubtypeOf => self.sub().relate(&a_ty, &b_ty),
- SupertypeOf => self.sub().relate_with_variance(ty::Contravariant, &a_ty, &b_ty),
+ BiTo => self.bivariate(a_is_expected).relate(&a_ty, &b_ty),
+ EqTo => self.equate(a_is_expected).relate(&a_ty, &b_ty),
+ SubtypeOf => self.sub(a_is_expected).relate(&a_ty, &b_ty),
+ SupertypeOf => self.sub(a_is_expected).relate_with_variance(
+ ty::Contravariant, &a_ty, &b_ty),
}?;
}
diff --git a/src/librustc/infer/equate.rs b/src/librustc/infer/equate.rs
index 408f22c..e06f730 100644
--- a/src/librustc/infer/equate.rs
+++ b/src/librustc/infer/equate.rs
@@ -15,29 +15,29 @@
use ty::{self, Ty, TyCtxt};
use ty::TyVar;
use ty::relate::{Relate, RelateResult, TypeRelation};
-use traits::PredicateObligations;
/// Ensures `a` is made equal to `b`. Returns `a` on success.
-pub struct Equate<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
- fields: CombineFields<'a, 'gcx, 'tcx>
+pub struct Equate<'combine, 'infcx: 'combine, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> {
+ fields: &'combine mut CombineFields<'infcx, 'gcx, 'tcx>,
+ a_is_expected: bool,
}
-impl<'a, 'gcx, 'tcx> Equate<'a, 'gcx, 'tcx> {
- pub fn new(fields: CombineFields<'a, 'gcx, 'tcx>) -> Equate<'a, 'gcx, 'tcx> {
- Equate { fields: fields }
- }
-
- pub fn obligations(self) -> PredicateObligations<'tcx> {
- self.fields.obligations
+impl<'combine, 'infcx, 'gcx, 'tcx> Equate<'combine, 'infcx, 'gcx, 'tcx> {
+ pub fn new(fields: &'combine mut CombineFields<'infcx, 'gcx, 'tcx>, a_is_expected: bool)
+ -> Equate<'combine, 'infcx, 'gcx, 'tcx>
+ {
+ Equate { fields: fields, a_is_expected: a_is_expected }
}
}
-impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Equate<'a, 'gcx, 'tcx> {
+impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
+ for Equate<'combine, 'infcx, 'gcx, 'tcx>
+{
fn tag(&self) -> &'static str { "Equate" }
- fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> { self.fields.tcx() }
+ fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> { self.fields.tcx() }
- fn a_is_expected(&self) -> bool { self.fields.a_is_expected }
+ fn a_is_expected(&self) -> bool { self.a_is_expected }
fn relate_with_variance<T: Relate<'tcx>>(&mut self,
_: ty::Variance,
@@ -63,12 +63,12 @@
}
(&ty::TyInfer(TyVar(a_id)), _) => {
- self.fields.instantiate(b, EqTo, a_id)?;
+ self.fields.instantiate(b, EqTo, a_id, self.a_is_expected)?;
Ok(a)
}
(_, &ty::TyInfer(TyVar(b_id))) => {
- self.fields.instantiate(a, EqTo, b_id)?;
+ self.fields.instantiate(a, EqTo, b_id, self.a_is_expected)?;
Ok(a)
}
@@ -93,7 +93,7 @@
-> RelateResult<'tcx, ty::Binder<T>>
where T: Relate<'tcx>
{
- self.fields.higher_ranked_sub(a, b)?;
- self.fields.higher_ranked_sub(b, a)
+ self.fields.higher_ranked_sub(a, b, self.a_is_expected)?;
+ self.fields.higher_ranked_sub(b, a, self.a_is_expected)
}
}
diff --git a/src/librustc/infer/error_reporting.rs b/src/librustc/infer/error_reporting.rs
index 96ecad6..511cc32 100644
--- a/src/librustc/infer/error_reporting.rs
+++ b/src/librustc/infer/error_reporting.rs
@@ -83,7 +83,7 @@
use infer::{self, TypeOrigin};
use middle::region;
use ty::subst;
-use ty::{self, Ty, TyCtxt, TypeFoldable};
+use ty::{self, TyCtxt, TypeFoldable};
use ty::{Region, ReFree};
use ty::error::TypeError;
@@ -462,52 +462,6 @@
}
}
- fn report_type_error(&self,
- trace: TypeTrace<'tcx>,
- terr: &TypeError<'tcx>)
- -> DiagnosticBuilder<'tcx> {
- let (expected, found) = match self.values_str(&trace.values) {
- Some(v) => v,
- None => {
- return self.tcx.sess.diagnostic().struct_dummy(); /* derived error */
- }
- };
-
- let is_simple_error = if let &TypeError::Sorts(ref values) = terr {
- values.expected.is_primitive() && values.found.is_primitive()
- } else {
- false
- };
-
- let mut err = struct_span_err!(self.tcx.sess,
- trace.origin.span(),
- E0308,
- "{}",
- trace.origin);
-
- if !is_simple_error || check_old_school() {
- err.note_expected_found(&"type", &expected, &found);
- }
-
- err.span_label(trace.origin.span(), &terr);
-
- self.check_and_note_conflicting_crates(&mut err, terr, trace.origin.span());
-
- match trace.origin {
- TypeOrigin::MatchExpressionArm(_, arm_span, source) => match source {
- hir::MatchSource::IfLetDesugar{..} => {
- err.span_note(arm_span, "`if let` arm with an incompatible type");
- }
- _ => {
- err.span_note(arm_span, "match arm with an incompatible type");
- }
- },
- _ => ()
- }
-
- err
- }
-
/// Adds a note if the types come from similarly named crates
fn check_and_note_conflicting_crates(&self,
err: &mut DiagnosticBuilder,
@@ -550,42 +504,102 @@
}
}
+ fn note_error_origin(&self,
+ err: &mut DiagnosticBuilder<'tcx>,
+ origin: &TypeOrigin)
+ {
+ match origin {
+ &TypeOrigin::MatchExpressionArm(_, arm_span, source) => match source {
+ hir::MatchSource::IfLetDesugar {..} => {
+ err.span_note(arm_span, "`if let` arm with an incompatible type");
+ }
+ _ => {
+ err.span_note(arm_span, "match arm with an incompatible type");
+ }
+ },
+ _ => ()
+ }
+ }
+
+ pub fn note_type_err(&self,
+ diag: &mut DiagnosticBuilder<'tcx>,
+ origin: TypeOrigin,
+ values: Option<ValuePairs<'tcx>>,
+ terr: &TypeError<'tcx>)
+ {
+ let expected_found = match values {
+ None => None,
+ Some(values) => match self.values_str(&values) {
+ Some((expected, found)) => Some((expected, found)),
+ None => {
+ // Derived error. Cancel the emitter.
+ self.tcx.sess.diagnostic().cancel(diag);
+ return
+ }
+ }
+ };
+
+ let span = origin.span();
+
+ let mut is_simple_error = false;
+
+ if let Some((expected, found)) = expected_found {
+ is_simple_error = if let &TypeError::Sorts(ref values) = terr {
+ values.expected.is_primitive() && values.found.is_primitive()
+ } else {
+ false
+ };
+
+ if !is_simple_error || check_old_school() {
+ diag.note_expected_found(&"type", &expected, &found);
+ }
+ }
+
+ if !is_simple_error && check_old_school() {
+ diag.span_note(span, &format!("{}", terr));
+ } else {
+ diag.span_label(span, &terr);
+ }
+
+ self.note_error_origin(diag, &origin);
+ self.check_and_note_conflicting_crates(diag, terr, span);
+ self.tcx.note_and_explain_type_err(diag, terr, span);
+ }
+
pub fn report_and_explain_type_error(&self,
trace: TypeTrace<'tcx>,
terr: &TypeError<'tcx>)
- -> DiagnosticBuilder<'tcx> {
- let span = trace.origin.span();
- let mut err = self.report_type_error(trace, terr);
- self.tcx.note_and_explain_type_err(&mut err, terr, span);
- err
+ -> DiagnosticBuilder<'tcx>
+ {
+ // FIXME: do we want to use a different error code for each origin?
+ let mut diag = struct_span_err!(
+ self.tcx.sess, trace.origin.span(), E0308,
+ "{}", trace.origin.as_failure_str()
+ );
+ self.note_type_err(&mut diag, trace.origin, Some(trace.values), terr);
+ diag
}
- /// Returns a string of the form "expected `{}`, found `{}`", or None if this is a derived
- /// error.
+ /// Returns a string of the form "expected `{}`, found `{}`".
fn values_str(&self, values: &ValuePairs<'tcx>) -> Option<(String, String)> {
match *values {
infer::Types(ref exp_found) => self.expected_found_str(exp_found),
infer::TraitRefs(ref exp_found) => self.expected_found_str(exp_found),
- infer::PolyTraitRefs(ref exp_found) => self.expected_found_str(exp_found)
+ infer::PolyTraitRefs(ref exp_found) => self.expected_found_str(exp_found),
}
}
- fn expected_found_str<T: fmt::Display + Resolvable<'tcx> + TypeFoldable<'tcx>>(
+ fn expected_found_str<T: fmt::Display + TypeFoldable<'tcx>>(
&self,
exp_found: &ty::error::ExpectedFound<T>)
-> Option<(String, String)>
{
- let expected = exp_found.expected.resolve(self);
- if expected.references_error() {
+ let exp_found = self.resolve_type_vars_if_possible(exp_found);
+ if exp_found.references_error() {
return None;
}
- let found = exp_found.found.resolve(self);
- if found.references_error() {
- return None;
- }
-
- Some((format!("{}", expected), format!("{}", found)))
+ Some((format!("{}", exp_found.expected), format!("{}", exp_found.found)))
}
fn report_generic_bound_failure(&self,
@@ -1608,59 +1622,21 @@
fn note_region_origin(&self, err: &mut DiagnosticBuilder, origin: &SubregionOrigin<'tcx>) {
match *origin {
infer::Subtype(ref trace) => {
- let desc = match trace.origin {
- TypeOrigin::Misc(_) => {
- "types are compatible"
- }
- TypeOrigin::MethodCompatCheck(_) => {
- "method type is compatible with trait"
- }
- TypeOrigin::ExprAssignable(_) => {
- "expression is assignable"
- }
- TypeOrigin::RelateTraitRefs(_) => {
- "traits are compatible"
- }
- TypeOrigin::RelateSelfType(_) => {
- "self type matches impl self type"
- }
- TypeOrigin::RelateOutputImplTypes(_) => {
- "trait type parameters matches those \
- specified on the impl"
- }
- TypeOrigin::MatchExpressionArm(_, _, _) => {
- "match arms have compatible types"
- }
- TypeOrigin::IfExpression(_) => {
- "if and else have compatible types"
- }
- TypeOrigin::IfExpressionWithNoElse(_) => {
- "if may be missing an else clause"
- }
- TypeOrigin::RangeExpression(_) => {
- "start and end of range have compatible types"
- }
- TypeOrigin::EquatePredicate(_) => {
- "equality where clause is satisfied"
- }
- };
+ if let Some((expected, found)) = self.values_str(&trace.values) {
+ // FIXME: do we want a "the" here?
+ err.span_note(
+ trace.origin.span(),
+ &format!("...so that {} (expected {}, found {})",
+ trace.origin.as_requirement_str(), expected, found));
+ } else {
+ // FIXME: this really should be handled at some earlier stage. Our
+ // handling of region checking when type errors are present is
+ // *terrible*.
- match self.values_str(&trace.values) {
- Some((expected, found)) => {
- err.span_note(
- trace.origin.span(),
- &format!("...so that {} (expected {}, found {})",
- desc, expected, found));
- }
- None => {
- // Really should avoid printing this error at
- // all, since it is derived, but that would
- // require more refactoring than I feel like
- // doing right now. - nmatsakis
- err.span_note(
- trace.origin.span(),
- &format!("...so that {}", desc));
- }
+ err.span_note(
+ trace.origin.span(),
+ &format!("...so that {}",
+ trace.origin.as_requirement_str()));
}
}
infer::Reborrow(span) => {
@@ -1803,32 +1779,6 @@
}
}
-pub trait Resolvable<'tcx> {
- fn resolve<'a, 'gcx>(&self, infcx: &InferCtxt<'a, 'gcx, 'tcx>) -> Self;
-}
-
-impl<'tcx> Resolvable<'tcx> for Ty<'tcx> {
- fn resolve<'a, 'gcx>(&self, infcx: &InferCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
- infcx.resolve_type_vars_if_possible(self)
- }
-}
-
-impl<'tcx> Resolvable<'tcx> for ty::TraitRef<'tcx> {
- fn resolve<'a, 'gcx>(&self, infcx: &InferCtxt<'a, 'gcx, 'tcx>)
- -> ty::TraitRef<'tcx> {
- infcx.resolve_type_vars_if_possible(self)
- }
-}
-
-impl<'tcx> Resolvable<'tcx> for ty::PolyTraitRef<'tcx> {
- fn resolve<'a, 'gcx>(&self,
- infcx: &InferCtxt<'a, 'gcx, 'tcx>)
- -> ty::PolyTraitRef<'tcx>
- {
- infcx.resolve_type_vars_if_possible(self)
- }
-}
-
fn lifetimes_in_scope<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
scope_id: ast::NodeId)
-> Vec<hir::LifetimeDef> {
diff --git a/src/librustc/infer/glb.rs b/src/librustc/infer/glb.rs
index b7085f0..5dd85a3 100644
--- a/src/librustc/infer/glb.rs
+++ b/src/librustc/infer/glb.rs
@@ -15,29 +15,29 @@
use ty::{self, Ty, TyCtxt};
use ty::relate::{Relate, RelateResult, TypeRelation};
-use traits::PredicateObligations;
/// "Greatest lower bound" (common subtype)
-pub struct Glb<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
- fields: CombineFields<'a, 'gcx, 'tcx>
+pub struct Glb<'combine, 'infcx: 'combine, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> {
+ fields: &'combine mut CombineFields<'infcx, 'gcx, 'tcx>,
+ a_is_expected: bool,
}
-impl<'a, 'gcx, 'tcx> Glb<'a, 'gcx, 'tcx> {
- pub fn new(fields: CombineFields<'a, 'gcx, 'tcx>) -> Glb<'a, 'gcx, 'tcx> {
- Glb { fields: fields }
- }
-
- pub fn obligations(self) -> PredicateObligations<'tcx> {
- self.fields.obligations
+impl<'combine, 'infcx, 'gcx, 'tcx> Glb<'combine, 'infcx, 'gcx, 'tcx> {
+ pub fn new(fields: &'combine mut CombineFields<'infcx, 'gcx, 'tcx>, a_is_expected: bool)
+ -> Glb<'combine, 'infcx, 'gcx, 'tcx>
+ {
+ Glb { fields: fields, a_is_expected: a_is_expected }
}
}
-impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Glb<'a, 'gcx, 'tcx> {
+impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
+ for Glb<'combine, 'infcx, 'gcx, 'tcx>
+{
fn tag(&self) -> &'static str { "Glb" }
- fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> { self.fields.tcx() }
+ fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> { self.fields.tcx() }
- fn a_is_expected(&self) -> bool { self.fields.a_is_expected }
+ fn a_is_expected(&self) -> bool { self.a_is_expected }
fn relate_with_variance<T: Relate<'tcx>>(&mut self,
variance: ty::Variance,
@@ -46,10 +46,10 @@
-> RelateResult<'tcx, T>
{
match variance {
- ty::Invariant => self.fields.equate().relate(a, b),
+ ty::Invariant => self.fields.equate(self.a_is_expected).relate(a, b),
ty::Covariant => self.relate(a, b),
- ty::Bivariant => self.fields.bivariate().relate(a, b),
- ty::Contravariant => self.fields.lub().relate(a, b),
+ ty::Bivariant => self.fields.bivariate(self.a_is_expected).relate(a, b),
+ ty::Contravariant => self.fields.lub(self.a_is_expected).relate(a, b),
}
}
@@ -71,17 +71,19 @@
-> RelateResult<'tcx, ty::Binder<T>>
where T: Relate<'tcx>
{
- self.fields.higher_ranked_glb(a, b)
+ self.fields.higher_ranked_glb(a, b, self.a_is_expected)
}
}
-impl<'a, 'gcx, 'tcx> LatticeDir<'a, 'gcx, 'tcx> for Glb<'a, 'gcx, 'tcx> {
- fn infcx(&self) -> &'a InferCtxt<'a, 'gcx, 'tcx> {
+impl<'combine, 'infcx, 'gcx, 'tcx> LatticeDir<'infcx, 'gcx, 'tcx>
+ for Glb<'combine, 'infcx, 'gcx, 'tcx>
+{
+ fn infcx(&self) -> &'infcx InferCtxt<'infcx, 'gcx, 'tcx> {
self.fields.infcx
}
- fn relate_bound(&self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> {
- let mut sub = self.fields.sub();
+ fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> {
+ let mut sub = self.fields.sub(self.a_is_expected);
sub.relate(&v, &a)?;
sub.relate(&v, &b)?;
Ok(())
diff --git a/src/librustc/infer/higher_ranked/mod.rs b/src/librustc/infer/higher_ranked/mod.rs
index 03a0991..743d613 100644
--- a/src/librustc/infer/higher_ranked/mod.rs
+++ b/src/librustc/infer/higher_ranked/mod.rs
@@ -40,7 +40,7 @@
}
impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
- pub fn higher_ranked_sub<T>(&self, a: &Binder<T>, b: &Binder<T>)
+ pub fn higher_ranked_sub<T>(&mut self, a: &Binder<T>, b: &Binder<T>, a_is_expected: bool)
-> RelateResult<'tcx, Binder<T>>
where T: Relate<'tcx>
{
@@ -77,11 +77,11 @@
debug!("b_prime={:?}", b_prime);
// Compare types now that bound regions have been replaced.
- let result = self.sub().relate(&a_prime, &b_prime)?;
+ let result = self.sub(a_is_expected).relate(&a_prime, &b_prime)?;
// Presuming type comparison succeeds, we need to check
// that the skolemized regions do not "leak".
- self.infcx.leak_check(!self.a_is_expected, span, &skol_map, snapshot)?;
+ self.infcx.leak_check(!a_is_expected, span, &skol_map, snapshot)?;
// We are finished with the skolemized regions now so pop
// them off.
@@ -106,10 +106,11 @@
/// NB. It should not happen that there are LBR appearing in `U`
/// that do not appear in `T`. If that happens, those regions are
/// unconstrained, and this routine replaces them with `'static`.
- pub fn higher_ranked_match<T, U>(&self,
+ pub fn higher_ranked_match<T, U>(&mut self,
span: Span,
a_pair: &Binder<(T, U)>,
- b_match: &T)
+ b_match: &T,
+ a_is_expected: bool)
-> RelateResult<'tcx, HrMatchResult<U>>
where T: Relate<'tcx>,
U: TypeFoldable<'tcx>
@@ -129,7 +130,7 @@
debug!("higher_ranked_match: skol_map={:?}", skol_map);
// Equate types now that bound regions have been replaced.
- try!(self.equate().relate(&a_match, &b_match));
+ try!(self.equate(a_is_expected).relate(&a_match, &b_match));
// Map each skolemized region to a vector of other regions that it
// must be equated with. (Note that this vector may include other
@@ -221,7 +222,7 @@
});
}
- pub fn higher_ranked_lub<T>(&self, a: &Binder<T>, b: &Binder<T>)
+ pub fn higher_ranked_lub<T>(&mut self, a: &Binder<T>, b: &Binder<T>, a_is_expected: bool)
-> RelateResult<'tcx, Binder<T>>
where T: Relate<'tcx>
{
@@ -239,7 +240,7 @@
// Collect constraints.
let result0 =
- self.lub().relate(&a_with_fresh, &b_with_fresh)?;
+ self.lub(a_is_expected).relate(&a_with_fresh, &b_with_fresh)?;
let result0 =
self.infcx.resolve_type_vars_if_possible(&result0);
debug!("lub result0 = {:?}", result0);
@@ -311,7 +312,7 @@
}
}
- pub fn higher_ranked_glb<T>(&self, a: &Binder<T>, b: &Binder<T>)
+ pub fn higher_ranked_glb<T>(&mut self, a: &Binder<T>, b: &Binder<T>, a_is_expected: bool)
-> RelateResult<'tcx, Binder<T>>
where T: Relate<'tcx>
{
@@ -333,7 +334,7 @@
// Collect constraints.
let result0 =
- self.glb().relate(&a_with_fresh, &b_with_fresh)?;
+ self.glb(a_is_expected).relate(&a_with_fresh, &b_with_fresh)?;
let result0 =
self.infcx.resolve_type_vars_if_possible(&result0);
debug!("glb result0 = {:?}", result0);
diff --git a/src/librustc/infer/lattice.rs b/src/librustc/infer/lattice.rs
index 1a2bc4b..eda7842 100644
--- a/src/librustc/infer/lattice.rs
+++ b/src/librustc/infer/lattice.rs
@@ -40,7 +40,7 @@
// Relates the type `v` to `a` and `b` such that `v` represents
// the LUB/GLB of `a` and `b` as appropriate.
- fn relate_bound(&self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()>;
+ fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()>;
}
pub fn super_lattice_tys<'a, 'gcx, 'tcx, L>(this: &mut L,
diff --git a/src/librustc/infer/lub.rs b/src/librustc/infer/lub.rs
index bd46f3a..ad1b32f 100644
--- a/src/librustc/infer/lub.rs
+++ b/src/librustc/infer/lub.rs
@@ -15,29 +15,29 @@
use ty::{self, Ty, TyCtxt};
use ty::relate::{Relate, RelateResult, TypeRelation};
-use traits::PredicateObligations;
/// "Least upper bound" (common supertype)
-pub struct Lub<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
- fields: CombineFields<'a, 'gcx, 'tcx>
+pub struct Lub<'combine, 'infcx: 'combine, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> {
+ fields: &'combine mut CombineFields<'infcx, 'gcx, 'tcx>,
+ a_is_expected: bool,
}
-impl<'a, 'gcx, 'tcx> Lub<'a, 'gcx, 'tcx> {
- pub fn new(fields: CombineFields<'a, 'gcx, 'tcx>) -> Lub<'a, 'gcx, 'tcx> {
- Lub { fields: fields }
- }
-
- pub fn obligations(self) -> PredicateObligations<'tcx> {
- self.fields.obligations
+impl<'combine, 'infcx, 'gcx, 'tcx> Lub<'combine, 'infcx, 'gcx, 'tcx> {
+ pub fn new(fields: &'combine mut CombineFields<'infcx, 'gcx, 'tcx>, a_is_expected: bool)
+ -> Lub<'combine, 'infcx, 'gcx, 'tcx>
+ {
+ Lub { fields: fields, a_is_expected: a_is_expected }
}
}
-impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Lub<'a, 'gcx, 'tcx> {
+impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
+ for Lub<'combine, 'infcx, 'gcx, 'tcx>
+{
fn tag(&self) -> &'static str { "Lub" }
- fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> { self.fields.tcx() }
+ fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> { self.fields.tcx() }
- fn a_is_expected(&self) -> bool { self.fields.a_is_expected }
+ fn a_is_expected(&self) -> bool { self.a_is_expected }
fn relate_with_variance<T: Relate<'tcx>>(&mut self,
variance: ty::Variance,
@@ -46,10 +46,10 @@
-> RelateResult<'tcx, T>
{
match variance {
- ty::Invariant => self.fields.equate().relate(a, b),
+ ty::Invariant => self.fields.equate(self.a_is_expected).relate(a, b),
ty::Covariant => self.relate(a, b),
- ty::Bivariant => self.fields.bivariate().relate(a, b),
- ty::Contravariant => self.fields.glb().relate(a, b),
+ ty::Bivariant => self.fields.bivariate(self.a_is_expected).relate(a, b),
+ ty::Contravariant => self.fields.glb(self.a_is_expected).relate(a, b),
}
}
@@ -71,17 +71,19 @@
-> RelateResult<'tcx, ty::Binder<T>>
where T: Relate<'tcx>
{
- self.fields.higher_ranked_lub(a, b)
+ self.fields.higher_ranked_lub(a, b, self.a_is_expected)
}
}
-impl<'a, 'gcx, 'tcx> LatticeDir<'a, 'gcx, 'tcx> for Lub<'a, 'gcx, 'tcx> {
- fn infcx(&self) -> &'a InferCtxt<'a, 'gcx, 'tcx> {
+impl<'combine, 'infcx, 'gcx, 'tcx> LatticeDir<'infcx, 'gcx, 'tcx>
+ for Lub<'combine, 'infcx, 'gcx, 'tcx>
+{
+ fn infcx(&self) -> &'infcx InferCtxt<'infcx, 'gcx, 'tcx> {
self.fields.infcx
}
- fn relate_bound(&self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> {
- let mut sub = self.fields.sub();
+ fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> {
+ let mut sub = self.fields.sub(self.a_is_expected);
sub.relate(&a, &v)?;
sub.relate(&b, &v)?;
Ok(())
diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs
index 2ea2978..be9adf7 100644
--- a/src/librustc/infer/mod.rs
+++ b/src/librustc/infer/mod.rs
@@ -32,7 +32,7 @@
use ty::{TyVid, IntVid, FloatVid};
use ty::{self, Ty, TyCtxt};
use ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric};
-use ty::fold::TypeFoldable;
+use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
use ty::relate::{Relate, RelateResult, TypeRelation};
use traits::{self, PredicateObligations, ProjectionMode};
use rustc_data_structures::unify::{self, UnificationTable};
@@ -48,18 +48,18 @@
use self::region_inference::{RegionVarBindings, RegionSnapshot};
use self::unify_key::ToType;
-pub mod bivariate;
-pub mod combine;
-pub mod equate;
+mod bivariate;
+mod combine;
+mod equate;
pub mod error_reporting;
-pub mod glb;
+mod glb;
mod higher_ranked;
pub mod lattice;
-pub mod lub;
+mod lub;
pub mod region_inference;
pub mod resolve;
mod freshen;
-pub mod sub;
+mod sub;
pub mod type_variable;
pub mod unify_key;
@@ -196,12 +196,6 @@
// FIXME(eddyb) #11161 is the original Expr required?
ExprAssignable(Span),
- // Relating trait refs when resolving vtables
- RelateTraitRefs(Span),
-
- // Relating self types when resolving vtables
- RelateSelfType(Span),
-
// Relating trait type parameters to those found in impl etc
RelateOutputImplTypes(Span),
@@ -219,16 +213,26 @@
// `where a == b`
EquatePredicate(Span),
+
+ // `main` has wrong type
+ MainFunctionType(Span),
+
+ // `start` has wrong type
+ StartFunctionType(Span),
+
+ // intrinsic has wrong type
+ IntrinsicType(Span),
+
+ // method receiver
+ MethodReceiver(Span),
}
impl TypeOrigin {
- fn as_str(&self) -> &'static str {
+ fn as_failure_str(&self) -> &'static str {
match self {
&TypeOrigin::Misc(_) |
- &TypeOrigin::RelateSelfType(_) |
&TypeOrigin::RelateOutputImplTypes(_) |
&TypeOrigin::ExprAssignable(_) => "mismatched types",
- &TypeOrigin::RelateTraitRefs(_) => "mismatched traits",
&TypeOrigin::MethodCompatCheck(_) => "method not compatible with trait",
&TypeOrigin::MatchExpressionArm(_, _, source) => match source {
hir::MatchSource::IfLetDesugar{..} => "`if let` arms have incompatible types",
@@ -238,13 +242,31 @@
&TypeOrigin::IfExpressionWithNoElse(_) => "if may be missing an else clause",
&TypeOrigin::RangeExpression(_) => "start and end of range have incompatible types",
&TypeOrigin::EquatePredicate(_) => "equality predicate not satisfied",
+ &TypeOrigin::MainFunctionType(_) => "main function has wrong type",
+ &TypeOrigin::StartFunctionType(_) => "start function has wrong type",
+ &TypeOrigin::IntrinsicType(_) => "intrinsic has wrong type",
+ &TypeOrigin::MethodReceiver(_) => "mismatched method receiver",
}
}
-}
-impl fmt::Display for TypeOrigin {
- fn fmt(&self, f: &mut fmt::Formatter) -> Result<(),fmt::Error> {
- fmt::Display::fmt(self.as_str(), f)
+ fn as_requirement_str(&self) -> &'static str {
+ match self {
+ &TypeOrigin::Misc(_) => "types are compatible",
+ &TypeOrigin::MethodCompatCheck(_) => "method type is compatible with trait",
+ &TypeOrigin::ExprAssignable(_) => "expression is assignable",
+ &TypeOrigin::RelateOutputImplTypes(_) => {
+ "trait type parameters matches those specified on the impl"
+ }
+ &TypeOrigin::MatchExpressionArm(_, _, _) => "match arms have compatible types",
+ &TypeOrigin::IfExpression(_) => "if and else have compatible types",
+ &TypeOrigin::IfExpressionWithNoElse(_) => "if missing an else returns ()",
+ &TypeOrigin::RangeExpression(_) => "start and end of range have compatible types",
+ &TypeOrigin::EquatePredicate(_) => "equality where clause is satisfied",
+ &TypeOrigin::MainFunctionType(_) => "`main` function has the correct type",
+ &TypeOrigin::StartFunctionType(_) => "`start` function has the correct type",
+ &TypeOrigin::IntrinsicType(_) => "intrinsic has the correct type",
+ &TypeOrigin::MethodReceiver(_) => "method receiver has the correct type",
+ }
}
}
@@ -799,11 +821,10 @@
return variables;
}
- fn combine_fields(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>)
+ fn combine_fields(&'a self, trace: TypeTrace<'tcx>)
-> CombineFields<'a, 'gcx, 'tcx> {
CombineFields {
infcx: self,
- a_is_expected: a_is_expected,
trace: trace,
cause: None,
obligations: PredicateObligations::new(),
@@ -814,36 +835,36 @@
-> InferResult<'tcx, T>
where T: Relate<'tcx>
{
- let mut equate = self.combine_fields(a_is_expected, trace).equate();
- let result = equate.relate(a, b);
- result.map(|t| InferOk { value: t, obligations: equate.obligations() })
+ let mut fields = self.combine_fields(trace);
+ let result = fields.equate(a_is_expected).relate(a, b);
+ result.map(move |t| InferOk { value: t, obligations: fields.obligations })
}
pub fn sub<T>(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>, a: &T, b: &T)
-> InferResult<'tcx, T>
where T: Relate<'tcx>
{
- let mut sub = self.combine_fields(a_is_expected, trace).sub();
- let result = sub.relate(a, b);
- result.map(|t| InferOk { value: t, obligations: sub.obligations() })
+ let mut fields = self.combine_fields(trace);
+ let result = fields.sub(a_is_expected).relate(a, b);
+ result.map(move |t| InferOk { value: t, obligations: fields.obligations })
}
pub fn lub<T>(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>, a: &T, b: &T)
-> InferResult<'tcx, T>
where T: Relate<'tcx>
{
- let mut lub = self.combine_fields(a_is_expected, trace).lub();
- let result = lub.relate(a, b);
- result.map(|t| InferOk { value: t, obligations: lub.obligations() })
+ let mut fields = self.combine_fields(trace);
+ let result = fields.lub(a_is_expected).relate(a, b);
+ result.map(move |t| InferOk { value: t, obligations: fields.obligations })
}
pub fn glb<T>(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>, a: &T, b: &T)
-> InferResult<'tcx, T>
where T: Relate<'tcx>
{
- let mut glb = self.combine_fields(a_is_expected, trace).glb();
- let result = glb.relate(a, b);
- result.map(|t| InferOk { value: t, obligations: glb.obligations() })
+ let mut fields = self.combine_fields(trace);
+ let result = fields.glb(a_is_expected).relate(a, b);
+ result.map(move |t| InferOk { value: t, obligations: fields.obligations })
}
fn start_snapshot(&self) -> CombinedSnapshot {
@@ -1468,104 +1489,50 @@
// error type, meaning that an error occurred when typechecking this expression),
// this is a derived error. The error cascaded from another error (that was already
// reported), so it's not useful to display it to the user.
- // The following four methods -- type_error_message_str, type_error_message_str_with_expected,
- // type_error_message, and report_mismatched_types -- implement this logic.
+ // The following methods implement this logic.
// They check if either the actual or expected type is TyError, and don't print the error
// in this case. The typechecker should only ever report type errors involving mismatched
- // types using one of these four methods, and should not call span_err directly for such
+ // types using one of these methods, and should not call span_err directly for such
// errors.
- pub fn type_error_message_str<M>(&self,
- sp: Span,
- mk_msg: M,
- actual_ty: String,
- err: Option<&TypeError<'tcx>>)
- where M: FnOnce(Option<String>, String) -> String,
- {
- self.type_error_message_str_with_expected(sp, mk_msg, None, actual_ty, err)
- }
-
- pub fn type_error_struct_str<M>(&self,
- sp: Span,
- mk_msg: M,
- actual_ty: String,
- err: Option<&TypeError<'tcx>>)
- -> DiagnosticBuilder<'tcx>
- where M: FnOnce(Option<String>, String) -> String,
- {
- self.type_error_struct_str_with_expected(sp, mk_msg, None, actual_ty, err)
- }
-
- pub fn type_error_message_str_with_expected<M>(&self,
- sp: Span,
- mk_msg: M,
- expected_ty: Option<Ty<'tcx>>,
- actual_ty: String,
- err: Option<&TypeError<'tcx>>)
- where M: FnOnce(Option<String>, String) -> String,
- {
- self.type_error_struct_str_with_expected(sp, mk_msg, expected_ty, actual_ty, err)
- .emit();
- }
-
- pub fn type_error_struct_str_with_expected<M>(&self,
- sp: Span,
- mk_msg: M,
- expected_ty: Option<Ty<'tcx>>,
- actual_ty: String,
- err: Option<&TypeError<'tcx>>)
- -> DiagnosticBuilder<'tcx>
- where M: FnOnce(Option<String>, String) -> String,
- {
- debug!("hi! expected_ty = {:?}, actual_ty = {}", expected_ty, actual_ty);
-
- let resolved_expected = expected_ty.map(|e_ty| self.resolve_type_vars_if_possible(&e_ty));
-
- if !resolved_expected.references_error() {
- let error_str = err.map_or("".to_string(), |t_err| {
- format!(" ({})", t_err)
- });
-
- let mut db = self.tcx.sess.struct_span_err(sp, &format!("{}{}",
- mk_msg(resolved_expected.map(|t| self.ty_to_string(t)), actual_ty),
- error_str));
-
- if let Some(err) = err {
- self.tcx.note_and_explain_type_err(&mut db, err, sp);
- }
- db
- } else {
- self.tcx.sess.diagnostic().struct_dummy()
- }
- }
pub fn type_error_message<M>(&self,
sp: Span,
mk_msg: M,
- actual_ty: Ty<'tcx>,
- err: Option<&TypeError<'tcx>>)
+ actual_ty: Ty<'tcx>)
where M: FnOnce(String) -> String,
{
- self.type_error_struct(sp, mk_msg, actual_ty, err).emit();
+ self.type_error_struct(sp, mk_msg, actual_ty).emit();
}
+ // FIXME: this results in errors without an error code. Deprecate?
pub fn type_error_struct<M>(&self,
sp: Span,
mk_msg: M,
- actual_ty: Ty<'tcx>,
- err: Option<&TypeError<'tcx>>)
+ actual_ty: Ty<'tcx>)
-> DiagnosticBuilder<'tcx>
where M: FnOnce(String) -> String,
{
+ self.type_error_struct_with_diag(sp, |actual_ty| {
+ self.tcx.sess.struct_span_err(sp, &mk_msg(actual_ty))
+ }, actual_ty)
+ }
+
+ pub fn type_error_struct_with_diag<M>(&self,
+ sp: Span,
+ mk_diag: M,
+ actual_ty: Ty<'tcx>)
+ -> DiagnosticBuilder<'tcx>
+ where M: FnOnce(String) -> DiagnosticBuilder<'tcx>,
+ {
let actual_ty = self.resolve_type_vars_if_possible(&actual_ty);
+ debug!("type_error_struct_with_diag({:?}, {:?})", sp, actual_ty);
// Don't report an error if actual type is TyError.
if actual_ty.references_error() {
return self.tcx.sess.diagnostic().struct_dummy();
}
- self.type_error_struct_str(sp,
- move |_e, a| { mk_msg(a) },
- self.ty_to_string(actual_ty), err)
+ mk_diag(self.ty_to_string(actual_ty))
}
pub fn report_mismatched_types(&self,
@@ -1646,8 +1613,8 @@
};
let match_pair = match_a.map_bound(|p| (p.projection_ty.trait_ref, p.ty));
- let combine = self.combine_fields(true, trace);
- let result = combine.higher_ranked_match(span, &match_pair, &match_b)?;
+ let mut combine = self.combine_fields(trace);
+ let result = combine.higher_ranked_match(span, &match_pair, &match_b, true)?;
Ok(InferOk { value: result, obligations: combine.obligations })
}
@@ -1833,14 +1800,16 @@
TypeOrigin::MethodCompatCheck(span) => span,
TypeOrigin::ExprAssignable(span) => span,
TypeOrigin::Misc(span) => span,
- TypeOrigin::RelateTraitRefs(span) => span,
- TypeOrigin::RelateSelfType(span) => span,
TypeOrigin::RelateOutputImplTypes(span) => span,
TypeOrigin::MatchExpressionArm(match_span, _, _) => match_span,
TypeOrigin::IfExpression(span) => span,
TypeOrigin::IfExpressionWithNoElse(span) => span,
TypeOrigin::RangeExpression(span) => span,
TypeOrigin::EquatePredicate(span) => span,
+ TypeOrigin::MainFunctionType(span) => span,
+ TypeOrigin::StartFunctionType(span) => span,
+ TypeOrigin::IntrinsicType(span) => span,
+ TypeOrigin::MethodReceiver(span) => span,
}
}
}
@@ -1891,3 +1860,50 @@
}
}
}
+
+impl<'tcx> TypeFoldable<'tcx> for TypeOrigin {
+ fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, _folder: &mut F) -> Self {
+ self.clone()
+ }
+
+ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> bool {
+ false
+ }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for ValuePairs<'tcx> {
+ fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
+ match *self {
+ ValuePairs::Types(ref ef) => {
+ ValuePairs::Types(ef.fold_with(folder))
+ }
+ ValuePairs::TraitRefs(ref ef) => {
+ ValuePairs::TraitRefs(ef.fold_with(folder))
+ }
+ ValuePairs::PolyTraitRefs(ref ef) => {
+ ValuePairs::PolyTraitRefs(ef.fold_with(folder))
+ }
+ }
+ }
+
+ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
+ match *self {
+ ValuePairs::Types(ref ef) => ef.visit_with(visitor),
+ ValuePairs::TraitRefs(ref ef) => ef.visit_with(visitor),
+ ValuePairs::PolyTraitRefs(ref ef) => ef.visit_with(visitor),
+ }
+ }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for TypeTrace<'tcx> {
+ fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
+ TypeTrace {
+ origin: self.origin.fold_with(folder),
+ values: self.values.fold_with(folder)
+ }
+ }
+
+ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
+ self.origin.visit_with(visitor) || self.values.visit_with(visitor)
+ }
+}
diff --git a/src/librustc/infer/sub.rs b/src/librustc/infer/sub.rs
index 680dd0d..2f7f525 100644
--- a/src/librustc/infer/sub.rs
+++ b/src/librustc/infer/sub.rs
@@ -15,28 +15,35 @@
use ty::{self, Ty, TyCtxt};
use ty::TyVar;
use ty::relate::{Cause, Relate, RelateResult, TypeRelation};
-use traits::PredicateObligations;
use std::mem;
/// Ensures `a` is made a subtype of `b`. Returns `a` on success.
-pub struct Sub<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
- fields: CombineFields<'a, 'gcx, 'tcx>,
+pub struct Sub<'combine, 'infcx: 'combine, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> {
+ fields: &'combine mut CombineFields<'infcx, 'gcx, 'tcx>,
+ a_is_expected: bool,
}
-impl<'a, 'gcx, 'tcx> Sub<'a, 'gcx, 'tcx> {
- pub fn new(f: CombineFields<'a, 'gcx, 'tcx>) -> Sub<'a, 'gcx, 'tcx> {
- Sub { fields: f }
+impl<'combine, 'infcx, 'gcx, 'tcx> Sub<'combine, 'infcx, 'gcx, 'tcx> {
+ pub fn new(f: &'combine mut CombineFields<'infcx, 'gcx, 'tcx>, a_is_expected: bool)
+ -> Sub<'combine, 'infcx, 'gcx, 'tcx>
+ {
+ Sub { fields: f, a_is_expected: a_is_expected }
}
- pub fn obligations(self) -> PredicateObligations<'tcx> {
- self.fields.obligations
+ fn with_expected_switched<R, F: FnOnce(&mut Self) -> R>(&mut self, f: F) -> R {
+ self.a_is_expected = !self.a_is_expected;
+ let result = f(self);
+ self.a_is_expected = !self.a_is_expected;
+ result
}
}
-impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Sub<'a, 'gcx, 'tcx> {
+impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
+ for Sub<'combine, 'infcx, 'gcx, 'tcx>
+{
fn tag(&self) -> &'static str { "Sub" }
- fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> { self.fields.infcx.tcx }
- fn a_is_expected(&self) -> bool { self.fields.a_is_expected }
+ fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> { self.fields.infcx.tcx }
+ fn a_is_expected(&self) -> bool { self.a_is_expected }
fn with_cause<F,R>(&mut self, cause: Cause, f: F) -> R
where F: FnOnce(&mut Self) -> R
@@ -56,10 +63,10 @@
-> RelateResult<'tcx, T>
{
match variance {
- ty::Invariant => self.fields.equate().relate(a, b),
+ ty::Invariant => self.fields.equate(self.a_is_expected).relate(a, b),
ty::Covariant => self.relate(a, b),
- ty::Bivariant => self.fields.bivariate().relate(a, b),
- ty::Contravariant => self.fields.switch_expected().sub().relate(b, a),
+ ty::Bivariant => self.fields.bivariate(self.a_is_expected).relate(a, b),
+ ty::Contravariant => self.with_expected_switched(|this| { this.relate(b, a) }),
}
}
@@ -80,12 +87,11 @@
}
(&ty::TyInfer(TyVar(a_id)), _) => {
self.fields
- .switch_expected()
- .instantiate(b, SupertypeOf, a_id)?;
+ .instantiate(b, SupertypeOf, a_id, !self.a_is_expected)?;
Ok(a)
}
(_, &ty::TyInfer(TyVar(b_id))) => {
- self.fields.instantiate(a, SubtypeOf, b_id)?;
+ self.fields.instantiate(a, SubtypeOf, b_id, self.a_is_expected)?;
Ok(a)
}
@@ -116,6 +122,6 @@
-> RelateResult<'tcx, ty::Binder<T>>
where T: Relate<'tcx>
{
- self.fields.higher_ranked_sub(a, b)
+ self.fields.higher_ranked_sub(a, b, self.a_is_expected)
}
}
diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs
index ce3d72d..daac315 100644
--- a/src/librustc/lint/context.rs
+++ b/src/librustc/lint/context.rs
@@ -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 @@
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 @@
};
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 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_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_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_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_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 @@
}
}
+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 @@
// 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);
});
diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs
index fd9463b..32344a7 100644
--- a/src/librustc/middle/cstore.rs
+++ b/src/librustc/middle/cstore.rs
@@ -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};
@@ -120,12 +120,6 @@
pub vis: ty::Visibility,
}
-pub enum FoundAst<'ast> {
- Found(&'ast InlinedItem),
- FoundParent(DefId, &'ast hir::Item),
- NotFound,
-}
-
#[derive(Copy, Clone, Debug)]
pub struct ExternCrate {
/// def_id of an `extern crate` in the current crate that caused
@@ -250,7 +244,10 @@
// misc. metadata
fn maybe_get_item_ast<'a>(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
- -> FoundAst<'tcx>;
+ -> Option<(&'tcx InlinedItem, ast::NodeId)>;
+ fn local_node_for_inlined_defid(&'tcx self, def_id: DefId) -> Option<ast::NodeId>;
+ fn defid_for_inlined_node(&'tcx self, node_id: ast::NodeId) -> Option<DefId>;
+
fn maybe_get_item_mir<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-> Option<Mir<'tcx>>;
fn is_item_mir_available(&self, def: DefId) -> bool;
@@ -292,11 +289,6 @@
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?
@@ -452,7 +444,16 @@
// misc. metadata
fn maybe_get_item_ast<'a>(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
- -> FoundAst<'tcx> { bug!("maybe_get_item_ast") }
+ -> Option<(&'tcx InlinedItem, ast::NodeId)> {
+ bug!("maybe_get_item_ast")
+ }
+ fn local_node_for_inlined_defid(&'tcx self, def_id: DefId) -> Option<ast::NodeId> {
+ bug!("local_node_for_inlined_defid")
+ }
+ fn defid_for_inlined_node(&'tcx self, node_id: ast::NodeId) -> Option<DefId> {
+ bug!("defid_for_inlined_node")
+ }
+
fn maybe_get_item_mir<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-> Option<Mir<'tcx>> { bug!("maybe_get_item_mir") }
fn is_item_mir_available(&self, def: DefId) -> bool {
diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs
index 6fe9811..446767e 100644
--- a/src/librustc/middle/effect.rs
+++ b/src/librustc/middle/effect.rs
@@ -79,7 +79,7 @@
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 @@
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
}
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index 6551e01..18b80a9 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -271,10 +271,19 @@
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
}
}
diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs
index 960305e..a209b1d 100644
--- a/src/librustc/middle/lang_items.rs
+++ b/src/librustc/middle/lang_items.rs
@@ -359,7 +359,6 @@
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;
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index ea3765c..1222b5f 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -390,7 +390,7 @@
// 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
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 28bfb46..0bc3c1a 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -259,6 +259,18 @@
#[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 @@
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 @@
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)
}
}
}
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index a0c2416..6ed91cd 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -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;
@@ -61,7 +61,7 @@
FullDebugInfo,
}
-#[derive(Clone, Copy, PartialEq, Eq, Hash)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
pub enum OutputType {
Bitcode,
Assembly,
@@ -105,6 +105,17 @@
OutputType::DepInfo => "dep-info",
}
}
+
+ pub fn extension(&self) -> &'static str {
+ match *self {
+ OutputType::Bitcode => "bc",
+ OutputType::Assembly => "s",
+ OutputType::LlvmAssembly => "ll",
+ OutputType::Object => "o",
+ OutputType::DepInfo => "d",
+ OutputType::Exe => "",
+ }
+ }
}
#[derive(Clone)]
@@ -215,15 +226,7 @@
flavor: OutputType,
codegen_unit_name: Option<&str>)
-> PathBuf {
- let extension = match flavor {
- OutputType::Bitcode => "bc",
- OutputType::Assembly => "s",
- OutputType::LlvmAssembly => "ll",
- OutputType::Object => "o",
- OutputType::DepInfo => "d",
- OutputType::Exe => "",
- };
-
+ let extension = flavor.extension();
self.temp_path_ext(extension, codegen_unit_name)
}
@@ -327,6 +330,11 @@
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
@@ -455,6 +463,8 @@
pub const parse_bool: Option<&'static str> = None;
pub const parse_opt_bool: Option<&'static str> =
Some("one of: `y`, `yes`, `on`, `n`, `no`, or `off`");
+ pub const parse_all_bool: Option<&'static str> =
+ Some("one of: `y`, `yes`, `on`, `n`, `no`, or `off`");
pub const parse_string: Option<&'static str> = Some("a string");
pub const parse_opt_string: Option<&'static str> = Some("a string");
pub const parse_list: Option<&'static str> = Some("a space-separated list of strings");
@@ -504,6 +514,25 @@
}
}
+ fn parse_all_bool(slot: &mut bool, v: Option<&str>) -> bool {
+ match v {
+ Some(s) => {
+ match s {
+ "n" | "no" | "off" => {
+ *slot = false;
+ }
+ "y" | "yes" | "on" => {
+ *slot = true;
+ }
+ _ => { return false; }
+ }
+
+ true
+ },
+ None => { *slot = true; true }
+ }
+ }
+
fn parse_opt_string(slot: &mut Option<String>, v: Option<&str>) -> bool {
match v {
Some(s) => { *slot = Some(s.to_string()); true },
@@ -652,7 +681,6 @@
"panic strategy to compile crate with"),
}
-
options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
build_debugging_options, "Z", "debugging",
DB_OPTIONS, db_type_desc, dbsetters,
@@ -749,7 +777,7 @@
"dump MIR state at various points in translation"),
dump_mir_dir: Option<String> = (None, parse_opt_string,
"the directory the MIR is dumped into"),
- orbit: bool = (false, parse_bool,
+ orbit: bool = (true, parse_all_bool,
"get MIR where it belongs - everywhere; most importantly, in orbit"),
}
@@ -833,7 +861,10 @@
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);
}
};
@@ -1137,7 +1168,15 @@
})
});
- let debugging_opts = build_debugging_options(matches, error_format);
+ let mut debugging_opts = build_debugging_options(matches, error_format);
+
+ // Incremental compilation only works reliably when translation is done via
+ // MIR, so let's enable -Z orbit if necessary (see #34973).
+ if debugging_opts.incremental.is_some() && !debugging_opts.orbit {
+ early_warn(error_format, "Automatically enabling `-Z orbit` because \
+ `-Z incremental` was specified");
+ debugging_opts.orbit = true;
+ }
let parse_only = debugging_opts.parse_only;
let no_trans = debugging_opts.no_trans;
diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index fa9bc7c..cee1823 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -80,7 +80,7 @@
// forms a unique global identifier for the crate. It is used to allow
// multiple crates with the same name to coexist. See the
// trans::back::symbol_names module for more information.
- pub crate_disambiguator: Cell<ast::Name>,
+ pub crate_disambiguator: RefCell<token::InternedString>,
pub features: RefCell<feature_gate::Features>,
/// The maximum recursion limit for potentially infinitely recursive
@@ -106,6 +106,9 @@
}
impl Session {
+ pub fn local_crate_disambiguator(&self) -> token::InternedString {
+ self.crate_disambiguator.borrow().clone()
+ }
pub fn struct_span_warn<'a, S: Into<MultiSpan>>(&'a self,
sp: S,
msg: &str)
@@ -126,20 +129,14 @@
sp: S,
msg: &str)
-> DiagnosticBuilder<'a> {
- match split_msg_into_multilines(msg) {
- Some(ref msg) => self.diagnostic().struct_span_err(sp, msg),
- None => self.diagnostic().struct_span_err(sp, msg),
- }
+ self.diagnostic().struct_span_err(sp, msg)
}
pub fn struct_span_err_with_code<'a, S: Into<MultiSpan>>(&'a self,
sp: S,
msg: &str,
code: &str)
-> DiagnosticBuilder<'a> {
- match split_msg_into_multilines(msg) {
- Some(ref msg) => self.diagnostic().struct_span_err_with_code(sp, msg, code),
- None => self.diagnostic().struct_span_err_with_code(sp, msg, code),
- }
+ self.diagnostic().struct_span_err_with_code(sp, msg, code)
}
pub fn struct_err<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> {
self.diagnostic().struct_err(msg)
@@ -178,16 +175,10 @@
}
}
pub fn span_err<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
- match split_msg_into_multilines(msg) {
- Some(msg) => self.diagnostic().span_err(sp, &msg),
- None => self.diagnostic().span_err(sp, msg)
- }
+ self.diagnostic().span_err(sp, msg)
}
pub fn span_err_with_code<S: Into<MultiSpan>>(&self, sp: S, msg: &str, code: &str) {
- match split_msg_into_multilines(msg) {
- Some(msg) => self.diagnostic().span_err_with_code(sp, &msg, code),
- None => self.diagnostic().span_err_with_code(sp, msg, code)
- }
+ self.diagnostic().span_err_with_code(sp, &msg, code)
}
pub fn err(&self, msg: &str) {
self.diagnostic().err(msg)
@@ -343,67 +334,6 @@
}
}
-fn split_msg_into_multilines(msg: &str) -> Option<String> {
- // Conditions for enabling multi-line errors:
- if !msg.contains("mismatched types") &&
- !msg.contains("type mismatch resolving") &&
- !msg.contains("if and else have incompatible types") &&
- !msg.contains("if may be missing an else clause") &&
- !msg.contains("match arms have incompatible types") &&
- !msg.contains("structure constructor specifies a structure of type") &&
- !msg.contains("has an incompatible type for trait") {
- return None
- }
- let first = msg.match_indices("expected").filter(|s| {
- let last = msg[..s.0].chars().rev().next();
- last == Some(' ') || last == Some('(')
- }).map(|(a, b)| (a - 1, a + b.len()));
- let second = msg.match_indices("found").filter(|s| {
- msg[..s.0].chars().rev().next() == Some(' ')
- }).map(|(a, b)| (a - 1, a + b.len()));
-
- let mut new_msg = String::new();
- let mut head = 0;
-
- // Insert `\n` before expected and found.
- for (pos1, pos2) in first.zip(second) {
- new_msg = new_msg +
- // A `(` may be preceded by a space and it should be trimmed
- msg[head..pos1.0].trim_right() + // prefix
- "\n" + // insert before first
- &msg[pos1.0..pos1.1] + // insert what first matched
- &msg[pos1.1..pos2.0] + // between matches
- "\n " + // insert before second
- // 123
- // `expected` is 3 char longer than `found`. To align the types,
- // `found` gets 3 spaces prepended.
- &msg[pos2.0..pos2.1]; // insert what second matched
-
- head = pos2.1;
- }
-
- let mut tail = &msg[head..];
- let third = tail.find("(values differ")
- .or(tail.find("(lifetime"))
- .or(tail.find("(cyclic type of infinite size"));
- // Insert `\n` before any remaining messages which match.
- if let Some(pos) = third {
- // The end of the message may just be wrapped in `()` without
- // `expected`/`found`. Push this also to a new line and add the
- // final tail after.
- new_msg = new_msg +
- // `(` is usually preceded by a space and should be trimmed.
- tail[..pos].trim_right() + // prefix
- "\n" + // insert before paren
- &tail[pos..]; // append the tail
-
- tail = "";
- }
-
- new_msg.push_str(tail);
- return Some(new_msg);
-}
-
pub fn build_session(sopts: config::Options,
dep_graph: &DepGraph,
local_crate_source_file: Option<PathBuf>,
@@ -511,7 +441,7 @@
plugin_attributes: RefCell::new(Vec::new()),
crate_types: RefCell::new(Vec::new()),
dependency_formats: RefCell::new(FnvHashMap()),
- crate_disambiguator: Cell::new(token::intern("")),
+ crate_disambiguator: RefCell::new(token::intern("").as_str()),
features: RefCell::new(feature_gate::Features::new()),
recursion_limit: Cell::new(64),
next_node_id: Cell::new(1),
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index 3b9ecb8..67ad887 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -26,8 +26,9 @@
use fmt_macros::{Parser, Piece, Position};
use hir::def_id::DefId;
-use infer::{InferCtxt};
+use infer::{self, InferCtxt, TypeOrigin};
use ty::{self, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable};
+use ty::error::ExpectedFound;
use ty::fast_reject;
use ty::fold::TypeFolder;
use ty::subst::{self, Subst, TypeSpace};
@@ -107,24 +108,63 @@
let predicate =
self.resolve_type_vars_if_possible(&obligation.predicate);
- if !predicate.references_error() {
- if let Some(warning_node_id) = warning_node_id {
- self.tcx.sess.add_lint(
- ::lint::builtin::UNSIZED_IN_TUPLE,
- warning_node_id,
- obligation.cause.span,
- format!("type mismatch resolving `{}`: {}",
- predicate,
- error.err));
- } else {
- let mut err = struct_span_err!(self.tcx.sess, obligation.cause.span, E0271,
- "type mismatch resolving `{}`: {}",
- predicate,
- error.err);
- self.note_obligation_cause(&mut err, obligation);
- err.emit();
- }
+ if predicate.references_error() {
+ return
}
+ if let Some(warning_node_id) = warning_node_id {
+ self.tcx.sess.add_lint(
+ ::lint::builtin::UNSIZED_IN_TUPLE,
+ warning_node_id,
+ obligation.cause.span,
+ format!("type mismatch resolving `{}`: {}",
+ predicate,
+ error.err));
+ return
+ }
+ self.probe(|_| {
+ let origin = TypeOrigin::Misc(obligation.cause.span);
+ let err_buf;
+ let mut err = &error.err;
+ let mut values = None;
+
+ // try to find the mismatched types to report the error with.
+ //
+ // this can fail if the problem was higher-ranked, in which
+ // cause I have no idea for a good error message.
+ if let ty::Predicate::Projection(ref data) = predicate {
+ let mut selcx = SelectionContext::new(self);
+ let (data, _) = self.replace_late_bound_regions_with_fresh_var(
+ obligation.cause.span,
+ infer::LateBoundRegionConversionTime::HigherRankedType,
+ data);
+ let normalized = super::normalize_projection_type(
+ &mut selcx,
+ data.projection_ty,
+ obligation.cause.clone(),
+ 0
+ );
+ let origin = TypeOrigin::Misc(obligation.cause.span);
+ if let Err(error) = self.eq_types(
+ false, origin,
+ data.ty, normalized.value
+ ) {
+ values = Some(infer::ValuePairs::Types(ExpectedFound {
+ expected: normalized.value,
+ found: data.ty,
+ }));
+ err_buf = error;
+ err = &err_buf;
+ }
+ }
+
+ let mut diag = struct_span_err!(
+ self.tcx.sess, origin.span(), E0271,
+ "type mismatch resolving `{}`", predicate
+ );
+ self.note_type_err(&mut diag, origin, values, err);
+ self.note_obligation_cause(&mut diag, obligation);
+ diag.emit();
+ });
}
fn impl_substs(&self,
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 56938a7..5444dd9 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -504,7 +504,7 @@
pub fn crate_disambiguator(self, cnum: ast::CrateNum) -> token::InternedString {
if cnum == LOCAL_CRATE {
- self.sess.crate_disambiguator.get().as_str()
+ self.sess.local_crate_disambiguator()
} else {
self.sess.cstore.crate_disambiguator(cnum)
}
diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs
index 1e2920c..16a54c2 100644
--- a/src/librustc/ty/structural_impls.rs
+++ b/src/librustc/ty/structural_impls.rs
@@ -1018,3 +1018,16 @@
self.generics.visit_with(visitor) || self.ty.visit_with(visitor)
}
}
+
+impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::error::ExpectedFound<T> {
+ fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
+ ty::error::ExpectedFound {
+ expected: self.expected.fold_with(folder),
+ found: self.found.fold_with(folder),
+ }
+ }
+
+ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
+ self.expected.visit_with(visitor) || self.found.visit_with(visitor)
+ }
+}
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index 21c14e6..fadf364 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -182,6 +182,21 @@
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,
diff --git a/src/librustc/util/fs.rs b/src/librustc/util/fs.rs
index 4936e04..f4e1c06 100644
--- a/src/librustc/util/fs.rs
+++ b/src/librustc/util/fs.rs
@@ -10,6 +10,8 @@
use std::path::{self, Path, PathBuf};
use std::ffi::OsString;
+use std::fs;
+use std::io;
// Unfortunately, on windows, it looks like msvcrt.dll is silently translating
// verbatim paths under the hood to non-verbatim paths! This manifests itself as
@@ -53,3 +55,15 @@
_ => p.to_path_buf(),
}
}
+
+/// Copy `p` into `q`, preferring to use hard-linking if possible. If
+/// `q` already exists, it is removed first.
+pub fn link_or_copy<P: AsRef<Path>, Q: AsRef<Path>>(p: P, q: Q) -> io::Result<()> {
+ let p = p.as_ref();
+ let q = q.as_ref();
+ if q.exists() {
+ try!(fs::remove_file(&q));
+ }
+ fs::hard_link(p, q)
+ .or_else(|_| fs::copy(p, q).map(|_| ()))
+}
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index 0bfb7c1..60977a8 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -974,7 +974,9 @@
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)
diff --git a/src/librustc_back/target/aarch64_apple_ios.rs b/src/librustc_back/target/aarch64_apple_ios.rs
index 481338d..6530ccb 100644
--- a/src/librustc_back/target/aarch64_apple_ios.rs
+++ b/src/librustc_back/target/aarch64_apple_ios.rs
@@ -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 @@
features: "+neon,+fp-armv8,+cyclone".to_string(),
eliminate_frame_pointer: false,
max_atomic_width: 128,
- .. opts(Arch::Arm64)
+ .. base
},
- }
+ })
}
diff --git a/src/librustc_back/target/aarch64_linux_android.rs b/src/librustc_back/target/aarch64_linux_android.rs
index 81be546..7f54dab 100644
--- a/src/librustc_back/target/aarch64_linux_android.rs
+++ b/src/librustc_back/target/aarch64_linux_android.rs
@@ -8,23 +8,23 @@
// 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(),
- data_layout: "e-m:e-i64:64-i128:128-n32:64-S128".to_string(),
+ data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
arch: "aarch64".to_string(),
target_os: "android".to_string(),
target_env: "".to_string(),
target_vendor: "unknown".to_string(),
options: base,
- }
+ })
}
diff --git a/src/librustc_back/target/aarch64_unknown_linux_gnu.rs b/src/librustc_back/target/aarch64_unknown_linux_gnu.rs
index aec1bae..cca965f 100644
--- a/src/librustc_back/target/aarch64_unknown_linux_gnu.rs
+++ b/src/librustc_back/target/aarch64_unknown_linux_gnu.rs
@@ -8,20 +8,20 @@
// 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(),
target_env: "gnu".to_string(),
- data_layout: "e-m:e-i64:64-i128:128-n32:64-S128".to_string(),
+ data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
arch: "aarch64".to_string(),
target_os: "linux".to_string(),
target_vendor: "unknown".to_string(),
options: base,
- }
+ })
}
diff --git a/src/librustc_back/target/apple_ios_base.rs b/src/librustc_back/target/apple_ios_base.rs
index d182fd9..8bd9fea 100644
--- a/src/librustc_back/target/apple_ios_base.rs
+++ b/src/librustc_back/target/apple_ios_base.rs
@@ -36,7 +36,7 @@
}
}
-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 @@
});
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 @@
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 @@
}.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()
- }
+ })
}
diff --git a/src/librustc_back/target/arm_linux_androideabi.rs b/src/librustc_back/target/arm_linux_androideabi.rs
index e1b1704..f3a18b1 100644
--- a/src/librustc_back/target/arm_linux_androideabi.rs
+++ b/src/librustc_back/target/arm_linux_androideabi.rs
@@ -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 @@
target_env: "".to_string(),
target_vendor: "unknown".to_string(),
options: base,
- }
+ })
}
diff --git a/src/librustc_back/target/arm_unknown_linux_gnueabi.rs b/src/librustc_back/target/arm_unknown_linux_gnueabi.rs
index 60c4a7c..e666a84 100644
--- a/src/librustc_back/target/arm_unknown_linux_gnueabi.rs
+++ b/src/librustc_back/target/arm_unknown_linux_gnueabi.rs
@@ -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 @@
features: "+v6".to_string(),
.. base
},
- }
+ })
}
diff --git a/src/librustc_back/target/arm_unknown_linux_gnueabihf.rs b/src/librustc_back/target/arm_unknown_linux_gnueabihf.rs
index 72128e3..d65c89a 100644
--- a/src/librustc_back/target/arm_unknown_linux_gnueabihf.rs
+++ b/src/librustc_back/target/arm_unknown_linux_gnueabihf.rs
@@ -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 @@
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
index 0000000..028c91e
--- /dev/null
+++ b/src/librustc_back/target/arm_unknown_linux_musleabi.rs
@@ -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
index 0000000..c7dda18
--- /dev/null
+++ b/src/librustc_back/target/arm_unknown_linux_musleabihf.rs
@@ -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,
+ })
+}
diff --git a/src/librustc_back/target/armv7_apple_ios.rs b/src/librustc_back/target/armv7_apple_ios.rs
index a2486a1..a806204 100644
--- a/src/librustc_back/target/armv7_apple_ios.rs
+++ b/src/librustc_back/target/armv7_apple_ios.rs
@@ -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 @@
options: TargetOptions {
features: "+v7,+vfp3,+neon".to_string(),
max_atomic_width: 64,
- .. opts(Arch::Armv7)
+ .. base
}
- }
+ })
}
diff --git a/src/librustc_back/target/armv7_linux_androideabi.rs b/src/librustc_back/target/armv7_linux_androideabi.rs
index fd8f35d..1c59262 100644
--- a/src/librustc_back/target/armv7_linux_androideabi.rs
+++ b/src/librustc_back/target/armv7_linux_androideabi.rs
@@ -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 @@
target_env: "".to_string(),
target_vendor: "unknown".to_string(),
options: base,
- }
+ })
}
diff --git a/src/librustc_back/target/armv7_unknown_linux_gnueabihf.rs b/src/librustc_back/target/armv7_unknown_linux_gnueabihf.rs
index 7bcca3a..52269f0 100644
--- a/src/librustc_back/target/armv7_unknown_linux_gnueabihf.rs
+++ b/src/librustc_back/target/armv7_unknown_linux_gnueabihf.rs
@@ -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 @@
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
index 0000000..e40704e
--- /dev/null
+++ b/src/librustc_back/target/armv7_unknown_linux_musleabihf.rs
@@ -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,
+ })
+}
diff --git a/src/librustc_back/target/armv7s_apple_ios.rs b/src/librustc_back/target/armv7s_apple_ios.rs
index e5379aa..aaa3570 100644
--- a/src/librustc_back/target/armv7s_apple_ios.rs
+++ b/src/librustc_back/target/armv7s_apple_ios.rs
@@ -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 @@
options: TargetOptions {
features: "+v7,+vfp4,+neon".to_string(),
max_atomic_width: 64,
- .. opts(Arch::Armv7s)
+ .. base
}
- }
+ })
}
diff --git a/src/librustc_back/target/asmjs_unknown_emscripten.rs b/src/librustc_back/target/asmjs_unknown_emscripten.rs
index e620017..07eb191 100644
--- a/src/librustc_back/target/asmjs_unknown_emscripten.rs
+++ b/src/librustc_back/target/asmjs_unknown_emscripten.rs
@@ -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 @@
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 @@
data_layout: "e-p:32:32-i64:64-v128:32:128-n32-S128".to_string(),
arch: "asmjs".to_string(),
options: opts,
- }
+ })
}
diff --git a/src/librustc_back/target/i386_apple_ios.rs b/src/librustc_back/target/i386_apple_ios.rs
index cf4020e..f391d41 100644
--- a/src/librustc_back/target/i386_apple_ios.rs
+++ b/src/librustc_back/target/i386_apple_ios.rs
@@ -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 @@
target_vendor: "apple".to_string(),
options: TargetOptions {
max_atomic_width: 64,
- .. opts(Arch::I386)
+ .. base
}
- }
+ })
}
diff --git a/src/librustc_back/target/i586_pc_windows_msvc.rs b/src/librustc_back/target/i586_pc_windows_msvc.rs
index 12bed37..445ee6c 100644
--- a/src/librustc_back/target/i586_pc_windows_msvc.rs
+++ b/src/librustc_back/target/i586_pc_windows_msvc.rs
@@ -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)
}
diff --git a/src/librustc_back/target/i586_unknown_linux_gnu.rs b/src/librustc_back/target/i586_unknown_linux_gnu.rs
index 6eb64556..1ca8606 100644
--- a/src/librustc_back/target/i586_unknown_linux_gnu.rs
+++ b/src/librustc_back/target/i586_unknown_linux_gnu.rs
@@ -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)
}
diff --git a/src/librustc_back/target/i686_apple_darwin.rs b/src/librustc_back/target/i686_apple_darwin.rs
index 302691e..4876a34 100644
--- a/src/librustc_back/target/i686_apple_darwin.rs
+++ b/src/librustc_back/target/i686_apple_darwin.rs
@@ -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 @@
target_env: "".to_string(),
target_vendor: "apple".to_string(),
options: base,
- }
+ })
}
diff --git a/src/librustc_back/target/i686_linux_android.rs b/src/librustc_back/target/i686_linux_android.rs
index 2376de1..1de6292 100644
--- a/src/librustc_back/target/i686_linux_android.rs
+++ b/src/librustc_back/target/i686_linux_android.rs
@@ -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 @@
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 @@
target_env: "".to_string(),
target_vendor: "unknown".to_string(),
options: base,
- }
+ })
}
diff --git a/src/librustc_back/target/i686_pc_windows_gnu.rs b/src/librustc_back/target/i686_pc_windows_gnu.rs
index c2cc624..2c19b81 100644
--- a/src/librustc_back/target/i686_pc_windows_gnu.rs
+++ b/src/librustc_back/target/i686_pc_windows_gnu.rs
@@ -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 @@
// 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 @@
target_env: "gnu".to_string(),
target_vendor: "pc".to_string(),
options: base,
- }
+ })
}
diff --git a/src/librustc_back/target/i686_pc_windows_msvc.rs b/src/librustc_back/target/i686_pc_windows_msvc.rs
index 8c1bacc..cb02fcc 100644
--- a/src/librustc_back/target/i686_pc_windows_msvc.rs
+++ b/src/librustc_back/target/i686_pc_windows_msvc.rs
@@ -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 @@
// 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 @@
target_env: "msvc".to_string(),
target_vendor: "pc".to_string(),
options: base,
- }
+ })
}
diff --git a/src/librustc_back/target/i686_unknown_dragonfly.rs b/src/librustc_back/target/i686_unknown_dragonfly.rs
index 6446ac4..f96ec00 100644
--- a/src/librustc_back/target/i686_unknown_dragonfly.rs
+++ b/src/librustc_back/target/i686_unknown_dragonfly.rs
@@ -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 @@
target_env: "".to_string(),
target_vendor: "unknown".to_string(),
options: base,
- }
+ })
}
diff --git a/src/librustc_back/target/i686_unknown_freebsd.rs b/src/librustc_back/target/i686_unknown_freebsd.rs
index a7903d5..3489ecf 100644
--- a/src/librustc_back/target/i686_unknown_freebsd.rs
+++ b/src/librustc_back/target/i686_unknown_freebsd.rs
@@ -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 @@
target_env: "".to_string(),
target_vendor: "unknown".to_string(),
options: base,
- }
+ })
}
diff --git a/src/librustc_back/target/i686_unknown_linux_gnu.rs b/src/librustc_back/target/i686_unknown_linux_gnu.rs
index 7813d55..f2e865c 100644
--- a/src/librustc_back/target/i686_unknown_linux_gnu.rs
+++ b/src/librustc_back/target/i686_unknown_linux_gnu.rs
@@ -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 @@
target_env: "gnu".to_string(),
target_vendor: "unknown".to_string(),
options: base,
- }
+ })
}
diff --git a/src/librustc_back/target/i686_unknown_linux_musl.rs b/src/librustc_back/target/i686_unknown_linux_musl.rs
index 5274429..a0a8de4 100644
--- a/src/librustc_back/target/i686_unknown_linux_musl.rs
+++ b/src/librustc_back/target/i686_unknown_linux_musl.rs
@@ -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 @@
target_env: "musl".to_string(),
target_vendor: "unknown".to_string(),
options: base,
- }
+ })
}
diff --git a/src/librustc_back/target/le32_unknown_nacl.rs b/src/librustc_back/target/le32_unknown_nacl.rs
index f4f0262..25132f8 100644
--- a/src/librustc_back/target/le32_unknown_nacl.rs
+++ b/src/librustc_back/target/le32_unknown_nacl.rs
@@ -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 @@
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 @@
data_layout: "e-i64:64:64-p:32:32:32-v128:32:32".to_string(),
arch: "le32".to_string(),
options: opts,
- }
+ })
}
diff --git a/src/librustc_back/target/mips_unknown_linux_gnu.rs b/src/librustc_back/target/mips_unknown_linux_gnu.rs
index ceb17e5..ab967f6 100644
--- a/src/librustc_back/target/mips_unknown_linux_gnu.rs
+++ b/src/librustc_back/target/mips_unknown_linux_gnu.rs
@@ -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 @@
max_atomic_width: 32,
..super::linux_base::opts()
},
- }
+ })
}
diff --git a/src/librustc_back/target/mips_unknown_linux_musl.rs b/src/librustc_back/target/mips_unknown_linux_musl.rs
index 3536665..4a69bce 100644
--- a/src/librustc_back/target/mips_unknown_linux_musl.rs
+++ b/src/librustc_back/target/mips_unknown_linux_musl.rs
@@ -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 @@
max_atomic_width: 32,
..super::linux_base::opts()
}
- }
+ })
}
diff --git a/src/librustc_back/target/mipsel_unknown_linux_gnu.rs b/src/librustc_back/target/mipsel_unknown_linux_gnu.rs
index ac1536b..b66fb62 100644
--- a/src/librustc_back/target/mipsel_unknown_linux_gnu.rs
+++ b/src/librustc_back/target/mipsel_unknown_linux_gnu.rs
@@ -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 @@
max_atomic_width: 32,
..super::linux_base::opts()
},
- }
+ })
}
diff --git a/src/librustc_back/target/mipsel_unknown_linux_musl.rs b/src/librustc_back/target/mipsel_unknown_linux_musl.rs
index a9ea52c..a0524e5 100644
--- a/src/librustc_back/target/mipsel_unknown_linux_musl.rs
+++ b/src/librustc_back/target/mipsel_unknown_linux_musl.rs
@@ -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(),
@@ -22,9 +22,9 @@
target_vendor: "unknown".to_string(),
options: TargetOptions {
cpu: "mips32".to_string(),
- features: "+mips32".to_string(),
+ features: "+mips32,+soft-float".to_string(),
max_atomic_width: 32,
..super::linux_base::opts()
}
- }
+ })
}
diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs
index 99bc268..3d24fd8 100644
--- a/src/librustc_back/target/mod.rs
+++ b/src/librustc_back/target/mod.rs
@@ -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;
@@ -63,26 +64,62 @@
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 @@
("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 @@
/// 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 @@
///
/// 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 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 @@
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 @@
}
/// 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 @@
};
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 @@
} );
}
- 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 @@
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 @@
}
}
+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()
diff --git a/src/librustc_back/target/powerpc64_unknown_linux_gnu.rs b/src/librustc_back/target/powerpc64_unknown_linux_gnu.rs
index be4be8e..1c04e76 100644
--- a/src/librustc_back/target/powerpc64_unknown_linux_gnu.rs
+++ b/src/librustc_back/target/powerpc64_unknown_linux_gnu.rs
@@ -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 @@
target_env: "gnu".to_string(),
target_vendor: "unknown".to_string(),
options: base,
- }
+ })
}
diff --git a/src/librustc_back/target/powerpc64le_unknown_linux_gnu.rs b/src/librustc_back/target/powerpc64le_unknown_linux_gnu.rs
index b0a81ce..906e28d 100644
--- a/src/librustc_back/target/powerpc64le_unknown_linux_gnu.rs
+++ b/src/librustc_back/target/powerpc64le_unknown_linux_gnu.rs
@@ -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 @@
target_env: "gnu".to_string(),
target_vendor: "unknown".to_string(),
options: base,
- }
+ })
}
diff --git a/src/librustc_back/target/powerpc_unknown_linux_gnu.rs b/src/librustc_back/target/powerpc_unknown_linux_gnu.rs
index aea57dc..aebf9cd 100644
--- a/src/librustc_back/target/powerpc_unknown_linux_gnu.rs
+++ b/src/librustc_back/target/powerpc_unknown_linux_gnu.rs
@@ -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 @@
target_env: "gnu".to_string(),
target_vendor: "unknown".to_string(),
options: base,
- }
+ })
}
diff --git a/src/librustc_back/target/windows_base.rs b/src/librustc_back/target/windows_base.rs
index 1e46f45..c398ee4 100644
--- a/src/librustc_back/target/windows_base.rs
+++ b/src/librustc_back/target/windows_base.rs
@@ -25,6 +25,7 @@
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.
diff --git a/src/librustc_back/target/x86_64_apple_darwin.rs b/src/librustc_back/target/x86_64_apple_darwin.rs
index 5542c91..65e4b14 100644
--- a/src/librustc_back/target/x86_64_apple_darwin.rs
+++ b/src/librustc_back/target/x86_64_apple_darwin.rs
@@ -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 @@
target_env: "".to_string(),
target_vendor: "apple".to_string(),
options: base,
- }
+ })
}
diff --git a/src/librustc_back/target/x86_64_apple_ios.rs b/src/librustc_back/target/x86_64_apple_ios.rs
index 8638241..4afc9bc 100644
--- a/src/librustc_back/target/x86_64_apple_ios.rs
+++ b/src/librustc_back/target/x86_64_apple_ios.rs
@@ -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 @@
target_vendor: "apple".to_string(),
options: TargetOptions {
max_atomic_width: 64,
- .. opts(Arch::X86_64)
+ .. base
}
- }
+ })
}
diff --git a/src/librustc_back/target/x86_64_pc_windows_gnu.rs b/src/librustc_back/target/x86_64_pc_windows_gnu.rs
index e243054..086e0e6 100644
--- a/src/librustc_back/target/x86_64_pc_windows_gnu.rs
+++ b/src/librustc_back/target/x86_64_pc_windows_gnu.rs
@@ -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 @@
target_env: "gnu".to_string(),
target_vendor: "pc".to_string(),
options: base,
- }
+ })
}
diff --git a/src/librustc_back/target/x86_64_pc_windows_msvc.rs b/src/librustc_back/target/x86_64_pc_windows_msvc.rs
index a23a807..064f06e 100644
--- a/src/librustc_back/target/x86_64_pc_windows_msvc.rs
+++ b/src/librustc_back/target/x86_64_pc_windows_msvc.rs
@@ -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 @@
target_env: "msvc".to_string(),
target_vendor: "pc".to_string(),
options: base,
- }
+ })
}
diff --git a/src/librustc_back/target/x86_64_rumprun_netbsd.rs b/src/librustc_back/target/x86_64_rumprun_netbsd.rs
index af5d21c..fd6578c 100644
--- a/src/librustc_back/target/x86_64_rumprun_netbsd.rs
+++ b/src/librustc_back/target/x86_64_rumprun_netbsd.rs
@@ -8,10 +8,11 @@
// 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.cpu = "x86-64".to_string();
base.pre_link_args.push("-m64".to_string());
base.linker = "x86_64-rumprun-netbsd-gcc".to_string();
base.ar = "x86_64-rumprun-netbsd-ar".to_string();
@@ -24,7 +25,7 @@
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 +35,5 @@
target_env: "".to_string(),
target_vendor: "rumprun".to_string(),
options: base,
- }
+ })
}
diff --git a/src/librustc_back/target/x86_64_sun_solaris.rs b/src/librustc_back/target/x86_64_sun_solaris.rs
index 8f2c905..2a1feb9 100644
--- a/src/librustc_back/target/x86_64_sun_solaris.rs
+++ b/src/librustc_back/target/x86_64_sun_solaris.rs
@@ -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 @@
target_env: "".to_string(),
target_vendor: "sun".to_string(),
options: base,
- }
+ })
}
diff --git a/src/librustc_back/target/x86_64_unknown_bitrig.rs b/src/librustc_back/target/x86_64_unknown_bitrig.rs
index 87753da..3820965 100644
--- a/src/librustc_back/target/x86_64_unknown_bitrig.rs
+++ b/src/librustc_back/target/x86_64_unknown_bitrig.rs
@@ -8,14 +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::bitrig_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-bitrig".to_string(),
target_endian: "little".to_string(),
target_pointer_width: "64".to_string(),
@@ -25,5 +26,5 @@
target_env: "".to_string(),
target_vendor: "unknown".to_string(),
options: base,
- }
+ })
}
diff --git a/src/librustc_back/target/x86_64_unknown_dragonfly.rs b/src/librustc_back/target/x86_64_unknown_dragonfly.rs
index 2535071..7e40d49 100644
--- a/src/librustc_back/target/x86_64_unknown_dragonfly.rs
+++ b/src/librustc_back/target/x86_64_unknown_dragonfly.rs
@@ -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 @@
target_env: "".to_string(),
target_vendor: "unknown".to_string(),
options: base,
- }
+ })
}
diff --git a/src/librustc_back/target/x86_64_unknown_freebsd.rs b/src/librustc_back/target/x86_64_unknown_freebsd.rs
index d3ad057..f38cdd4 100644
--- a/src/librustc_back/target/x86_64_unknown_freebsd.rs
+++ b/src/librustc_back/target/x86_64_unknown_freebsd.rs
@@ -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 @@
target_env: "".to_string(),
target_vendor: "unknown".to_string(),
options: base,
- }
+ })
}
diff --git a/src/librustc_back/target/x86_64_unknown_linux_gnu.rs b/src/librustc_back/target/x86_64_unknown_linux_gnu.rs
index 7908e0d..ef81d39 100644
--- a/src/librustc_back/target/x86_64_unknown_linux_gnu.rs
+++ b/src/librustc_back/target/x86_64_unknown_linux_gnu.rs
@@ -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 @@
target_env: "gnu".to_string(),
target_vendor: "unknown".to_string(),
options: base,
- }
+ })
}
diff --git a/src/librustc_back/target/x86_64_unknown_linux_musl.rs b/src/librustc_back/target/x86_64_unknown_linux_musl.rs
index 3301e0e..4bad775 100644
--- a/src/librustc_back/target/x86_64_unknown_linux_musl.rs
+++ b/src/librustc_back/target/x86_64_unknown_linux_musl.rs
@@ -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 @@
target_env: "musl".to_string(),
target_vendor: "unknown".to_string(),
options: base,
- }
+ })
}
diff --git a/src/librustc_back/target/x86_64_unknown_netbsd.rs b/src/librustc_back/target/x86_64_unknown_netbsd.rs
index 7e6d1b7..2d0b1e2 100644
--- a/src/librustc_back/target/x86_64_unknown_netbsd.rs
+++ b/src/librustc_back/target/x86_64_unknown_netbsd.rs
@@ -8,14 +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::netbsd_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-netbsd".to_string(),
target_endian: "little".to_string(),
target_pointer_width: "64".to_string(),
@@ -25,5 +26,5 @@
target_env: "".to_string(),
target_vendor: "unknown".to_string(),
options: base,
- }
+ })
}
diff --git a/src/librustc_back/target/x86_64_unknown_openbsd.rs b/src/librustc_back/target/x86_64_unknown_openbsd.rs
index 823b099..339dbd5 100644
--- a/src/librustc_back/target/x86_64_unknown_openbsd.rs
+++ b/src/librustc_back/target/x86_64_unknown_openbsd.rs
@@ -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 @@
target_env: "".to_string(),
target_vendor: "unknown".to_string(),
options: base,
- }
+ })
}
diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs
index e86120b..1fe47cd 100644
--- a/src/librustc_borrowck/borrowck/mod.rs
+++ b/src/librustc_borrowck/borrowck/mod.rs
@@ -197,7 +197,7 @@
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>,
diff --git a/src/librustc_const_eval/Cargo.toml b/src/librustc_const_eval/Cargo.toml
index 01872bb..8967672 100644
--- a/src/librustc_const_eval/Cargo.toml
+++ b/src/librustc_const_eval/Cargo.toml
@@ -14,6 +14,7 @@
rustc = { path = "../librustc" }
rustc_back = { path = "../librustc_back" }
rustc_const_math = { path = "../librustc_const_math" }
+rustc_errors = { path = "../librustc_errors" }
syntax = { path = "../libsyntax" }
graphviz = { path = "../libgraphviz" }
syntax_pos = { path = "../libsyntax_pos" }
\ No newline at end of file
diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs
index 0de00d9..d3952de 100644
--- a/src/librustc_const_eval/check_match.rs
+++ b/src/librustc_const_eval/check_match.rs
@@ -17,6 +17,7 @@
use ::{eval_const_expr, eval_const_expr_partial, compare_const_vals};
use ::{const_expr_to_pat, lookup_const_by_id};
use ::EvalHint::ExprTypeChecked;
+use eval::report_const_eval_err;
use rustc::hir::def::*;
use rustc::hir::def_id::{DefId};
use rustc::middle::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor};
@@ -33,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};
@@ -42,6 +43,7 @@
use rustc::hir::fold::{Folder, noop_fold_pat};
use rustc::hir::print::pat_to_string;
use syntax::ptr::P;
+use rustc::util::common::ErrorReported;
use rustc::util::nodemap::FnvHashMap;
pub const DUMMY_WILD_PAT: &'static Pat = &Pat {
@@ -279,13 +281,7 @@
Ok(_) => {}
Err(err) => {
- let mut diag = struct_span_err!(cx.tcx.sess, err.span, E0471,
- "constant evaluation error: {}",
- err.description());
- if !p.span.contains(err.span) {
- diag.span_note(p.span, "in pattern here");
- }
- diag.emit();
+ report_const_eval_err(cx.tcx, &err, p.span, "pattern").emit();
}
}
}
@@ -478,7 +474,7 @@
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);
@@ -533,9 +529,7 @@
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);
}
}
}
@@ -838,22 +832,19 @@
}
}
-fn range_covered_by_constructor(ctor: &Constructor,
- from: &ConstVal, to: &ConstVal) -> Option<bool> {
+fn range_covered_by_constructor(tcx: TyCtxt, span: Span,
+ ctor: &Constructor,
+ from: &ConstVal, to: &ConstVal)
+ -> Result<bool, ErrorReported> {
let (c_from, c_to) = match *ctor {
ConstantValue(ref value) => (value, value),
ConstantRange(ref from, ref to) => (from, to),
- Single => return Some(true),
+ Single => return Ok(true),
_ => bug!()
};
- let cmp_from = compare_const_vals(c_from, from);
- let cmp_to = compare_const_vals(c_to, to);
- match (cmp_from, cmp_to) {
- (Some(cmp_from), Some(cmp_to)) => {
- Some(cmp_from != Ordering::Less && cmp_to != Ordering::Greater)
- }
- _ => None
- }
+ let cmp_from = compare_const_vals(tcx, span, c_from, from)?;
+ let cmp_to = compare_const_vals(tcx, span, c_to, to)?;
+ Ok(cmp_from != Ordering::Less && cmp_to != Ordering::Greater)
}
fn wrap_pat<'a, 'b, 'tcx>(cx: &MatchCheckCtxt<'b, 'tcx>,
@@ -965,13 +956,12 @@
Some(vec![(pat, Some(mt.ty))])
} else {
let expr_value = eval_const_expr(cx.tcx, &expr);
- match range_covered_by_constructor(constructor, &expr_value, &expr_value) {
- Some(true) => Some(vec![]),
- Some(false) => None,
- None => {
- span_err!(cx.tcx.sess, pat_span, E0298, "mismatched types between arms");
- None
- }
+ match range_covered_by_constructor(
+ cx.tcx, expr.span, constructor, &expr_value, &expr_value
+ ) {
+ Ok(true) => Some(vec![]),
+ Ok(false) => None,
+ Err(ErrorReported) => None,
}
}
}
@@ -979,13 +969,12 @@
PatKind::Range(ref from, ref to) => {
let from_value = eval_const_expr(cx.tcx, &from);
let to_value = eval_const_expr(cx.tcx, &to);
- match range_covered_by_constructor(constructor, &from_value, &to_value) {
- Some(true) => Some(vec![]),
- Some(false) => None,
- None => {
- span_err!(cx.tcx.sess, pat_span, E0299, "mismatched types between arms");
- None
- }
+ match range_covered_by_constructor(
+ cx.tcx, pat_span, constructor, &from_value, &to_value
+ ) {
+ Ok(true) => Some(vec![]),
+ Ok(false) => None,
+ Err(ErrorReported) => None,
}
}
@@ -1058,7 +1047,7 @@
_ => 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);
diff --git a/src/librustc_const_eval/diagnostics.rs b/src/librustc_const_eval/diagnostics.rs
index f2abdf8..45414c3 100644
--- a/src/librustc_const_eval/diagnostics.rs
+++ b/src/librustc_const_eval/diagnostics.rs
@@ -551,6 +551,26 @@
See also https://github.com/rust-lang/rust/issues/14587
"##,
+E0080: r##"
+This error indicates that the compiler was unable to sensibly evaluate an
+constant expression that had to be evaluated. Attempting to divide by 0
+or causing integer overflow are two ways to induce this error. For example:
+
+```compile_fail
+enum Enum {
+ X = (1 << 500),
+ Y = (1 / 0)
+}
+```
+
+Ensure that the expressions given can be evaluated as the desired integer type.
+See the FFI section of the Reference for more information about using a custom
+integer type:
+
+https://doc.rust-lang.org/reference.html#ffi-attributes
+"##,
+
+
E0306: r##"
In an array literal `[x; N]`, `N` is the number of elements in the array. This
must be an unsigned integer. Erroneous code example:
@@ -566,29 +586,11 @@
let x = [0i32; 2];
```
"##,
-
-E0307: r##"
-The length of an array is part of its type. For this reason, this length must
-be a compile-time constant. Erroneous code example:
-
-```compile_fail
- let len = 10;
- let x = [0i32; len]; // error: expected constant integer for repeat count,
- // found variable
-```
-
-Working example:
-
-```
-let x = [0i32; 10];
-```
-"##,
-
}
register_diagnostics! {
-E0298, // mismatched types between arms
-E0299, // mismatched types between arms
-E0471, // constant evaluation error: ..
+ E0298, // cannot compare constants
+// E0299, // mismatched types between arms
+// E0471, // constant evaluation error (in pattern)
}
diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs
index 4643686..d424b57 100644
--- a/src/librustc_const_eval/eval.rs
+++ b/src/librustc_const_eval/eval.rs
@@ -17,7 +17,7 @@
use rustc::hir::map as ast_map;
use rustc::hir::map::blocks::FnLikeNode;
-use rustc::middle::cstore::{self, InlinedItem};
+use rustc::middle::cstore::InlinedItem;
use rustc::traits;
use rustc::hir::def::{Def, PathResolution};
use rustc::hir::def_id::DefId;
@@ -25,6 +25,7 @@
use rustc::ty::{self, Ty, TyCtxt, subst};
use rustc::ty::util::IntTypeExt;
use rustc::traits::ProjectionMode;
+use rustc::util::common::ErrorReported;
use rustc::util::nodemap::NodeMap;
use rustc::lint;
@@ -43,6 +44,7 @@
use std::collections::hash_map::Entry::Vacant;
use rustc_const_math::*;
+use rustc_errors::{DiagnosticBuilder, check_old_school};
macro_rules! math {
($e:expr, $op:expr) => {
@@ -140,13 +142,13 @@
}
let mut used_substs = false;
let expr_ty = match tcx.sess.cstore.maybe_get_item_ast(tcx, def_id) {
- cstore::FoundAst::Found(&InlinedItem::Item(ref item)) => match item.node {
+ Some((&InlinedItem::Item(ref item), _)) => match item.node {
hir::ItemConst(ref ty, ref const_expr) => {
Some((&**const_expr, tcx.ast_ty_to_prim_ty(ty)))
},
_ => None
},
- cstore::FoundAst::Found(&InlinedItem::TraitItem(trait_id, ref ti)) => match ti.node {
+ Some((&InlinedItem::TraitItem(trait_id, ref ti), _)) => match ti.node {
hir::ConstTraitItem(_, _) => {
used_substs = true;
if let Some(substs) = substs {
@@ -161,7 +163,7 @@
}
_ => None
},
- cstore::FoundAst::Found(&InlinedItem::ImplItem(_, ref ii)) => match ii.node {
+ Some((&InlinedItem::ImplItem(_, ref ii), _)) => match ii.node {
hir::ImplItemKind::Const(ref ty, ref expr) => {
Some((&**expr, tcx.ast_ty_to_prim_ty(ty)))
},
@@ -196,8 +198,8 @@
}
let fn_id = match tcx.sess.cstore.maybe_get_item_ast(tcx, def_id) {
- cstore::FoundAst::Found(&InlinedItem::Item(ref item)) => Some(item.id),
- cstore::FoundAst::Found(&InlinedItem::ImplItem(_, ref item)) => Some(item.id),
+ Some((&InlinedItem::Item(ref item), _)) => Some(item.id),
+ Some((&InlinedItem::ImplItem(_, ref item), _)) => Some(item.id),
_ => None
};
tcx.extern_const_fns.borrow_mut().insert(def_id,
@@ -338,20 +340,71 @@
Ok(P(hir::Pat { id: expr.id, node: pat, span: span }))
}
+pub fn report_const_eval_err<'a, 'tcx>(
+ tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ err: &ConstEvalErr,
+ primary_span: Span,
+ primary_kind: &str)
+ -> DiagnosticBuilder<'tcx>
+{
+ let mut err = err;
+ while let &ConstEvalErr { kind: ErroneousReferencedConstant(box ref i_err), .. } = err {
+ err = i_err;
+ }
+
+ let mut diag = struct_span_err!(tcx.sess, err.span, E0080, "constant evaluation error");
+ note_const_eval_err(tcx, err, primary_span, primary_kind, &mut diag);
+ diag
+}
+
+pub fn fatal_const_eval_err<'a, 'tcx>(
+ tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ err: &ConstEvalErr,
+ primary_span: Span,
+ primary_kind: &str)
+ -> !
+{
+ report_const_eval_err(tcx, err, primary_span, primary_kind).emit();
+ tcx.sess.abort_if_errors();
+ unreachable!()
+}
+
+pub fn note_const_eval_err<'a, 'tcx>(
+ _tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ err: &ConstEvalErr,
+ primary_span: Span,
+ primary_kind: &str,
+ diag: &mut DiagnosticBuilder)
+{
+ match err.description() {
+ ConstEvalErrDescription::Simple(message) => {
+ if check_old_school() {
+ diag.note(&message);
+ } else {
+ diag.span_label(err.span, &message);
+ }
+ }
+ }
+
+ if !primary_span.contains(err.span) {
+ diag.span_note(primary_span,
+ &format!("for {} here", primary_kind));
+ }
+}
+
pub fn eval_const_expr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
e: &Expr) -> ConstVal {
match eval_const_expr_partial(tcx, e, ExprTypeChecked, None) {
Ok(r) => r,
// non-const path still needs to be a fatal error, because enums are funky
Err(s) => {
+ report_const_eval_err(tcx, &s, e.span, "expression").emit();
match s.kind {
NonConstPath |
- UnimplementedConstVal(_) => tcx.sess.span_fatal(s.span, &s.description()),
- _ => {
- tcx.sess.span_err(s.span, &s.description());
- Dummy
- }
+ UnimplementedConstVal(_) => tcx.sess.abort_if_errors(),
+ _ => {}
}
+ Dummy
},
}
}
@@ -400,6 +453,7 @@
IntermediateUnsignedNegative,
/// Expected, Got
TypeMismatch(String, ConstInt),
+
BadType(ConstVal),
ErroneousReferencedConstant(Box<ConstEvalErr>),
CharCast(ConstInt),
@@ -411,57 +465,79 @@
}
}
+#[derive(Clone, Debug)]
+pub enum ConstEvalErrDescription<'a> {
+ Simple(Cow<'a, str>),
+}
+
+impl<'a> ConstEvalErrDescription<'a> {
+ /// Return a one-line description of the error, for lints and such
+ pub fn into_oneline(self) -> Cow<'a, str> {
+ match self {
+ ConstEvalErrDescription::Simple(simple) => simple,
+ }
+ }
+}
+
impl ConstEvalErr {
- pub fn description(&self) -> Cow<str> {
+ pub fn description(&self) -> ConstEvalErrDescription {
use self::ErrKind::*;
+ use self::ConstEvalErrDescription::*;
+
+ macro_rules! simple {
+ ($msg:expr) => ({ Simple($msg.into_cow()) });
+ ($fmt:expr, $($arg:tt)+) => ({
+ Simple(format!($fmt, $($arg)+).into_cow())
+ })
+ }
match self.kind {
- CannotCast => "can't cast this type".into_cow(),
- CannotCastTo(s) => format!("can't cast this type to {}", s).into_cow(),
- InvalidOpForInts(_) => "can't do this op on integrals".into_cow(),
- InvalidOpForBools(_) => "can't do this op on bools".into_cow(),
- InvalidOpForFloats(_) => "can't do this op on floats".into_cow(),
- InvalidOpForIntUint(..) => "can't do this op on an isize and usize".into_cow(),
- InvalidOpForUintInt(..) => "can't do this op on a usize and isize".into_cow(),
- NegateOn(ref const_val) => format!("negate on {}", const_val.description()).into_cow(),
- NotOn(ref const_val) => format!("not on {}", const_val.description()).into_cow(),
- CallOn(ref const_val) => format!("call on {}", const_val.description()).into_cow(),
+ CannotCast => simple!("can't cast this type"),
+ CannotCastTo(s) => simple!("can't cast this type to {}", s),
+ InvalidOpForInts(_) => simple!("can't do this op on integrals"),
+ InvalidOpForBools(_) => simple!("can't do this op on bools"),
+ InvalidOpForFloats(_) => simple!("can't do this op on floats"),
+ InvalidOpForIntUint(..) => simple!("can't do this op on an isize and usize"),
+ InvalidOpForUintInt(..) => simple!("can't do this op on a usize and isize"),
+ NegateOn(ref const_val) => simple!("negate on {}", const_val.description()),
+ NotOn(ref const_val) => simple!("not on {}", const_val.description()),
+ CallOn(ref const_val) => simple!("call on {}", const_val.description()),
- MissingStructField => "nonexistent struct field".into_cow(),
- NonConstPath => "non-constant path in constant expression".into_cow(),
+ MissingStructField => simple!("nonexistent struct field"),
+ NonConstPath => simple!("non-constant path in constant expression"),
UnimplementedConstVal(what) =>
- format!("unimplemented constant expression: {}", what).into_cow(),
- UnresolvedPath => "unresolved path in constant expression".into_cow(),
- ExpectedConstTuple => "expected constant tuple".into_cow(),
- ExpectedConstStruct => "expected constant struct".into_cow(),
- TupleIndexOutOfBounds => "tuple index out of bounds".into_cow(),
- IndexedNonVec => "indexing is only supported for arrays".into_cow(),
- IndexNegative => "indices must be non-negative integers".into_cow(),
- IndexNotInt => "indices must be integers".into_cow(),
+ simple!("unimplemented constant expression: {}", what),
+ UnresolvedPath => simple!("unresolved path in constant expression"),
+ ExpectedConstTuple => simple!("expected constant tuple"),
+ ExpectedConstStruct => simple!("expected constant struct"),
+ TupleIndexOutOfBounds => simple!("tuple index out of bounds"),
+ IndexedNonVec => simple!("indexing is only supported for arrays"),
+ IndexNegative => simple!("indices must be non-negative integers"),
+ IndexNotInt => simple!("indices must be integers"),
IndexOutOfBounds { len, index } => {
- format!("index out of bounds: the len is {} but the index is {}",
- len, index).into_cow()
+ simple!("index out of bounds: the len is {} but the index is {}",
+ len, index)
}
- RepeatCountNotNatural => "repeat count must be a natural number".into_cow(),
- RepeatCountNotInt => "repeat count must be integers".into_cow(),
+ RepeatCountNotNatural => simple!("repeat count must be a natural number"),
+ RepeatCountNotInt => simple!("repeat count must be integers"),
- MiscBinaryOp => "bad operands for binary".into_cow(),
- MiscCatchAll => "unsupported constant expr".into_cow(),
- IndexOpFeatureGated => "the index operation on const values is unstable".into_cow(),
- Math(ref err) => err.description().into_cow(),
+ MiscBinaryOp => simple!("bad operands for binary"),
+ MiscCatchAll => simple!("unsupported constant expr"),
+ IndexOpFeatureGated => simple!("the index operation on const values is unstable"),
+ Math(ref err) => Simple(err.description().into_cow()),
- IntermediateUnsignedNegative => "during the computation of an unsigned a negative \
- number was encountered. This is most likely a bug in\
- the constant evaluator".into_cow(),
+ IntermediateUnsignedNegative => simple!(
+ "during the computation of an unsigned a negative \
+ number was encountered. This is most likely a bug in\
+ the constant evaluator"),
TypeMismatch(ref expected, ref got) => {
- format!("mismatched types: expected `{}`, found `{}`",
- expected, got.description()).into_cow()
+ simple!("expected {}, found {}", expected, got.description())
},
- BadType(ref i) => format!("value of wrong type: {:?}", i).into_cow(),
- ErroneousReferencedConstant(_) => "could not evaluate referenced constant".into_cow(),
+ BadType(ref i) => simple!("value of wrong type: {:?}", i),
+ ErroneousReferencedConstant(_) => simple!("could not evaluate referenced constant"),
CharCast(ref got) => {
- format!("only `u8` can be cast as `char`, not `{}`", got.description()).into_cow()
+ simple!("only `u8` can be cast as `char`, not `{}`", got.description())
},
}
}
@@ -1199,8 +1275,10 @@
})
}
-pub fn compare_const_vals(a: &ConstVal, b: &ConstVal) -> Option<Ordering> {
- match (a, b) {
+pub fn compare_const_vals(tcx: TyCtxt, span: Span, a: &ConstVal, b: &ConstVal)
+ -> Result<Ordering, ErrorReported>
+{
+ let result = match (a, b) {
(&Integral(a), &Integral(b)) => a.try_cmp(b).ok(),
(&Float(a), &Float(b)) => a.try_cmp(b).ok(),
(&Str(ref a), &Str(ref b)) => Some(a.cmp(b)),
@@ -1208,62 +1286,82 @@
(&ByteStr(ref a), &ByteStr(ref b)) => Some(a.cmp(b)),
(&Char(a), &Char(ref b)) => Some(a.cmp(b)),
_ => None,
+ };
+
+ match result {
+ Some(result) => Ok(result),
+ None => {
+ // FIXME: can this ever be reached?
+ span_err!(tcx.sess, span, E0298,
+ "type mismatch comparing {} and {}",
+ a.description(),
+ b.description());
+ Err(ErrorReported)
+ }
}
}
pub fn compare_lit_exprs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ span: Span,
a: &Expr,
- b: &Expr) -> Option<Ordering> {
+ b: &Expr) -> Result<Ordering, ErrorReported> {
let a = match eval_const_expr_partial(tcx, a, ExprTypeChecked, None) {
Ok(a) => a,
Err(e) => {
- tcx.sess.span_err(a.span, &e.description());
- return None;
+ report_const_eval_err(tcx, &e, a.span, "expression").emit();
+ return Err(ErrorReported);
}
};
let b = match eval_const_expr_partial(tcx, b, ExprTypeChecked, None) {
Ok(b) => b,
Err(e) => {
- tcx.sess.span_err(b.span, &e.description());
- return None;
+ report_const_eval_err(tcx, &e, b.span, "expression").emit();
+ return Err(ErrorReported);
}
};
- compare_const_vals(&a, &b)
+ compare_const_vals(tcx, span, &a, &b)
}
-/// Returns the repeat count for a repeating vector expression.
-pub fn eval_repeat_count<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- count_expr: &hir::Expr) -> usize {
+/// Returns the value of the length-valued expression
+pub fn eval_length<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ count_expr: &hir::Expr,
+ reason: &str)
+ -> Result<usize, ErrorReported>
+{
let hint = UncheckedExprHint(tcx.types.usize);
match eval_const_expr_partial(tcx, count_expr, hint, None) {
Ok(Integral(Usize(count))) => {
let val = count.as_u64(tcx.sess.target.uint_type);
assert_eq!(val as usize as u64, val);
- val as usize
+ Ok(val as usize)
},
Ok(const_val) => {
span_err!(tcx.sess, count_expr.span, E0306,
- "expected positive integer for repeat count, found {}",
+ "expected usize for {}, found {}",
+ reason,
const_val.description());
- 0
+ Err(ErrorReported)
}
Err(err) => {
- let err_msg = match count_expr.node {
+ let mut diag = report_const_eval_err(
+ tcx, &err, count_expr.span, reason);
+
+ match count_expr.node {
hir::ExprPath(None, hir::Path {
global: false,
ref segments,
..
- }) if segments.len() == 1 =>
- format!("found variable"),
- _ => match err.kind {
- MiscCatchAll => format!("but found {}", err.description()),
- _ => format!("but {}", err.description())
+ }) if segments.len() == 1 => {
+ if let Some(Def::Local(..)) = tcx.expect_def_or_none(count_expr.id) {
+ diag.note(&format!("`{}` is a variable", segments[0].name));
+ }
}
- };
- span_err!(tcx.sess, count_expr.span, E0307,
- "expected constant integer for repeat count, {}", err_msg);
- 0
+ _ => {}
+ }
+
+ diag.emit();
+ Err(ErrorReported)
}
}
}
diff --git a/src/librustc_const_eval/lib.rs b/src/librustc_const_eval/lib.rs
index 726ba4f..a6714c1 100644
--- a/src/librustc_const_eval/lib.rs
+++ b/src/librustc_const_eval/lib.rs
@@ -36,6 +36,7 @@
#[macro_use] extern crate rustc;
extern crate rustc_back;
extern crate rustc_const_math;
+extern crate rustc_errors;
extern crate graphviz;
extern crate syntax_pos;
extern crate serialize as rustc_serialize; // used by deriving
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index 657fc6c..f1f5e19 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -88,7 +88,7 @@
// We need nested scopes here, because the intermediate results can keep
// large chunks of memory alive and we want to free them as soon as
// possible to keep the peak memory usage low
- let (outputs, trans) = {
+ let (outputs, trans, crate_name) = {
let krate = match phase_1_parse_input(sess, cfg, input) {
Ok(krate) => krate,
Err(mut parse_error) => {
@@ -113,13 +113,13 @@
};
let outputs = build_output_filenames(input, outdir, output, &krate.attrs, sess);
- let id = link::find_crate_name(Some(sess), &krate.attrs, input);
+ let crate_name = link::find_crate_name(Some(sess), &krate.attrs, input);
let ExpansionResult { expanded_crate, defs, analysis, resolutions, mut hir_forest } = {
phase_2_configure_and_expand(
- sess, &cstore, krate, &id, addl_plugins, control.make_glob_map,
+ sess, &cstore, krate, &crate_name, addl_plugins, control.make_glob_map,
|expanded_crate| {
let mut state = CompileState::state_after_expand(
- input, sess, outdir, output, &cstore, expanded_crate, &id,
+ input, sess, outdir, output, &cstore, expanded_crate, &crate_name,
);
controller_entry_point!(after_expand, sess, state, Ok(()));
Ok(())
@@ -127,7 +127,7 @@
)?
};
- write_out_deps(sess, &outputs, &id);
+ write_out_deps(sess, &outputs, &crate_name);
let arenas = ty::CtxtArenas::new();
@@ -151,7 +151,7 @@
&resolutions,
&expanded_crate,
&hir_map.krate(),
- &id),
+ &crate_name),
Ok(()));
}
@@ -171,7 +171,7 @@
analysis,
resolutions,
&arenas,
- &id,
+ &crate_name,
|tcx, mir_map, analysis, result| {
{
// Eventually, we will want to track plugins.
@@ -186,7 +186,7 @@
&analysis,
mir_map.as_ref(),
tcx,
- &id);
+ &crate_name);
(control.after_analysis.callback)(&mut state);
if control.after_analysis.stop == Compilation::Stop {
@@ -212,11 +212,11 @@
// Discard interned strings as they are no longer required.
token::clear_ident_interner();
- Ok((outputs, trans))
+ Ok((outputs, trans, crate_name.clone()))
})??
};
- let phase5_result = phase_5_run_llvm_passes(sess, &trans, &outputs);
+ let phase5_result = phase_5_run_llvm_passes(sess, &crate_name, &trans, &outputs);
controller_entry_point!(after_llvm,
sess,
@@ -566,7 +566,8 @@
});
*sess.crate_types.borrow_mut() = collect_crate_types(sess, &krate.attrs);
- sess.crate_disambiguator.set(token::intern(&compute_crate_disambiguator(sess)));
+ *sess.crate_disambiguator.borrow_mut() =
+ token::intern(&compute_crate_disambiguator(sess)).as_str();
time(time_passes, "recursion limit", || {
middle::recursion_limit::update_recursion_limit(sess, &krate);
@@ -1021,6 +1022,7 @@
/// Run LLVM itself, producing a bitcode file, assembly file or object file
/// as a side effect.
pub fn phase_5_run_llvm_passes(sess: &Session,
+ crate_name: &str,
trans: &trans::CrateTranslation,
outputs: &OutputFilenames) -> CompileResult {
if sess.opts.cg.no_integrated_as {
@@ -1042,6 +1044,10 @@
|| write::run_passes(sess, trans, &sess.opts.output_types, outputs));
}
+ time(sess.time_passes(),
+ "serialize work products",
+ move || rustc_incremental::save_work_products(sess, crate_name));
+
if sess.err_count() > 0 {
Err(sess.err_count())
} else {
@@ -1065,14 +1071,14 @@
filename.replace(" ", "\\ ")
}
-fn write_out_deps(sess: &Session, outputs: &OutputFilenames, id: &str) {
+fn write_out_deps(sess: &Session, outputs: &OutputFilenames, crate_name: &str) {
let mut out_filenames = Vec::new();
for output_type in sess.opts.output_types.keys() {
let file = outputs.path(*output_type);
match *output_type {
OutputType::Exe => {
for output in sess.crate_types.borrow().iter() {
- let p = link::filename_for_input(sess, *output, id, outputs);
+ let p = link::filename_for_input(sess, *output, crate_name, outputs);
out_filenames.push(p);
}
}
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index 0a8df92..772c59b 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -31,7 +31,6 @@
#![feature(set_stdio)]
#![feature(staged_api)]
#![feature(question_mark)]
-#![feature(unboxed_closures)]
extern crate arena;
extern crate flate;
@@ -95,6 +94,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};
@@ -186,7 +186,7 @@
let sopts = config::build_session_options(&matches);
if sopts.debugging_opts.debug_llvm {
- unsafe { llvm::LLVMSetDebug(1); }
+ unsafe { llvm::LLVMRustSetDebug(1); }
}
let descriptions = diagnostics_registry();
@@ -392,15 +392,12 @@
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 +606,7 @@
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 +646,17 @@
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")
}
}
}
diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs
index 6a48f65..610e564 100644
--- a/src/librustc_errors/lib.rs
+++ b/src/librustc_errors/lib.rs
@@ -531,10 +531,12 @@
DiagnosticBuilder::new(self, Level::Fatal, msg)
}
- pub fn cancel(&mut self, err: &mut DiagnosticBuilder) {
+ pub fn cancel(&self, err: &mut DiagnosticBuilder) {
if err.level == Level::Error || err.level == Level::Fatal {
- assert!(self.has_errors());
- self.err_count.set(self.err_count.get() + 1);
+ self.err_count.set(
+ self.err_count.get().checked_sub(1)
+ .expect("cancelled an error but err_count is 0")
+ );
}
err.cancel();
}
diff --git a/src/librustc_incremental/assert_dep_graph.rs b/src/librustc_incremental/assert_dep_graph.rs
index d38f979..774c5ca 100644
--- a/src/librustc_incremental/assert_dep_graph.rs
+++ b/src/librustc_incremental/assert_dep_graph.rs
@@ -110,13 +110,11 @@
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 @@
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 {
diff --git a/src/librustc_incremental/calculate_svh.rs b/src/librustc_incremental/calculate_svh.rs
index cbc246a..bea6b7e 100644
--- a/src/librustc_incremental/calculate_svh.rs
+++ b/src/librustc_incremental/calculate_svh.rs
@@ -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;
@@ -36,7 +37,7 @@
// to ensure it is not incorporating implementation artifacts into
// the hash that are not otherwise visible.)
- let crate_disambiguator = self.sess.crate_disambiguator.get();
+ let crate_disambiguator = self.sess.local_crate_disambiguator();
let krate = self.map.krate();
// FIXME: this should use SHA1, not SipHash. SipHash is not built to
@@ -47,10 +48,10 @@
// FIXME(#32753) -- at (*) we `to_le` for endianness, but is
// this enough, and does it matter anyway?
"crate_disambiguator".hash(&mut state);
- crate_disambiguator.as_str().len().to_le().hash(&mut state); // (*)
- crate_disambiguator.as_str().hash(&mut state);
+ crate_disambiguator.len().to_le().hash(&mut state); // (*)
+ crate_disambiguator.hash(&mut state);
- debug!("crate_disambiguator: {:?}", crate_disambiguator.as_str());
+ debug!("crate_disambiguator: {:?}", crate_disambiguator);
debug!("state: {:?}", state);
{
@@ -69,7 +70,7 @@
// 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())
@@ -119,6 +120,7 @@
use rustc::ty::TyCtxt;
use rustc::hir;
use rustc::hir::*;
+ use rustc::hir::map::DefPath;
use rustc::hir::intravisit as visit;
use rustc::hir::intravisit::{Visitor, FnKind};
@@ -135,6 +137,15 @@
-> Self {
StrictVersionHashVisitor { st: st, tcx: tcx }
}
+
+ fn hash_def_path(&mut self, path: &DefPath) {
+ self.tcx.crate_name(path.krate).hash(self.st);
+ self.tcx.crate_disambiguator(path.krate).hash(self.st);
+ for data in &path.data {
+ data.data.as_interned_str().hash(self.st);
+ data.disambiguator.hash(self.st);
+ }
+ }
}
// To off-load the bulk of the hash-computation on #[derive(Hash)],
@@ -289,19 +300,21 @@
impl<'a, 'tcx> Visitor<'a> for StrictVersionHashVisitor<'a, 'tcx> {
fn visit_nested_item(&mut self, item: ItemId) {
- debug!("visit_nested_item: {:?} st={:?}", item, self.st);
- let def_path = self.tcx.map.def_path_from_id(item.id);
- def_path.hash(self.st);
+ let def_path = self.tcx.map.def_path_from_id(item.id).unwrap();
+ debug!("visit_nested_item: def_path={:?} st={:?}", def_path, self.st);
+ self.hash_def_path(&def_path);
}
fn visit_variant_data(&mut self, s: &'a VariantData, name: Name,
g: &'a Generics, _: NodeId, _: Span) {
+ debug!("visit_variant_data: st={:?}", self.st);
SawStructDef(name.as_str()).hash(self.st);
visit::walk_generics(self, g);
visit::walk_struct_def(self, s)
}
fn visit_variant(&mut self, v: &'a Variant, g: &'a Generics, item_id: NodeId) {
+ debug!("visit_variant: st={:?}", self.st);
SawVariant.hash(self.st);
// walk_variant does not call walk_generics, so do it here.
visit::walk_generics(self, g);
@@ -323,14 +336,17 @@
// pattern, please move that method up above this comment.)
fn visit_name(&mut self, _: Span, name: Name) {
+ debug!("visit_name: st={:?}", self.st);
SawIdent(name.as_str()).hash(self.st);
}
fn visit_lifetime(&mut self, l: &'a Lifetime) {
+ debug!("visit_lifetime: st={:?}", self.st);
SawLifetime(l.name.as_str()).hash(self.st);
}
fn visit_lifetime_def(&mut self, l: &'a LifetimeDef) {
+ debug!("visit_lifetime_def: st={:?}", self.st);
SawLifetimeDef(l.lifetime.name.as_str()).hash(self.st);
}
@@ -340,14 +356,18 @@
// that a change to a crate body will require downstream
// crates to be recompiled.
fn visit_expr(&mut self, ex: &'a Expr) {
+ debug!("visit_expr: st={:?}", self.st);
SawExpr(saw_expr(&ex.node)).hash(self.st); visit::walk_expr(self, ex)
}
fn visit_stmt(&mut self, s: &'a Stmt) {
+ debug!("visit_stmt: st={:?}", self.st);
SawStmt(saw_stmt(&s.node)).hash(self.st); visit::walk_stmt(self, s)
}
fn visit_foreign_item(&mut self, i: &'a ForeignItem) {
+ debug!("visit_foreign_item: st={:?}", self.st);
+
// FIXME (#14132) ideally we would incorporate privacy (or
// perhaps reachability) somewhere here, so foreign items
// that do not leak into downstream crates would not be
@@ -357,6 +377,7 @@
fn visit_item(&mut self, i: &'a Item) {
debug!("visit_item: {:?} st={:?}", i, self.st);
+
// FIXME (#14132) ideally would incorporate reachability
// analysis somewhere here, so items that never leak into
// downstream crates (e.g. via monomorphisation or
@@ -364,56 +385,69 @@
SawItem.hash(self.st); visit::walk_item(self, i)
}
- fn visit_mod(&mut self, m: &'a Mod, _s: Span, _n: NodeId) {
- SawMod.hash(self.st); visit::walk_mod(self, m)
+ 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, n)
}
fn visit_decl(&mut self, d: &'a Decl) {
+ debug!("visit_decl: st={:?}", self.st);
SawDecl.hash(self.st); visit::walk_decl(self, d)
}
fn visit_ty(&mut self, t: &'a Ty) {
+ debug!("visit_ty: st={:?}", self.st);
SawTy.hash(self.st); visit::walk_ty(self, t)
}
fn visit_generics(&mut self, g: &'a Generics) {
+ debug!("visit_generics: st={:?}", self.st);
SawGenerics.hash(self.st); visit::walk_generics(self, g)
}
fn visit_fn(&mut self, fk: FnKind<'a>, fd: &'a FnDecl,
- b: &'a Block, s: Span, _: NodeId) {
- SawFn.hash(self.st); visit::walk_fn(self, fk, fd, b, s)
+ 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, n)
}
fn visit_trait_item(&mut self, ti: &'a TraitItem) {
+ debug!("visit_trait_item: st={:?}", self.st);
SawTraitItem.hash(self.st); visit::walk_trait_item(self, ti)
}
fn visit_impl_item(&mut self, ii: &'a ImplItem) {
+ debug!("visit_impl_item: st={:?}", self.st);
SawImplItem.hash(self.st); visit::walk_impl_item(self, ii)
}
fn visit_struct_field(&mut self, s: &'a StructField) {
+ debug!("visit_struct_field: st={:?}", self.st);
SawStructField.hash(self.st); visit::walk_struct_field(self, s)
}
fn visit_path(&mut self, path: &'a Path, _: ast::NodeId) {
+ debug!("visit_path: st={:?}", self.st);
SawPath.hash(self.st); visit::walk_path(self, path)
}
fn visit_block(&mut self, b: &'a Block) {
+ debug!("visit_block: st={:?}", self.st);
SawBlock.hash(self.st); visit::walk_block(self, b)
}
fn visit_pat(&mut self, p: &'a Pat) {
+ debug!("visit_pat: st={:?}", self.st);
SawPat.hash(self.st); visit::walk_pat(self, p)
}
fn visit_local(&mut self, l: &'a Local) {
+ debug!("visit_local: st={:?}", self.st);
SawLocal.hash(self.st); visit::walk_local(self, l)
}
fn visit_arm(&mut self, a: &'a Arm) {
+ debug!("visit_arm: st={:?}", self.st);
SawArm.hash(self.st); visit::walk_arm(self, a)
}
}
diff --git a/src/librustc_incremental/lib.rs b/src/librustc_incremental/lib.rs
index ed31e0b..0d11b07 100644
--- a/src/librustc_incremental/lib.rs
+++ b/src/librustc_incremental/lib.rs
@@ -19,6 +19,7 @@
html_root_url = "https://doc.rust-lang.org/nightly/")]
#![cfg_attr(not(stage0), deny(warnings))]
+#![feature(question_mark)]
#![feature(rustc_private)]
#![feature(staged_api)]
@@ -40,3 +41,6 @@
pub use calculate_svh::SvhCalculate;
pub use persist::load_dep_graph;
pub use persist::save_dep_graph;
+pub use persist::save_trans_partition;
+pub use persist::save_work_products;
+pub use persist::in_incr_comp_dir;
diff --git a/src/librustc_incremental/persist/data.rs b/src/librustc_incremental/persist/data.rs
index f57ab19..95e9a16 100644
--- a/src/librustc_incremental/persist/data.rs
+++ b/src/librustc_incremental/persist/data.rs
@@ -10,8 +10,9 @@
//! The data that we will serialize and deserialize.
-use rustc::dep_graph::DepNode;
+use rustc::dep_graph::{DepNode, WorkProduct, WorkProductId};
use rustc::hir::def_id::DefIndex;
+use std::sync::Arc;
use super::directory::DefPathIndex;
@@ -55,6 +56,15 @@
pub hash: u64,
}
+#[derive(Debug, RustcEncodable, RustcDecodable)]
+pub struct SerializedWorkProduct {
+ /// node that produced the work-product
+ pub id: Arc<WorkProductId>,
+
+ /// work-product data itself
+ pub work_product: WorkProduct,
+}
+
/// Data for use when downstream crates get recompiled.
#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct SerializedMetadataHashes {
diff --git a/src/librustc_incremental/persist/load.rs b/src/librustc_incremental/persist/load.rs
index 0ac1018..36b6c79 100644
--- a/src/librustc_incremental/persist/load.rs
+++ b/src/librustc_incremental/persist/load.rs
@@ -14,12 +14,13 @@
use rbml::opaque::Decoder;
use rustc::dep_graph::DepNode;
use rustc::hir::def_id::DefId;
+use rustc::session::Session;
use rustc::ty::TyCtxt;
use rustc_data_structures::fnv::FnvHashSet;
use rustc_serialize::Decodable as RustcDecodable;
use std::io::Read;
-use std::fs::File;
-use std::path::Path;
+use std::fs::{self, File};
+use std::path::{Path};
use super::data::*;
use super::directory::*;
@@ -38,18 +39,43 @@
/// actually it doesn't matter all that much.) See `README.md` for
/// more general overview.
pub fn load_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
- let _ignore = tcx.dep_graph.in_ignore();
+ if tcx.sess.opts.incremental.is_none() {
+ return;
+ }
- if let Some(dep_graph) = dep_graph_path(tcx) {
- // FIXME(#32754) lock file?
- load_dep_graph_if_exists(tcx, &dep_graph);
- dirty_clean::check_dirty_clean_annotations(tcx);
+ let _ignore = tcx.dep_graph.in_ignore();
+ load_dep_graph_if_exists(tcx);
+ dirty_clean::check_dirty_clean_annotations(tcx);
+}
+
+fn load_dep_graph_if_exists<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
+ let dep_graph_path = dep_graph_path(tcx).unwrap();
+ let dep_graph_data = match load_data(tcx.sess, &dep_graph_path) {
+ Some(p) => p,
+ None => return // no file
+ };
+
+ let work_products_path = tcx_work_products_path(tcx).unwrap();
+ let work_products_data = match load_data(tcx.sess, &work_products_path) {
+ Some(p) => p,
+ None => return // no file
+ };
+
+ match decode_dep_graph(tcx, &dep_graph_data, &work_products_data) {
+ Ok(()) => return,
+ Err(err) => {
+ tcx.sess.warn(
+ &format!("decoding error in dep-graph from `{}` and `{}`: {}",
+ dep_graph_path.display(),
+ work_products_path.display(),
+ err));
+ }
}
}
-pub fn load_dep_graph_if_exists<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, path: &Path) {
+fn load_data(sess: &Session, path: &Path) -> Option<Vec<u8>> {
if !path.exists() {
- return;
+ return None;
}
let mut data = vec![];
@@ -57,31 +83,30 @@
File::open(path)
.and_then(|mut file| file.read_to_end(&mut data))
{
- Ok(_) => { }
+ Ok(_) => {
+ Some(data)
+ }
Err(err) => {
- tcx.sess.err(
+ sess.err(
&format!("could not load dep-graph from `{}`: {}",
path.display(), err));
- return;
+ None
}
}
- match decode_dep_graph(tcx, &data) {
- Ok(dirty) => dirty,
- Err(err) => {
- bug!("decoding error in dep-graph from `{}`: {}", path.display(), err);
- }
- }
}
+/// Decode the dep graph and load the edges/nodes that are still clean
+/// into `tcx.dep_graph`.
pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- data: &[u8])
+ dep_graph_data: &[u8],
+ work_products_data: &[u8])
-> Result<(), Error>
{
// Deserialize the directory and dep-graph.
- let mut decoder = Decoder::new(data, 0);
- let directory = try!(DefIdDirectory::decode(&mut decoder));
- let serialized_dep_graph = try!(SerializedDepGraph::decode(&mut decoder));
+ let mut dep_graph_decoder = Decoder::new(dep_graph_data, 0);
+ let directory = try!(DefIdDirectory::decode(&mut dep_graph_decoder));
+ let serialized_dep_graph = try!(SerializedDepGraph::decode(&mut dep_graph_decoder));
debug!("decode_dep_graph: directory = {:#?}", directory);
debug!("decode_dep_graph: serialized_dep_graph = {:#?}", serialized_dep_graph);
@@ -121,12 +146,18 @@
// Add nodes and edges that are not dirty into our main graph.
let dep_graph = tcx.dep_graph.clone();
for (source, target) in clean_edges.into_iter().chain(clean_nodes) {
- let _task = dep_graph.in_task(target.clone());
- dep_graph.read(source.clone());
-
debug!("decode_dep_graph: clean edge: {:?} -> {:?}", source, target);
+
+ let _task = dep_graph.in_task(target);
+ dep_graph.read(source);
}
+ // Add in work-products that are still clean, and delete those that are
+ // dirty.
+ let mut work_product_decoder = Decoder::new(work_products_data, 0);
+ let work_products = try!(<Vec<SerializedWorkProduct>>::decode(&mut work_product_decoder));
+ reconcile_work_products(tcx, work_products, &dirty_nodes);
+
Ok(())
}
@@ -141,9 +172,9 @@
match hash.node.map_def(|&i| retraced.def_id(i)) {
Some(dep_node) => {
let current_hash = hcx.hash(&dep_node).unwrap();
- debug!("initial_dirty_nodes: hash of {:?} is {:?}, was {:?}",
- dep_node, current_hash, hash.hash);
if current_hash != hash.hash {
+ debug!("initial_dirty_nodes: {:?} is dirty as hash is {:?}, was {:?}",
+ dep_node, current_hash, hash.hash);
dirty_nodes.insert(dep_node);
}
}
@@ -177,6 +208,8 @@
clean_edges.push((source, target))
} else {
// source removed, target must be dirty
+ debug!("compute_clean_edges: {:?} dirty because {:?} no longer exists",
+ target, serialized_source);
dirty_nodes.insert(target);
}
} else {
@@ -213,3 +246,51 @@
clean_edges
}
+
+/// Go through the list of work-products produced in the previous run.
+/// Delete any whose nodes have been found to be dirty or which are
+/// otherwise no longer applicable.
+fn reconcile_work_products<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ work_products: Vec<SerializedWorkProduct>,
+ dirty_nodes: &DirtyNodes) {
+ debug!("reconcile_work_products({:?})", work_products);
+ for swp in work_products {
+ let dep_node = DepNode::WorkProduct(swp.id.clone());
+ if dirty_nodes.contains(&dep_node) {
+ debug!("reconcile_work_products: dep-node for {:?} is dirty", swp);
+ delete_dirty_work_product(tcx, swp);
+ } else {
+ let all_files_exist =
+ swp.work_product
+ .saved_files
+ .iter()
+ .all(|&(_, ref file_name)| {
+ let path = in_incr_comp_dir(tcx.sess, &file_name).unwrap();
+ path.exists()
+ });
+ if all_files_exist {
+ debug!("reconcile_work_products: all files for {:?} exist", swp);
+ tcx.dep_graph.insert_previous_work_product(&swp.id, swp.work_product);
+ } else {
+ debug!("reconcile_work_products: some file for {:?} does not exist", swp);
+ delete_dirty_work_product(tcx, swp);
+ }
+ }
+ }
+}
+
+fn delete_dirty_work_product(tcx: TyCtxt,
+ swp: SerializedWorkProduct) {
+ debug!("delete_dirty_work_product({:?})", swp);
+ for &(_, ref file_name) in &swp.work_product.saved_files {
+ let path = in_incr_comp_dir(tcx.sess, file_name).unwrap();
+ match fs::remove_file(&path) {
+ Ok(()) => { }
+ Err(err) => {
+ tcx.sess.warn(
+ &format!("file-system error deleting outdated file `{}`: {}",
+ path.display(), err));
+ }
+ }
+ }
+}
diff --git a/src/librustc_incremental/persist/mod.rs b/src/librustc_incremental/persist/mod.rs
index 72ccc29..1157f49 100644
--- a/src/librustc_incremental/persist/mod.rs
+++ b/src/librustc_incremental/persist/mod.rs
@@ -19,6 +19,10 @@
mod load;
mod save;
mod util;
+mod work_product;
pub use self::load::load_dep_graph;
pub use self::save::save_dep_graph;
+pub use self::save::save_work_products;
+pub use self::work_product::save_trans_partition;
+pub use self::util::in_incr_comp_dir;
diff --git a/src/librustc_incremental/persist/save.rs b/src/librustc_incremental/persist/save.rs
index 99f4d4f..305250d 100644
--- a/src/librustc_incremental/persist/save.rs
+++ b/src/librustc_incremental/persist/save.rs
@@ -11,6 +11,7 @@
use rbml::opaque::Encoder;
use rustc::dep_graph::DepNode;
use rustc::middle::cstore::LOCAL_CRATE;
+use rustc::session::Session;
use rustc::ty::TyCtxt;
use rustc_serialize::{Encodable as RustcEncodable};
use std::hash::{Hasher, SipHasher};
@@ -24,19 +25,26 @@
use super::util::*;
pub fn save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
+ debug!("save_dep_graph()");
let _ignore = tcx.dep_graph.in_ignore();
+ let sess = tcx.sess;
let mut hcx = HashContext::new(tcx);
- save_in(&mut hcx, dep_graph_path(tcx), encode_dep_graph);
- save_in(&mut hcx, metadata_hash_path(tcx, LOCAL_CRATE), encode_metadata_hashes);
+ save_in(sess, dep_graph_path(tcx), |e| encode_dep_graph(&mut hcx, e));
+ save_in(sess, metadata_hash_path(tcx, LOCAL_CRATE), |e| encode_metadata_hashes(&mut hcx, e));
}
-fn save_in<'a, 'tcx, F>(hcx: &mut HashContext<'a, 'tcx>,
- opt_path_buf: Option<PathBuf>,
- encode: F)
- where F: FnOnce(&mut HashContext<'a, 'tcx>, &mut Encoder) -> io::Result<()>
-{
- let tcx = hcx.tcx;
+pub fn save_work_products(sess: &Session, local_crate_name: &str) {
+ debug!("save_work_products()");
+ let _ignore = sess.dep_graph.in_ignore();
+ let path = sess_work_products_path(sess, local_crate_name);
+ save_in(sess, path, |e| encode_work_products(sess, e));
+}
+fn save_in<F>(sess: &Session,
+ opt_path_buf: Option<PathBuf>,
+ encode: F)
+ where F: FnOnce(&mut Encoder) -> io::Result<()>
+{
let path_buf = match opt_path_buf {
Some(p) => p,
None => return
@@ -49,7 +57,7 @@
match fs::remove_file(&path_buf) {
Ok(()) => { }
Err(err) => {
- tcx.sess.err(
+ sess.err(
&format!("unable to delete old dep-graph at `{}`: {}",
path_buf.display(), err));
return;
@@ -59,10 +67,10 @@
// generate the data in a memory buffer
let mut wr = Cursor::new(Vec::new());
- match encode(hcx, &mut Encoder::new(&mut wr)) {
+ match encode(&mut Encoder::new(&mut wr)) {
Ok(()) => { }
Err(err) => {
- tcx.sess.err(
+ sess.err(
&format!("could not encode dep-graph to `{}`: {}",
path_buf.display(), err));
return;
@@ -77,7 +85,7 @@
{
Ok(_) => { }
Err(err) => {
- tcx.sess.err(
+ sess.err(
&format!("failed to write dep-graph to `{}`: {}",
path_buf.display(), err));
return;
@@ -192,3 +200,22 @@
Ok(())
}
+
+pub fn encode_work_products(sess: &Session,
+ encoder: &mut Encoder)
+ -> io::Result<()>
+{
+ let work_products: Vec<_> =
+ sess.dep_graph.work_products()
+ .iter()
+ .map(|(id, work_product)| {
+ SerializedWorkProduct {
+ id: id.clone(),
+ work_product: work_product.clone(),
+ }
+ })
+ .collect();
+
+ work_products.encode(encoder)
+}
+
diff --git a/src/librustc_incremental/persist/util.rs b/src/librustc_incremental/persist/util.rs
index a77a960..f1e81fd 100644
--- a/src/librustc_incremental/persist/util.rs
+++ b/src/librustc_incremental/persist/util.rs
@@ -9,6 +9,7 @@
// except according to those terms.
use rustc::middle::cstore::LOCAL_CRATE;
+use rustc::session::Session;
use rustc::ty::TyCtxt;
use std::fs;
@@ -17,33 +18,56 @@
use syntax::ast;
pub fn dep_graph_path(tcx: TyCtxt) -> Option<PathBuf> {
- path(tcx, LOCAL_CRATE, "local")
+ tcx_path(tcx, LOCAL_CRATE, "local")
}
pub fn metadata_hash_path(tcx: TyCtxt, cnum: ast::CrateNum) -> Option<PathBuf> {
- path(tcx, cnum, "metadata")
+ tcx_path(tcx, cnum, "metadata")
}
-fn path(tcx: TyCtxt, cnum: ast::CrateNum, suffix: &str) -> Option<PathBuf> {
+pub fn tcx_work_products_path(tcx: TyCtxt) -> Option<PathBuf> {
+ let crate_name = tcx.crate_name(LOCAL_CRATE);
+ sess_work_products_path(tcx.sess, &crate_name)
+}
+
+pub fn sess_work_products_path(sess: &Session,
+ local_crate_name: &str)
+ -> Option<PathBuf> {
+ let crate_disambiguator = sess.local_crate_disambiguator();
+ path(sess, local_crate_name, &crate_disambiguator, "work-products")
+}
+
+pub fn in_incr_comp_dir(sess: &Session, file_name: &str) -> Option<PathBuf> {
+ sess.opts.incremental.as_ref().map(|incr_dir| incr_dir.join(file_name))
+}
+
+fn tcx_path(tcx: TyCtxt,
+ cnum: ast::CrateNum,
+ middle: &str)
+ -> Option<PathBuf> {
+ path(tcx.sess, &tcx.crate_name(cnum), &tcx.crate_disambiguator(cnum), middle)
+}
+
+fn path(sess: &Session,
+ crate_name: &str,
+ crate_disambiguator: &str,
+ middle: &str)
+ -> Option<PathBuf> {
// For now, just save/load dep-graph from
// directory/dep_graph.rbml
- tcx.sess.opts.incremental.as_ref().and_then(|incr_dir| {
+ sess.opts.incremental.as_ref().and_then(|incr_dir| {
match create_dir_racy(&incr_dir) {
Ok(()) => {}
Err(err) => {
- tcx.sess.err(
+ sess.err(
&format!("could not create the directory `{}`: {}",
incr_dir.display(), err));
return None;
}
}
- let crate_name = tcx.crate_name(cnum);
- let crate_disambiguator = tcx.crate_disambiguator(cnum);
- let file_name = format!("{}-{}.{}.bin",
- crate_name,
- crate_disambiguator,
- suffix);
+ let file_name = format!("{}-{}.{}.bin", crate_name, crate_disambiguator, middle);
+
Some(incr_dir.join(file_name))
})
}
diff --git a/src/librustc_incremental/persist/work_product.rs b/src/librustc_incremental/persist/work_product.rs
new file mode 100644
index 0000000..c106ea8
--- /dev/null
+++ b/src/librustc_incremental/persist/work_product.rs
@@ -0,0 +1,63 @@
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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 module contains files for saving intermediate work-products.
+
+use persist::util::*;
+use rustc::dep_graph::{WorkProduct, WorkProductId};
+use rustc::session::Session;
+use rustc::session::config::OutputType;
+use rustc::util::fs::link_or_copy;
+use std::path::PathBuf;
+use std::sync::Arc;
+
+pub fn save_trans_partition(sess: &Session,
+ cgu_name: &str,
+ partition_hash: u64,
+ files: &[(OutputType, PathBuf)]) {
+ debug!("save_trans_partition({:?},{},{:?})",
+ cgu_name,
+ partition_hash,
+ files);
+ if sess.opts.incremental.is_none() {
+ return;
+ }
+ let work_product_id = Arc::new(WorkProductId(cgu_name.to_string()));
+
+ let saved_files: Option<Vec<_>> =
+ files.iter()
+ .map(|&(kind, ref path)| {
+ let file_name = format!("cgu-{}.{}", cgu_name, kind.extension());
+ let path_in_incr_dir = in_incr_comp_dir(sess, &file_name).unwrap();
+ match link_or_copy(path, &path_in_incr_dir) {
+ Ok(_) => Some((kind, file_name)),
+ Err(err) => {
+ sess.warn(&format!("error copying object file `{}` \
+ to incremental directory as `{}`: {}",
+ path.display(),
+ path_in_incr_dir.display(),
+ err));
+ None
+ }
+ }
+ })
+ .collect();
+ let saved_files = match saved_files {
+ Some(v) => v,
+ None => return,
+ };
+
+ let work_product = WorkProduct {
+ input_hash: partition_hash,
+ saved_files: saved_files,
+ };
+
+ sess.dep_graph.insert_work_product(&work_product_id, work_product);
+}
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index 18f9733..7547e28 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -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 @@
}
}
- 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 @@
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");
}
}
}
diff --git a/src/librustc_llvm/Cargo.toml b/src/librustc_llvm/Cargo.toml
index 05d2091..f97daa2 100644
--- a/src/librustc_llvm/Cargo.toml
+++ b/src/librustc_llvm/Cargo.toml
@@ -17,4 +17,4 @@
[build-dependencies]
build_helper = { path = "../build_helper" }
-gcc = "0.3"
+gcc = "0.3.27"
diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs
index a2c808c..b8548aa 100644
--- a/src/librustc_llvm/build.rs
+++ b/src/librustc_llvm/build.rs
@@ -13,7 +13,7 @@
use std::process::Command;
use std::env;
-use std::path::PathBuf;
+use std::path::{PathBuf, Path};
use build_helper::output;
@@ -112,8 +112,7 @@
cfg.flag(&flag);
}
- cfg.file("../rustllvm/ExecutionEngineWrapper.cpp")
- .file("../rustllvm/PassWrapper.cpp")
+ cfg.file("../rustllvm/PassWrapper.cpp")
.file("../rustllvm/RustWrapper.cpp")
.file("../rustllvm/ArchiveWrapper.cpp")
.cpp(true)
@@ -135,8 +134,17 @@
&lib[2..]
} else if lib.starts_with("-") {
&lib[1..]
+ } else if Path::new(lib).exists() {
+ // On MSVC llvm-config will print the full name to libraries, but
+ // we're only interested in the name part
+ let name = Path::new(lib).file_name().unwrap().to_str().unwrap();
+ name.trim_right_matches(".lib")
+ } else if lib.ends_with(".lib") {
+ // Some MSVC libraries just come up with `.lib` tacked on, so chop
+ // that off
+ lib.trim_right_matches(".lib")
} else {
- continue;
+ continue
};
// Don't need or want this library, but LLVM's CMake build system
@@ -145,7 +153,7 @@
// library and it otherwise may just pull in extra dependencies on
// libedit which we don't want
if name == "LLVMLineEditor" {
- continue;
+ continue
}
let kind = if name.starts_with("LLVM") {
@@ -165,7 +173,9 @@
let mut cmd = Command::new(&llvm_config);
cmd.arg("--ldflags");
for lib in output(&mut cmd).split_whitespace() {
- if is_crossed {
+ if lib.starts_with("-LIBPATH:") {
+ println!("cargo:rustc-link-search=native={}", &lib[9..]);
+ } else if is_crossed {
if lib.starts_with("-L") {
println!("cargo:rustc-link-search=native={}",
lib[2..].replace(&host, &target));
diff --git a/src/librustc_llvm/diagnostic.rs b/src/librustc_llvm/diagnostic.rs
index 44e0156..8520ae1 100644
--- a/src/librustc_llvm/diagnostic.rs
+++ b/src/librustc_llvm/diagnostic.rs
@@ -16,22 +16,29 @@
use libc::{c_char, c_uint};
use std::ptr;
-use {DebugLocRef, DiagnosticInfoRef, TwineRef, ValueRef};
+use {DiagnosticInfoRef, TwineRef, ValueRef};
+use ffi::DebugLocRef;
#[derive(Copy, Clone)]
pub enum OptimizationDiagnosticKind {
OptimizationRemark,
OptimizationMissed,
OptimizationAnalysis,
+ OptimizationAnalysisFPCommute,
+ OptimizationAnalysisAliasing,
OptimizationFailure,
+ OptimizationRemarkOther,
}
impl OptimizationDiagnosticKind {
pub fn describe(self) -> &'static str {
match self {
- OptimizationRemark => "remark",
+ OptimizationRemark |
+ OptimizationRemarkOther => "remark",
OptimizationMissed => "missed",
OptimizationAnalysis => "analysis",
+ OptimizationAnalysisFPCommute => "floating-point",
+ OptimizationAnalysisAliasing => "aliasing",
OptimizationFailure => "failure",
}
}
@@ -58,11 +65,11 @@
message: ptr::null_mut(),
};
- super::LLVMUnpackOptimizationDiagnostic(di,
- &mut opt.pass_name,
- &mut opt.function,
- &mut opt.debug_loc,
- &mut opt.message);
+ super::LLVMRustUnpackOptimizationDiagnostic(di,
+ &mut opt.pass_name,
+ &mut opt.function,
+ &mut opt.debug_loc,
+ &mut opt.message);
opt
}
@@ -84,10 +91,10 @@
instruction: ptr::null_mut(),
};
- super::LLVMUnpackInlineAsmDiagnostic(di,
- &mut opt.cookie,
- &mut opt.message,
- &mut opt.instruction);
+ super::LLVMRustUnpackInlineAsmDiagnostic(di,
+ &mut opt.cookie,
+ &mut opt.message,
+ &mut opt.instruction);
opt
}
@@ -103,24 +110,39 @@
impl Diagnostic {
pub unsafe fn unpack(di: DiagnosticInfoRef) -> Diagnostic {
- let kind = super::LLVMGetDiagInfoKind(di);
+ use super::DiagnosticKind as Dk;
+ let kind = super::LLVMRustGetDiagInfoKind(di);
match kind {
- super::DK_InlineAsm => InlineAsm(InlineAsmDiagnostic::unpack(di)),
+ Dk::InlineAsm => InlineAsm(InlineAsmDiagnostic::unpack(di)),
- super::DK_OptimizationRemark => {
+ Dk::OptimizationRemark => {
Optimization(OptimizationDiagnostic::unpack(OptimizationRemark, di))
}
-
- super::DK_OptimizationRemarkMissed => {
+ Dk::OptimizationRemarkOther => {
+ Optimization(OptimizationDiagnostic::unpack(OptimizationRemarkOther, di))
+ }
+ Dk::OptimizationRemarkMissed => {
Optimization(OptimizationDiagnostic::unpack(OptimizationMissed, di))
}
- super::DK_OptimizationRemarkAnalysis => {
+ Dk::OptimizationRemarkAnalysis => {
Optimization(OptimizationDiagnostic::unpack(OptimizationAnalysis, di))
}
- super::DK_OptimizationFailure => {
+
+ Dk::OptimizationRemarkAnalysisFPCommute => {
+ Optimization(OptimizationDiagnostic::unpack(
+ OptimizationAnalysisFPCommute, di))
+ }
+
+ Dk::OptimizationRemarkAnalysisAliasing => {
+ Optimization(OptimizationDiagnostic::unpack(
+ OptimizationAnalysisAliasing, di))
+ }
+
+
+ Dk::OptimizationFailure => {
Optimization(OptimizationDiagnostic::unpack(OptimizationFailure, di))
}
diff --git a/src/librustc_llvm/ffi.rs b/src/librustc_llvm/ffi.rs
new file mode 100644
index 0000000..6301c57
--- /dev/null
+++ b/src/librustc_llvm/ffi.rs
@@ -0,0 +1,2068 @@
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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 debuginfo::{DIBuilderRef, DIDescriptor,
+ DIFile, DILexicalBlock, DISubprogram, DIType,
+ DIBasicType, DIDerivedType, DICompositeType, DIScope,
+ DIVariable, DIGlobalVariable, DIArray, DISubrange,
+ DITemplateTypeParameter, DIEnumerator, DINameSpace};
+
+use libc::{c_uint, c_int, size_t, c_char};
+use libc::{c_longlong, c_ulonglong, c_void};
+
+use RustStringRef;
+
+pub type Opcode = u32;
+pub type Bool = c_uint;
+
+pub const True: Bool = 1 as Bool;
+pub const False: Bool = 0 as Bool;
+
+#[derive(Copy, Clone, PartialEq)]
+#[repr(C)]
+pub enum LLVMRustResult {
+ Success,
+ Failure,
+}
+// Consts for the LLVM CallConv type, pre-cast to usize.
+
+/// LLVM CallingConv::ID. Should we wrap this?
+#[derive(Copy, Clone, PartialEq)]
+#[repr(C)]
+pub enum CallConv {
+ CCallConv = 0,
+ FastCallConv = 8,
+ ColdCallConv = 9,
+ X86StdcallCallConv = 64,
+ X86FastcallCallConv = 65,
+ X86_64_Win64 = 79,
+ X86_VectorCall = 80
+}
+
+/// LLVMLinkage
+///
+/// This enum omits the obsolete (and no-op) linkage types DLLImportLinkage,
+/// DLLExportLinkage, GhostLinkage and LinkOnceODRAutoHideLinkage.
+/// LinkerPrivateLinkage and LinkerPrivateWeakLinkage are not included either;
+/// they've been removed in upstream LLVM commit r203866.
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
+#[repr(C)]
+pub enum Linkage {
+ ExternalLinkage = 0,
+ AvailableExternallyLinkage = 1,
+ LinkOnceAnyLinkage = 2,
+ LinkOnceODRLinkage = 3,
+ WeakAnyLinkage = 5,
+ WeakODRLinkage = 6,
+ AppendingLinkage = 7,
+ InternalLinkage = 8,
+ PrivateLinkage = 9,
+ ExternalWeakLinkage = 12,
+ CommonLinkage = 14,
+}
+
+/// LLVMDiagnosticSeverity
+#[derive(Copy, Clone, Debug)]
+#[repr(C)]
+pub enum DiagnosticSeverity {
+ Error = 0,
+ Warning = 1,
+ Remark = 2,
+ Note = 3,
+}
+
+/// LLVMDLLStorageClass
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub enum DLLStorageClass {
+ Default = 0,
+ DllImport = 1, /* Function to be imported from DLL. */
+ DllExport = 2, /* Function to be accessible from DLL. */
+}
+
+bitflags! {
+ #[derive(Default, Debug)]
+ flags Attribute : u64 {
+ const ZExt = 1 << 0,
+ const SExt = 1 << 1,
+ const NoReturn = 1 << 2,
+ const InReg = 1 << 3,
+ const StructRet = 1 << 4,
+ const NoUnwind = 1 << 5,
+ const NoAlias = 1 << 6,
+ const ByVal = 1 << 7,
+ const Nest = 1 << 8,
+ const ReadNone = 1 << 9,
+ const ReadOnly = 1 << 10,
+ const NoInline = 1 << 11,
+ const AlwaysInline = 1 << 12,
+ const OptimizeForSize = 1 << 13,
+ const StackProtect = 1 << 14,
+ const StackProtectReq = 1 << 15,
+ const NoCapture = 1 << 21,
+ const NoRedZone = 1 << 22,
+ const NoImplicitFloat = 1 << 23,
+ const Naked = 1 << 24,
+ const InlineHint = 1 << 25,
+ const ReturnsTwice = 1 << 29,
+ const UWTable = 1 << 30,
+ const NonLazyBind = 1 << 31,
+
+ // Some of these are missing from the LLVM C API, the rest are
+ // present, but commented out, and preceded by the following warning:
+ // FIXME: These attributes are currently not included in the C API as
+ // a temporary measure until the API/ABI impact to the C API is understood
+ // and the path forward agreed upon.
+ const SanitizeAddress = 1 << 32,
+ const MinSize = 1 << 33,
+ const NoDuplicate = 1 << 34,
+ const StackProtectStrong = 1 << 35,
+ const SanitizeThread = 1 << 36,
+ const SanitizeMemory = 1 << 37,
+ const NoBuiltin = 1 << 38,
+ const Returned = 1 << 39,
+ const Cold = 1 << 40,
+ const Builtin = 1 << 41,
+ const OptimizeNone = 1 << 42,
+ const InAlloca = 1 << 43,
+ const NonNull = 1 << 44,
+ const JumpTable = 1 << 45,
+ const Convergent = 1 << 46,
+ const SafeStack = 1 << 47,
+ const NoRecurse = 1 << 48,
+ const InaccessibleMemOnly = 1 << 49,
+ const InaccessibleMemOrArgMemOnly = 1 << 50,
+ }
+}
+
+/// LLVMIntPredicate
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub enum IntPredicate {
+ IntEQ = 32,
+ IntNE = 33,
+ IntUGT = 34,
+ IntUGE = 35,
+ IntULT = 36,
+ IntULE = 37,
+ IntSGT = 38,
+ IntSGE = 39,
+ IntSLT = 40,
+ IntSLE = 41,
+}
+
+/// LLVMRealPredicate
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub enum RealPredicate {
+ RealPredicateFalse = 0,
+ RealOEQ = 1,
+ RealOGT = 2,
+ RealOGE = 3,
+ RealOLT = 4,
+ RealOLE = 5,
+ RealONE = 6,
+ RealORD = 7,
+ RealUNO = 8,
+ RealUEQ = 9,
+ RealUGT = 10,
+ RealUGE = 11,
+ RealULT = 12,
+ RealULE = 13,
+ RealUNE = 14,
+ RealPredicateTrue = 15,
+}
+
+/// LLVMTypeKind
+#[derive(Copy, Clone, PartialEq, Debug)]
+#[repr(C)]
+pub enum TypeKind {
+ Void = 0,
+ Half = 1,
+ Float = 2,
+ Double = 3,
+ X86_FP80 = 4,
+ FP128 = 5,
+ PPC_FP128 = 6,
+ Label = 7,
+ Integer = 8,
+ Function = 9,
+ Struct = 10,
+ Array = 11,
+ Pointer = 12,
+ Vector = 13,
+ Metadata = 14,
+ X86_MMX = 15,
+ Token = 16,
+}
+
+/// LLVMAtomicRmwBinOp
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub enum AtomicRmwBinOp {
+ AtomicXchg = 0,
+ AtomicAdd = 1,
+ AtomicSub = 2,
+ AtomicAnd = 3,
+ AtomicNand = 4,
+ AtomicOr = 5,
+ AtomicXor = 6,
+ AtomicMax = 7,
+ AtomicMin = 8,
+ AtomicUMax = 9,
+ AtomicUMin = 10,
+}
+
+/// LLVMAtomicOrdering
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub enum AtomicOrdering {
+ NotAtomic = 0,
+ Unordered = 1,
+ Monotonic = 2,
+ // Consume = 3, // Not specified yet.
+ Acquire = 4,
+ Release = 5,
+ AcquireRelease = 6,
+ SequentiallyConsistent = 7
+}
+
+/// LLVMRustSynchronizationScope
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub enum SynchronizationScope {
+ Other,
+ SingleThread,
+ CrossThread,
+}
+
+/// LLVMRustFileType
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub enum FileType {
+ Other,
+ AssemblyFile,
+ ObjectFile,
+}
+
+/// Enum pinned in LLVMContext, used in
+/// LLVMSetMetadata so ABI-stable.
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub enum MetadataType {
+ MD_dbg = 0,
+ MD_tbaa = 1,
+ MD_prof = 2,
+ MD_fpmath = 3,
+ MD_range = 4,
+ MD_tbaa_struct = 5,
+ MD_invariant_load = 6,
+ MD_alias_scope = 7,
+ MD_noalias = 8,
+ MD_nontemporal = 9,
+ MD_mem_parallel_loop_access = 10,
+ MD_nonnull = 11,
+}
+
+/// LLVMRustAsmDialect
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub enum AsmDialect {
+ Other,
+ Att,
+ Intel,
+}
+
+/// LLVMRustCodeGenOptLevel
+#[derive(Copy, Clone, PartialEq)]
+#[repr(C)]
+pub enum CodeGenOptLevel {
+ Other,
+ None,
+ Less,
+ Default,
+ Aggressive,
+}
+
+/// LLVMRelocMode
+#[derive(Copy, Clone, PartialEq)]
+#[repr(C)]
+pub enum RelocMode {
+ Default = 0,
+ Static = 1,
+ PIC = 2,
+ DynamicNoPic = 3,
+}
+
+/// LLVMRustCodeModel
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub enum CodeModel {
+ Other,
+ Default,
+ JITDefault,
+ Small,
+ Kernel,
+ Medium,
+ Large,
+}
+
+/// LLVMRustDiagnosticKind
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub enum DiagnosticKind {
+ Other,
+ InlineAsm,
+ StackSize,
+ DebugMetadataVersion,
+ SampleProfile,
+ OptimizationRemark,
+ OptimizationRemarkMissed,
+ OptimizationRemarkAnalysis,
+ OptimizationRemarkAnalysisFPCommute,
+ OptimizationRemarkAnalysisAliasing,
+ OptimizationRemarkOther,
+ OptimizationFailure,
+}
+
+/// LLVMRustArchiveKind
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub enum ArchiveKind {
+ Other,
+ K_GNU,
+ K_MIPS64,
+ K_BSD,
+ K_COFF,
+}
+
+/// LLVMRustPassKind
+#[derive(Copy, Clone, PartialEq, Debug)]
+#[repr(C)]
+pub enum PassKind {
+ Other,
+ Function,
+ Module,
+}
+
+// Opaque pointer types
+#[allow(missing_copy_implementations)]
+pub enum Module_opaque {}
+pub type ModuleRef = *mut Module_opaque;
+#[allow(missing_copy_implementations)]
+pub enum Context_opaque {}
+pub type ContextRef = *mut Context_opaque;
+#[allow(missing_copy_implementations)]
+pub enum Type_opaque {}
+pub type TypeRef = *mut Type_opaque;
+#[allow(missing_copy_implementations)]
+pub enum Value_opaque {}
+pub type ValueRef = *mut Value_opaque;
+#[allow(missing_copy_implementations)]
+pub enum Metadata_opaque {}
+pub type MetadataRef = *mut Metadata_opaque;
+#[allow(missing_copy_implementations)]
+pub enum BasicBlock_opaque {}
+pub type BasicBlockRef = *mut BasicBlock_opaque;
+#[allow(missing_copy_implementations)]
+pub enum Builder_opaque {}
+pub type BuilderRef = *mut Builder_opaque;
+#[allow(missing_copy_implementations)]
+pub enum ExecutionEngine_opaque {}
+pub type ExecutionEngineRef = *mut ExecutionEngine_opaque;
+#[allow(missing_copy_implementations)]
+pub enum MemoryBuffer_opaque {}
+pub type MemoryBufferRef = *mut MemoryBuffer_opaque;
+#[allow(missing_copy_implementations)]
+pub enum PassManager_opaque {}
+pub type PassManagerRef = *mut PassManager_opaque;
+#[allow(missing_copy_implementations)]
+pub enum PassManagerBuilder_opaque {}
+pub type PassManagerBuilderRef = *mut PassManagerBuilder_opaque;
+#[allow(missing_copy_implementations)]
+pub enum Use_opaque {}
+pub type UseRef = *mut Use_opaque;
+#[allow(missing_copy_implementations)]
+pub enum TargetData_opaque {}
+pub type TargetDataRef = *mut TargetData_opaque;
+#[allow(missing_copy_implementations)]
+pub enum ObjectFile_opaque {}
+pub type ObjectFileRef = *mut ObjectFile_opaque;
+#[allow(missing_copy_implementations)]
+pub enum SectionIterator_opaque {}
+pub type SectionIteratorRef = *mut SectionIterator_opaque;
+#[allow(missing_copy_implementations)]
+pub enum Pass_opaque {}
+pub type PassRef = *mut Pass_opaque;
+#[allow(missing_copy_implementations)]
+pub enum TargetMachine_opaque {}
+pub type TargetMachineRef = *mut TargetMachine_opaque;
+pub enum Archive_opaque {}
+pub type ArchiveRef = *mut Archive_opaque;
+pub enum ArchiveIterator_opaque {}
+pub type ArchiveIteratorRef = *mut ArchiveIterator_opaque;
+pub enum ArchiveChild_opaque {}
+pub type ArchiveChildRef = *mut ArchiveChild_opaque;
+#[allow(missing_copy_implementations)]
+pub enum Twine_opaque {}
+pub type TwineRef = *mut Twine_opaque;
+#[allow(missing_copy_implementations)]
+pub enum DiagnosticInfo_opaque {}
+pub type DiagnosticInfoRef = *mut DiagnosticInfo_opaque;
+#[allow(missing_copy_implementations)]
+pub enum DebugLoc_opaque {}
+pub type DebugLocRef = *mut DebugLoc_opaque;
+#[allow(missing_copy_implementations)]
+pub enum SMDiagnostic_opaque {}
+pub type SMDiagnosticRef = *mut SMDiagnostic_opaque;
+#[allow(missing_copy_implementations)]
+pub enum RustArchiveMember_opaque {}
+pub type RustArchiveMemberRef = *mut RustArchiveMember_opaque;
+#[allow(missing_copy_implementations)]
+pub enum OperandBundleDef_opaque {}
+pub type OperandBundleDefRef = *mut OperandBundleDef_opaque;
+
+pub type DiagnosticHandler = unsafe extern "C" fn(DiagnosticInfoRef, *mut c_void);
+pub type InlineAsmDiagHandler = unsafe extern "C" fn(SMDiagnosticRef, *const c_void, c_uint);
+
+pub mod debuginfo {
+ pub use self::DIDescriptorFlags::*;
+ use super::{MetadataRef};
+
+ #[allow(missing_copy_implementations)]
+ pub enum DIBuilder_opaque {}
+ pub type DIBuilderRef = *mut DIBuilder_opaque;
+
+ pub type DIDescriptor = MetadataRef;
+ pub type DIScope = DIDescriptor;
+ pub type DILocation = DIDescriptor;
+ pub type DIFile = DIScope;
+ pub type DILexicalBlock = DIScope;
+ pub type DISubprogram = DIScope;
+ pub type DINameSpace = DIScope;
+ pub type DIType = DIDescriptor;
+ pub type DIBasicType = DIType;
+ pub type DIDerivedType = DIType;
+ pub type DICompositeType = DIDerivedType;
+ pub type DIVariable = DIDescriptor;
+ pub type DIGlobalVariable = DIDescriptor;
+ pub type DIArray = DIDescriptor;
+ pub type DISubrange = DIDescriptor;
+ pub type DIEnumerator = DIDescriptor;
+ pub type DITemplateTypeParameter = DIDescriptor;
+
+ #[derive(Copy, Clone)]
+ pub enum DIDescriptorFlags {
+ FlagPrivate = 1 << 0,
+ FlagProtected = 1 << 1,
+ FlagFwdDecl = 1 << 2,
+ FlagAppleBlock = 1 << 3,
+ FlagBlockByrefStruct = 1 << 4,
+ FlagVirtual = 1 << 5,
+ FlagArtificial = 1 << 6,
+ FlagExplicit = 1 << 7,
+ FlagPrototyped = 1 << 8,
+ FlagObjcClassComplete = 1 << 9,
+ FlagObjectPointer = 1 << 10,
+ FlagVector = 1 << 11,
+ FlagStaticMember = 1 << 12,
+ FlagIndirectVariable = 1 << 13,
+ FlagLValueReference = 1 << 14,
+ FlagRValueReference = 1 << 15
+ }
+}
+
+
+// Link to our native llvm bindings (things that we need to use the C++ api
+// for) and because llvm is written in C++ we need to link against libstdc++
+//
+// You'll probably notice that there is an omission of all LLVM libraries
+// from this location. This is because the set of LLVM libraries that we
+// link to is mostly defined by LLVM, and the `llvm-config` tool is used to
+// figure out the exact set of libraries. To do this, the build system
+// generates an llvmdeps.rs file next to this one which will be
+// automatically updated whenever LLVM is updated to include an up-to-date
+// set of the libraries we need to link to LLVM for.
+#[link(name = "rustllvm", kind = "static")]
+#[cfg(not(cargobuild))]
+extern {}
+
+#[linked_from = "rustllvm"] // not quite true but good enough
+extern {
+ /* Create and destroy contexts. */
+ pub fn LLVMContextCreate() -> ContextRef;
+ pub fn LLVMContextDispose(C: ContextRef);
+ pub fn LLVMGetMDKindIDInContext(C: ContextRef,
+ Name: *const c_char,
+ SLen: c_uint)
+ -> c_uint;
+
+ /* Create and destroy modules. */
+ pub fn LLVMModuleCreateWithNameInContext(ModuleID: *const c_char,
+ C: ContextRef)
+ -> ModuleRef;
+ pub fn LLVMGetModuleContext(M: ModuleRef) -> ContextRef;
+ pub fn LLVMCloneModule(M: ModuleRef) -> ModuleRef;
+ pub fn LLVMDisposeModule(M: ModuleRef);
+
+ /// Data layout. See Module::getDataLayout.
+ pub fn LLVMGetDataLayout(M: ModuleRef) -> *const c_char;
+ pub fn LLVMSetDataLayout(M: ModuleRef, Triple: *const c_char);
+
+ /// Target triple. See Module::getTargetTriple.
+ pub fn LLVMGetTarget(M: ModuleRef) -> *const c_char;
+ pub fn LLVMSetTarget(M: ModuleRef, Triple: *const c_char);
+
+ /// See Module::dump.
+ pub fn LLVMDumpModule(M: ModuleRef);
+
+ /// See Module::setModuleInlineAsm.
+ pub fn LLVMSetModuleInlineAsm(M: ModuleRef, Asm: *const c_char);
+
+ /// See llvm::LLVMTypeKind::getTypeID.
+ pub fn LLVMRustGetTypeKind(Ty: TypeRef) -> TypeKind;
+
+ /// See llvm::LLVMType::getContext.
+ pub fn LLVMGetTypeContext(Ty: TypeRef) -> ContextRef;
+
+ /* Operations on integer types */
+ pub fn LLVMInt1TypeInContext(C: ContextRef) -> TypeRef;
+ pub fn LLVMInt8TypeInContext(C: ContextRef) -> TypeRef;
+ pub fn LLVMInt16TypeInContext(C: ContextRef) -> TypeRef;
+ pub fn LLVMInt32TypeInContext(C: ContextRef) -> TypeRef;
+ pub fn LLVMInt64TypeInContext(C: ContextRef) -> TypeRef;
+ pub fn LLVMIntTypeInContext(C: ContextRef, NumBits: c_uint)
+ -> TypeRef;
+
+ pub fn LLVMGetIntTypeWidth(IntegerTy: TypeRef) -> c_uint;
+
+ /* Operations on real types */
+ pub fn LLVMFloatTypeInContext(C: ContextRef) -> TypeRef;
+ pub fn LLVMDoubleTypeInContext(C: ContextRef) -> TypeRef;
+ pub fn LLVMX86FP80TypeInContext(C: ContextRef) -> TypeRef;
+ pub fn LLVMFP128TypeInContext(C: ContextRef) -> TypeRef;
+ pub fn LLVMPPCFP128TypeInContext(C: ContextRef) -> TypeRef;
+
+ /* Operations on function types */
+ pub fn LLVMFunctionType(ReturnType: TypeRef,
+ ParamTypes: *const TypeRef,
+ ParamCount: c_uint,
+ IsVarArg: Bool)
+ -> TypeRef;
+ pub fn LLVMIsFunctionVarArg(FunctionTy: TypeRef) -> Bool;
+ pub fn LLVMGetReturnType(FunctionTy: TypeRef) -> TypeRef;
+ pub fn LLVMCountParamTypes(FunctionTy: TypeRef) -> c_uint;
+ pub fn LLVMGetParamTypes(FunctionTy: TypeRef, Dest: *mut TypeRef);
+
+ /* Operations on struct types */
+ pub fn LLVMStructTypeInContext(C: ContextRef,
+ ElementTypes: *const TypeRef,
+ ElementCount: c_uint,
+ Packed: Bool)
+ -> TypeRef;
+ pub fn LLVMCountStructElementTypes(StructTy: TypeRef) -> c_uint;
+ pub fn LLVMGetStructElementTypes(StructTy: TypeRef,
+ Dest: *mut TypeRef);
+ pub fn LLVMIsPackedStruct(StructTy: TypeRef) -> Bool;
+
+ /* Operations on array, pointer, and vector types (sequence types) */
+ pub fn LLVMRustArrayType(ElementType: TypeRef, ElementCount: u64) -> TypeRef;
+ pub fn LLVMPointerType(ElementType: TypeRef, AddressSpace: c_uint)
+ -> TypeRef;
+ pub fn LLVMVectorType(ElementType: TypeRef, ElementCount: c_uint)
+ -> TypeRef;
+
+ pub fn LLVMGetElementType(Ty: TypeRef) -> TypeRef;
+ pub fn LLVMGetArrayLength(ArrayTy: TypeRef) -> c_uint;
+ pub fn LLVMGetPointerAddressSpace(PointerTy: TypeRef) -> c_uint;
+ pub fn LLVMGetPointerToGlobal(EE: ExecutionEngineRef, V: ValueRef)
+ -> *const c_void;
+ pub fn LLVMGetVectorSize(VectorTy: TypeRef) -> c_uint;
+
+ /* Operations on other types */
+ pub fn LLVMVoidTypeInContext(C: ContextRef) -> TypeRef;
+ pub fn LLVMLabelTypeInContext(C: ContextRef) -> TypeRef;
+ pub fn LLVMRustMetadataTypeInContext(C: ContextRef) -> TypeRef;
+
+ /* Operations on all values */
+ pub fn LLVMTypeOf(Val: ValueRef) -> TypeRef;
+ pub fn LLVMGetValueName(Val: ValueRef) -> *const c_char;
+ pub fn LLVMSetValueName(Val: ValueRef, Name: *const c_char);
+ pub fn LLVMDumpValue(Val: ValueRef);
+ pub fn LLVMReplaceAllUsesWith(OldVal: ValueRef, NewVal: ValueRef);
+ pub fn LLVMSetMetadata(Val: ValueRef, KindID: c_uint, Node: ValueRef);
+
+ /* Operations on Uses */
+ pub fn LLVMGetFirstUse(Val: ValueRef) -> UseRef;
+ pub fn LLVMGetNextUse(U: UseRef) -> UseRef;
+ pub fn LLVMGetUser(U: UseRef) -> ValueRef;
+ pub fn LLVMGetUsedValue(U: UseRef) -> ValueRef;
+
+ /* Operations on Users */
+ pub fn LLVMGetNumOperands(Val: ValueRef) -> c_int;
+ pub fn LLVMGetOperand(Val: ValueRef, Index: c_uint) -> ValueRef;
+ pub fn LLVMSetOperand(Val: ValueRef, Index: c_uint, Op: ValueRef);
+
+ /* Operations on constants of any type */
+ pub fn LLVMConstNull(Ty: TypeRef) -> ValueRef;
+ /* all zeroes */
+ pub fn LLVMConstAllOnes(Ty: TypeRef) -> ValueRef;
+ pub fn LLVMConstICmp(Pred: IntPredicate, V1: ValueRef, V2: ValueRef)
+ -> ValueRef;
+ pub fn LLVMConstFCmp(Pred: RealPredicate, V1: ValueRef, V2: ValueRef)
+ -> ValueRef;
+ /* only for isize/vector */
+ pub fn LLVMGetUndef(Ty: TypeRef) -> ValueRef;
+ pub fn LLVMIsConstant(Val: ValueRef) -> Bool;
+ pub fn LLVMIsNull(Val: ValueRef) -> Bool;
+ pub fn LLVMIsUndef(Val: ValueRef) -> Bool;
+ pub fn LLVMConstPointerNull(Ty: TypeRef) -> ValueRef;
+
+ /* Operations on metadata */
+ pub fn LLVMMDStringInContext(C: ContextRef,
+ Str: *const c_char,
+ SLen: c_uint)
+ -> ValueRef;
+ pub fn LLVMMDNodeInContext(C: ContextRef,
+ Vals: *const ValueRef,
+ Count: c_uint)
+ -> ValueRef;
+ pub fn LLVMAddNamedMetadataOperand(M: ModuleRef,
+ Str: *const c_char,
+ Val: ValueRef);
+
+ /* Operations on scalar constants */
+ pub fn LLVMConstInt(IntTy: TypeRef, N: c_ulonglong, SignExtend: Bool)
+ -> ValueRef;
+ pub fn LLVMConstIntOfString(IntTy: TypeRef, Text: *const c_char, Radix: u8)
+ -> ValueRef;
+ pub fn LLVMConstIntOfStringAndSize(IntTy: TypeRef,
+ Text: *const c_char,
+ SLen: c_uint,
+ Radix: u8)
+ -> ValueRef;
+ pub fn LLVMConstReal(RealTy: TypeRef, N: f64) -> ValueRef;
+ pub fn LLVMConstRealOfString(RealTy: TypeRef, Text: *const c_char)
+ -> ValueRef;
+ pub fn LLVMConstRealOfStringAndSize(RealTy: TypeRef,
+ Text: *const c_char,
+ SLen: c_uint)
+ -> ValueRef;
+ pub fn LLVMConstIntGetZExtValue(ConstantVal: ValueRef) -> c_ulonglong;
+ pub fn LLVMConstIntGetSExtValue(ConstantVal: ValueRef) -> c_longlong;
+
+
+ /* Operations on composite constants */
+ pub fn LLVMConstStringInContext(C: ContextRef,
+ Str: *const c_char,
+ Length: c_uint,
+ DontNullTerminate: Bool)
+ -> ValueRef;
+ pub fn LLVMConstStructInContext(C: ContextRef,
+ ConstantVals: *const ValueRef,
+ Count: c_uint,
+ Packed: Bool)
+ -> ValueRef;
+
+ pub fn LLVMConstArray(ElementTy: TypeRef,
+ ConstantVals: *const ValueRef,
+ Length: c_uint)
+ -> ValueRef;
+ pub fn LLVMConstVector(ScalarConstantVals: *const ValueRef, Size: c_uint)
+ -> ValueRef;
+
+ /* Constant expressions */
+ pub fn LLVMAlignOf(Ty: TypeRef) -> ValueRef;
+ pub fn LLVMSizeOf(Ty: TypeRef) -> ValueRef;
+ pub fn LLVMConstNeg(ConstantVal: ValueRef) -> ValueRef;
+ pub fn LLVMConstNSWNeg(ConstantVal: ValueRef) -> ValueRef;
+ pub fn LLVMConstNUWNeg(ConstantVal: ValueRef) -> ValueRef;
+ pub fn LLVMConstFNeg(ConstantVal: ValueRef) -> ValueRef;
+ pub fn LLVMConstNot(ConstantVal: ValueRef) -> ValueRef;
+ pub fn LLVMConstAdd(LHSConstant: ValueRef, RHSConstant: ValueRef)
+ -> ValueRef;
+ pub fn LLVMConstNSWAdd(LHSConstant: ValueRef, RHSConstant: ValueRef)
+ -> ValueRef;
+ pub fn LLVMConstNUWAdd(LHSConstant: ValueRef, RHSConstant: ValueRef)
+ -> ValueRef;
+ pub fn LLVMConstFAdd(LHSConstant: ValueRef, RHSConstant: ValueRef)
+ -> ValueRef;
+ pub fn LLVMConstSub(LHSConstant: ValueRef, RHSConstant: ValueRef)
+ -> ValueRef;
+ pub fn LLVMConstNSWSub(LHSConstant: ValueRef, RHSConstant: ValueRef)
+ -> ValueRef;
+ pub fn LLVMConstNUWSub(LHSConstant: ValueRef, RHSConstant: ValueRef)
+ -> ValueRef;
+ pub fn LLVMConstFSub(LHSConstant: ValueRef, RHSConstant: ValueRef)
+ -> ValueRef;
+ pub fn LLVMConstMul(LHSConstant: ValueRef, RHSConstant: ValueRef)
+ -> ValueRef;
+ pub fn LLVMConstNSWMul(LHSConstant: ValueRef, RHSConstant: ValueRef)
+ -> ValueRef;
+ pub fn LLVMConstNUWMul(LHSConstant: ValueRef, RHSConstant: ValueRef)
+ -> ValueRef;
+ pub fn LLVMConstFMul(LHSConstant: ValueRef, RHSConstant: ValueRef)
+ -> ValueRef;
+ pub fn LLVMConstUDiv(LHSConstant: ValueRef, RHSConstant: ValueRef)
+ -> ValueRef;
+ pub fn LLVMConstSDiv(LHSConstant: ValueRef, RHSConstant: ValueRef)
+ -> ValueRef;
+ pub fn LLVMConstExactSDiv(LHSConstant: ValueRef,
+ RHSConstant: ValueRef)
+ -> ValueRef;
+ pub fn LLVMConstFDiv(LHSConstant: ValueRef, RHSConstant: ValueRef)
+ -> ValueRef;
+ pub fn LLVMConstURem(LHSConstant: ValueRef, RHSConstant: ValueRef)
+ -> ValueRef;
+ pub fn LLVMConstSRem(LHSConstant: ValueRef, RHSConstant: ValueRef)
+ -> ValueRef;
+ pub fn LLVMConstFRem(LHSConstant: ValueRef, RHSConstant: ValueRef)
+ -> ValueRef;
+ pub fn LLVMConstAnd(LHSConstant: ValueRef, RHSConstant: ValueRef)
+ -> ValueRef;
+ pub fn LLVMConstOr(LHSConstant: ValueRef, RHSConstant: ValueRef)
+ -> ValueRef;
+ pub fn LLVMConstXor(LHSConstant: ValueRef, RHSConstant: ValueRef)
+ -> ValueRef;
+ pub fn LLVMConstShl(LHSConstant: ValueRef, RHSConstant: ValueRef)
+ -> ValueRef;
+ pub fn LLVMConstLShr(LHSConstant: ValueRef, RHSConstant: ValueRef)
+ -> ValueRef;
+ pub fn LLVMConstAShr(LHSConstant: ValueRef, RHSConstant: ValueRef)
+ -> ValueRef;
+ pub fn LLVMConstGEP(ConstantVal: ValueRef,
+ ConstantIndices: *const ValueRef,
+ NumIndices: c_uint)
+ -> ValueRef;
+ pub fn LLVMConstInBoundsGEP(ConstantVal: ValueRef,
+ ConstantIndices: *const ValueRef,
+ NumIndices: c_uint)
+ -> ValueRef;
+ pub fn LLVMConstTrunc(ConstantVal: ValueRef, ToType: TypeRef)
+ -> ValueRef;
+ pub fn LLVMConstSExt(ConstantVal: ValueRef, ToType: TypeRef)
+ -> ValueRef;
+ pub fn LLVMConstZExt(ConstantVal: ValueRef, ToType: TypeRef)
+ -> ValueRef;
+ pub fn LLVMConstFPTrunc(ConstantVal: ValueRef, ToType: TypeRef)
+ -> ValueRef;
+ pub fn LLVMConstFPExt(ConstantVal: ValueRef, ToType: TypeRef)
+ -> ValueRef;
+ pub fn LLVMConstUIToFP(ConstantVal: ValueRef, ToType: TypeRef)
+ -> ValueRef;
+ pub fn LLVMConstSIToFP(ConstantVal: ValueRef, ToType: TypeRef)
+ -> ValueRef;
+ pub fn LLVMConstFPToUI(ConstantVal: ValueRef, ToType: TypeRef)
+ -> ValueRef;
+ pub fn LLVMConstFPToSI(ConstantVal: ValueRef, ToType: TypeRef)
+ -> ValueRef;
+ pub fn LLVMConstPtrToInt(ConstantVal: ValueRef, ToType: TypeRef)
+ -> ValueRef;
+ pub fn LLVMConstIntToPtr(ConstantVal: ValueRef, ToType: TypeRef)
+ -> ValueRef;
+ pub fn LLVMConstBitCast(ConstantVal: ValueRef, ToType: TypeRef)
+ -> ValueRef;
+ pub fn LLVMConstZExtOrBitCast(ConstantVal: ValueRef, ToType: TypeRef)
+ -> ValueRef;
+ pub fn LLVMConstSExtOrBitCast(ConstantVal: ValueRef, ToType: TypeRef)
+ -> ValueRef;
+ pub fn LLVMConstTruncOrBitCast(ConstantVal: ValueRef, ToType: TypeRef)
+ -> ValueRef;
+ pub fn LLVMConstPointerCast(ConstantVal: ValueRef, ToType: TypeRef)
+ -> ValueRef;
+ pub fn LLVMConstIntCast(ConstantVal: ValueRef,
+ ToType: TypeRef,
+ isSigned: Bool)
+ -> ValueRef;
+ pub fn LLVMConstFPCast(ConstantVal: ValueRef, ToType: TypeRef)
+ -> ValueRef;
+ pub fn LLVMConstSelect(ConstantCondition: ValueRef,
+ ConstantIfTrue: ValueRef,
+ ConstantIfFalse: ValueRef)
+ -> ValueRef;
+ pub fn LLVMConstExtractElement(VectorConstant: ValueRef,
+ IndexConstant: ValueRef)
+ -> ValueRef;
+ pub fn LLVMConstInsertElement(VectorConstant: ValueRef,
+ ElementValueConstant: ValueRef,
+ IndexConstant: ValueRef)
+ -> ValueRef;
+ pub fn LLVMConstShuffleVector(VectorAConstant: ValueRef,
+ VectorBConstant: ValueRef,
+ MaskConstant: ValueRef)
+ -> ValueRef;
+ pub fn LLVMConstExtractValue(AggConstant: ValueRef,
+ IdxList: *const c_uint,
+ NumIdx: c_uint)
+ -> ValueRef;
+ pub fn LLVMConstInsertValue(AggConstant: ValueRef,
+ ElementValueConstant: ValueRef,
+ IdxList: *const c_uint,
+ NumIdx: c_uint)
+ -> ValueRef;
+ pub fn LLVMConstInlineAsm(Ty: TypeRef,
+ AsmString: *const c_char,
+ Constraints: *const c_char,
+ HasSideEffects: Bool,
+ IsAlignStack: Bool)
+ -> ValueRef;
+ pub fn LLVMBlockAddress(F: ValueRef, BB: BasicBlockRef) -> ValueRef;
+
+
+
+ /* Operations on global variables, functions, and aliases (globals) */
+ pub fn LLVMGetGlobalParent(Global: ValueRef) -> ModuleRef;
+ pub fn LLVMIsDeclaration(Global: ValueRef) -> Bool;
+ pub fn LLVMGetLinkage(Global: ValueRef) -> c_uint;
+ pub fn LLVMSetLinkage(Global: ValueRef, Link: Linkage);
+ pub fn LLVMGetSection(Global: ValueRef) -> *const c_char;
+ pub fn LLVMSetSection(Global: ValueRef, Section: *const c_char);
+ pub fn LLVMGetVisibility(Global: ValueRef) -> c_uint;
+ pub fn LLVMSetVisibility(Global: ValueRef, Viz: c_uint);
+ pub fn LLVMGetAlignment(Global: ValueRef) -> c_uint;
+ pub fn LLVMSetAlignment(Global: ValueRef, Bytes: c_uint);
+ pub fn LLVMSetDLLStorageClass(V: ValueRef,
+ C: DLLStorageClass);
+
+
+ /* Operations on global variables */
+ pub fn LLVMIsAGlobalVariable(GlobalVar: ValueRef) -> ValueRef;
+ pub fn LLVMAddGlobal(M: ModuleRef, Ty: TypeRef, Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMAddGlobalInAddressSpace(M: ModuleRef,
+ Ty: TypeRef,
+ Name: *const c_char,
+ AddressSpace: c_uint)
+ -> ValueRef;
+ pub fn LLVMGetNamedGlobal(M: ModuleRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMRustGetOrInsertGlobal(M: ModuleRef,
+ Name: *const c_char,
+ T: TypeRef)
+ -> ValueRef;
+ pub fn LLVMGetFirstGlobal(M: ModuleRef) -> ValueRef;
+ pub fn LLVMGetLastGlobal(M: ModuleRef) -> ValueRef;
+ pub fn LLVMGetNextGlobal(GlobalVar: ValueRef) -> ValueRef;
+ pub fn LLVMGetPreviousGlobal(GlobalVar: ValueRef) -> ValueRef;
+ pub fn LLVMDeleteGlobal(GlobalVar: ValueRef);
+ pub fn LLVMGetInitializer(GlobalVar: ValueRef) -> ValueRef;
+ pub fn LLVMSetInitializer(GlobalVar: ValueRef,
+ ConstantVal: ValueRef);
+ pub fn LLVMIsThreadLocal(GlobalVar: ValueRef) -> Bool;
+ pub fn LLVMSetThreadLocal(GlobalVar: ValueRef, IsThreadLocal: Bool);
+ pub fn LLVMIsGlobalConstant(GlobalVar: ValueRef) -> Bool;
+ pub fn LLVMSetGlobalConstant(GlobalVar: ValueRef, IsConstant: Bool);
+ pub fn LLVMRustGetNamedValue(M: ModuleRef, Name: *const c_char) -> ValueRef;
+
+ /* Operations on aliases */
+ pub fn LLVMAddAlias(M: ModuleRef,
+ Ty: TypeRef,
+ Aliasee: ValueRef,
+ Name: *const c_char)
+ -> ValueRef;
+
+ /* Operations on functions */
+ pub fn LLVMAddFunction(M: ModuleRef,
+ Name: *const c_char,
+ FunctionTy: TypeRef)
+ -> ValueRef;
+ pub fn LLVMGetNamedFunction(M: ModuleRef, Name: *const c_char) -> ValueRef;
+ pub fn LLVMGetFirstFunction(M: ModuleRef) -> ValueRef;
+ pub fn LLVMGetLastFunction(M: ModuleRef) -> ValueRef;
+ pub fn LLVMGetNextFunction(Fn: ValueRef) -> ValueRef;
+ pub fn LLVMGetPreviousFunction(Fn: ValueRef) -> ValueRef;
+ pub fn LLVMDeleteFunction(Fn: ValueRef);
+ pub fn LLVMRustGetOrInsertFunction(M: ModuleRef,
+ Name: *const c_char,
+ FunctionTy: TypeRef)
+ -> ValueRef;
+ pub fn LLVMGetIntrinsicID(Fn: ValueRef) -> c_uint;
+ pub fn LLVMGetFunctionCallConv(Fn: ValueRef) -> c_uint;
+ pub fn LLVMSetFunctionCallConv(Fn: ValueRef, CC: c_uint);
+ pub fn LLVMGetGC(Fn: ValueRef) -> *const c_char;
+ pub fn LLVMSetGC(Fn: ValueRef, Name: *const c_char);
+ pub fn LLVMRustAddDereferenceableAttr(Fn: ValueRef, index: c_uint, bytes: u64);
+ pub fn LLVMRustAddFunctionAttribute(Fn: ValueRef, index: c_uint, PA: u64);
+ pub fn LLVMRustAddFunctionAttrString(Fn: ValueRef, index: c_uint, Name: *const c_char);
+ pub fn LLVMRustAddFunctionAttrStringValue(Fn: ValueRef, index: c_uint,
+ Name: *const c_char,
+ Value: *const c_char);
+ pub fn LLVMRustRemoveFunctionAttributes(Fn: ValueRef,
+ index: c_uint,
+ attr: u64);
+ pub fn LLVMRustRemoveFunctionAttrString(Fn: ValueRef,
+ index: c_uint,
+ Name: *const c_char);
+ pub fn LLVMGetFunctionAttr(Fn: ValueRef) -> c_uint;
+ pub fn LLVMRemoveFunctionAttr(Fn: ValueRef, val: c_uint);
+
+ /* Operations on parameters */
+ pub fn LLVMCountParams(Fn: ValueRef) -> c_uint;
+ pub fn LLVMGetParams(Fn: ValueRef, Params: *const ValueRef);
+ pub fn LLVMGetParam(Fn: ValueRef, Index: c_uint) -> ValueRef;
+ pub fn LLVMGetParamParent(Inst: ValueRef) -> ValueRef;
+ pub fn LLVMGetFirstParam(Fn: ValueRef) -> ValueRef;
+ pub fn LLVMGetLastParam(Fn: ValueRef) -> ValueRef;
+ pub fn LLVMGetNextParam(Arg: ValueRef) -> ValueRef;
+ pub fn LLVMGetPreviousParam(Arg: ValueRef) -> ValueRef;
+ pub fn LLVMAddAttribute(Arg: ValueRef, PA: c_uint);
+ pub fn LLVMRemoveAttribute(Arg: ValueRef, PA: c_uint);
+ pub fn LLVMGetAttribute(Arg: ValueRef) -> c_uint;
+ pub fn LLVMSetParamAlignment(Arg: ValueRef, align: c_uint);
+
+ /* Operations on basic blocks */
+ pub fn LLVMBasicBlockAsValue(BB: BasicBlockRef) -> ValueRef;
+ pub fn LLVMValueIsBasicBlock(Val: ValueRef) -> Bool;
+ pub fn LLVMValueAsBasicBlock(Val: ValueRef) -> BasicBlockRef;
+ pub fn LLVMGetBasicBlockParent(BB: BasicBlockRef) -> ValueRef;
+ pub fn LLVMCountBasicBlocks(Fn: ValueRef) -> c_uint;
+ pub fn LLVMGetBasicBlocks(Fn: ValueRef, BasicBlocks: *const ValueRef);
+ pub fn LLVMGetFirstBasicBlock(Fn: ValueRef) -> BasicBlockRef;
+ pub fn LLVMGetLastBasicBlock(Fn: ValueRef) -> BasicBlockRef;
+ pub fn LLVMGetNextBasicBlock(BB: BasicBlockRef) -> BasicBlockRef;
+ pub fn LLVMGetPreviousBasicBlock(BB: BasicBlockRef) -> BasicBlockRef;
+ pub fn LLVMGetEntryBasicBlock(Fn: ValueRef) -> BasicBlockRef;
+
+ pub fn LLVMAppendBasicBlockInContext(C: ContextRef,
+ Fn: ValueRef,
+ Name: *const c_char)
+ -> BasicBlockRef;
+ pub fn LLVMInsertBasicBlockInContext(C: ContextRef,
+ BB: BasicBlockRef,
+ Name: *const c_char)
+ -> BasicBlockRef;
+ pub fn LLVMDeleteBasicBlock(BB: BasicBlockRef);
+
+ pub fn LLVMMoveBasicBlockAfter(BB: BasicBlockRef,
+ MoveAfter: BasicBlockRef);
+
+ pub fn LLVMMoveBasicBlockBefore(BB: BasicBlockRef,
+ MoveBefore: BasicBlockRef);
+
+ /* Operations on instructions */
+ pub fn LLVMGetInstructionParent(Inst: ValueRef) -> BasicBlockRef;
+ pub fn LLVMGetFirstInstruction(BB: BasicBlockRef) -> ValueRef;
+ pub fn LLVMGetLastInstruction(BB: BasicBlockRef) -> ValueRef;
+ pub fn LLVMGetNextInstruction(Inst: ValueRef) -> ValueRef;
+ pub fn LLVMGetPreviousInstruction(Inst: ValueRef) -> ValueRef;
+ pub fn LLVMInstructionEraseFromParent(Inst: ValueRef);
+
+ /* Operations on call sites */
+ pub fn LLVMSetInstructionCallConv(Instr: ValueRef, CC: c_uint);
+ pub fn LLVMGetInstructionCallConv(Instr: ValueRef) -> c_uint;
+ pub fn LLVMAddInstrAttribute(Instr: ValueRef,
+ index: c_uint,
+ IA: c_uint);
+ pub fn LLVMRemoveInstrAttribute(Instr: ValueRef,
+ index: c_uint,
+ IA: c_uint);
+ pub fn LLVMSetInstrParamAlignment(Instr: ValueRef,
+ index: c_uint,
+ align: c_uint);
+ pub fn LLVMRustAddCallSiteAttribute(Instr: ValueRef,
+ index: c_uint,
+ Val: u64);
+ pub fn LLVMRustAddDereferenceableCallSiteAttr(Instr: ValueRef,
+ index: c_uint,
+ bytes: u64);
+
+ /* Operations on call instructions (only) */
+ pub fn LLVMIsTailCall(CallInst: ValueRef) -> Bool;
+ pub fn LLVMSetTailCall(CallInst: ValueRef, IsTailCall: Bool);
+
+ /* Operations on load/store instructions (only) */
+ pub fn LLVMGetVolatile(MemoryAccessInst: ValueRef) -> Bool;
+ pub fn LLVMSetVolatile(MemoryAccessInst: ValueRef, volatile: Bool);
+
+ /* Operations on phi nodes */
+ pub fn LLVMAddIncoming(PhiNode: ValueRef,
+ IncomingValues: *const ValueRef,
+ IncomingBlocks: *const BasicBlockRef,
+ Count: c_uint);
+ pub fn LLVMCountIncoming(PhiNode: ValueRef) -> c_uint;
+ pub fn LLVMGetIncomingValue(PhiNode: ValueRef, Index: c_uint)
+ -> ValueRef;
+ pub fn LLVMGetIncomingBlock(PhiNode: ValueRef, Index: c_uint)
+ -> BasicBlockRef;
+
+ /* Instruction builders */
+ pub fn LLVMCreateBuilderInContext(C: ContextRef) -> BuilderRef;
+ pub fn LLVMPositionBuilder(Builder: BuilderRef,
+ Block: BasicBlockRef,
+ Instr: ValueRef);
+ pub fn LLVMPositionBuilderBefore(Builder: BuilderRef,
+ Instr: ValueRef);
+ pub fn LLVMPositionBuilderAtEnd(Builder: BuilderRef,
+ Block: BasicBlockRef);
+ pub fn LLVMGetInsertBlock(Builder: BuilderRef) -> BasicBlockRef;
+ pub fn LLVMClearInsertionPosition(Builder: BuilderRef);
+ pub fn LLVMInsertIntoBuilder(Builder: BuilderRef, Instr: ValueRef);
+ pub fn LLVMInsertIntoBuilderWithName(Builder: BuilderRef,
+ Instr: ValueRef,
+ Name: *const c_char);
+ pub fn LLVMDisposeBuilder(Builder: BuilderRef);
+
+ /* Metadata */
+ pub fn LLVMSetCurrentDebugLocation(Builder: BuilderRef, L: ValueRef);
+ pub fn LLVMGetCurrentDebugLocation(Builder: BuilderRef) -> ValueRef;
+ pub fn LLVMSetInstDebugLocation(Builder: BuilderRef, Inst: ValueRef);
+
+ /* Terminators */
+ pub fn LLVMBuildRetVoid(B: BuilderRef) -> ValueRef;
+ pub fn LLVMBuildRet(B: BuilderRef, V: ValueRef) -> ValueRef;
+ pub fn LLVMBuildAggregateRet(B: BuilderRef,
+ RetVals: *const ValueRef,
+ N: c_uint)
+ -> ValueRef;
+ pub fn LLVMBuildBr(B: BuilderRef, Dest: BasicBlockRef) -> ValueRef;
+ pub fn LLVMBuildCondBr(B: BuilderRef,
+ If: ValueRef,
+ Then: BasicBlockRef,
+ Else: BasicBlockRef)
+ -> ValueRef;
+ pub fn LLVMBuildSwitch(B: BuilderRef,
+ V: ValueRef,
+ Else: BasicBlockRef,
+ NumCases: c_uint)
+ -> ValueRef;
+ pub fn LLVMBuildIndirectBr(B: BuilderRef,
+ Addr: ValueRef,
+ NumDests: c_uint)
+ -> ValueRef;
+ pub fn LLVMRustBuildInvoke(B: BuilderRef,
+ Fn: ValueRef,
+ Args: *const ValueRef,
+ NumArgs: c_uint,
+ Then: BasicBlockRef,
+ Catch: BasicBlockRef,
+ Bundle: OperandBundleDefRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMRustBuildLandingPad(B: BuilderRef,
+ Ty: TypeRef,
+ PersFn: ValueRef,
+ NumClauses: c_uint,
+ Name: *const c_char,
+ F: ValueRef)
+ -> ValueRef;
+ pub fn LLVMBuildResume(B: BuilderRef, Exn: ValueRef) -> ValueRef;
+ pub fn LLVMBuildUnreachable(B: BuilderRef) -> ValueRef;
+
+ pub fn LLVMRustBuildCleanupPad(B: BuilderRef,
+ ParentPad: ValueRef,
+ ArgCnt: c_uint,
+ Args: *const ValueRef,
+ Name: *const c_char) -> ValueRef;
+ pub fn LLVMRustBuildCleanupRet(B: BuilderRef,
+ CleanupPad: ValueRef,
+ UnwindBB: BasicBlockRef) -> ValueRef;
+ pub fn LLVMRustBuildCatchPad(B: BuilderRef,
+ ParentPad: ValueRef,
+ ArgCnt: c_uint,
+ Args: *const ValueRef,
+ Name: *const c_char) -> ValueRef;
+ pub fn LLVMRustBuildCatchRet(B: BuilderRef,
+ Pad: ValueRef,
+ BB: BasicBlockRef) -> ValueRef;
+ pub fn LLVMRustBuildCatchSwitch(Builder: BuilderRef,
+ ParentPad: ValueRef,
+ BB: BasicBlockRef,
+ NumHandlers: c_uint,
+ Name: *const c_char) -> ValueRef;
+ pub fn LLVMRustAddHandler(CatchSwitch: ValueRef,
+ Handler: BasicBlockRef);
+ pub fn LLVMRustSetPersonalityFn(B: BuilderRef, Pers: ValueRef);
+
+ /* Add a case to the switch instruction */
+ pub fn LLVMAddCase(Switch: ValueRef,
+ OnVal: ValueRef,
+ Dest: BasicBlockRef);
+
+ /* Add a destination to the indirectbr instruction */
+ pub fn LLVMAddDestination(IndirectBr: ValueRef, Dest: BasicBlockRef);
+
+ /* Add a clause to the landing pad instruction */
+ pub fn LLVMAddClause(LandingPad: ValueRef, ClauseVal: ValueRef);
+
+ /* Set the cleanup on a landing pad instruction */
+ pub fn LLVMSetCleanup(LandingPad: ValueRef, Val: Bool);
+
+ /* Arithmetic */
+ pub fn LLVMBuildAdd(B: BuilderRef,
+ LHS: ValueRef,
+ RHS: ValueRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildNSWAdd(B: BuilderRef,
+ LHS: ValueRef,
+ RHS: ValueRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildNUWAdd(B: BuilderRef,
+ LHS: ValueRef,
+ RHS: ValueRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildFAdd(B: BuilderRef,
+ LHS: ValueRef,
+ RHS: ValueRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildSub(B: BuilderRef,
+ LHS: ValueRef,
+ RHS: ValueRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildNSWSub(B: BuilderRef,
+ LHS: ValueRef,
+ RHS: ValueRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildNUWSub(B: BuilderRef,
+ LHS: ValueRef,
+ RHS: ValueRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildFSub(B: BuilderRef,
+ LHS: ValueRef,
+ RHS: ValueRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildMul(B: BuilderRef,
+ LHS: ValueRef,
+ RHS: ValueRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildNSWMul(B: BuilderRef,
+ LHS: ValueRef,
+ RHS: ValueRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildNUWMul(B: BuilderRef,
+ LHS: ValueRef,
+ RHS: ValueRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildFMul(B: BuilderRef,
+ LHS: ValueRef,
+ RHS: ValueRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildUDiv(B: BuilderRef,
+ LHS: ValueRef,
+ RHS: ValueRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildSDiv(B: BuilderRef,
+ LHS: ValueRef,
+ RHS: ValueRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildExactSDiv(B: BuilderRef,
+ LHS: ValueRef,
+ RHS: ValueRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildFDiv(B: BuilderRef,
+ LHS: ValueRef,
+ RHS: ValueRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildURem(B: BuilderRef,
+ LHS: ValueRef,
+ RHS: ValueRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildSRem(B: BuilderRef,
+ LHS: ValueRef,
+ RHS: ValueRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildFRem(B: BuilderRef,
+ LHS: ValueRef,
+ RHS: ValueRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildShl(B: BuilderRef,
+ LHS: ValueRef,
+ RHS: ValueRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildLShr(B: BuilderRef,
+ LHS: ValueRef,
+ RHS: ValueRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildAShr(B: BuilderRef,
+ LHS: ValueRef,
+ RHS: ValueRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildAnd(B: BuilderRef,
+ LHS: ValueRef,
+ RHS: ValueRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildOr(B: BuilderRef,
+ LHS: ValueRef,
+ RHS: ValueRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildXor(B: BuilderRef,
+ LHS: ValueRef,
+ RHS: ValueRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildBinOp(B: BuilderRef,
+ Op: Opcode,
+ LHS: ValueRef,
+ RHS: ValueRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildNeg(B: BuilderRef, V: ValueRef, Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildNSWNeg(B: BuilderRef, V: ValueRef, Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildNUWNeg(B: BuilderRef, V: ValueRef, Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildFNeg(B: BuilderRef, V: ValueRef, Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildNot(B: BuilderRef, V: ValueRef, Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMRustSetHasUnsafeAlgebra(Instr: ValueRef);
+
+ /* Memory */
+ pub fn LLVMBuildAlloca(B: BuilderRef, Ty: TypeRef, Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildFree(B: BuilderRef, PointerVal: ValueRef) -> ValueRef;
+ pub fn LLVMBuildLoad(B: BuilderRef,
+ PointerVal: ValueRef,
+ Name: *const c_char)
+ -> ValueRef;
+
+ pub fn LLVMBuildStore(B: BuilderRef, Val: ValueRef, Ptr: ValueRef)
+ -> ValueRef;
+
+ pub fn LLVMBuildGEP(B: BuilderRef,
+ Pointer: ValueRef,
+ Indices: *const ValueRef,
+ NumIndices: c_uint,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildInBoundsGEP(B: BuilderRef,
+ Pointer: ValueRef,
+ Indices: *const ValueRef,
+ NumIndices: c_uint,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildStructGEP(B: BuilderRef,
+ Pointer: ValueRef,
+ Idx: c_uint,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildGlobalString(B: BuilderRef,
+ Str: *const c_char,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildGlobalStringPtr(B: BuilderRef,
+ Str: *const c_char,
+ Name: *const c_char)
+ -> ValueRef;
+
+ /* Casts */
+ pub fn LLVMBuildTrunc(B: BuilderRef,
+ Val: ValueRef,
+ DestTy: TypeRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildZExt(B: BuilderRef,
+ Val: ValueRef,
+ DestTy: TypeRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildSExt(B: BuilderRef,
+ Val: ValueRef,
+ DestTy: TypeRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildFPToUI(B: BuilderRef,
+ Val: ValueRef,
+ DestTy: TypeRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildFPToSI(B: BuilderRef,
+ Val: ValueRef,
+ DestTy: TypeRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildUIToFP(B: BuilderRef,
+ Val: ValueRef,
+ DestTy: TypeRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildSIToFP(B: BuilderRef,
+ Val: ValueRef,
+ DestTy: TypeRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildFPTrunc(B: BuilderRef,
+ Val: ValueRef,
+ DestTy: TypeRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildFPExt(B: BuilderRef,
+ Val: ValueRef,
+ DestTy: TypeRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildPtrToInt(B: BuilderRef,
+ Val: ValueRef,
+ DestTy: TypeRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildIntToPtr(B: BuilderRef,
+ Val: ValueRef,
+ DestTy: TypeRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildBitCast(B: BuilderRef,
+ Val: ValueRef,
+ DestTy: TypeRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildZExtOrBitCast(B: BuilderRef,
+ Val: ValueRef,
+ DestTy: TypeRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildSExtOrBitCast(B: BuilderRef,
+ Val: ValueRef,
+ DestTy: TypeRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildTruncOrBitCast(B: BuilderRef,
+ Val: ValueRef,
+ DestTy: TypeRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildCast(B: BuilderRef,
+ Op: Opcode,
+ Val: ValueRef,
+ DestTy: TypeRef,
+ Name: *const c_char) -> ValueRef;
+ pub fn LLVMBuildPointerCast(B: BuilderRef,
+ Val: ValueRef,
+ DestTy: TypeRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildIntCast(B: BuilderRef,
+ Val: ValueRef,
+ DestTy: TypeRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildFPCast(B: BuilderRef,
+ Val: ValueRef,
+ DestTy: TypeRef,
+ Name: *const c_char)
+ -> ValueRef;
+
+ /* Comparisons */
+ pub fn LLVMBuildICmp(B: BuilderRef,
+ Op: c_uint,
+ LHS: ValueRef,
+ RHS: ValueRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildFCmp(B: BuilderRef,
+ Op: c_uint,
+ LHS: ValueRef,
+ RHS: ValueRef,
+ Name: *const c_char)
+ -> ValueRef;
+
+ /* Miscellaneous instructions */
+ pub fn LLVMBuildPhi(B: BuilderRef, Ty: TypeRef, Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMRustBuildCall(B: BuilderRef,
+ Fn: ValueRef,
+ Args: *const ValueRef,
+ NumArgs: c_uint,
+ Bundle: OperandBundleDefRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildSelect(B: BuilderRef,
+ If: ValueRef,
+ Then: ValueRef,
+ Else: ValueRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildVAArg(B: BuilderRef,
+ list: ValueRef,
+ Ty: TypeRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildExtractElement(B: BuilderRef,
+ VecVal: ValueRef,
+ Index: ValueRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildInsertElement(B: BuilderRef,
+ VecVal: ValueRef,
+ EltVal: ValueRef,
+ Index: ValueRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildShuffleVector(B: BuilderRef,
+ V1: ValueRef,
+ V2: ValueRef,
+ Mask: ValueRef,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildExtractValue(B: BuilderRef,
+ AggVal: ValueRef,
+ Index: c_uint,
+ Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildInsertValue(B: BuilderRef,
+ AggVal: ValueRef,
+ EltVal: ValueRef,
+ Index: c_uint,
+ Name: *const c_char)
+ -> ValueRef;
+
+ pub fn LLVMBuildIsNull(B: BuilderRef, Val: ValueRef, Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildIsNotNull(B: BuilderRef, Val: ValueRef, Name: *const c_char)
+ -> ValueRef;
+ pub fn LLVMBuildPtrDiff(B: BuilderRef,
+ LHS: ValueRef,
+ RHS: ValueRef,
+ Name: *const c_char)
+ -> ValueRef;
+
+ /* Atomic Operations */
+ pub fn LLVMRustBuildAtomicLoad(B: BuilderRef,
+ PointerVal: ValueRef,
+ Name: *const c_char,
+ Order: AtomicOrdering,
+ Alignment: c_uint)
+ -> ValueRef;
+
+ pub fn LLVMRustBuildAtomicStore(B: BuilderRef,
+ Val: ValueRef,
+ Ptr: ValueRef,
+ Order: AtomicOrdering,
+ Alignment: c_uint)
+ -> ValueRef;
+
+ pub fn LLVMRustBuildAtomicCmpXchg(B: BuilderRef,
+ LHS: ValueRef,
+ CMP: ValueRef,
+ RHS: ValueRef,
+ Order: AtomicOrdering,
+ FailureOrder: AtomicOrdering,
+ Weak: Bool)
+ -> ValueRef;
+
+ pub fn LLVMBuildAtomicRMW(B: BuilderRef,
+ Op: AtomicRmwBinOp,
+ LHS: ValueRef,
+ RHS: ValueRef,
+ Order: AtomicOrdering,
+ SingleThreaded: Bool)
+ -> ValueRef;
+
+ pub fn LLVMRustBuildAtomicFence(B: BuilderRef,
+ Order: AtomicOrdering,
+ Scope: SynchronizationScope);
+
+
+ /* Selected entries from the downcasts. */
+ pub fn LLVMIsATerminatorInst(Inst: ValueRef) -> ValueRef;
+ pub fn LLVMIsAStoreInst(Inst: ValueRef) -> ValueRef;
+
+ /// Writes a module to the specified path. Returns 0 on success.
+ pub fn LLVMWriteBitcodeToFile(M: ModuleRef, Path: *const c_char) -> c_int;
+
+ /// Creates target data from a target layout string.
+ pub fn LLVMCreateTargetData(StringRep: *const c_char) -> TargetDataRef;
+ /// Number of bytes clobbered when doing a Store to *T.
+ pub fn LLVMStoreSizeOfType(TD: TargetDataRef, Ty: TypeRef)
+ -> c_ulonglong;
+
+ /// Number of bytes clobbered when doing a Store to *T.
+ pub fn LLVMSizeOfTypeInBits(TD: TargetDataRef, Ty: TypeRef)
+ -> c_ulonglong;
+
+ /// Distance between successive elements in an array of T. Includes ABI padding.
+ pub fn LLVMABISizeOfType(TD: TargetDataRef, Ty: TypeRef) -> c_ulonglong;
+
+ /// Returns the preferred alignment of a type.
+ pub fn LLVMPreferredAlignmentOfType(TD: TargetDataRef, Ty: TypeRef)
+ -> c_uint;
+ /// Returns the minimum alignment of a type.
+ pub fn LLVMABIAlignmentOfType(TD: TargetDataRef, Ty: TypeRef)
+ -> c_uint;
+
+ /// Computes the byte offset of the indexed struct element for a
+ /// target.
+ pub fn LLVMOffsetOfElement(TD: TargetDataRef,
+ StructTy: TypeRef,
+ Element: c_uint)
+ -> c_ulonglong;
+
+ /// Returns the minimum alignment of a type when part of a call frame.
+ pub fn LLVMCallFrameAlignmentOfType(TD: TargetDataRef, Ty: TypeRef)
+ -> c_uint;
+
+ /// Disposes target data.
+ pub fn LLVMDisposeTargetData(TD: TargetDataRef);
+
+ /// Creates a pass manager.
+ pub fn LLVMCreatePassManager() -> PassManagerRef;
+
+ /// Creates a function-by-function pass manager
+ pub fn LLVMCreateFunctionPassManagerForModule(M: ModuleRef)
+ -> PassManagerRef;
+
+ /// Disposes a pass manager.
+ pub fn LLVMDisposePassManager(PM: PassManagerRef);
+
+ /// Runs a pass manager on a module.
+ pub fn LLVMRunPassManager(PM: PassManagerRef, M: ModuleRef) -> Bool;
+
+ /// Runs the function passes on the provided function.
+ pub fn LLVMRunFunctionPassManager(FPM: PassManagerRef, F: ValueRef)
+ -> Bool;
+
+ /// Initializes all the function passes scheduled in the manager
+ pub fn LLVMInitializeFunctionPassManager(FPM: PassManagerRef) -> Bool;
+
+ /// Finalizes all the function passes scheduled in the manager
+ pub fn LLVMFinalizeFunctionPassManager(FPM: PassManagerRef) -> Bool;
+
+ pub fn LLVMInitializePasses();
+
+ /// Adds a verification pass.
+ pub fn LLVMAddVerifierPass(PM: PassManagerRef);
+
+ pub fn LLVMAddGlobalOptimizerPass(PM: PassManagerRef);
+ pub fn LLVMAddIPSCCPPass(PM: PassManagerRef);
+ pub fn LLVMAddDeadArgEliminationPass(PM: PassManagerRef);
+ pub fn LLVMAddInstructionCombiningPass(PM: PassManagerRef);
+ pub fn LLVMAddCFGSimplificationPass(PM: PassManagerRef);
+ pub fn LLVMAddFunctionInliningPass(PM: PassManagerRef);
+ pub fn LLVMAddFunctionAttrsPass(PM: PassManagerRef);
+ pub fn LLVMAddScalarReplAggregatesPass(PM: PassManagerRef);
+ pub fn LLVMAddScalarReplAggregatesPassSSA(PM: PassManagerRef);
+ pub fn LLVMAddJumpThreadingPass(PM: PassManagerRef);
+ pub fn LLVMAddConstantPropagationPass(PM: PassManagerRef);
+ pub fn LLVMAddReassociatePass(PM: PassManagerRef);
+ pub fn LLVMAddLoopRotatePass(PM: PassManagerRef);
+ pub fn LLVMAddLICMPass(PM: PassManagerRef);
+ pub fn LLVMAddLoopUnswitchPass(PM: PassManagerRef);
+ pub fn LLVMAddLoopDeletionPass(PM: PassManagerRef);
+ pub fn LLVMAddLoopUnrollPass(PM: PassManagerRef);
+ pub fn LLVMAddGVNPass(PM: PassManagerRef);
+ pub fn LLVMAddMemCpyOptPass(PM: PassManagerRef);
+ pub fn LLVMAddSCCPPass(PM: PassManagerRef);
+ pub fn LLVMAddDeadStoreEliminationPass(PM: PassManagerRef);
+ pub fn LLVMAddStripDeadPrototypesPass(PM: PassManagerRef);
+ pub fn LLVMAddConstantMergePass(PM: PassManagerRef);
+ pub fn LLVMAddArgumentPromotionPass(PM: PassManagerRef);
+ pub fn LLVMAddTailCallEliminationPass(PM: PassManagerRef);
+ pub fn LLVMAddIndVarSimplifyPass(PM: PassManagerRef);
+ pub fn LLVMAddAggressiveDCEPass(PM: PassManagerRef);
+ pub fn LLVMAddGlobalDCEPass(PM: PassManagerRef);
+ pub fn LLVMAddCorrelatedValuePropagationPass(PM: PassManagerRef);
+ pub fn LLVMAddPruneEHPass(PM: PassManagerRef);
+ pub fn LLVMAddSimplifyLibCallsPass(PM: PassManagerRef);
+ pub fn LLVMAddLoopIdiomPass(PM: PassManagerRef);
+ pub fn LLVMAddEarlyCSEPass(PM: PassManagerRef);
+ pub fn LLVMAddTypeBasedAliasAnalysisPass(PM: PassManagerRef);
+ pub fn LLVMAddBasicAliasAnalysisPass(PM: PassManagerRef);
+
+ pub fn LLVMPassManagerBuilderCreate() -> PassManagerBuilderRef;
+ pub fn LLVMPassManagerBuilderDispose(PMB: PassManagerBuilderRef);
+ pub fn LLVMPassManagerBuilderSetOptLevel(PMB: PassManagerBuilderRef,
+ OptimizationLevel: c_uint);
+ pub fn LLVMPassManagerBuilderSetSizeLevel(PMB: PassManagerBuilderRef,
+ Value: Bool);
+ pub fn LLVMPassManagerBuilderSetDisableUnitAtATime(
+ PMB: PassManagerBuilderRef,
+ Value: Bool);
+ pub fn LLVMPassManagerBuilderSetDisableUnrollLoops(
+ PMB: PassManagerBuilderRef,
+ Value: Bool);
+ pub fn LLVMPassManagerBuilderSetDisableSimplifyLibCalls(
+ PMB: PassManagerBuilderRef,
+ Value: Bool);
+ pub fn LLVMPassManagerBuilderUseInlinerWithThreshold(
+ PMB: PassManagerBuilderRef,
+ threshold: c_uint);
+ pub fn LLVMPassManagerBuilderPopulateModulePassManager(
+ PMB: PassManagerBuilderRef,
+ PM: PassManagerRef);
+
+ pub fn LLVMPassManagerBuilderPopulateFunctionPassManager(
+ PMB: PassManagerBuilderRef,
+ PM: PassManagerRef);
+ pub fn LLVMPassManagerBuilderPopulateLTOPassManager(
+ PMB: PassManagerBuilderRef,
+ PM: PassManagerRef,
+ Internalize: Bool,
+ RunInliner: Bool);
+
+ /// Destroys a memory buffer.
+ pub fn LLVMDisposeMemoryBuffer(MemBuf: MemoryBufferRef);
+
+
+ /* Stuff that's in rustllvm/ because it's not upstream yet. */
+
+ /// Opens an object file.
+ pub fn LLVMCreateObjectFile(MemBuf: MemoryBufferRef) -> ObjectFileRef;
+ /// Closes an object file.
+ pub fn LLVMDisposeObjectFile(ObjFile: ObjectFileRef);
+
+ /// Enumerates the sections in an object file.
+ pub fn LLVMGetSections(ObjFile: ObjectFileRef) -> SectionIteratorRef;
+ /// Destroys a section iterator.
+ pub fn LLVMDisposeSectionIterator(SI: SectionIteratorRef);
+ /// Returns true if the section iterator is at the end of the section
+ /// list:
+ pub fn LLVMIsSectionIteratorAtEnd(ObjFile: ObjectFileRef,
+ SI: SectionIteratorRef)
+ -> Bool;
+ /// Moves the section iterator to point to the next section.
+ pub fn LLVMMoveToNextSection(SI: SectionIteratorRef);
+ /// Returns the current section size.
+ pub fn LLVMGetSectionSize(SI: SectionIteratorRef) -> c_ulonglong;
+ /// Returns the current section contents as a string buffer.
+ pub fn LLVMGetSectionContents(SI: SectionIteratorRef) -> *const c_char;
+
+ /// Reads the given file and returns it as a memory buffer. Use
+ /// LLVMDisposeMemoryBuffer() to get rid of it.
+ pub fn LLVMRustCreateMemoryBufferWithContentsOfFile(Path: *const c_char)
+ -> MemoryBufferRef;
+ /// Borrows the contents of the memory buffer (doesn't copy it)
+ pub fn LLVMCreateMemoryBufferWithMemoryRange(InputData: *const c_char,
+ InputDataLength: size_t,
+ BufferName: *const c_char,
+ RequiresNull: Bool)
+ -> MemoryBufferRef;
+ pub fn LLVMCreateMemoryBufferWithMemoryRangeCopy(InputData: *const c_char,
+ InputDataLength: size_t,
+ BufferName: *const c_char)
+ -> MemoryBufferRef;
+
+ pub fn LLVMIsMultithreaded() -> Bool;
+ pub fn LLVMStartMultithreaded() -> Bool;
+
+ /// Returns a string describing the last error caused by an LLVMRust* call.
+ pub fn LLVMRustGetLastError() -> *const c_char;
+
+ /// Print the pass timings since static dtors aren't picking them up.
+ pub fn LLVMRustPrintPassTimings();
+
+ pub fn LLVMStructCreateNamed(C: ContextRef, Name: *const c_char) -> TypeRef;
+
+ pub fn LLVMStructSetBody(StructTy: TypeRef,
+ ElementTypes: *const TypeRef,
+ ElementCount: c_uint,
+ Packed: Bool);
+
+ pub fn LLVMConstNamedStruct(S: TypeRef,
+ ConstantVals: *const ValueRef,
+ Count: c_uint)
+ -> ValueRef;
+
+ /// Enables LLVM debug output.
+ pub fn LLVMRustSetDebug(Enabled: c_int);
+
+ /// Prepares inline assembly.
+ pub fn LLVMRustInlineAsm(Ty: TypeRef,
+ AsmString: *const c_char,
+ Constraints: *const c_char,
+ SideEffects: Bool,
+ AlignStack: Bool,
+ Dialect: AsmDialect)
+ -> ValueRef;
+
+ pub fn LLVMRustDebugMetadataVersion() -> u32;
+ pub fn LLVMRustVersionMajor() -> u32;
+ pub fn LLVMRustVersionMinor() -> u32;
+
+ pub fn LLVMRustAddModuleFlag(M: ModuleRef,
+ name: *const c_char,
+ value: u32);
+
+ pub fn LLVMRustDIBuilderCreate(M: ModuleRef) -> DIBuilderRef;
+
+ pub fn LLVMRustDIBuilderDispose(Builder: DIBuilderRef);
+
+ pub fn LLVMRustDIBuilderFinalize(Builder: DIBuilderRef);
+
+ pub fn LLVMRustDIBuilderCreateCompileUnit(Builder: DIBuilderRef,
+ Lang: c_uint,
+ File: *const c_char,
+ Dir: *const c_char,
+ Producer: *const c_char,
+ isOptimized: bool,
+ Flags: *const c_char,
+ RuntimeVer: c_uint,
+ SplitName: *const c_char)
+ -> DIDescriptor;
+
+ pub fn LLVMRustDIBuilderCreateFile(Builder: DIBuilderRef,
+ Filename: *const c_char,
+ Directory: *const c_char)
+ -> DIFile;
+
+ pub fn LLVMRustDIBuilderCreateSubroutineType(Builder: DIBuilderRef,
+ File: DIFile,
+ ParameterTypes: DIArray)
+ -> DICompositeType;
+
+ pub fn LLVMRustDIBuilderCreateFunction(Builder: DIBuilderRef,
+ Scope: DIDescriptor,
+ Name: *const c_char,
+ LinkageName: *const c_char,
+ File: DIFile,
+ LineNo: c_uint,
+ Ty: DIType,
+ isLocalToUnit: bool,
+ isDefinition: bool,
+ ScopeLine: c_uint,
+ Flags: c_uint,
+ isOptimized: bool,
+ Fn: ValueRef,
+ TParam: DIArray,
+ Decl: DIDescriptor)
+ -> DISubprogram;
+
+ pub fn LLVMRustDIBuilderCreateBasicType(Builder: DIBuilderRef,
+ Name: *const c_char,
+ SizeInBits: u64,
+ AlignInBits: u64,
+ Encoding: c_uint)
+ -> DIBasicType;
+
+ pub fn LLVMRustDIBuilderCreatePointerType(Builder: DIBuilderRef,
+ PointeeTy: DIType,
+ SizeInBits: u64,
+ AlignInBits: u64,
+ Name: *const c_char)
+ -> DIDerivedType;
+
+ pub fn LLVMRustDIBuilderCreateStructType(Builder: DIBuilderRef,
+ Scope: DIDescriptor,
+ Name: *const c_char,
+ File: DIFile,
+ LineNumber: c_uint,
+ SizeInBits: u64,
+ AlignInBits: u64,
+ Flags: c_uint,
+ DerivedFrom: DIType,
+ Elements: DIArray,
+ RunTimeLang: c_uint,
+ VTableHolder: DIType,
+ UniqueId: *const c_char)
+ -> DICompositeType;
+
+ pub fn LLVMRustDIBuilderCreateMemberType(Builder: DIBuilderRef,
+ Scope: DIDescriptor,
+ Name: *const c_char,
+ File: DIFile,
+ LineNo: c_uint,
+ SizeInBits: u64,
+ AlignInBits: u64,
+ OffsetInBits: u64,
+ Flags: c_uint,
+ Ty: DIType)
+ -> DIDerivedType;
+
+ pub fn LLVMRustDIBuilderCreateLexicalBlock(Builder: DIBuilderRef,
+ Scope: DIScope,
+ File: DIFile,
+ Line: c_uint,
+ Col: c_uint)
+ -> DILexicalBlock;
+
+ pub fn LLVMRustDIBuilderCreateStaticVariable(Builder: DIBuilderRef,
+ Context: DIScope,
+ Name: *const c_char,
+ LinkageName: *const c_char,
+ File: DIFile,
+ LineNo: c_uint,
+ Ty: DIType,
+ isLocalToUnit: bool,
+ Val: ValueRef,
+ Decl: DIDescriptor)
+ -> DIGlobalVariable;
+
+ pub fn LLVMRustDIBuilderCreateVariable(Builder: DIBuilderRef,
+ Tag: c_uint,
+ Scope: DIDescriptor,
+ Name: *const c_char,
+ File: DIFile,
+ LineNo: c_uint,
+ Ty: DIType,
+ AlwaysPreserve: bool,
+ Flags: c_uint,
+ AddrOps: *const i64,
+ AddrOpsCount: c_uint,
+ ArgNo: c_uint)
+ -> DIVariable;
+
+ pub fn LLVMRustDIBuilderCreateArrayType(Builder: DIBuilderRef,
+ Size: u64,
+ AlignInBits: u64,
+ Ty: DIType,
+ Subscripts: DIArray)
+ -> DIType;
+
+ pub fn LLVMRustDIBuilderCreateVectorType(Builder: DIBuilderRef,
+ Size: u64,
+ AlignInBits: u64,
+ Ty: DIType,
+ Subscripts: DIArray)
+ -> DIType;
+
+ pub fn LLVMRustDIBuilderGetOrCreateSubrange(Builder: DIBuilderRef,
+ Lo: i64,
+ Count: i64)
+ -> DISubrange;
+
+ pub fn LLVMRustDIBuilderGetOrCreateArray(Builder: DIBuilderRef,
+ Ptr: *const DIDescriptor,
+ Count: c_uint)
+ -> DIArray;
+
+ pub fn LLVMRustDIBuilderInsertDeclareAtEnd(Builder: DIBuilderRef,
+ Val: ValueRef,
+ VarInfo: DIVariable,
+ AddrOps: *const i64,
+ AddrOpsCount: c_uint,
+ DL: ValueRef,
+ InsertAtEnd: BasicBlockRef)
+ -> ValueRef;
+
+ pub fn LLVMRustDIBuilderInsertDeclareBefore(Builder: DIBuilderRef,
+ Val: ValueRef,
+ VarInfo: DIVariable,
+ AddrOps: *const i64,
+ AddrOpsCount: c_uint,
+ DL: ValueRef,
+ InsertBefore: ValueRef)
+ -> ValueRef;
+
+ pub fn LLVMRustDIBuilderCreateEnumerator(Builder: DIBuilderRef,
+ Name: *const c_char,
+ Val: u64)
+ -> DIEnumerator;
+
+ pub fn LLVMRustDIBuilderCreateEnumerationType(Builder: DIBuilderRef,
+ Scope: DIScope,
+ Name: *const c_char,
+ File: DIFile,
+ LineNumber: c_uint,
+ SizeInBits: u64,
+ AlignInBits: u64,
+ Elements: DIArray,
+ ClassType: DIType)
+ -> DIType;
+
+ pub fn LLVMRustDIBuilderCreateUnionType(Builder: DIBuilderRef,
+ Scope: DIScope,
+ Name: *const c_char,
+ File: DIFile,
+ LineNumber: c_uint,
+ SizeInBits: u64,
+ AlignInBits: u64,
+ Flags: c_uint,
+ Elements: DIArray,
+ RunTimeLang: c_uint,
+ UniqueId: *const c_char)
+ -> DIType;
+
+ pub fn LLVMSetUnnamedAddr(GlobalVar: ValueRef, UnnamedAddr: Bool);
+
+ pub fn LLVMRustDIBuilderCreateTemplateTypeParameter(Builder: DIBuilderRef,
+ Scope: DIScope,
+ Name: *const c_char,
+ Ty: DIType,
+ File: DIFile,
+ LineNo: c_uint,
+ ColumnNo: c_uint)
+ -> DITemplateTypeParameter;
+
+
+ pub fn LLVMRustDIBuilderCreateNameSpace(Builder: DIBuilderRef,
+ Scope: DIScope,
+ Name: *const c_char,
+ File: DIFile,
+ LineNo: c_uint)
+ -> DINameSpace;
+ pub fn LLVMRustDICompositeTypeSetTypeArray(Builder: DIBuilderRef,
+ CompositeType: DIType,
+ TypeArray: DIArray);
+
+
+ pub fn LLVMRustDIBuilderCreateDebugLocation(Context: ContextRef,
+ Line: c_uint,
+ Column: c_uint,
+ Scope: DIScope,
+ InlinedAt: MetadataRef)
+ -> ValueRef;
+ pub fn LLVMRustDIBuilderCreateOpDeref() -> i64;
+ pub fn LLVMRustDIBuilderCreateOpPlus() -> i64;
+
+ pub fn LLVMRustWriteTypeToString(Type: TypeRef, s: RustStringRef);
+ pub fn LLVMRustWriteValueToString(value_ref: ValueRef, s: RustStringRef);
+
+ pub fn LLVMIsAArgument(value_ref: ValueRef) -> ValueRef;
+
+ pub fn LLVMIsAAllocaInst(value_ref: ValueRef) -> ValueRef;
+ pub fn LLVMIsAConstantInt(value_ref: ValueRef) -> ValueRef;
+
+ pub fn LLVMRustPassKind(Pass: PassRef) -> PassKind;
+ pub fn LLVMRustFindAndCreatePass(Pass: *const c_char) -> PassRef;
+ pub fn LLVMRustAddPass(PM: PassManagerRef, Pass: PassRef);
+
+ pub fn LLVMRustHasFeature(T: TargetMachineRef,
+ s: *const c_char) -> bool;
+
+ pub fn LLVMRustCreateTargetMachine(Triple: *const c_char,
+ CPU: *const c_char,
+ Features: *const c_char,
+ Model: CodeModel,
+ Reloc: RelocMode,
+ Level: CodeGenOptLevel,
+ UseSoftFP: bool,
+ PositionIndependentExecutable: bool,
+ FunctionSections: bool,
+ DataSections: bool) -> TargetMachineRef;
+ pub fn LLVMRustDisposeTargetMachine(T: TargetMachineRef);
+ pub fn LLVMRustAddAnalysisPasses(T: TargetMachineRef,
+ PM: PassManagerRef,
+ M: ModuleRef);
+ pub fn LLVMRustAddBuilderLibraryInfo(PMB: PassManagerBuilderRef,
+ M: ModuleRef,
+ DisableSimplifyLibCalls: bool);
+ pub fn LLVMRustConfigurePassManagerBuilder(PMB: PassManagerBuilderRef,
+ OptLevel: CodeGenOptLevel,
+ MergeFunctions: bool,
+ SLPVectorize: bool,
+ LoopVectorize: bool);
+ pub fn LLVMRustAddLibraryInfo(PM: PassManagerRef, M: ModuleRef,
+ DisableSimplifyLibCalls: bool);
+ pub fn LLVMRustRunFunctionPassManager(PM: PassManagerRef, M: ModuleRef);
+ pub fn LLVMRustWriteOutputFile(T: TargetMachineRef,
+ PM: PassManagerRef,
+ M: ModuleRef,
+ Output: *const c_char,
+ FileType: FileType)
+ -> LLVMRustResult;
+ pub fn LLVMRustPrintModule(PM: PassManagerRef,
+ M: ModuleRef,
+ Output: *const c_char);
+ pub fn LLVMRustSetLLVMOptions(Argc: c_int, Argv: *const *const c_char);
+ pub fn LLVMRustPrintPasses();
+ pub fn LLVMRustSetNormalizedTarget(M: ModuleRef, triple: *const c_char);
+ pub fn LLVMRustAddAlwaysInlinePass(P: PassManagerBuilderRef,
+ AddLifetimes: bool);
+ pub fn LLVMRustLinkInExternalBitcode(M: ModuleRef,
+ bc: *const c_char,
+ len: size_t) -> bool;
+ pub fn LLVMRustRunRestrictionPass(M: ModuleRef,
+ syms: *const *const c_char,
+ len: size_t);
+ pub fn LLVMRustMarkAllFunctionsNounwind(M: ModuleRef);
+
+ pub fn LLVMRustOpenArchive(path: *const c_char) -> ArchiveRef;
+ pub fn LLVMRustArchiveIteratorNew(AR: ArchiveRef) -> ArchiveIteratorRef;
+ pub fn LLVMRustArchiveIteratorNext(AIR: ArchiveIteratorRef) -> ArchiveChildRef;
+ pub fn LLVMRustArchiveChildName(ACR: ArchiveChildRef,
+ size: *mut size_t) -> *const c_char;
+ pub fn LLVMRustArchiveChildData(ACR: ArchiveChildRef,
+ size: *mut size_t) -> *const c_char;
+ pub fn LLVMRustArchiveChildFree(ACR: ArchiveChildRef);
+ pub fn LLVMRustArchiveIteratorFree(AIR: ArchiveIteratorRef);
+ pub fn LLVMRustDestroyArchive(AR: ArchiveRef);
+
+ pub fn LLVMRustGetSectionName(SI: SectionIteratorRef,
+ data: *mut *const c_char) -> size_t;
+
+ pub fn LLVMRustWriteTwineToString(T: TwineRef, s: RustStringRef);
+
+ pub fn LLVMContextSetDiagnosticHandler(C: ContextRef,
+ Handler: DiagnosticHandler,
+ DiagnosticContext: *mut c_void);
+
+ pub fn LLVMRustUnpackOptimizationDiagnostic(DI: DiagnosticInfoRef,
+ pass_name_out: *mut *const c_char,
+ function_out: *mut ValueRef,
+ debugloc_out: *mut DebugLocRef,
+ message_out: *mut TwineRef);
+ pub fn LLVMRustUnpackInlineAsmDiagnostic(DI: DiagnosticInfoRef,
+ cookie_out: *mut c_uint,
+ message_out: *mut TwineRef,
+ instruction_out: *mut ValueRef);
+
+ pub fn LLVMRustWriteDiagnosticInfoToString(DI: DiagnosticInfoRef,
+ s: RustStringRef);
+ pub fn LLVMGetDiagInfoSeverity(DI: DiagnosticInfoRef) -> DiagnosticSeverity;
+ pub fn LLVMRustGetDiagInfoKind(DI: DiagnosticInfoRef) -> DiagnosticKind;
+
+ pub fn LLVMRustWriteDebugLocToString(C: ContextRef,
+ DL: DebugLocRef,
+ s: RustStringRef);
+
+ pub fn LLVMRustSetInlineAsmDiagnosticHandler(C: ContextRef,
+ H: InlineAsmDiagHandler,
+ CX: *mut c_void);
+
+ pub fn LLVMRustWriteSMDiagnosticToString(d: SMDiagnosticRef, s: RustStringRef);
+
+ pub fn LLVMRustWriteArchive(Dst: *const c_char,
+ NumMembers: size_t,
+ Members: *const RustArchiveMemberRef,
+ WriteSymbtab: bool,
+ Kind: ArchiveKind) ->
+ LLVMRustResult;
+ pub fn LLVMRustArchiveMemberNew(Filename: *const c_char,
+ Name: *const c_char,
+ Child: ArchiveChildRef) -> RustArchiveMemberRef;
+ pub fn LLVMRustArchiveMemberFree(Member: RustArchiveMemberRef);
+
+ pub fn LLVMRustSetDataLayoutFromTargetMachine(M: ModuleRef,
+ TM: TargetMachineRef);
+ pub fn LLVMRustGetModuleDataLayout(M: ModuleRef) -> TargetDataRef;
+
+ pub fn LLVMRustBuildOperandBundleDef(Name: *const c_char,
+ Inputs: *const ValueRef,
+ NumInputs: c_uint)
+ -> OperandBundleDefRef;
+ pub fn LLVMRustFreeOperandBundleDef(Bundle: OperandBundleDefRef);
+
+ pub fn LLVMRustPositionBuilderAtStart(B: BuilderRef, BB: BasicBlockRef);
+
+ pub fn LLVMRustSetComdat(M: ModuleRef, V: ValueRef, Name: *const c_char);
+ pub fn LLVMRustUnsetComdat(V: ValueRef);
+ pub fn LLVMRustSetModulePIELevel(M: ModuleRef);
+}
+
+
+// LLVM requires symbols from this library, but apparently they're not printed
+// during llvm-config?
+#[cfg(windows)]
+#[link(name = "ole32")]
+extern {}
diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs
index e757201..6c4e1a5 100644
--- a/src/librustc_llvm/lib.rs
+++ b/src/librustc_llvm/lib.rs
@@ -33,157 +33,35 @@
extern crate libc;
#[macro_use] #[no_link] extern crate rustc_bitflags;
-pub use self::AttributeSet::*;
pub use self::IntPredicate::*;
pub use self::RealPredicate::*;
pub use self::TypeKind::*;
-pub use self::AtomicBinOp::*;
-pub use self::AtomicOrdering::*;
-pub use self::SynchronizationScope::*;
-pub use self::FileType::*;
+pub use self::AtomicRmwBinOp::*;
pub use self::MetadataType::*;
-pub use self::AsmDialect::*;
-pub use self::CodeGenOptLevel::*;
pub use self::CodeGenOptSize::*;
-pub use self::RelocMode::*;
-pub use self::CodeGenModel::*;
pub use self::DiagnosticKind::*;
pub use self::CallConv::*;
-pub use self::Visibility::*;
pub use self::DiagnosticSeverity::*;
pub use self::Linkage::*;
-pub use self::DLLStorageClassTypes::*;
use std::str::FromStr;
+use std::slice;
use std::ffi::{CString, CStr};
use std::cell::RefCell;
-use std::slice;
-use libc::{c_uint, c_ushort, uint64_t, c_int, size_t, c_char};
-use libc::{c_longlong, c_ulonglong, c_void};
-use debuginfo::{DIBuilderRef, DIDescriptor,
- DIFile, DILexicalBlock, DISubprogram, DIType,
- DIBasicType, DIDerivedType, DICompositeType, DIScope,
- DIVariable, DIGlobalVariable, DIArray, DISubrange,
- DITemplateTypeParameter, DIEnumerator, DINameSpace};
+use libc::{c_uint, c_char, size_t};
pub mod archive_ro;
pub mod diagnostic;
+pub mod ffi;
-pub type Opcode = u32;
-pub type Bool = c_uint;
+pub use ffi::*;
-pub const True: Bool = 1 as Bool;
-pub const False: Bool = 0 as Bool;
-
-// Consts for the LLVM CallConv type, pre-cast to usize.
-
-#[derive(Copy, Clone, PartialEq)]
-pub enum CallConv {
- CCallConv = 0,
- FastCallConv = 8,
- ColdCallConv = 9,
- X86StdcallCallConv = 64,
- X86FastcallCallConv = 65,
- X86_64_Win64 = 79,
- X86_VectorCall = 80
-}
-
-#[derive(Copy, Clone)]
-pub enum Visibility {
- LLVMDefaultVisibility = 0,
- HiddenVisibility = 1,
- ProtectedVisibility = 2,
-}
-
-// This enum omits the obsolete (and no-op) linkage types DLLImportLinkage,
-// DLLExportLinkage, GhostLinkage and LinkOnceODRAutoHideLinkage.
-// LinkerPrivateLinkage and LinkerPrivateWeakLinkage are not included either;
-// they've been removed in upstream LLVM commit r203866.
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
-pub enum Linkage {
- ExternalLinkage = 0,
- AvailableExternallyLinkage = 1,
- LinkOnceAnyLinkage = 2,
- LinkOnceODRLinkage = 3,
- WeakAnyLinkage = 5,
- WeakODRLinkage = 6,
- AppendingLinkage = 7,
- InternalLinkage = 8,
- PrivateLinkage = 9,
- ExternalWeakLinkage = 12,
- CommonLinkage = 14,
-}
-
-#[repr(C)]
-#[derive(Copy, Clone, Debug)]
-pub enum DiagnosticSeverity {
- Error,
- Warning,
- Remark,
- Note,
-}
-
-
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub enum DLLStorageClassTypes {
- DefaultStorageClass = 0,
- DLLImportStorageClass = 1,
- DLLExportStorageClass = 2,
-}
-
-bitflags! {
- #[derive(Default, Debug)]
- flags Attribute : u64 {
- const ZExt = 1 << 0,
- const SExt = 1 << 1,
- const NoReturn = 1 << 2,
- const InReg = 1 << 3,
- const StructRet = 1 << 4,
- const NoUnwind = 1 << 5,
- const NoAlias = 1 << 6,
- const ByVal = 1 << 7,
- const Nest = 1 << 8,
- const ReadNone = 1 << 9,
- const ReadOnly = 1 << 10,
- const NoInline = 1 << 11,
- const AlwaysInline = 1 << 12,
- const OptimizeForSize = 1 << 13,
- const StackProtect = 1 << 14,
- const StackProtectReq = 1 << 15,
- const NoCapture = 1 << 21,
- const NoRedZone = 1 << 22,
- const NoImplicitFloat = 1 << 23,
- const Naked = 1 << 24,
- const InlineHint = 1 << 25,
- const ReturnsTwice = 1 << 29,
- const UWTable = 1 << 30,
- const NonLazyBind = 1 << 31,
-
- // Some of these are missing from the LLVM C API, the rest are
- // present, but commented out, and preceded by the following warning:
- // FIXME: These attributes are currently not included in the C API as
- // a temporary measure until the API/ABI impact to the C API is understood
- // and the path forward agreed upon.
- const SanitizeAddress = 1 << 32,
- const MinSize = 1 << 33,
- const NoDuplicate = 1 << 34,
- const StackProtectStrong = 1 << 35,
- const SanitizeThread = 1 << 36,
- const SanitizeMemory = 1 << 37,
- const NoBuiltin = 1 << 38,
- const Returned = 1 << 39,
- const Cold = 1 << 40,
- const Builtin = 1 << 41,
- const OptimizeNone = 1 << 42,
- const InAlloca = 1 << 43,
- const NonNull = 1 << 44,
- const JumpTable = 1 << 45,
- const Convergent = 1 << 46,
- const SafeStack = 1 << 47,
- const NoRecurse = 1 << 48,
- const InaccessibleMemOnly = 1 << 49,
- const InaccessibleMemOrArgMemOnly = 1 << 50,
+impl LLVMRustResult {
+ pub fn into_result(self) -> Result<(), ()> {
+ match self {
+ LLVMRustResult::Success => Ok(()),
+ LLVMRustResult::Failure => Err(()),
+ }
}
}
@@ -214,167 +92,64 @@
self
}
- pub fn apply_llfn(&self, idx: usize, llfn: ValueRef) {
+ pub fn apply_llfn(&self, idx: AttributePlace, llfn: ValueRef) {
unsafe {
- LLVMAddFunctionAttribute(llfn, idx as c_uint, self.regular.bits());
+ self.regular.apply_llfn(idx, llfn);
if self.dereferenceable_bytes != 0 {
- LLVMAddDereferenceableAttr(llfn, idx as c_uint,
- self.dereferenceable_bytes);
+ LLVMRustAddDereferenceableAttr(
+ llfn,
+ idx.as_uint(),
+ self.dereferenceable_bytes);
}
}
}
- pub fn apply_callsite(&self, idx: usize, callsite: ValueRef) {
+ pub fn apply_callsite(&self, idx: AttributePlace, callsite: ValueRef) {
unsafe {
- LLVMAddCallSiteAttribute(callsite, idx as c_uint, self.regular.bits());
+ self.regular.apply_callsite(idx, callsite);
if self.dereferenceable_bytes != 0 {
- LLVMAddDereferenceableCallSiteAttr(callsite, idx as c_uint,
- self.dereferenceable_bytes);
+ LLVMRustAddDereferenceableCallSiteAttr(
+ callsite,
+ idx.as_uint(),
+ self.dereferenceable_bytes);
}
}
}
}
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub enum AttributeSet {
- ReturnIndex = 0,
- FunctionIndex = !0
-}
-
-// enum for the LLVM IntPredicate type
-#[derive(Copy, Clone)]
-pub enum IntPredicate {
- IntEQ = 32,
- IntNE = 33,
- IntUGT = 34,
- IntUGE = 35,
- IntULT = 36,
- IntULE = 37,
- IntSGT = 38,
- IntSGE = 39,
- IntSLT = 40,
- IntSLE = 41,
-}
-
-// enum for the LLVM RealPredicate type
-#[derive(Copy, Clone)]
-pub enum RealPredicate {
- RealPredicateFalse = 0,
- RealOEQ = 1,
- RealOGT = 2,
- RealOGE = 3,
- RealOLT = 4,
- RealOLE = 5,
- RealONE = 6,
- RealORD = 7,
- RealUNO = 8,
- RealUEQ = 9,
- RealUGT = 10,
- RealUGE = 11,
- RealULT = 12,
- RealULE = 13,
- RealUNE = 14,
- RealPredicateTrue = 15,
-}
-
-// The LLVM TypeKind type - must stay in sync with the def of
-// LLVMTypeKind in llvm/include/llvm-c/Core.h
-#[derive(Copy, Clone, PartialEq, Debug)]
-#[repr(C)]
-pub enum TypeKind {
- Void = 0,
- Half = 1,
- Float = 2,
- Double = 3,
- X86_FP80 = 4,
- FP128 = 5,
- PPC_FP128 = 6,
- Label = 7,
- Integer = 8,
- Function = 9,
- Struct = 10,
- Array = 11,
- Pointer = 12,
- Vector = 13,
- Metadata = 14,
- X86_MMX = 15,
+pub fn AddFunctionAttrStringValue(
+ llfn: ValueRef,
+ idx: AttributePlace,
+ attr: &'static str,
+ value: &'static str
+) {
+ unsafe {
+ LLVMRustAddFunctionAttrStringValue(
+ llfn,
+ idx.as_uint(),
+ attr.as_ptr() as *const _,
+ value.as_ptr() as *const _)
+ }
}
#[repr(C)]
#[derive(Copy, Clone)]
-pub enum AtomicBinOp {
- AtomicXchg = 0,
- AtomicAdd = 1,
- AtomicSub = 2,
- AtomicAnd = 3,
- AtomicNand = 4,
- AtomicOr = 5,
- AtomicXor = 6,
- AtomicMax = 7,
- AtomicMin = 8,
- AtomicUMax = 9,
- AtomicUMin = 10,
+pub enum AttributePlace {
+ Argument(u32),
+ Function,
}
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub enum AtomicOrdering {
- NotAtomic = 0,
- Unordered = 1,
- Monotonic = 2,
- // Consume = 3, // Not specified yet.
- Acquire = 4,
- Release = 5,
- AcquireRelease = 6,
- SequentiallyConsistent = 7
-}
+impl AttributePlace {
+ pub fn ReturnValue() -> Self {
+ AttributePlace::Argument(0)
+ }
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub enum SynchronizationScope {
- SingleThread = 0,
- CrossThread = 1
-}
-
-// Consts for the LLVMCodeGenFileType type (in include/llvm/c/TargetMachine.h)
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub enum FileType {
- AssemblyFileType = 0,
- ObjectFileType = 1
-}
-
-#[derive(Copy, Clone)]
-pub enum MetadataType {
- MD_dbg = 0,
- MD_tbaa = 1,
- MD_prof = 2,
- MD_fpmath = 3,
- MD_range = 4,
- MD_tbaa_struct = 5,
- MD_invariant_load = 6,
- MD_alias_scope = 7,
- MD_noalias = 8,
- MD_nontemporal = 9,
- MD_mem_parallel_loop_access = 10,
- MD_nonnull = 11,
-}
-
-// Inline Asm Dialect
-#[derive(Copy, Clone)]
-pub enum AsmDialect {
- AD_ATT = 0,
- AD_Intel = 1
-}
-
-#[derive(Copy, Clone, PartialEq)]
-#[repr(C)]
-pub enum CodeGenOptLevel {
- CodeGenLevelNone = 0,
- CodeGenLevelLess = 1,
- CodeGenLevelDefault = 2,
- CodeGenLevelAggressive = 3,
+ fn as_uint(self) -> c_uint {
+ match self {
+ AttributePlace::Function => !0,
+ AttributePlace::Argument(i) => i,
+ }
+ }
}
#[derive(Copy, Clone, PartialEq)]
@@ -385,48 +160,6 @@
CodeGenOptSizeAggressive = 2,
}
-#[derive(Copy, Clone, PartialEq)]
-#[repr(C)]
-pub enum RelocMode {
- RelocDefault = 0,
- RelocStatic = 1,
- RelocPIC = 2,
- RelocDynamicNoPic = 3,
-}
-
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub enum CodeGenModel {
- CodeModelDefault = 0,
- CodeModelJITDefault = 1,
- CodeModelSmall = 2,
- CodeModelKernel = 3,
- CodeModelMedium = 4,
- CodeModelLarge = 5,
-}
-
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub enum DiagnosticKind {
- DK_InlineAsm = 0,
- DK_StackSize,
- DK_DebugMetadataVersion,
- DK_SampleProfile,
- DK_OptimizationRemark,
- DK_OptimizationRemarkMissed,
- DK_OptimizationRemarkAnalysis,
- DK_OptimizationFailure,
-}
-
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub enum ArchiveKind {
- K_GNU,
- K_MIPS64,
- K_BSD,
- K_COFF,
-}
-
impl FromStr for ArchiveKind {
type Err = ();
@@ -441,1728 +174,22 @@
}
}
-/// Represents the different LLVM passes Rust supports
-#[derive(Copy, Clone, PartialEq, Debug)]
-#[repr(C)]
-pub enum SupportedPassKind {
- Function,
- Module,
- Unsupported,
+#[allow(missing_copy_implementations)]
+pub enum RustString_opaque {}
+pub type RustStringRef = *mut RustString_opaque;
+type RustStringRepr = *mut RefCell<Vec<u8>>;
+
+/// Appending to a Rust string -- used by raw_rust_string_ostream.
+#[no_mangle]
+pub unsafe extern "C" fn rust_llvm_string_write_impl(sr: RustStringRef,
+ ptr: *const c_char,
+ size: size_t) {
+ let slice = slice::from_raw_parts(ptr as *const u8, size as usize);
+
+ let sr = sr as RustStringRepr;
+ (*sr).borrow_mut().extend_from_slice(slice);
}
-// Opaque pointer types
-#[allow(missing_copy_implementations)]
-pub enum Module_opaque {}
-pub type ModuleRef = *mut Module_opaque;
-#[allow(missing_copy_implementations)]
-pub enum Context_opaque {}
-pub type ContextRef = *mut Context_opaque;
-#[allow(missing_copy_implementations)]
-pub enum Type_opaque {}
-pub type TypeRef = *mut Type_opaque;
-#[allow(missing_copy_implementations)]
-pub enum Value_opaque {}
-pub type ValueRef = *mut Value_opaque;
-#[allow(missing_copy_implementations)]
-pub enum Metadata_opaque {}
-pub type MetadataRef = *mut Metadata_opaque;
-#[allow(missing_copy_implementations)]
-pub enum BasicBlock_opaque {}
-pub type BasicBlockRef = *mut BasicBlock_opaque;
-#[allow(missing_copy_implementations)]
-pub enum Builder_opaque {}
-pub type BuilderRef = *mut Builder_opaque;
-#[allow(missing_copy_implementations)]
-pub enum ExecutionEngine_opaque {}
-pub type ExecutionEngineRef = *mut ExecutionEngine_opaque;
-#[allow(missing_copy_implementations)]
-pub enum MemoryBuffer_opaque {}
-pub type MemoryBufferRef = *mut MemoryBuffer_opaque;
-#[allow(missing_copy_implementations)]
-pub enum PassManager_opaque {}
-pub type PassManagerRef = *mut PassManager_opaque;
-#[allow(missing_copy_implementations)]
-pub enum PassManagerBuilder_opaque {}
-pub type PassManagerBuilderRef = *mut PassManagerBuilder_opaque;
-#[allow(missing_copy_implementations)]
-pub enum Use_opaque {}
-pub type UseRef = *mut Use_opaque;
-#[allow(missing_copy_implementations)]
-pub enum TargetData_opaque {}
-pub type TargetDataRef = *mut TargetData_opaque;
-#[allow(missing_copy_implementations)]
-pub enum ObjectFile_opaque {}
-pub type ObjectFileRef = *mut ObjectFile_opaque;
-#[allow(missing_copy_implementations)]
-pub enum SectionIterator_opaque {}
-pub type SectionIteratorRef = *mut SectionIterator_opaque;
-#[allow(missing_copy_implementations)]
-pub enum Pass_opaque {}
-pub type PassRef = *mut Pass_opaque;
-#[allow(missing_copy_implementations)]
-pub enum TargetMachine_opaque {}
-pub type TargetMachineRef = *mut TargetMachine_opaque;
-pub enum Archive_opaque {}
-pub type ArchiveRef = *mut Archive_opaque;
-pub enum ArchiveIterator_opaque {}
-pub type ArchiveIteratorRef = *mut ArchiveIterator_opaque;
-pub enum ArchiveChild_opaque {}
-pub type ArchiveChildRef = *mut ArchiveChild_opaque;
-#[allow(missing_copy_implementations)]
-pub enum Twine_opaque {}
-pub type TwineRef = *mut Twine_opaque;
-#[allow(missing_copy_implementations)]
-pub enum DiagnosticInfo_opaque {}
-pub type DiagnosticInfoRef = *mut DiagnosticInfo_opaque;
-#[allow(missing_copy_implementations)]
-pub enum DebugLoc_opaque {}
-pub type DebugLocRef = *mut DebugLoc_opaque;
-#[allow(missing_copy_implementations)]
-pub enum SMDiagnostic_opaque {}
-pub type SMDiagnosticRef = *mut SMDiagnostic_opaque;
-#[allow(missing_copy_implementations)]
-pub enum RustArchiveMember_opaque {}
-pub type RustArchiveMemberRef = *mut RustArchiveMember_opaque;
-#[allow(missing_copy_implementations)]
-pub enum OperandBundleDef_opaque {}
-pub type OperandBundleDefRef = *mut OperandBundleDef_opaque;
-
-pub type DiagnosticHandler = unsafe extern "C" fn(DiagnosticInfoRef, *mut c_void);
-pub type InlineAsmDiagHandler = unsafe extern "C" fn(SMDiagnosticRef, *const c_void, c_uint);
-
-pub mod debuginfo {
- pub use self::DIDescriptorFlags::*;
- use super::{MetadataRef};
-
- #[allow(missing_copy_implementations)]
- pub enum DIBuilder_opaque {}
- pub type DIBuilderRef = *mut DIBuilder_opaque;
-
- pub type DIDescriptor = MetadataRef;
- pub type DIScope = DIDescriptor;
- pub type DILocation = DIDescriptor;
- pub type DIFile = DIScope;
- pub type DILexicalBlock = DIScope;
- pub type DISubprogram = DIScope;
- pub type DINameSpace = DIScope;
- pub type DIType = DIDescriptor;
- pub type DIBasicType = DIType;
- pub type DIDerivedType = DIType;
- pub type DICompositeType = DIDerivedType;
- pub type DIVariable = DIDescriptor;
- pub type DIGlobalVariable = DIDescriptor;
- pub type DIArray = DIDescriptor;
- pub type DISubrange = DIDescriptor;
- pub type DIEnumerator = DIDescriptor;
- pub type DITemplateTypeParameter = DIDescriptor;
-
- #[derive(Copy, Clone)]
- pub enum DIDescriptorFlags {
- FlagPrivate = 1 << 0,
- FlagProtected = 1 << 1,
- FlagFwdDecl = 1 << 2,
- FlagAppleBlock = 1 << 3,
- FlagBlockByrefStruct = 1 << 4,
- FlagVirtual = 1 << 5,
- FlagArtificial = 1 << 6,
- FlagExplicit = 1 << 7,
- FlagPrototyped = 1 << 8,
- FlagObjcClassComplete = 1 << 9,
- FlagObjectPointer = 1 << 10,
- FlagVector = 1 << 11,
- FlagStaticMember = 1 << 12,
- FlagIndirectVariable = 1 << 13,
- FlagLValueReference = 1 << 14,
- FlagRValueReference = 1 << 15
- }
-}
-
-
-// Link to our native llvm bindings (things that we need to use the C++ api
-// for) and because llvm is written in C++ we need to link against libstdc++
-//
-// You'll probably notice that there is an omission of all LLVM libraries
-// from this location. This is because the set of LLVM libraries that we
-// link to is mostly defined by LLVM, and the `llvm-config` tool is used to
-// figure out the exact set of libraries. To do this, the build system
-// generates an llvmdeps.rs file next to this one which will be
-// automatically updated whenever LLVM is updated to include an up-to-date
-// set of the libraries we need to link to LLVM for.
-#[link(name = "rustllvm", kind = "static")]
-#[cfg(not(cargobuild))]
-extern {}
-
-#[linked_from = "rustllvm"] // not quite true but good enough
-extern {
- /* Create and destroy contexts. */
- pub fn LLVMContextCreate() -> ContextRef;
- pub fn LLVMContextDispose(C: ContextRef);
- pub fn LLVMGetMDKindIDInContext(C: ContextRef,
- Name: *const c_char,
- SLen: c_uint)
- -> c_uint;
-
- /* Create and destroy modules. */
- pub fn LLVMModuleCreateWithNameInContext(ModuleID: *const c_char,
- C: ContextRef)
- -> ModuleRef;
- pub fn LLVMGetModuleContext(M: ModuleRef) -> ContextRef;
- pub fn LLVMCloneModule(M: ModuleRef) -> ModuleRef;
- pub fn LLVMDisposeModule(M: ModuleRef);
-
- /// Data layout. See Module::getDataLayout.
- pub fn LLVMGetDataLayout(M: ModuleRef) -> *const c_char;
- pub fn LLVMSetDataLayout(M: ModuleRef, Triple: *const c_char);
-
- /// Target triple. See Module::getTargetTriple.
- pub fn LLVMGetTarget(M: ModuleRef) -> *const c_char;
- pub fn LLVMSetTarget(M: ModuleRef, Triple: *const c_char);
-
- /// See Module::dump.
- pub fn LLVMDumpModule(M: ModuleRef);
-
- /// See Module::setModuleInlineAsm.
- pub fn LLVMSetModuleInlineAsm(M: ModuleRef, Asm: *const c_char);
-
- /// See llvm::LLVMTypeKind::getTypeID.
- pub fn LLVMGetTypeKind(Ty: TypeRef) -> TypeKind;
-
- /// See llvm::LLVMType::getContext.
- pub fn LLVMGetTypeContext(Ty: TypeRef) -> ContextRef;
-
- /* Operations on integer types */
- pub fn LLVMInt1TypeInContext(C: ContextRef) -> TypeRef;
- pub fn LLVMInt8TypeInContext(C: ContextRef) -> TypeRef;
- pub fn LLVMInt16TypeInContext(C: ContextRef) -> TypeRef;
- pub fn LLVMInt32TypeInContext(C: ContextRef) -> TypeRef;
- pub fn LLVMInt64TypeInContext(C: ContextRef) -> TypeRef;
- pub fn LLVMIntTypeInContext(C: ContextRef, NumBits: c_uint)
- -> TypeRef;
-
- pub fn LLVMGetIntTypeWidth(IntegerTy: TypeRef) -> c_uint;
-
- /* Operations on real types */
- pub fn LLVMFloatTypeInContext(C: ContextRef) -> TypeRef;
- pub fn LLVMDoubleTypeInContext(C: ContextRef) -> TypeRef;
- pub fn LLVMX86FP80TypeInContext(C: ContextRef) -> TypeRef;
- pub fn LLVMFP128TypeInContext(C: ContextRef) -> TypeRef;
- pub fn LLVMPPCFP128TypeInContext(C: ContextRef) -> TypeRef;
-
- /* Operations on function types */
- pub fn LLVMFunctionType(ReturnType: TypeRef,
- ParamTypes: *const TypeRef,
- ParamCount: c_uint,
- IsVarArg: Bool)
- -> TypeRef;
- pub fn LLVMIsFunctionVarArg(FunctionTy: TypeRef) -> Bool;
- pub fn LLVMGetReturnType(FunctionTy: TypeRef) -> TypeRef;
- pub fn LLVMCountParamTypes(FunctionTy: TypeRef) -> c_uint;
- pub fn LLVMGetParamTypes(FunctionTy: TypeRef, Dest: *mut TypeRef);
-
- /* Operations on struct types */
- pub fn LLVMStructTypeInContext(C: ContextRef,
- ElementTypes: *const TypeRef,
- ElementCount: c_uint,
- Packed: Bool)
- -> TypeRef;
- pub fn LLVMCountStructElementTypes(StructTy: TypeRef) -> c_uint;
- pub fn LLVMGetStructElementTypes(StructTy: TypeRef,
- Dest: *mut TypeRef);
- pub fn LLVMIsPackedStruct(StructTy: TypeRef) -> Bool;
-
- /* Operations on array, pointer, and vector types (sequence types) */
- pub fn LLVMRustArrayType(ElementType: TypeRef, ElementCount: u64) -> TypeRef;
- pub fn LLVMPointerType(ElementType: TypeRef, AddressSpace: c_uint)
- -> TypeRef;
- pub fn LLVMVectorType(ElementType: TypeRef, ElementCount: c_uint)
- -> TypeRef;
-
- pub fn LLVMGetElementType(Ty: TypeRef) -> TypeRef;
- pub fn LLVMGetArrayLength(ArrayTy: TypeRef) -> c_uint;
- pub fn LLVMGetPointerAddressSpace(PointerTy: TypeRef) -> c_uint;
- pub fn LLVMGetPointerToGlobal(EE: ExecutionEngineRef, V: ValueRef)
- -> *const c_void;
- pub fn LLVMGetVectorSize(VectorTy: TypeRef) -> c_uint;
-
- /* Operations on other types */
- pub fn LLVMVoidTypeInContext(C: ContextRef) -> TypeRef;
- pub fn LLVMLabelTypeInContext(C: ContextRef) -> TypeRef;
- pub fn LLVMMetadataTypeInContext(C: ContextRef) -> TypeRef;
-
- /* Operations on all values */
- pub fn LLVMTypeOf(Val: ValueRef) -> TypeRef;
- pub fn LLVMGetValueName(Val: ValueRef) -> *const c_char;
- pub fn LLVMSetValueName(Val: ValueRef, Name: *const c_char);
- pub fn LLVMDumpValue(Val: ValueRef);
- pub fn LLVMReplaceAllUsesWith(OldVal: ValueRef, NewVal: ValueRef);
- pub fn LLVMHasMetadata(Val: ValueRef) -> c_int;
- pub fn LLVMGetMetadata(Val: ValueRef, KindID: c_uint) -> ValueRef;
- pub fn LLVMSetMetadata(Val: ValueRef, KindID: c_uint, Node: ValueRef);
-
- /* Operations on Uses */
- pub fn LLVMGetFirstUse(Val: ValueRef) -> UseRef;
- pub fn LLVMGetNextUse(U: UseRef) -> UseRef;
- pub fn LLVMGetUser(U: UseRef) -> ValueRef;
- pub fn LLVMGetUsedValue(U: UseRef) -> ValueRef;
-
- /* Operations on Users */
- pub fn LLVMGetNumOperands(Val: ValueRef) -> c_int;
- pub fn LLVMGetOperand(Val: ValueRef, Index: c_uint) -> ValueRef;
- pub fn LLVMSetOperand(Val: ValueRef, Index: c_uint, Op: ValueRef);
-
- /* Operations on constants of any type */
- pub fn LLVMConstNull(Ty: TypeRef) -> ValueRef;
- /* all zeroes */
- pub fn LLVMConstAllOnes(Ty: TypeRef) -> ValueRef;
- pub fn LLVMConstICmp(Pred: c_ushort, V1: ValueRef, V2: ValueRef)
- -> ValueRef;
- pub fn LLVMConstFCmp(Pred: c_ushort, V1: ValueRef, V2: ValueRef)
- -> ValueRef;
- /* only for isize/vector */
- pub fn LLVMGetUndef(Ty: TypeRef) -> ValueRef;
- pub fn LLVMIsConstant(Val: ValueRef) -> Bool;
- pub fn LLVMIsNull(Val: ValueRef) -> Bool;
- pub fn LLVMIsUndef(Val: ValueRef) -> Bool;
- pub fn LLVMConstPointerNull(Ty: TypeRef) -> ValueRef;
-
- /* Operations on metadata */
- pub fn LLVMMDStringInContext(C: ContextRef,
- Str: *const c_char,
- SLen: c_uint)
- -> ValueRef;
- pub fn LLVMMDNodeInContext(C: ContextRef,
- Vals: *const ValueRef,
- Count: c_uint)
- -> ValueRef;
- pub fn LLVMAddNamedMetadataOperand(M: ModuleRef,
- Str: *const c_char,
- Val: ValueRef);
-
- /* Operations on scalar constants */
- pub fn LLVMConstInt(IntTy: TypeRef, N: c_ulonglong, SignExtend: Bool)
- -> ValueRef;
- pub fn LLVMConstIntOfString(IntTy: TypeRef, Text: *const c_char, Radix: u8)
- -> ValueRef;
- pub fn LLVMConstIntOfStringAndSize(IntTy: TypeRef,
- Text: *const c_char,
- SLen: c_uint,
- Radix: u8)
- -> ValueRef;
- pub fn LLVMConstReal(RealTy: TypeRef, N: f64) -> ValueRef;
- pub fn LLVMConstRealOfString(RealTy: TypeRef, Text: *const c_char)
- -> ValueRef;
- pub fn LLVMConstRealOfStringAndSize(RealTy: TypeRef,
- Text: *const c_char,
- SLen: c_uint)
- -> ValueRef;
- pub fn LLVMConstIntGetZExtValue(ConstantVal: ValueRef) -> c_ulonglong;
- pub fn LLVMConstIntGetSExtValue(ConstantVal: ValueRef) -> c_longlong;
-
-
- /* Operations on composite constants */
- pub fn LLVMConstStringInContext(C: ContextRef,
- Str: *const c_char,
- Length: c_uint,
- DontNullTerminate: Bool)
- -> ValueRef;
- pub fn LLVMConstStructInContext(C: ContextRef,
- ConstantVals: *const ValueRef,
- Count: c_uint,
- Packed: Bool)
- -> ValueRef;
-
- pub fn LLVMConstArray(ElementTy: TypeRef,
- ConstantVals: *const ValueRef,
- Length: c_uint)
- -> ValueRef;
- pub fn LLVMConstVector(ScalarConstantVals: *const ValueRef, Size: c_uint)
- -> ValueRef;
-
- /* Constant expressions */
- pub fn LLVMAlignOf(Ty: TypeRef) -> ValueRef;
- pub fn LLVMSizeOf(Ty: TypeRef) -> ValueRef;
- pub fn LLVMConstNeg(ConstantVal: ValueRef) -> ValueRef;
- pub fn LLVMConstNSWNeg(ConstantVal: ValueRef) -> ValueRef;
- pub fn LLVMConstNUWNeg(ConstantVal: ValueRef) -> ValueRef;
- pub fn LLVMConstFNeg(ConstantVal: ValueRef) -> ValueRef;
- pub fn LLVMConstNot(ConstantVal: ValueRef) -> ValueRef;
- pub fn LLVMConstAdd(LHSConstant: ValueRef, RHSConstant: ValueRef)
- -> ValueRef;
- pub fn LLVMConstNSWAdd(LHSConstant: ValueRef, RHSConstant: ValueRef)
- -> ValueRef;
- pub fn LLVMConstNUWAdd(LHSConstant: ValueRef, RHSConstant: ValueRef)
- -> ValueRef;
- pub fn LLVMConstFAdd(LHSConstant: ValueRef, RHSConstant: ValueRef)
- -> ValueRef;
- pub fn LLVMConstSub(LHSConstant: ValueRef, RHSConstant: ValueRef)
- -> ValueRef;
- pub fn LLVMConstNSWSub(LHSConstant: ValueRef, RHSConstant: ValueRef)
- -> ValueRef;
- pub fn LLVMConstNUWSub(LHSConstant: ValueRef, RHSConstant: ValueRef)
- -> ValueRef;
- pub fn LLVMConstFSub(LHSConstant: ValueRef, RHSConstant: ValueRef)
- -> ValueRef;
- pub fn LLVMConstMul(LHSConstant: ValueRef, RHSConstant: ValueRef)
- -> ValueRef;
- pub fn LLVMConstNSWMul(LHSConstant: ValueRef, RHSConstant: ValueRef)
- -> ValueRef;
- pub fn LLVMConstNUWMul(LHSConstant: ValueRef, RHSConstant: ValueRef)
- -> ValueRef;
- pub fn LLVMConstFMul(LHSConstant: ValueRef, RHSConstant: ValueRef)
- -> ValueRef;
- pub fn LLVMConstUDiv(LHSConstant: ValueRef, RHSConstant: ValueRef)
- -> ValueRef;
- pub fn LLVMConstSDiv(LHSConstant: ValueRef, RHSConstant: ValueRef)
- -> ValueRef;
- pub fn LLVMConstExactSDiv(LHSConstant: ValueRef,
- RHSConstant: ValueRef)
- -> ValueRef;
- pub fn LLVMConstFDiv(LHSConstant: ValueRef, RHSConstant: ValueRef)
- -> ValueRef;
- pub fn LLVMConstURem(LHSConstant: ValueRef, RHSConstant: ValueRef)
- -> ValueRef;
- pub fn LLVMConstSRem(LHSConstant: ValueRef, RHSConstant: ValueRef)
- -> ValueRef;
- pub fn LLVMConstFRem(LHSConstant: ValueRef, RHSConstant: ValueRef)
- -> ValueRef;
- pub fn LLVMConstAnd(LHSConstant: ValueRef, RHSConstant: ValueRef)
- -> ValueRef;
- pub fn LLVMConstOr(LHSConstant: ValueRef, RHSConstant: ValueRef)
- -> ValueRef;
- pub fn LLVMConstXor(LHSConstant: ValueRef, RHSConstant: ValueRef)
- -> ValueRef;
- pub fn LLVMConstShl(LHSConstant: ValueRef, RHSConstant: ValueRef)
- -> ValueRef;
- pub fn LLVMConstLShr(LHSConstant: ValueRef, RHSConstant: ValueRef)
- -> ValueRef;
- pub fn LLVMConstAShr(LHSConstant: ValueRef, RHSConstant: ValueRef)
- -> ValueRef;
- pub fn LLVMConstGEP(ConstantVal: ValueRef,
- ConstantIndices: *const ValueRef,
- NumIndices: c_uint)
- -> ValueRef;
- pub fn LLVMConstInBoundsGEP(ConstantVal: ValueRef,
- ConstantIndices: *const ValueRef,
- NumIndices: c_uint)
- -> ValueRef;
- pub fn LLVMConstTrunc(ConstantVal: ValueRef, ToType: TypeRef)
- -> ValueRef;
- pub fn LLVMConstSExt(ConstantVal: ValueRef, ToType: TypeRef)
- -> ValueRef;
- pub fn LLVMConstZExt(ConstantVal: ValueRef, ToType: TypeRef)
- -> ValueRef;
- pub fn LLVMConstFPTrunc(ConstantVal: ValueRef, ToType: TypeRef)
- -> ValueRef;
- pub fn LLVMConstFPExt(ConstantVal: ValueRef, ToType: TypeRef)
- -> ValueRef;
- pub fn LLVMConstUIToFP(ConstantVal: ValueRef, ToType: TypeRef)
- -> ValueRef;
- pub fn LLVMConstSIToFP(ConstantVal: ValueRef, ToType: TypeRef)
- -> ValueRef;
- pub fn LLVMConstFPToUI(ConstantVal: ValueRef, ToType: TypeRef)
- -> ValueRef;
- pub fn LLVMConstFPToSI(ConstantVal: ValueRef, ToType: TypeRef)
- -> ValueRef;
- pub fn LLVMConstPtrToInt(ConstantVal: ValueRef, ToType: TypeRef)
- -> ValueRef;
- pub fn LLVMConstIntToPtr(ConstantVal: ValueRef, ToType: TypeRef)
- -> ValueRef;
- pub fn LLVMConstBitCast(ConstantVal: ValueRef, ToType: TypeRef)
- -> ValueRef;
- pub fn LLVMConstZExtOrBitCast(ConstantVal: ValueRef, ToType: TypeRef)
- -> ValueRef;
- pub fn LLVMConstSExtOrBitCast(ConstantVal: ValueRef, ToType: TypeRef)
- -> ValueRef;
- pub fn LLVMConstTruncOrBitCast(ConstantVal: ValueRef, ToType: TypeRef)
- -> ValueRef;
- pub fn LLVMConstPointerCast(ConstantVal: ValueRef, ToType: TypeRef)
- -> ValueRef;
- pub fn LLVMConstIntCast(ConstantVal: ValueRef,
- ToType: TypeRef,
- isSigned: Bool)
- -> ValueRef;
- pub fn LLVMConstFPCast(ConstantVal: ValueRef, ToType: TypeRef)
- -> ValueRef;
- pub fn LLVMConstSelect(ConstantCondition: ValueRef,
- ConstantIfTrue: ValueRef,
- ConstantIfFalse: ValueRef)
- -> ValueRef;
- pub fn LLVMConstExtractElement(VectorConstant: ValueRef,
- IndexConstant: ValueRef)
- -> ValueRef;
- pub fn LLVMConstInsertElement(VectorConstant: ValueRef,
- ElementValueConstant: ValueRef,
- IndexConstant: ValueRef)
- -> ValueRef;
- pub fn LLVMConstShuffleVector(VectorAConstant: ValueRef,
- VectorBConstant: ValueRef,
- MaskConstant: ValueRef)
- -> ValueRef;
- pub fn LLVMConstExtractValue(AggConstant: ValueRef,
- IdxList: *const c_uint,
- NumIdx: c_uint)
- -> ValueRef;
- pub fn LLVMConstInsertValue(AggConstant: ValueRef,
- ElementValueConstant: ValueRef,
- IdxList: *const c_uint,
- NumIdx: c_uint)
- -> ValueRef;
- pub fn LLVMConstInlineAsm(Ty: TypeRef,
- AsmString: *const c_char,
- Constraints: *const c_char,
- HasSideEffects: Bool,
- IsAlignStack: Bool)
- -> ValueRef;
- pub fn LLVMBlockAddress(F: ValueRef, BB: BasicBlockRef) -> ValueRef;
-
-
-
- /* Operations on global variables, functions, and aliases (globals) */
- pub fn LLVMGetGlobalParent(Global: ValueRef) -> ModuleRef;
- pub fn LLVMIsDeclaration(Global: ValueRef) -> Bool;
- pub fn LLVMGetLinkage(Global: ValueRef) -> c_uint;
- pub fn LLVMSetLinkage(Global: ValueRef, Link: c_uint);
- pub fn LLVMGetSection(Global: ValueRef) -> *const c_char;
- pub fn LLVMSetSection(Global: ValueRef, Section: *const c_char);
- pub fn LLVMGetVisibility(Global: ValueRef) -> c_uint;
- pub fn LLVMSetVisibility(Global: ValueRef, Viz: c_uint);
- pub fn LLVMGetAlignment(Global: ValueRef) -> c_uint;
- pub fn LLVMSetAlignment(Global: ValueRef, Bytes: c_uint);
-
-
- /* Operations on global variables */
- pub fn LLVMIsAGlobalVariable(GlobalVar: ValueRef) -> ValueRef;
- pub fn LLVMAddGlobal(M: ModuleRef, Ty: TypeRef, Name: *const c_char)
- -> ValueRef;
- pub fn LLVMAddGlobalInAddressSpace(M: ModuleRef,
- Ty: TypeRef,
- Name: *const c_char,
- AddressSpace: c_uint)
- -> ValueRef;
- pub fn LLVMGetNamedGlobal(M: ModuleRef, Name: *const c_char) -> ValueRef;
- pub fn LLVMGetOrInsertGlobal(M: ModuleRef, Name: *const c_char, T: TypeRef) -> ValueRef;
- pub fn LLVMGetFirstGlobal(M: ModuleRef) -> ValueRef;
- pub fn LLVMGetLastGlobal(M: ModuleRef) -> ValueRef;
- pub fn LLVMGetNextGlobal(GlobalVar: ValueRef) -> ValueRef;
- pub fn LLVMGetPreviousGlobal(GlobalVar: ValueRef) -> ValueRef;
- pub fn LLVMDeleteGlobal(GlobalVar: ValueRef);
- pub fn LLVMGetInitializer(GlobalVar: ValueRef) -> ValueRef;
- pub fn LLVMSetInitializer(GlobalVar: ValueRef,
- ConstantVal: ValueRef);
- pub fn LLVMIsThreadLocal(GlobalVar: ValueRef) -> Bool;
- pub fn LLVMSetThreadLocal(GlobalVar: ValueRef, IsThreadLocal: Bool);
- pub fn LLVMIsGlobalConstant(GlobalVar: ValueRef) -> Bool;
- pub fn LLVMSetGlobalConstant(GlobalVar: ValueRef, IsConstant: Bool);
- pub fn LLVMGetNamedValue(M: ModuleRef, Name: *const c_char) -> ValueRef;
-
- /* Operations on aliases */
- pub fn LLVMAddAlias(M: ModuleRef,
- Ty: TypeRef,
- Aliasee: ValueRef,
- Name: *const c_char)
- -> ValueRef;
-
- /* Operations on functions */
- pub fn LLVMAddFunction(M: ModuleRef,
- Name: *const c_char,
- FunctionTy: TypeRef)
- -> ValueRef;
- pub fn LLVMGetNamedFunction(M: ModuleRef, Name: *const c_char) -> ValueRef;
- pub fn LLVMGetFirstFunction(M: ModuleRef) -> ValueRef;
- pub fn LLVMGetLastFunction(M: ModuleRef) -> ValueRef;
- pub fn LLVMGetNextFunction(Fn: ValueRef) -> ValueRef;
- pub fn LLVMGetPreviousFunction(Fn: ValueRef) -> ValueRef;
- pub fn LLVMDeleteFunction(Fn: ValueRef);
- pub fn LLVMGetOrInsertFunction(M: ModuleRef,
- Name: *const c_char,
- FunctionTy: TypeRef)
- -> ValueRef;
- pub fn LLVMGetIntrinsicID(Fn: ValueRef) -> c_uint;
- pub fn LLVMGetFunctionCallConv(Fn: ValueRef) -> c_uint;
- pub fn LLVMSetFunctionCallConv(Fn: ValueRef, CC: c_uint);
- pub fn LLVMGetGC(Fn: ValueRef) -> *const c_char;
- pub fn LLVMSetGC(Fn: ValueRef, Name: *const c_char);
- pub fn LLVMAddDereferenceableAttr(Fn: ValueRef, index: c_uint, bytes: uint64_t);
- pub fn LLVMAddFunctionAttribute(Fn: ValueRef, index: c_uint, PA: uint64_t);
- pub fn LLVMAddFunctionAttrString(Fn: ValueRef, index: c_uint, Name: *const c_char);
- pub fn LLVMAddFunctionAttrStringValue(Fn: ValueRef, index: c_uint,
- Name: *const c_char,
- Value: *const c_char);
- pub fn LLVMRemoveFunctionAttributes(Fn: ValueRef, index: c_uint, attr: uint64_t);
- pub fn LLVMRemoveFunctionAttrString(Fn: ValueRef, index: c_uint, Name: *const c_char);
- pub fn LLVMGetFunctionAttr(Fn: ValueRef) -> c_uint;
- pub fn LLVMRemoveFunctionAttr(Fn: ValueRef, val: c_uint);
-
- /* Operations on parameters */
- pub fn LLVMCountParams(Fn: ValueRef) -> c_uint;
- pub fn LLVMGetParams(Fn: ValueRef, Params: *const ValueRef);
- pub fn LLVMGetParam(Fn: ValueRef, Index: c_uint) -> ValueRef;
- pub fn LLVMGetParamParent(Inst: ValueRef) -> ValueRef;
- pub fn LLVMGetFirstParam(Fn: ValueRef) -> ValueRef;
- pub fn LLVMGetLastParam(Fn: ValueRef) -> ValueRef;
- pub fn LLVMGetNextParam(Arg: ValueRef) -> ValueRef;
- pub fn LLVMGetPreviousParam(Arg: ValueRef) -> ValueRef;
- pub fn LLVMAddAttribute(Arg: ValueRef, PA: c_uint);
- pub fn LLVMRemoveAttribute(Arg: ValueRef, PA: c_uint);
- pub fn LLVMGetAttribute(Arg: ValueRef) -> c_uint;
- pub fn LLVMSetParamAlignment(Arg: ValueRef, align: c_uint);
-
- /* Operations on basic blocks */
- pub fn LLVMBasicBlockAsValue(BB: BasicBlockRef) -> ValueRef;
- pub fn LLVMValueIsBasicBlock(Val: ValueRef) -> Bool;
- pub fn LLVMValueAsBasicBlock(Val: ValueRef) -> BasicBlockRef;
- pub fn LLVMGetBasicBlockParent(BB: BasicBlockRef) -> ValueRef;
- pub fn LLVMCountBasicBlocks(Fn: ValueRef) -> c_uint;
- pub fn LLVMGetBasicBlocks(Fn: ValueRef, BasicBlocks: *const ValueRef);
- pub fn LLVMGetFirstBasicBlock(Fn: ValueRef) -> BasicBlockRef;
- pub fn LLVMGetLastBasicBlock(Fn: ValueRef) -> BasicBlockRef;
- pub fn LLVMGetNextBasicBlock(BB: BasicBlockRef) -> BasicBlockRef;
- pub fn LLVMGetPreviousBasicBlock(BB: BasicBlockRef) -> BasicBlockRef;
- pub fn LLVMGetEntryBasicBlock(Fn: ValueRef) -> BasicBlockRef;
-
- pub fn LLVMAppendBasicBlockInContext(C: ContextRef,
- Fn: ValueRef,
- Name: *const c_char)
- -> BasicBlockRef;
- pub fn LLVMInsertBasicBlockInContext(C: ContextRef,
- BB: BasicBlockRef,
- Name: *const c_char)
- -> BasicBlockRef;
- pub fn LLVMDeleteBasicBlock(BB: BasicBlockRef);
-
- pub fn LLVMMoveBasicBlockAfter(BB: BasicBlockRef,
- MoveAfter: BasicBlockRef);
-
- pub fn LLVMMoveBasicBlockBefore(BB: BasicBlockRef,
- MoveBefore: BasicBlockRef);
-
- /* Operations on instructions */
- pub fn LLVMGetInstructionParent(Inst: ValueRef) -> BasicBlockRef;
- pub fn LLVMGetFirstInstruction(BB: BasicBlockRef) -> ValueRef;
- pub fn LLVMGetLastInstruction(BB: BasicBlockRef) -> ValueRef;
- pub fn LLVMGetNextInstruction(Inst: ValueRef) -> ValueRef;
- pub fn LLVMGetPreviousInstruction(Inst: ValueRef) -> ValueRef;
- pub fn LLVMInstructionEraseFromParent(Inst: ValueRef);
-
- /* Operations on call sites */
- pub fn LLVMSetInstructionCallConv(Instr: ValueRef, CC: c_uint);
- pub fn LLVMGetInstructionCallConv(Instr: ValueRef) -> c_uint;
- pub fn LLVMAddInstrAttribute(Instr: ValueRef,
- index: c_uint,
- IA: c_uint);
- pub fn LLVMRemoveInstrAttribute(Instr: ValueRef,
- index: c_uint,
- IA: c_uint);
- pub fn LLVMSetInstrParamAlignment(Instr: ValueRef,
- index: c_uint,
- align: c_uint);
- pub fn LLVMAddCallSiteAttribute(Instr: ValueRef,
- index: c_uint,
- Val: uint64_t);
- pub fn LLVMAddDereferenceableCallSiteAttr(Instr: ValueRef,
- index: c_uint,
- bytes: uint64_t);
-
- /* Operations on call instructions (only) */
- pub fn LLVMIsTailCall(CallInst: ValueRef) -> Bool;
- pub fn LLVMSetTailCall(CallInst: ValueRef, IsTailCall: Bool);
-
- /* Operations on load/store instructions (only) */
- pub fn LLVMGetVolatile(MemoryAccessInst: ValueRef) -> Bool;
- pub fn LLVMSetVolatile(MemoryAccessInst: ValueRef, volatile: Bool);
-
- /* Operations on phi nodes */
- pub fn LLVMAddIncoming(PhiNode: ValueRef,
- IncomingValues: *const ValueRef,
- IncomingBlocks: *const BasicBlockRef,
- Count: c_uint);
- pub fn LLVMCountIncoming(PhiNode: ValueRef) -> c_uint;
- pub fn LLVMGetIncomingValue(PhiNode: ValueRef, Index: c_uint)
- -> ValueRef;
- pub fn LLVMGetIncomingBlock(PhiNode: ValueRef, Index: c_uint)
- -> BasicBlockRef;
-
- /* Instruction builders */
- pub fn LLVMCreateBuilderInContext(C: ContextRef) -> BuilderRef;
- pub fn LLVMPositionBuilder(Builder: BuilderRef,
- Block: BasicBlockRef,
- Instr: ValueRef);
- pub fn LLVMPositionBuilderBefore(Builder: BuilderRef,
- Instr: ValueRef);
- pub fn LLVMPositionBuilderAtEnd(Builder: BuilderRef,
- Block: BasicBlockRef);
- pub fn LLVMGetInsertBlock(Builder: BuilderRef) -> BasicBlockRef;
- pub fn LLVMClearInsertionPosition(Builder: BuilderRef);
- pub fn LLVMInsertIntoBuilder(Builder: BuilderRef, Instr: ValueRef);
- pub fn LLVMInsertIntoBuilderWithName(Builder: BuilderRef,
- Instr: ValueRef,
- Name: *const c_char);
- pub fn LLVMDisposeBuilder(Builder: BuilderRef);
-
- /* Execution engine */
- pub fn LLVMBuildExecutionEngine(Mod: ModuleRef) -> ExecutionEngineRef;
- pub fn LLVMDisposeExecutionEngine(EE: ExecutionEngineRef);
- pub fn LLVMExecutionEngineFinalizeObject(EE: ExecutionEngineRef);
- pub fn LLVMRustLoadDynamicLibrary(path: *const c_char) -> Bool;
- pub fn LLVMExecutionEngineAddModule(EE: ExecutionEngineRef, M: ModuleRef);
- pub fn LLVMExecutionEngineRemoveModule(EE: ExecutionEngineRef, M: ModuleRef)
- -> Bool;
-
- /* Metadata */
- pub fn LLVMSetCurrentDebugLocation(Builder: BuilderRef, L: ValueRef);
- pub fn LLVMGetCurrentDebugLocation(Builder: BuilderRef) -> ValueRef;
- pub fn LLVMSetInstDebugLocation(Builder: BuilderRef, Inst: ValueRef);
-
- /* Terminators */
- pub fn LLVMBuildRetVoid(B: BuilderRef) -> ValueRef;
- pub fn LLVMBuildRet(B: BuilderRef, V: ValueRef) -> ValueRef;
- pub fn LLVMBuildAggregateRet(B: BuilderRef,
- RetVals: *const ValueRef,
- N: c_uint)
- -> ValueRef;
- pub fn LLVMBuildBr(B: BuilderRef, Dest: BasicBlockRef) -> ValueRef;
- pub fn LLVMBuildCondBr(B: BuilderRef,
- If: ValueRef,
- Then: BasicBlockRef,
- Else: BasicBlockRef)
- -> ValueRef;
- pub fn LLVMBuildSwitch(B: BuilderRef,
- V: ValueRef,
- Else: BasicBlockRef,
- NumCases: c_uint)
- -> ValueRef;
- pub fn LLVMBuildIndirectBr(B: BuilderRef,
- Addr: ValueRef,
- NumDests: c_uint)
- -> ValueRef;
- pub fn LLVMRustBuildInvoke(B: BuilderRef,
- Fn: ValueRef,
- Args: *const ValueRef,
- NumArgs: c_uint,
- Then: BasicBlockRef,
- Catch: BasicBlockRef,
- Bundle: OperandBundleDefRef,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMRustBuildLandingPad(B: BuilderRef,
- Ty: TypeRef,
- PersFn: ValueRef,
- NumClauses: c_uint,
- Name: *const c_char,
- F: ValueRef)
- -> ValueRef;
- pub fn LLVMBuildResume(B: BuilderRef, Exn: ValueRef) -> ValueRef;
- pub fn LLVMBuildUnreachable(B: BuilderRef) -> ValueRef;
-
- pub fn LLVMRustBuildCleanupPad(B: BuilderRef,
- ParentPad: ValueRef,
- ArgCnt: c_uint,
- Args: *const ValueRef,
- Name: *const c_char) -> ValueRef;
- pub fn LLVMRustBuildCleanupRet(B: BuilderRef,
- CleanupPad: ValueRef,
- UnwindBB: BasicBlockRef) -> ValueRef;
- pub fn LLVMRustBuildCatchPad(B: BuilderRef,
- ParentPad: ValueRef,
- ArgCnt: c_uint,
- Args: *const ValueRef,
- Name: *const c_char) -> ValueRef;
- pub fn LLVMRustBuildCatchRet(B: BuilderRef,
- Pad: ValueRef,
- BB: BasicBlockRef) -> ValueRef;
- pub fn LLVMRustBuildCatchSwitch(Builder: BuilderRef,
- ParentPad: ValueRef,
- BB: BasicBlockRef,
- NumHandlers: c_uint,
- Name: *const c_char) -> ValueRef;
- pub fn LLVMRustAddHandler(CatchSwitch: ValueRef,
- Handler: BasicBlockRef);
- pub fn LLVMRustSetPersonalityFn(B: BuilderRef, Pers: ValueRef);
-
- /* Add a case to the switch instruction */
- pub fn LLVMAddCase(Switch: ValueRef,
- OnVal: ValueRef,
- Dest: BasicBlockRef);
-
- /* Add a destination to the indirectbr instruction */
- pub fn LLVMAddDestination(IndirectBr: ValueRef, Dest: BasicBlockRef);
-
- /* Add a clause to the landing pad instruction */
- pub fn LLVMAddClause(LandingPad: ValueRef, ClauseVal: ValueRef);
-
- /* Set the cleanup on a landing pad instruction */
- pub fn LLVMSetCleanup(LandingPad: ValueRef, Val: Bool);
-
- /* Arithmetic */
- pub fn LLVMBuildAdd(B: BuilderRef,
- LHS: ValueRef,
- RHS: ValueRef,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildNSWAdd(B: BuilderRef,
- LHS: ValueRef,
- RHS: ValueRef,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildNUWAdd(B: BuilderRef,
- LHS: ValueRef,
- RHS: ValueRef,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildFAdd(B: BuilderRef,
- LHS: ValueRef,
- RHS: ValueRef,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildSub(B: BuilderRef,
- LHS: ValueRef,
- RHS: ValueRef,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildNSWSub(B: BuilderRef,
- LHS: ValueRef,
- RHS: ValueRef,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildNUWSub(B: BuilderRef,
- LHS: ValueRef,
- RHS: ValueRef,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildFSub(B: BuilderRef,
- LHS: ValueRef,
- RHS: ValueRef,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildMul(B: BuilderRef,
- LHS: ValueRef,
- RHS: ValueRef,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildNSWMul(B: BuilderRef,
- LHS: ValueRef,
- RHS: ValueRef,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildNUWMul(B: BuilderRef,
- LHS: ValueRef,
- RHS: ValueRef,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildFMul(B: BuilderRef,
- LHS: ValueRef,
- RHS: ValueRef,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildUDiv(B: BuilderRef,
- LHS: ValueRef,
- RHS: ValueRef,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildSDiv(B: BuilderRef,
- LHS: ValueRef,
- RHS: ValueRef,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildExactSDiv(B: BuilderRef,
- LHS: ValueRef,
- RHS: ValueRef,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildFDiv(B: BuilderRef,
- LHS: ValueRef,
- RHS: ValueRef,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildURem(B: BuilderRef,
- LHS: ValueRef,
- RHS: ValueRef,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildSRem(B: BuilderRef,
- LHS: ValueRef,
- RHS: ValueRef,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildFRem(B: BuilderRef,
- LHS: ValueRef,
- RHS: ValueRef,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildShl(B: BuilderRef,
- LHS: ValueRef,
- RHS: ValueRef,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildLShr(B: BuilderRef,
- LHS: ValueRef,
- RHS: ValueRef,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildAShr(B: BuilderRef,
- LHS: ValueRef,
- RHS: ValueRef,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildAnd(B: BuilderRef,
- LHS: ValueRef,
- RHS: ValueRef,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildOr(B: BuilderRef,
- LHS: ValueRef,
- RHS: ValueRef,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildXor(B: BuilderRef,
- LHS: ValueRef,
- RHS: ValueRef,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildBinOp(B: BuilderRef,
- Op: Opcode,
- LHS: ValueRef,
- RHS: ValueRef,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildNeg(B: BuilderRef, V: ValueRef, Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildNSWNeg(B: BuilderRef, V: ValueRef, Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildNUWNeg(B: BuilderRef, V: ValueRef, Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildFNeg(B: BuilderRef, V: ValueRef, Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildNot(B: BuilderRef, V: ValueRef, Name: *const c_char)
- -> ValueRef;
- pub fn LLVMRustSetHasUnsafeAlgebra(Instr: ValueRef);
-
- /* Memory */
- pub fn LLVMBuildAlloca(B: BuilderRef, Ty: TypeRef, Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildFree(B: BuilderRef, PointerVal: ValueRef) -> ValueRef;
- pub fn LLVMBuildLoad(B: BuilderRef,
- PointerVal: ValueRef,
- Name: *const c_char)
- -> ValueRef;
-
- pub fn LLVMBuildStore(B: BuilderRef, Val: ValueRef, Ptr: ValueRef)
- -> ValueRef;
-
- pub fn LLVMBuildGEP(B: BuilderRef,
- Pointer: ValueRef,
- Indices: *const ValueRef,
- NumIndices: c_uint,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildInBoundsGEP(B: BuilderRef,
- Pointer: ValueRef,
- Indices: *const ValueRef,
- NumIndices: c_uint,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildStructGEP(B: BuilderRef,
- Pointer: ValueRef,
- Idx: c_uint,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildGlobalString(B: BuilderRef,
- Str: *const c_char,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildGlobalStringPtr(B: BuilderRef,
- Str: *const c_char,
- Name: *const c_char)
- -> ValueRef;
-
- /* Casts */
- pub fn LLVMBuildTrunc(B: BuilderRef,
- Val: ValueRef,
- DestTy: TypeRef,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildZExt(B: BuilderRef,
- Val: ValueRef,
- DestTy: TypeRef,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildSExt(B: BuilderRef,
- Val: ValueRef,
- DestTy: TypeRef,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildFPToUI(B: BuilderRef,
- Val: ValueRef,
- DestTy: TypeRef,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildFPToSI(B: BuilderRef,
- Val: ValueRef,
- DestTy: TypeRef,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildUIToFP(B: BuilderRef,
- Val: ValueRef,
- DestTy: TypeRef,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildSIToFP(B: BuilderRef,
- Val: ValueRef,
- DestTy: TypeRef,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildFPTrunc(B: BuilderRef,
- Val: ValueRef,
- DestTy: TypeRef,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildFPExt(B: BuilderRef,
- Val: ValueRef,
- DestTy: TypeRef,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildPtrToInt(B: BuilderRef,
- Val: ValueRef,
- DestTy: TypeRef,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildIntToPtr(B: BuilderRef,
- Val: ValueRef,
- DestTy: TypeRef,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildBitCast(B: BuilderRef,
- Val: ValueRef,
- DestTy: TypeRef,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildZExtOrBitCast(B: BuilderRef,
- Val: ValueRef,
- DestTy: TypeRef,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildSExtOrBitCast(B: BuilderRef,
- Val: ValueRef,
- DestTy: TypeRef,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildTruncOrBitCast(B: BuilderRef,
- Val: ValueRef,
- DestTy: TypeRef,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildCast(B: BuilderRef,
- Op: Opcode,
- Val: ValueRef,
- DestTy: TypeRef,
- Name: *const c_char) -> ValueRef;
- pub fn LLVMBuildPointerCast(B: BuilderRef,
- Val: ValueRef,
- DestTy: TypeRef,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildIntCast(B: BuilderRef,
- Val: ValueRef,
- DestTy: TypeRef,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildFPCast(B: BuilderRef,
- Val: ValueRef,
- DestTy: TypeRef,
- Name: *const c_char)
- -> ValueRef;
-
- /* Comparisons */
- pub fn LLVMBuildICmp(B: BuilderRef,
- Op: c_uint,
- LHS: ValueRef,
- RHS: ValueRef,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildFCmp(B: BuilderRef,
- Op: c_uint,
- LHS: ValueRef,
- RHS: ValueRef,
- Name: *const c_char)
- -> ValueRef;
-
- /* Miscellaneous instructions */
- pub fn LLVMBuildPhi(B: BuilderRef, Ty: TypeRef, Name: *const c_char)
- -> ValueRef;
- pub fn LLVMRustBuildCall(B: BuilderRef,
- Fn: ValueRef,
- Args: *const ValueRef,
- NumArgs: c_uint,
- Bundle: OperandBundleDefRef,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildSelect(B: BuilderRef,
- If: ValueRef,
- Then: ValueRef,
- Else: ValueRef,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildVAArg(B: BuilderRef,
- list: ValueRef,
- Ty: TypeRef,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildExtractElement(B: BuilderRef,
- VecVal: ValueRef,
- Index: ValueRef,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildInsertElement(B: BuilderRef,
- VecVal: ValueRef,
- EltVal: ValueRef,
- Index: ValueRef,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildShuffleVector(B: BuilderRef,
- V1: ValueRef,
- V2: ValueRef,
- Mask: ValueRef,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildExtractValue(B: BuilderRef,
- AggVal: ValueRef,
- Index: c_uint,
- Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildInsertValue(B: BuilderRef,
- AggVal: ValueRef,
- EltVal: ValueRef,
- Index: c_uint,
- Name: *const c_char)
- -> ValueRef;
-
- pub fn LLVMBuildIsNull(B: BuilderRef, Val: ValueRef, Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildIsNotNull(B: BuilderRef, Val: ValueRef, Name: *const c_char)
- -> ValueRef;
- pub fn LLVMBuildPtrDiff(B: BuilderRef,
- LHS: ValueRef,
- RHS: ValueRef,
- Name: *const c_char)
- -> ValueRef;
-
- /* Atomic Operations */
- pub fn LLVMBuildAtomicLoad(B: BuilderRef,
- PointerVal: ValueRef,
- Name: *const c_char,
- Order: AtomicOrdering,
- Alignment: c_uint)
- -> ValueRef;
-
- pub fn LLVMBuildAtomicStore(B: BuilderRef,
- Val: ValueRef,
- Ptr: ValueRef,
- Order: AtomicOrdering,
- Alignment: c_uint)
- -> ValueRef;
-
- pub fn LLVMBuildAtomicCmpXchg(B: BuilderRef,
- LHS: ValueRef,
- CMP: ValueRef,
- RHS: ValueRef,
- Order: AtomicOrdering,
- FailureOrder: AtomicOrdering,
- Weak: Bool)
- -> ValueRef;
- pub fn LLVMBuildAtomicRMW(B: BuilderRef,
- Op: AtomicBinOp,
- LHS: ValueRef,
- RHS: ValueRef,
- Order: AtomicOrdering,
- SingleThreaded: Bool)
- -> ValueRef;
-
- pub fn LLVMBuildAtomicFence(B: BuilderRef,
- Order: AtomicOrdering,
- Scope: SynchronizationScope);
-
-
- /* Selected entries from the downcasts. */
- pub fn LLVMIsATerminatorInst(Inst: ValueRef) -> ValueRef;
- pub fn LLVMIsAStoreInst(Inst: ValueRef) -> ValueRef;
-
- /// Writes a module to the specified path. Returns 0 on success.
- pub fn LLVMWriteBitcodeToFile(M: ModuleRef, Path: *const c_char) -> c_int;
-
- /// Creates target data from a target layout string.
- pub fn LLVMCreateTargetData(StringRep: *const c_char) -> TargetDataRef;
- /// Adds the target data to the given pass manager. The pass manager
- /// references the target data only weakly.
- pub fn LLVMAddTargetData(TD: TargetDataRef, PM: PassManagerRef);
- /// Number of bytes clobbered when doing a Store to *T.
- pub fn LLVMStoreSizeOfType(TD: TargetDataRef, Ty: TypeRef)
- -> c_ulonglong;
-
- /// Number of bytes clobbered when doing a Store to *T.
- pub fn LLVMSizeOfTypeInBits(TD: TargetDataRef, Ty: TypeRef)
- -> c_ulonglong;
-
- /// Distance between successive elements in an array of T. Includes ABI padding.
- pub fn LLVMABISizeOfType(TD: TargetDataRef, Ty: TypeRef) -> c_ulonglong;
-
- /// Returns the preferred alignment of a type.
- pub fn LLVMPreferredAlignmentOfType(TD: TargetDataRef, Ty: TypeRef)
- -> c_uint;
- /// Returns the minimum alignment of a type.
- pub fn LLVMABIAlignmentOfType(TD: TargetDataRef, Ty: TypeRef)
- -> c_uint;
-
- /// Computes the byte offset of the indexed struct element for a
- /// target.
- pub fn LLVMOffsetOfElement(TD: TargetDataRef,
- StructTy: TypeRef,
- Element: c_uint)
- -> c_ulonglong;
-
- /// Returns the minimum alignment of a type when part of a call frame.
- pub fn LLVMCallFrameAlignmentOfType(TD: TargetDataRef, Ty: TypeRef)
- -> c_uint;
-
- /// Disposes target data.
- pub fn LLVMDisposeTargetData(TD: TargetDataRef);
-
- /// Creates a pass manager.
- pub fn LLVMCreatePassManager() -> PassManagerRef;
-
- /// Creates a function-by-function pass manager
- pub fn LLVMCreateFunctionPassManagerForModule(M: ModuleRef)
- -> PassManagerRef;
-
- /// Disposes a pass manager.
- pub fn LLVMDisposePassManager(PM: PassManagerRef);
-
- /// Runs a pass manager on a module.
- pub fn LLVMRunPassManager(PM: PassManagerRef, M: ModuleRef) -> Bool;
-
- /// Runs the function passes on the provided function.
- pub fn LLVMRunFunctionPassManager(FPM: PassManagerRef, F: ValueRef)
- -> Bool;
-
- /// Initializes all the function passes scheduled in the manager
- pub fn LLVMInitializeFunctionPassManager(FPM: PassManagerRef) -> Bool;
-
- /// Finalizes all the function passes scheduled in the manager
- pub fn LLVMFinalizeFunctionPassManager(FPM: PassManagerRef) -> Bool;
-
- pub fn LLVMInitializePasses();
-
- /// Adds a verification pass.
- pub fn LLVMAddVerifierPass(PM: PassManagerRef);
-
- pub fn LLVMAddGlobalOptimizerPass(PM: PassManagerRef);
- pub fn LLVMAddIPSCCPPass(PM: PassManagerRef);
- pub fn LLVMAddDeadArgEliminationPass(PM: PassManagerRef);
- pub fn LLVMAddInstructionCombiningPass(PM: PassManagerRef);
- pub fn LLVMAddCFGSimplificationPass(PM: PassManagerRef);
- pub fn LLVMAddFunctionInliningPass(PM: PassManagerRef);
- pub fn LLVMAddFunctionAttrsPass(PM: PassManagerRef);
- pub fn LLVMAddScalarReplAggregatesPass(PM: PassManagerRef);
- pub fn LLVMAddScalarReplAggregatesPassSSA(PM: PassManagerRef);
- pub fn LLVMAddJumpThreadingPass(PM: PassManagerRef);
- pub fn LLVMAddConstantPropagationPass(PM: PassManagerRef);
- pub fn LLVMAddReassociatePass(PM: PassManagerRef);
- pub fn LLVMAddLoopRotatePass(PM: PassManagerRef);
- pub fn LLVMAddLICMPass(PM: PassManagerRef);
- pub fn LLVMAddLoopUnswitchPass(PM: PassManagerRef);
- pub fn LLVMAddLoopDeletionPass(PM: PassManagerRef);
- pub fn LLVMAddLoopUnrollPass(PM: PassManagerRef);
- pub fn LLVMAddGVNPass(PM: PassManagerRef);
- pub fn LLVMAddMemCpyOptPass(PM: PassManagerRef);
- pub fn LLVMAddSCCPPass(PM: PassManagerRef);
- pub fn LLVMAddDeadStoreEliminationPass(PM: PassManagerRef);
- pub fn LLVMAddStripDeadPrototypesPass(PM: PassManagerRef);
- pub fn LLVMAddConstantMergePass(PM: PassManagerRef);
- pub fn LLVMAddArgumentPromotionPass(PM: PassManagerRef);
- pub fn LLVMAddTailCallEliminationPass(PM: PassManagerRef);
- pub fn LLVMAddIndVarSimplifyPass(PM: PassManagerRef);
- pub fn LLVMAddAggressiveDCEPass(PM: PassManagerRef);
- pub fn LLVMAddGlobalDCEPass(PM: PassManagerRef);
- pub fn LLVMAddCorrelatedValuePropagationPass(PM: PassManagerRef);
- pub fn LLVMAddPruneEHPass(PM: PassManagerRef);
- pub fn LLVMAddSimplifyLibCallsPass(PM: PassManagerRef);
- pub fn LLVMAddLoopIdiomPass(PM: PassManagerRef);
- pub fn LLVMAddEarlyCSEPass(PM: PassManagerRef);
- pub fn LLVMAddTypeBasedAliasAnalysisPass(PM: PassManagerRef);
- pub fn LLVMAddBasicAliasAnalysisPass(PM: PassManagerRef);
-
- pub fn LLVMPassManagerBuilderCreate() -> PassManagerBuilderRef;
- pub fn LLVMPassManagerBuilderDispose(PMB: PassManagerBuilderRef);
- pub fn LLVMPassManagerBuilderSetOptLevel(PMB: PassManagerBuilderRef,
- OptimizationLevel: c_uint);
- pub fn LLVMPassManagerBuilderSetSizeLevel(PMB: PassManagerBuilderRef,
- Value: Bool);
- pub fn LLVMPassManagerBuilderSetDisableUnitAtATime(
- PMB: PassManagerBuilderRef,
- Value: Bool);
- pub fn LLVMPassManagerBuilderSetDisableUnrollLoops(
- PMB: PassManagerBuilderRef,
- Value: Bool);
- pub fn LLVMPassManagerBuilderSetDisableSimplifyLibCalls(
- PMB: PassManagerBuilderRef,
- Value: Bool);
- pub fn LLVMPassManagerBuilderUseInlinerWithThreshold(
- PMB: PassManagerBuilderRef,
- threshold: c_uint);
- pub fn LLVMPassManagerBuilderPopulateModulePassManager(
- PMB: PassManagerBuilderRef,
- PM: PassManagerRef);
-
- pub fn LLVMPassManagerBuilderPopulateFunctionPassManager(
- PMB: PassManagerBuilderRef,
- PM: PassManagerRef);
- pub fn LLVMPassManagerBuilderPopulateLTOPassManager(
- PMB: PassManagerBuilderRef,
- PM: PassManagerRef,
- Internalize: Bool,
- RunInliner: Bool);
-
- /// Destroys a memory buffer.
- pub fn LLVMDisposeMemoryBuffer(MemBuf: MemoryBufferRef);
-
-
- /* Stuff that's in rustllvm/ because it's not upstream yet. */
-
- /// Opens an object file.
- pub fn LLVMCreateObjectFile(MemBuf: MemoryBufferRef) -> ObjectFileRef;
- /// Closes an object file.
- pub fn LLVMDisposeObjectFile(ObjFile: ObjectFileRef);
-
- /// Enumerates the sections in an object file.
- pub fn LLVMGetSections(ObjFile: ObjectFileRef) -> SectionIteratorRef;
- /// Destroys a section iterator.
- pub fn LLVMDisposeSectionIterator(SI: SectionIteratorRef);
- /// Returns true if the section iterator is at the end of the section
- /// list:
- pub fn LLVMIsSectionIteratorAtEnd(ObjFile: ObjectFileRef,
- SI: SectionIteratorRef)
- -> Bool;
- /// Moves the section iterator to point to the next section.
- pub fn LLVMMoveToNextSection(SI: SectionIteratorRef);
- /// Returns the current section size.
- pub fn LLVMGetSectionSize(SI: SectionIteratorRef) -> c_ulonglong;
- /// Returns the current section contents as a string buffer.
- pub fn LLVMGetSectionContents(SI: SectionIteratorRef) -> *const c_char;
-
- /// Reads the given file and returns it as a memory buffer. Use
- /// LLVMDisposeMemoryBuffer() to get rid of it.
- pub fn LLVMRustCreateMemoryBufferWithContentsOfFile(Path: *const c_char)
- -> MemoryBufferRef;
- /// Borrows the contents of the memory buffer (doesn't copy it)
- pub fn LLVMCreateMemoryBufferWithMemoryRange(InputData: *const c_char,
- InputDataLength: size_t,
- BufferName: *const c_char,
- RequiresNull: Bool)
- -> MemoryBufferRef;
- pub fn LLVMCreateMemoryBufferWithMemoryRangeCopy(InputData: *const c_char,
- InputDataLength: size_t,
- BufferName: *const c_char)
- -> MemoryBufferRef;
-
- pub fn LLVMIsMultithreaded() -> Bool;
- pub fn LLVMStartMultithreaded() -> Bool;
-
- /// Returns a string describing the last error caused by an LLVMRust* call.
- pub fn LLVMRustGetLastError() -> *const c_char;
-
- /// Print the pass timings since static dtors aren't picking them up.
- pub fn LLVMRustPrintPassTimings();
-
- pub fn LLVMStructCreateNamed(C: ContextRef, Name: *const c_char) -> TypeRef;
-
- pub fn LLVMStructSetBody(StructTy: TypeRef,
- ElementTypes: *const TypeRef,
- ElementCount: c_uint,
- Packed: Bool);
-
- pub fn LLVMConstNamedStruct(S: TypeRef,
- ConstantVals: *const ValueRef,
- Count: c_uint)
- -> ValueRef;
-
- /// Enables LLVM debug output.
- pub fn LLVMSetDebug(Enabled: c_int);
-
- /// Prepares inline assembly.
- pub fn LLVMInlineAsm(Ty: TypeRef,
- AsmString: *const c_char,
- Constraints: *const c_char,
- SideEffects: Bool,
- AlignStack: Bool,
- Dialect: c_uint)
- -> ValueRef;
-
- pub fn LLVMRustDebugMetadataVersion() -> u32;
- pub fn LLVMVersionMajor() -> u32;
- pub fn LLVMVersionMinor() -> u32;
-
- pub fn LLVMRustAddModuleFlag(M: ModuleRef,
- name: *const c_char,
- value: u32);
-
- pub fn LLVMDIBuilderCreate(M: ModuleRef) -> DIBuilderRef;
-
- pub fn LLVMDIBuilderDispose(Builder: DIBuilderRef);
-
- pub fn LLVMDIBuilderFinalize(Builder: DIBuilderRef);
-
- pub fn LLVMDIBuilderCreateCompileUnit(Builder: DIBuilderRef,
- Lang: c_uint,
- File: *const c_char,
- Dir: *const c_char,
- Producer: *const c_char,
- isOptimized: bool,
- Flags: *const c_char,
- RuntimeVer: c_uint,
- SplitName: *const c_char)
- -> DIDescriptor;
-
- pub fn LLVMDIBuilderCreateFile(Builder: DIBuilderRef,
- Filename: *const c_char,
- Directory: *const c_char)
- -> DIFile;
-
- pub fn LLVMDIBuilderCreateSubroutineType(Builder: DIBuilderRef,
- File: DIFile,
- ParameterTypes: DIArray)
- -> DICompositeType;
-
- pub fn LLVMDIBuilderCreateFunction(Builder: DIBuilderRef,
- Scope: DIDescriptor,
- Name: *const c_char,
- LinkageName: *const c_char,
- File: DIFile,
- LineNo: c_uint,
- Ty: DIType,
- isLocalToUnit: bool,
- isDefinition: bool,
- ScopeLine: c_uint,
- Flags: c_uint,
- isOptimized: bool,
- Fn: ValueRef,
- TParam: DIArray,
- Decl: DIDescriptor)
- -> DISubprogram;
-
- pub fn LLVMDIBuilderCreateBasicType(Builder: DIBuilderRef,
- Name: *const c_char,
- SizeInBits: c_ulonglong,
- AlignInBits: c_ulonglong,
- Encoding: c_uint)
- -> DIBasicType;
-
- pub fn LLVMDIBuilderCreatePointerType(Builder: DIBuilderRef,
- PointeeTy: DIType,
- SizeInBits: c_ulonglong,
- AlignInBits: c_ulonglong,
- Name: *const c_char)
- -> DIDerivedType;
-
- pub fn LLVMDIBuilderCreateStructType(Builder: DIBuilderRef,
- Scope: DIDescriptor,
- Name: *const c_char,
- File: DIFile,
- LineNumber: c_uint,
- SizeInBits: c_ulonglong,
- AlignInBits: c_ulonglong,
- Flags: c_uint,
- DerivedFrom: DIType,
- Elements: DIArray,
- RunTimeLang: c_uint,
- VTableHolder: DIType,
- UniqueId: *const c_char)
- -> DICompositeType;
-
- pub fn LLVMDIBuilderCreateMemberType(Builder: DIBuilderRef,
- Scope: DIDescriptor,
- Name: *const c_char,
- File: DIFile,
- LineNo: c_uint,
- SizeInBits: c_ulonglong,
- AlignInBits: c_ulonglong,
- OffsetInBits: c_ulonglong,
- Flags: c_uint,
- Ty: DIType)
- -> DIDerivedType;
-
- pub fn LLVMDIBuilderCreateLexicalBlock(Builder: DIBuilderRef,
- Scope: DIScope,
- File: DIFile,
- Line: c_uint,
- Col: c_uint)
- -> DILexicalBlock;
-
- pub fn LLVMDIBuilderCreateStaticVariable(Builder: DIBuilderRef,
- Context: DIScope,
- Name: *const c_char,
- LinkageName: *const c_char,
- File: DIFile,
- LineNo: c_uint,
- Ty: DIType,
- isLocalToUnit: bool,
- Val: ValueRef,
- Decl: DIDescriptor)
- -> DIGlobalVariable;
-
- pub fn LLVMDIBuilderCreateVariable(Builder: DIBuilderRef,
- Tag: c_uint,
- Scope: DIDescriptor,
- Name: *const c_char,
- File: DIFile,
- LineNo: c_uint,
- Ty: DIType,
- AlwaysPreserve: bool,
- Flags: c_uint,
- AddrOps: *const i64,
- AddrOpsCount: c_uint,
- ArgNo: c_uint)
- -> DIVariable;
-
- pub fn LLVMDIBuilderCreateArrayType(Builder: DIBuilderRef,
- Size: c_ulonglong,
- AlignInBits: c_ulonglong,
- Ty: DIType,
- Subscripts: DIArray)
- -> DIType;
-
- pub fn LLVMDIBuilderCreateVectorType(Builder: DIBuilderRef,
- Size: c_ulonglong,
- AlignInBits: c_ulonglong,
- Ty: DIType,
- Subscripts: DIArray)
- -> DIType;
-
- pub fn LLVMDIBuilderGetOrCreateSubrange(Builder: DIBuilderRef,
- Lo: c_longlong,
- Count: c_longlong)
- -> DISubrange;
-
- pub fn LLVMDIBuilderGetOrCreateArray(Builder: DIBuilderRef,
- Ptr: *const DIDescriptor,
- Count: c_uint)
- -> DIArray;
-
- pub fn LLVMDIBuilderInsertDeclareAtEnd(Builder: DIBuilderRef,
- Val: ValueRef,
- VarInfo: DIVariable,
- AddrOps: *const i64,
- AddrOpsCount: c_uint,
- DL: ValueRef,
- InsertAtEnd: BasicBlockRef)
- -> ValueRef;
-
- pub fn LLVMDIBuilderInsertDeclareBefore(Builder: DIBuilderRef,
- Val: ValueRef,
- VarInfo: DIVariable,
- AddrOps: *const i64,
- AddrOpsCount: c_uint,
- DL: ValueRef,
- InsertBefore: ValueRef)
- -> ValueRef;
-
- pub fn LLVMDIBuilderCreateEnumerator(Builder: DIBuilderRef,
- Name: *const c_char,
- Val: c_ulonglong)
- -> DIEnumerator;
-
- pub fn LLVMDIBuilderCreateEnumerationType(Builder: DIBuilderRef,
- Scope: DIScope,
- Name: *const c_char,
- File: DIFile,
- LineNumber: c_uint,
- SizeInBits: c_ulonglong,
- AlignInBits: c_ulonglong,
- Elements: DIArray,
- ClassType: DIType)
- -> DIType;
-
- pub fn LLVMDIBuilderCreateUnionType(Builder: DIBuilderRef,
- Scope: DIScope,
- Name: *const c_char,
- File: DIFile,
- LineNumber: c_uint,
- SizeInBits: c_ulonglong,
- AlignInBits: c_ulonglong,
- Flags: c_uint,
- Elements: DIArray,
- RunTimeLang: c_uint,
- UniqueId: *const c_char)
- -> DIType;
-
- pub fn LLVMSetUnnamedAddr(GlobalVar: ValueRef, UnnamedAddr: Bool);
-
- pub fn LLVMDIBuilderCreateTemplateTypeParameter(Builder: DIBuilderRef,
- Scope: DIScope,
- Name: *const c_char,
- Ty: DIType,
- File: DIFile,
- LineNo: c_uint,
- ColumnNo: c_uint)
- -> DITemplateTypeParameter;
-
- pub fn LLVMDIBuilderCreateOpDeref() -> i64;
-
- pub fn LLVMDIBuilderCreateOpPlus() -> i64;
-
- pub fn LLVMDIBuilderCreateNameSpace(Builder: DIBuilderRef,
- Scope: DIScope,
- Name: *const c_char,
- File: DIFile,
- LineNo: c_uint)
- -> DINameSpace;
-
- pub fn LLVMDIBuilderCreateDebugLocation(Context: ContextRef,
- Line: c_uint,
- Column: c_uint,
- Scope: DIScope,
- InlinedAt: MetadataRef)
- -> ValueRef;
-
- pub fn LLVMDICompositeTypeSetTypeArray(Builder: DIBuilderRef,
- CompositeType: DIType,
- TypeArray: DIArray);
- pub fn LLVMWriteTypeToString(Type: TypeRef, s: RustStringRef);
- pub fn LLVMWriteValueToString(value_ref: ValueRef, s: RustStringRef);
-
- pub fn LLVMIsAArgument(value_ref: ValueRef) -> ValueRef;
-
- pub fn LLVMIsAAllocaInst(value_ref: ValueRef) -> ValueRef;
- pub fn LLVMIsAConstantInt(value_ref: ValueRef) -> ValueRef;
-
- pub fn LLVMRustPassKind(Pass: PassRef) -> SupportedPassKind;
- pub fn LLVMRustFindAndCreatePass(Pass: *const c_char) -> PassRef;
- pub fn LLVMRustAddPass(PM: PassManagerRef, Pass: PassRef);
-
- pub fn LLVMRustHasFeature(T: TargetMachineRef,
- s: *const c_char) -> bool;
-
- pub fn LLVMRustCreateTargetMachine(Triple: *const c_char,
- CPU: *const c_char,
- Features: *const c_char,
- Model: CodeGenModel,
- Reloc: RelocMode,
- Level: CodeGenOptLevel,
- UseSoftFP: bool,
- PositionIndependentExecutable: bool,
- FunctionSections: bool,
- DataSections: bool) -> TargetMachineRef;
- pub fn LLVMRustDisposeTargetMachine(T: TargetMachineRef);
- pub fn LLVMRustAddAnalysisPasses(T: TargetMachineRef,
- PM: PassManagerRef,
- M: ModuleRef);
- pub fn LLVMRustAddBuilderLibraryInfo(PMB: PassManagerBuilderRef,
- M: ModuleRef,
- DisableSimplifyLibCalls: bool);
- pub fn LLVMRustConfigurePassManagerBuilder(PMB: PassManagerBuilderRef,
- OptLevel: CodeGenOptLevel,
- MergeFunctions: bool,
- SLPVectorize: bool,
- LoopVectorize: bool);
- pub fn LLVMRustAddLibraryInfo(PM: PassManagerRef, M: ModuleRef,
- DisableSimplifyLibCalls: bool);
- pub fn LLVMRustRunFunctionPassManager(PM: PassManagerRef, M: ModuleRef);
- pub fn LLVMRustWriteOutputFile(T: TargetMachineRef,
- PM: PassManagerRef,
- M: ModuleRef,
- Output: *const c_char,
- FileType: FileType) -> bool;
- pub fn LLVMRustPrintModule(PM: PassManagerRef,
- M: ModuleRef,
- Output: *const c_char);
- pub fn LLVMRustSetLLVMOptions(Argc: c_int, Argv: *const *const c_char);
- pub fn LLVMRustPrintPasses();
- pub fn LLVMRustSetNormalizedTarget(M: ModuleRef, triple: *const c_char);
- pub fn LLVMRustAddAlwaysInlinePass(P: PassManagerBuilderRef,
- AddLifetimes: bool);
- pub fn LLVMRustLinkInExternalBitcode(M: ModuleRef,
- bc: *const c_char,
- len: size_t) -> bool;
- pub fn LLVMRustRunRestrictionPass(M: ModuleRef,
- syms: *const *const c_char,
- len: size_t);
- pub fn LLVMRustMarkAllFunctionsNounwind(M: ModuleRef);
-
- pub fn LLVMRustOpenArchive(path: *const c_char) -> ArchiveRef;
- pub fn LLVMRustArchiveIteratorNew(AR: ArchiveRef) -> ArchiveIteratorRef;
- pub fn LLVMRustArchiveIteratorNext(AIR: ArchiveIteratorRef) -> ArchiveChildRef;
- pub fn LLVMRustArchiveChildName(ACR: ArchiveChildRef,
- size: *mut size_t) -> *const c_char;
- pub fn LLVMRustArchiveChildData(ACR: ArchiveChildRef,
- size: *mut size_t) -> *const c_char;
- pub fn LLVMRustArchiveChildFree(ACR: ArchiveChildRef);
- pub fn LLVMRustArchiveIteratorFree(AIR: ArchiveIteratorRef);
- pub fn LLVMRustDestroyArchive(AR: ArchiveRef);
-
- pub fn LLVMRustSetDLLStorageClass(V: ValueRef,
- C: DLLStorageClassTypes);
-
- pub fn LLVMRustGetSectionName(SI: SectionIteratorRef,
- data: *mut *const c_char) -> c_int;
-
- pub fn LLVMWriteTwineToString(T: TwineRef, s: RustStringRef);
-
- pub fn LLVMContextSetDiagnosticHandler(C: ContextRef,
- Handler: DiagnosticHandler,
- DiagnosticContext: *mut c_void);
-
- pub fn LLVMUnpackOptimizationDiagnostic(DI: DiagnosticInfoRef,
- pass_name_out: *mut *const c_char,
- function_out: *mut ValueRef,
- debugloc_out: *mut DebugLocRef,
- message_out: *mut TwineRef);
- pub fn LLVMUnpackInlineAsmDiagnostic(DI: DiagnosticInfoRef,
- cookie_out: *mut c_uint,
- message_out: *mut TwineRef,
- instruction_out: *mut ValueRef);
-
- pub fn LLVMWriteDiagnosticInfoToString(DI: DiagnosticInfoRef, s: RustStringRef);
- pub fn LLVMGetDiagInfoSeverity(DI: DiagnosticInfoRef) -> DiagnosticSeverity;
- pub fn LLVMGetDiagInfoKind(DI: DiagnosticInfoRef) -> DiagnosticKind;
-
- pub fn LLVMWriteDebugLocToString(C: ContextRef, DL: DebugLocRef, s: RustStringRef);
-
- pub fn LLVMSetInlineAsmDiagnosticHandler(C: ContextRef,
- H: InlineAsmDiagHandler,
- CX: *mut c_void);
-
- pub fn LLVMWriteSMDiagnosticToString(d: SMDiagnosticRef, s: RustStringRef);
-
- pub fn LLVMRustWriteArchive(Dst: *const c_char,
- NumMembers: size_t,
- Members: *const RustArchiveMemberRef,
- WriteSymbtab: bool,
- Kind: ArchiveKind) -> c_int;
- pub fn LLVMRustArchiveMemberNew(Filename: *const c_char,
- Name: *const c_char,
- Child: ArchiveChildRef) -> RustArchiveMemberRef;
- pub fn LLVMRustArchiveMemberFree(Member: RustArchiveMemberRef);
-
- pub fn LLVMRustSetDataLayoutFromTargetMachine(M: ModuleRef,
- TM: TargetMachineRef);
- pub fn LLVMRustGetModuleDataLayout(M: ModuleRef) -> TargetDataRef;
-
- pub fn LLVMRustBuildOperandBundleDef(Name: *const c_char,
- Inputs: *const ValueRef,
- NumInputs: c_uint)
- -> OperandBundleDefRef;
- pub fn LLVMRustFreeOperandBundleDef(Bundle: OperandBundleDefRef);
-
- pub fn LLVMRustPositionBuilderAtStart(B: BuilderRef, BB: BasicBlockRef);
-
- pub fn LLVMRustSetComdat(M: ModuleRef, V: ValueRef, Name: *const c_char);
- pub fn LLVMRustUnsetComdat(V: ValueRef);
-}
-
-// LLVM requires symbols from this library, but apparently they're not printed
-// during llvm-config?
-#[cfg(windows)]
-#[link(name = "ole32")]
-extern {}
-
pub fn SetInstructionCallConv(instr: ValueRef, cc: CallConv) {
unsafe {
LLVMSetInstructionCallConv(instr, cc as c_uint);
@@ -2173,11 +200,6 @@
LLVMSetFunctionCallConv(fn_, cc as c_uint);
}
}
-pub fn SetLinkage(global: ValueRef, link: Linkage) {
- unsafe {
- LLVMSetLinkage(global, link as c_uint);
- }
-}
// Externally visible symbols that might appear in multiple translation units need to appear in
// their own comdat section so that the duplicates can be discarded at link time. This can for
@@ -2197,12 +219,6 @@
}
}
-pub fn SetDLLStorageClass(global: ValueRef, class: DLLStorageClassTypes) {
- unsafe {
- LLVMRustSetDLLStorageClass(global, class);
- }
-}
-
pub fn SetUnnamedAddr(global: ValueRef, unnamed: bool) {
unsafe {
LLVMSetUnnamedAddr(global, unnamed as Bool);
@@ -2215,29 +231,40 @@
}
}
-pub fn ConstICmp(pred: IntPredicate, v1: ValueRef, v2: ValueRef) -> ValueRef {
- unsafe {
- LLVMConstICmp(pred as c_ushort, v1, v2)
+impl Attribute {
+ pub fn apply_llfn(&self, idx: AttributePlace, llfn: ValueRef) {
+ unsafe {
+ LLVMRustAddFunctionAttribute(
+ llfn, idx.as_uint(), self.bits())
+ }
}
-}
-pub fn ConstFCmp(pred: RealPredicate, v1: ValueRef, v2: ValueRef) -> ValueRef {
- unsafe {
- LLVMConstFCmp(pred as c_ushort, v1, v2)
- }
-}
-pub fn SetFunctionAttribute(fn_: ValueRef, attr: Attribute) {
- unsafe {
- LLVMAddFunctionAttribute(fn_, FunctionIndex as c_uint,
- attr.bits() as uint64_t)
+ pub fn apply_callsite(&self, idx: AttributePlace, callsite: ValueRef) {
+ unsafe {
+ LLVMRustAddCallSiteAttribute(
+ callsite, idx.as_uint(), self.bits())
+ }
}
-}
-pub fn RemoveFunctionAttributes(fn_: ValueRef, attr: Attribute) {
- unsafe {
- LLVMRemoveFunctionAttributes(fn_, FunctionIndex as c_uint,
- attr.bits() as uint64_t)
+ pub fn unapply_llfn(&self, idx: AttributePlace, llfn: ValueRef) {
+ unsafe {
+ LLVMRustRemoveFunctionAttributes(
+ llfn, idx.as_uint(), self.bits())
+ }
}
+
+ pub fn toggle_llfn(&self,
+ idx: AttributePlace,
+ llfn: ValueRef,
+ set: bool)
+ {
+ if set {
+ self.apply_llfn(idx, llfn);
+ } else {
+ self.unapply_llfn(idx, llfn);
+ }
+ }
+
}
/* Memory-managed interface to target data. */
@@ -2334,22 +361,6 @@
}
}
-#[allow(missing_copy_implementations)]
-pub enum RustString_opaque {}
-pub type RustStringRef = *mut RustString_opaque;
-type RustStringRepr = *mut RefCell<Vec<u8>>;
-
-/// Appending to a Rust string -- used by raw_rust_string_ostream.
-#[no_mangle]
-pub unsafe extern "C" fn rust_llvm_string_write_impl(sr: RustStringRef,
- ptr: *const c_char,
- size: size_t) {
- let slice = slice::from_raw_parts(ptr as *const u8, size as usize);
-
- let sr = sr as RustStringRepr;
- (*sr).borrow_mut().extend_from_slice(slice);
-}
-
pub fn build_string<F>(f: F) -> Option<String> where F: FnOnce(RustStringRef){
let mut buf = RefCell::new(Vec::new());
f(&mut buf as RustStringRepr as RustStringRef);
@@ -2357,12 +368,12 @@
}
pub unsafe fn twine_to_string(tr: TwineRef) -> String {
- build_string(|s| LLVMWriteTwineToString(tr, s))
+ build_string(|s| LLVMRustWriteTwineToString(tr, s))
.expect("got a non-UTF8 Twine from LLVM")
}
pub unsafe fn debug_loc_to_string(c: ContextRef, tr: DebugLocRef) -> String {
- build_string(|s| LLVMWriteDebugLocToString(c, tr, s))
+ build_string(|s| LLVMRustWriteDebugLocToString(c, tr, s))
.expect("got a non-UTF8 DebugLoc from LLVM")
}
diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs
index 2e8c5a7..c39ad41 100644
--- a/src/librustc_metadata/astencode.rs
+++ b/src/librustc_metadata/astencode.rs
@@ -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;
@@ -88,8 +88,9 @@
rbml_w.writer.seek(SeekFrom::Current(0)));
// Folding could be avoided with a smarter encoder.
- let ii = simplify_ast(ii);
+ let (ii, expected_id_range) = simplify_ast(ii);
let id_range = inlined_item_id_range(&ii);
+ assert_eq!(expected_id_range, id_range);
rbml_w.start_tag(c::tag_ast as usize);
id_range.encode(rbml_w);
@@ -186,6 +187,10 @@
pub fn tr_id(&self, id: ast::NodeId) -> ast::NodeId {
// from_id_range should be non-empty
assert!(!self.from_id_range.empty());
+ // Make sure that translating the NodeId will actually yield a
+ // meaningful result
+ assert!(self.from_id_range.contains(id));
+
// Use wrapping arithmetic because otherwise it introduces control flow.
// Maybe we should just have the control flow? -- aatch
(id.wrapping_sub(self.from_id_range.min).wrapping_add(self.to_id_range.min))
@@ -279,9 +284,23 @@
rbml_w.end_tag();
}
-struct NestedItemsDropper;
+struct NestedItemsDropper {
+ id_range: IdRange
+}
impl Folder for NestedItemsDropper {
+
+ // The unit tests below run on HIR with NodeIds not properly assigned. That
+ // causes an integer overflow. So we just don't track the id_range when
+ // building the unit tests.
+ #[cfg(not(test))]
+ fn new_id(&mut self, id: ast::NodeId) -> ast::NodeId {
+ // Record the range of NodeIds we are visiting, so we can do a sanity
+ // check later
+ self.id_range.add(id);
+ id
+ }
+
fn fold_block(&mut self, blk: P<hir::Block>) -> P<hir::Block> {
blk.and_then(|hir::Block {id, stmts, expr, rules, span, ..}| {
let stmts_sans_items = stmts.into_iter().filter_map(|stmt| {
@@ -322,10 +341,12 @@
// As it happens, trans relies on the fact that we do not export
// nested items, as otherwise it would get confused when translating
// inlined items.
-fn simplify_ast(ii: InlinedItemRef) -> InlinedItem {
- let mut fld = NestedItemsDropper;
+fn simplify_ast(ii: InlinedItemRef) -> (InlinedItem, IdRange) {
+ let mut fld = NestedItemsDropper {
+ id_range: IdRange::max()
+ };
- match ii {
+ let ii = match ii {
// HACK we're not dropping items.
InlinedItemRef::Item(i) => {
InlinedItem::Item(P(fold::noop_fold_item(i.clone(), &mut fld)))
@@ -339,7 +360,9 @@
InlinedItemRef::Foreign(i) => {
InlinedItem::Foreign(P(fold::noop_fold_foreign_item(i.clone(), &mut fld)))
}
- }
+ };
+
+ (ii, fld.id_range)
}
fn decode_ast(item_doc: rbml::Doc) -> InlinedItem {
@@ -361,8 +384,18 @@
match *self {
Def::Fn(did) => Def::Fn(did.tr(dcx)),
Def::Method(did) => Def::Method(did.tr(dcx)),
- Def::SelfTy(opt_did, impl_id) => { Def::SelfTy(opt_did.map(|did| did.tr(dcx)),
- impl_id.map(|id| dcx.tr_id(id))) }
+ Def::SelfTy(opt_did, impl_id) => {
+ // Since the impl_id will never lie within the reserved range of
+ // imported NodeIds, it does not make sense to translate it.
+ // The result would not make any sense within the importing crate.
+ // We also don't allow for impl items to be inlined (just their
+ // members), so even if we had a DefId here, we wouldn't be able
+ // to do much with it.
+ // So, we set the id to DUMMY_NODE_ID. That way we make it
+ // explicit that this is no usable NodeId.
+ Def::SelfTy(opt_did.map(|did| did.tr(dcx)),
+ impl_id.map(|_| ast::DUMMY_NODE_ID))
+ }
Def::Mod(did) => { Def::Mod(did.tr(dcx)) }
Def::ForeignMod(did) => { Def::ForeignMod(did.tr(dcx)) }
Def::Static(did, m) => { Def::Static(did.tr(dcx), m) }
@@ -693,7 +726,7 @@
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 +737,7 @@
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 +1275,9 @@
}
}
-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()
}
@@ -1361,7 +1394,7 @@
with_testing_context(|lcx| {
let hir_item = lcx.lower_item(&item);
let item_in = InlinedItemRef::Item(&hir_item);
- let item_out = simplify_ast(item_in);
+ let (item_out, _) = simplify_ast(item_in);
let item_exp = InlinedItem::Item(P(lcx.lower_item("e_item!(&cx,
fn new_int_alist<B>() -> alist<isize, B> {
return alist {eq_fn: eq_int, data: Vec::new()};
diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index d4443c6..0b60fc3 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -243,7 +243,7 @@
// Check for (potential) conflicts with the local crate
if self.local_crate_name == crate_name &&
- self.sess.crate_disambiguator.get().as_str() == disambiguator {
+ self.sess.local_crate_disambiguator() == disambiguator {
span_fatal!(self.sess, span, E0519,
"the current crate is indistinguishable from one of its \
dependencies: it has the same crate-name `{}` and was \
diff --git a/src/librustc_metadata/csearch.rs b/src/librustc_metadata/csearch.rs
index 850d6c9..862245b 100644
--- a/src/librustc_metadata/csearch.rs
+++ b/src/librustc_metadata/csearch.rs
@@ -14,7 +14,7 @@
use encoder;
use loader;
-use middle::cstore::{CrateStore, CrateSource, ChildItem, ExternCrate, FoundAst, DefLike};
+use middle::cstore::{InlinedItem, CrateStore, CrateSource, ChildItem, ExternCrate, DefLike};
use middle::cstore::{NativeLibraryKind, LinkMeta, LinkagePreference};
use rustc::hir::def;
use middle::lang_items;
@@ -482,12 +482,146 @@
result
}
- fn maybe_get_item_ast<'a>(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
- -> FoundAst<'tcx>
+ fn maybe_get_item_ast<'a>(&'tcx self,
+ tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ def_id: DefId)
+ -> Option<(&'tcx InlinedItem, ast::NodeId)>
{
- self.dep_graph.read(DepNode::MetaData(def));
- let cdata = self.get_crate_data(def.krate);
- decoder::maybe_get_item_ast(&cdata, tcx, def.index)
+ self.dep_graph.read(DepNode::MetaData(def_id));
+
+ match self.inlined_item_cache.borrow().get(&def_id) {
+ Some(&None) => {
+ return None; // Not inlinable
+ }
+ Some(&Some(ref cached_inlined_item)) => {
+ // Already inline
+ debug!("maybe_get_item_ast({}): already inline as node id {}",
+ tcx.item_path_str(def_id), cached_inlined_item.item_id);
+ return Some((tcx.map.expect_inlined_item(cached_inlined_item.inlined_root),
+ cached_inlined_item.item_id));
+ }
+ None => {
+ // Not seen yet
+ }
+ }
+
+ debug!("maybe_get_item_ast({}): inlining item", tcx.item_path_str(def_id));
+
+ let cdata = self.get_crate_data(def_id.krate);
+ let inlined = decoder::maybe_get_item_ast(&cdata, tcx, def_id.index);
+
+ let cache_inlined_item = |original_def_id, inlined_item_id, inlined_root_node_id| {
+ let cache_entry = cstore::CachedInlinedItem {
+ inlined_root: inlined_root_node_id,
+ item_id: inlined_item_id,
+ };
+ self.inlined_item_cache
+ .borrow_mut()
+ .insert(original_def_id, Some(cache_entry));
+ self.defid_for_inlined_node
+ .borrow_mut()
+ .insert(inlined_item_id, original_def_id);
+ };
+
+ let find_inlined_item_root = |inlined_item_id| {
+ let mut node = inlined_item_id;
+ let mut path = Vec::with_capacity(10);
+
+ // If we can't find the inline root after a thousand hops, we can
+ // be pretty sure there's something wrong with the HIR map.
+ for _ in 0 .. 1000 {
+ path.push(node);
+ let parent_node = tcx.map.get_parent_node(node);
+ if parent_node == node {
+ return node;
+ }
+ node = parent_node;
+ }
+ bug!("cycle in HIR map parent chain")
+ };
+
+ match inlined {
+ decoder::FoundAst::NotFound => {
+ self.inlined_item_cache
+ .borrow_mut()
+ .insert(def_id, None);
+ }
+ decoder::FoundAst::Found(&InlinedItem::Item(ref item)) => {
+ let inlined_root_node_id = find_inlined_item_root(item.id);
+ cache_inlined_item(def_id, item.id, inlined_root_node_id);
+ }
+ decoder::FoundAst::Found(&InlinedItem::Foreign(ref item)) => {
+ let inlined_root_node_id = find_inlined_item_root(item.id);
+ cache_inlined_item(def_id, item.id, inlined_root_node_id);
+ }
+ decoder::FoundAst::FoundParent(parent_did, item) => {
+ let inlined_root_node_id = find_inlined_item_root(item.id);
+ cache_inlined_item(parent_did, item.id, inlined_root_node_id);
+
+ match item.node {
+ hir::ItemEnum(ref ast_def, _) => {
+ let ast_vs = &ast_def.variants;
+ let ty_vs = &tcx.lookup_adt_def(parent_did).variants;
+ assert_eq!(ast_vs.len(), ty_vs.len());
+ for (ast_v, ty_v) in ast_vs.iter().zip(ty_vs.iter()) {
+ cache_inlined_item(ty_v.did,
+ ast_v.node.data.id(),
+ inlined_root_node_id);
+ }
+ }
+ hir::ItemStruct(ref struct_def, _) => {
+ if struct_def.is_struct() {
+ bug!("instantiate_inline: called on a non-tuple struct")
+ } else {
+ cache_inlined_item(def_id,
+ struct_def.id(),
+ inlined_root_node_id);
+ }
+ }
+ _ => bug!("instantiate_inline: item has a \
+ non-enum, non-struct parent")
+ }
+ }
+ decoder::FoundAst::Found(&InlinedItem::TraitItem(_, ref trait_item)) => {
+ let inlined_root_node_id = find_inlined_item_root(trait_item.id);
+ cache_inlined_item(def_id, trait_item.id, inlined_root_node_id);
+
+ // Associated consts already have to be evaluated in `typeck`, so
+ // the logic to do that already exists in `middle`. In order to
+ // reuse that code, it needs to be able to look up the traits for
+ // inlined items.
+ let ty_trait_item = tcx.impl_or_trait_item(def_id).clone();
+ let trait_item_def_id = tcx.map.local_def_id(trait_item.id);
+ tcx.impl_or_trait_items.borrow_mut()
+ .insert(trait_item_def_id, ty_trait_item);
+ }
+ decoder::FoundAst::Found(&InlinedItem::ImplItem(_, ref impl_item)) => {
+ let inlined_root_node_id = find_inlined_item_root(impl_item.id);
+ cache_inlined_item(def_id, impl_item.id, inlined_root_node_id);
+ }
+ }
+
+ // We can be sure to hit the cache now
+ return self.maybe_get_item_ast(tcx, def_id);
+ }
+
+ fn local_node_for_inlined_defid(&'tcx self, def_id: DefId) -> Option<ast::NodeId> {
+ assert!(!def_id.is_local());
+ match self.inlined_item_cache.borrow().get(&def_id) {
+ Some(&Some(ref cached_inlined_item)) => {
+ Some(cached_inlined_item.item_id)
+ }
+ Some(&None) => {
+ None
+ }
+ _ => {
+ bug!("Trying to lookup inlined NodeId for unexpected item");
+ }
+ }
+ }
+
+ fn defid_for_inlined_node(&'tcx self, node_id: ast::NodeId) -> Option<DefId> {
+ self.defid_for_inlined_node.borrow().get(&node_id).map(|x| *x)
}
fn maybe_get_item_mir<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
@@ -634,3 +768,4 @@
visible_parent_map
}
}
+
diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs
index 6baa0ac..d786cc5 100644
--- a/src/librustc_metadata/cstore.rs
+++ b/src/librustc_metadata/cstore.rs
@@ -25,7 +25,7 @@
use rustc::hir::def_id::{DefIndex, DefId};
use rustc::hir::map::DefKey;
use rustc::hir::svh::Svh;
-use rustc::middle::cstore::{ExternCrate};
+use rustc::middle::cstore::ExternCrate;
use rustc::session::config::PanicStrategy;
use rustc_data_structures::indexed_vec::IndexVec;
use rustc::util::nodemap::{FnvHashMap, NodeMap, NodeSet, DefIdMap};
@@ -96,6 +96,13 @@
pub explicitly_linked: Cell<bool>,
}
+pub struct CachedInlinedItem {
+ /// The NodeId of the RootInlinedParent HIR map entry
+ pub inlined_root: ast::NodeId,
+ /// The local NodeId of the inlined entity
+ pub item_id: ast::NodeId,
+}
+
pub struct CStore {
pub dep_graph: DepGraph,
metas: RefCell<FnvHashMap<ast::CrateNum, Rc<CrateMetadata>>>,
@@ -105,6 +112,8 @@
used_libraries: RefCell<Vec<(String, NativeLibraryKind)>>,
used_link_args: RefCell<Vec<String>>,
statically_included_foreign_items: RefCell<NodeSet>,
+ pub inlined_item_cache: RefCell<DefIdMap<Option<CachedInlinedItem>>>,
+ pub defid_for_inlined_node: RefCell<NodeMap<DefId>>,
pub visible_parent_map: RefCell<DefIdMap<DefId>>,
}
@@ -119,6 +128,8 @@
used_link_args: RefCell::new(Vec::new()),
statically_included_foreign_items: RefCell::new(NodeSet()),
visible_parent_map: RefCell::new(FnvHashMap()),
+ inlined_item_cache: RefCell::new(FnvHashMap()),
+ defid_for_inlined_node: RefCell::new(FnvHashMap()),
}
}
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index 409cec2..d8fd25d 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -30,7 +30,7 @@
use rustc::hir;
use rustc::session::config::PanicStrategy;
-use middle::cstore::{FoundAst, InlinedItem, LinkagePreference};
+use middle::cstore::{InlinedItem, LinkagePreference};
use middle::cstore::{DefLike, DlDef, DlField, DlImpl, tls};
use rustc::hir::def::Def;
use rustc::hir::def_id::{DefId, DefIndex};
@@ -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;
@@ -756,6 +755,12 @@
maybe_item_name(cdata.lookup_item(id))
}
+pub enum FoundAst<'ast> {
+ Found(&'ast InlinedItem),
+ FoundParent(DefId, &'ast hir::Item),
+ NotFound,
+}
+
pub fn maybe_get_item_ast<'a, 'tcx>(cdata: Cmd, tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefIndex)
-> FoundAst<'tcx> {
debug!("Looking up item: {:?}", id);
@@ -1160,15 +1165,7 @@
// 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 +1539,9 @@
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,
};
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index 7314259..732c256 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -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_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 @@
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();
@@ -1893,7 +1890,7 @@
encode_crate_name(rbml_w, &ecx.link_meta.crate_name);
encode_crate_triple(rbml_w, &ecx.tcx.sess.opts.target_triple);
encode_hash(rbml_w, &ecx.link_meta.crate_hash);
- encode_crate_disambiguator(rbml_w, &ecx.tcx.sess.crate_disambiguator.get().as_str());
+ encode_crate_disambiguator(rbml_w, &ecx.tcx.sess.local_crate_disambiguator());
encode_dylib_dependency_formats(rbml_w, &ecx);
encode_panic_strategy(rbml_w, &ecx);
diff --git a/src/librustc_metadata/macro_import.rs b/src/librustc_metadata/macro_import.rs
index 7dadf8d..4be044c 100644
--- a/src/librustc_metadata/macro_import.rs
+++ b/src/librustc_metadata/macro_import.rs
@@ -60,10 +60,10 @@
}
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 @@
};
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());
}
}
}
diff --git a/src/librustc_mir/mir_map.rs b/src/librustc_mir/mir_map.rs
index b7c5f35..11d6b07 100644
--- a/src/librustc_mir/mir_map.rs
+++ b/src/librustc_mir/mir_map.rs
@@ -250,7 +250,7 @@
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);
}
}
diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs
index a90b563..d2cf48e 100644
--- a/src/librustc_passes/ast_validation.rs
+++ b/src/librustc_passes/ast_validation.rs
@@ -55,6 +55,17 @@
err.emit();
}
}
+
+ fn check_decl_no_pat<ReportFn: Fn(Span, bool)>(&self, decl: &FnDecl, report_err: ReportFn) {
+ for arg in &decl.inputs {
+ match arg.pat.node {
+ PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), _, None) |
+ PatKind::Wild => {}
+ PatKind::Ident(..) => report_err(arg.pat.span, true),
+ _ => report_err(arg.pat.span, false),
+ }
+ }
+ }
}
impl<'a> Visitor for AstValidator<'a> {
@@ -82,6 +93,23 @@
visit::walk_expr(self, expr)
}
+ fn visit_ty(&mut self, ty: &Ty) {
+ match ty.node {
+ TyKind::BareFn(ref bfty) => {
+ self.check_decl_no_pat(&bfty.decl, |span, _| {
+ let mut err = struct_span_err!(self.session, span, E0561,
+ "patterns aren't allowed in function pointer types");
+ err.span_note(span, "this is a recent error, see \
+ issue #35203 for more details");
+ err.emit();
+ });
+ }
+ _ => {}
+ }
+
+ visit::walk_ty(self, ty)
+ }
+
fn visit_path(&mut self, path: &Path, id: NodeId) {
if path.global && path.segments.len() > 0 {
let ident = path.segments[0].identifier;
@@ -135,6 +163,25 @@
visit::walk_item(self, item)
}
+ fn visit_foreign_item(&mut self, fi: &ForeignItem) {
+ match fi.node {
+ ForeignItemKind::Fn(ref decl, _) => {
+ self.check_decl_no_pat(decl, |span, is_recent| {
+ let mut err = struct_span_err!(self.session, span, E0130,
+ "patterns aren't allowed in foreign function declarations");
+ if is_recent {
+ err.span_note(span, "this is a recent error, see \
+ issue #35203 for more details");
+ }
+ err.emit();
+ });
+ }
+ ForeignItemKind::Static(..) => {}
+ }
+
+ visit::walk_foreign_item(self, fi)
+ }
+
fn visit_variant_data(&mut self, vdata: &VariantData, _: Ident,
_: &Generics, _: NodeId, span: Span) {
if vdata.fields().is_empty() {
diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs
index 27ce03b..1030a4b 100644
--- a/src/librustc_passes/consts.rs
+++ b/src/librustc_passes/consts.rs
@@ -40,6 +40,7 @@
use rustc::middle::mem_categorization::Categorization;
use rustc::ty::{self, Ty, TyCtxt};
use rustc::traits::ProjectionMode;
+use rustc::util::common::ErrorReported;
use rustc::util::nodemap::NodeMap;
use rustc::middle::const_qualif::ConstQualif;
use rustc::lint::builtin::CONST_ERR;
@@ -116,7 +117,7 @@
_ => self.tcx.sess.add_lint(CONST_ERR, expr.id, expr.span,
format!("constant evaluation error: {}. This will \
become a HARD ERROR in the future",
- err.description())),
+ err.description().into_oneline())),
}
}
self.with_mode(mode, |this| {
@@ -157,7 +158,7 @@
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
});
@@ -211,15 +212,6 @@
}
}
}
-
- fn msg(&self) -> &'static str {
- match self.mode {
- Mode::Const => "constant",
- Mode::ConstFn => "constant function",
- Mode::StaticMut | Mode::Static => "static",
- Mode::Var => bug!(),
- }
- }
}
impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
@@ -289,18 +281,14 @@
self.global_expr(Mode::Const, &start);
self.global_expr(Mode::Const, &end);
- match compare_lit_exprs(self.tcx, start, end) {
- Some(Ordering::Less) |
- Some(Ordering::Equal) => {}
- Some(Ordering::Greater) => {
+ match compare_lit_exprs(self.tcx, p.span, start, end) {
+ Ok(Ordering::Less) |
+ Ok(Ordering::Equal) => {}
+ Ok(Ordering::Greater) => {
span_err!(self.tcx.sess, start.span, E0030,
"lower range bound must be less than or equal to upper");
}
- None => {
- span_err!(self.tcx.sess, p.span, E0014,
- "paths in {}s may only refer to constants",
- self.msg());
- }
+ Err(ErrorReported) => {}
}
}
_ => intravisit::walk_pat(self, p)
@@ -429,7 +417,7 @@
Err(msg) => {
self.tcx.sess.add_lint(CONST_ERR, ex.id,
msg.span,
- msg.description().into_owned())
+ msg.description().into_oneline().into_owned())
}
}
}
diff --git a/src/librustc_passes/diagnostics.rs b/src/librustc_passes/diagnostics.rs
index 918e17d..3e2dd47 100644
--- a/src/librustc_passes/diagnostics.rs
+++ b/src/librustc_passes/diagnostics.rs
@@ -11,7 +11,7 @@
#![allow(non_snake_case)]
register_long_diagnostics! {
-
+/*
E0014: r##"
Constants can only be initialized by a constant value or, in a future
version of Rust, a call to a const function. This error indicates the use
@@ -30,7 +30,7 @@
const FOO2: i32 = { 0 }; // but brackets are useless here
```
"##,
-
+*/
E0030: r##"
When matching against a range, the compiler verifies that the range is
non-empty. Range patterns include both end-points, so this is equivalent to
@@ -49,6 +49,39 @@
```
"##,
+E0130: r##"
+You declared a pattern as an argument in a foreign function declaration.
+Erroneous code example:
+
+```compile_fail
+extern {
+ fn foo((a, b): (u32, u32)); // error: patterns aren't allowed in foreign
+ // function declarations
+}
+```
+
+Please replace the pattern argument with a regular one. Example:
+
+```
+struct SomeStruct {
+ a: u32,
+ b: u32,
+}
+
+extern {
+ fn foo(s: SomeStruct); // ok!
+}
+```
+
+Or:
+
+```
+extern {
+ fn foo(a: (u32, u32)); // ok!
+}
+```
+"##,
+
E0161: r##"
A value was moved. However, its size was not known at compile time, and only
values of a known size can be moved.
@@ -187,4 +220,5 @@
register_diagnostics! {
E0472, // asm! is unsupported on this target
+ E0561, // patterns aren't allowed in function pointer types
}
diff --git a/src/librustc_passes/rvalues.rs b/src/librustc_passes/rvalues.rs
index 4684683..2a5dc50 100644
--- a/src/librustc_passes/rvalues.rs
+++ b/src/librustc_passes/rvalues.rs
@@ -49,7 +49,7 @@
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)
}
}
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index acaf9b9..793e52d 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -291,7 +291,7 @@
}
}
- intravisit::walk_mod(self, m);
+ intravisit::walk_mod(self, m, id);
}
fn visit_macro_def(&mut self, md: &'v hir::MacroDef) {
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index aa8c706..c1511b2 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -825,8 +825,6 @@
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 @@
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;
}
@@ -1814,39 +1807,25 @@
path_depth: usize)
-> Result<PathResolution, ()> {
self.resolve_path(id, trait_path, path_depth, TypeNS).and_then(|path_res| {
- if let Def::Trait(_) = path_res.base_def {
- debug!("(resolving trait) found trait def: {:?}", path_res);
- Ok(path_res)
- } else {
- let mut err =
- resolve_struct_error(self,
- trait_path.span,
- ResolutionError::IsNotATrait(&path_names_to_string(trait_path,
- path_depth)));
-
- // If it's a typedef, give a note
- if let Def::TyAlias(..) = path_res.base_def {
- let trait_name = trait_path.segments.last().unwrap().identifier.name;
- err.span_label(trait_path.span,
- &format!("`{}` is not a trait", trait_name));
-
- let definition_site = {
- let segments = &trait_path.segments;
- if trait_path.global {
- self.resolve_crate_relative_path(trait_path.span, segments, TypeNS)
- } else {
- self.resolve_module_relative_path(trait_path.span, segments, TypeNS)
- }.map(|binding| binding.span).unwrap_or(syntax_pos::DUMMY_SP)
- };
-
- if definition_site != syntax_pos::DUMMY_SP {
- err.span_label(definition_site,
- &format!("type aliases cannot be used for traits"));
- }
+ match path_res.base_def {
+ Def::Trait(_) => {
+ debug!("(resolving trait) found trait def: {:?}", path_res);
+ return Ok(path_res);
}
- err.emit();
- Err(true)
+ Def::Err => return Err(true),
+ _ => {}
}
+
+ let mut err = resolve_struct_error(self, trait_path.span, {
+ ResolutionError::IsNotATrait(&path_names_to_string(trait_path, path_depth))
+ });
+
+ // If it's a typedef, give a note
+ if let Def::TyAlias(..) = path_res.base_def {
+ err.note(&format!("type aliases cannot be used for traits"));
+ }
+ err.emit();
+ Err(true)
}).map_err(|error_reported| {
if error_reported { return }
@@ -2274,7 +2253,7 @@
let resolution = if let Some(resolution) = self.resolve_possibly_assoc_item(pat_id,
qself, path, namespace) {
if resolution.depth == 0 {
- if expected_fn(resolution.base_def) {
+ if expected_fn(resolution.base_def) || resolution.base_def == Def::Err {
resolution
} else {
resolve_error(
@@ -2345,7 +2324,7 @@
);
None
}
- Def::Local(..) | Def::Upvar(..) | Def::Fn(..) => {
+ Def::Local(..) | Def::Upvar(..) | Def::Fn(..) | Def::Err => {
// These entities are explicitly allowed
// to be shadowed by fresh bindings.
None
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index 681d9ec..fc5e2a4 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -73,13 +73,11 @@
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 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 @@
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 @@
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 @@
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 @@
_ => (),
}
+ 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 @@
_ => {}
}
- // 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 @@
}).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));
}
}
diff --git a/src/librustc_trans/_match.rs b/src/librustc_trans/_match.rs
index 08e894f..f7fd970 100644
--- a/src/librustc_trans/_match.rs
+++ b/src/librustc_trans/_match.rs
@@ -190,7 +190,7 @@
use llvm::{ValueRef, BasicBlockRef};
use rustc_const_eval::check_match::{self, Constructor, StaticInliner};
-use rustc_const_eval::{compare_lit_exprs, eval_const_expr};
+use rustc_const_eval::{compare_lit_exprs, eval_const_expr, fatal_const_eval_err};
use rustc::hir::def::{Def, DefMap};
use rustc::hir::def_id::DefId;
use middle::expr_use_visitor as euv;
@@ -239,9 +239,9 @@
impl<'a> ConstantExpr<'a> {
fn eq<'b, 'tcx>(self, other: ConstantExpr<'a>, tcx: TyCtxt<'b, 'tcx, 'tcx>) -> bool {
- match compare_lit_exprs(tcx, self.0, other.0) {
- Some(result) => result == Ordering::Equal,
- None => bug!("compare_list_exprs: type mismatch"),
+ match compare_lit_exprs(tcx, self.0.span, self.0, other.0) {
+ Ok(result) => result == Ordering::Equal,
+ Err(_) => bug!("compare_list_exprs: type mismatch"),
}
}
}
@@ -288,7 +288,9 @@
let expr = consts::const_expr(ccx, &lit_expr, bcx.fcx.param_substs, None, Yes);
let llval = match expr {
Ok((llval, _)) => llval,
- Err(err) => bcx.ccx().sess().span_fatal(lit_expr.span, &err.description()),
+ Err(err) => {
+ fatal_const_eval_err(bcx.tcx(), err.as_inner(), lit_expr.span, "pattern");
+ }
};
let lit_datum = immediate_rvalue(llval, lit_ty);
let lit_datum = unpack_datum!(bcx, lit_datum.to_appropriate_datum(bcx));
@@ -297,11 +299,11 @@
ConstantRange(ConstantExpr(ref l1), ConstantExpr(ref l2), _) => {
let l1 = match consts::const_expr(ccx, &l1, bcx.fcx.param_substs, None, Yes) {
Ok((l1, _)) => l1,
- Err(err) => bcx.ccx().sess().span_fatal(l1.span, &err.description()),
+ Err(err) => fatal_const_eval_err(bcx.tcx(), err.as_inner(), l1.span, "pattern"),
};
let l2 = match consts::const_expr(ccx, &l2, bcx.fcx.param_substs, None, Yes) {
Ok((l2, _)) => l2,
- Err(err) => bcx.ccx().sess().span_fatal(l2.span, &err.description()),
+ Err(err) => fatal_const_eval_err(bcx.tcx(), err.as_inner(), l2.span, "pattern"),
};
RangeResult(Result::new(bcx, l1), Result::new(bcx, l2))
}
diff --git a/src/librustc_trans/abi.rs b/src/librustc_trans/abi.rs
index 6c2a09f..587c03a 100644
--- a/src/librustc_trans/abi.rs
+++ b/src/librustc_trans/abi.rs
@@ -552,13 +552,13 @@
pub fn apply_attrs_llfn(&self, llfn: ValueRef) {
let mut i = if self.ret.is_indirect() { 1 } else { 0 };
if !self.ret.is_ignore() {
- self.ret.attrs.apply_llfn(i, llfn);
+ self.ret.attrs.apply_llfn(llvm::AttributePlace::Argument(i), llfn);
}
i += 1;
for arg in &self.args {
if !arg.is_ignore() {
if arg.pad.is_some() { i += 1; }
- arg.attrs.apply_llfn(i, llfn);
+ arg.attrs.apply_llfn(llvm::AttributePlace::Argument(i), llfn);
i += 1;
}
}
@@ -567,13 +567,13 @@
pub fn apply_attrs_callsite(&self, callsite: ValueRef) {
let mut i = if self.ret.is_indirect() { 1 } else { 0 };
if !self.ret.is_ignore() {
- self.ret.attrs.apply_callsite(i, callsite);
+ self.ret.attrs.apply_callsite(llvm::AttributePlace::Argument(i), callsite);
}
i += 1;
for arg in &self.args {
if !arg.is_ignore() {
if arg.pad.is_some() { i += 1; }
- arg.attrs.apply_callsite(i, callsite);
+ arg.attrs.apply_callsite(llvm::AttributePlace::Argument(i), callsite);
i += 1;
}
}
diff --git a/src/librustc_trans/asm.rs b/src/librustc_trans/asm.rs
index e27bec6..5514fb0 100644
--- a/src/librustc_trans/asm.rs
+++ b/src/librustc_trans/asm.rs
@@ -83,8 +83,8 @@
};
let dialect = match ia.dialect {
- AsmDialect::Att => llvm::AD_ATT,
- AsmDialect::Intel => llvm::AD_Intel
+ AsmDialect::Att => llvm::AsmDialect::Att,
+ AsmDialect::Intel => llvm::AsmDialect::Intel,
};
let asm = CString::new(ia.asm.as_bytes()).unwrap();
diff --git a/src/librustc_trans/assert_module_sources.rs b/src/librustc_trans/assert_module_sources.rs
new file mode 100644
index 0000000..e0532e7
--- /dev/null
+++ b/src/librustc_trans/assert_module_sources.rs
@@ -0,0 +1,149 @@
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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 pass is only used for UNIT TESTS related to incremental
+//! compilation. It tests whether a particular `.o` file will be re-used
+//! from a previous compilation or whether it must be regenerated.
+//!
+//! The user adds annotations to the crate of the following form:
+//!
+//! ```
+//! #![rustc_partition_reused(module="spike", cfg="rpass2")]
+//! #![rustc_partition_translated(module="spike-x", cfg="rpass2")]
+//! ```
+//!
+//! The first indicates (in the cfg `rpass2`) that `spike.o` will be
+//! reused, the second that `spike-x.o` will be recreated. If these
+//! annotations are inaccurate, errors are reported.
+//!
+//! The reason that we use `cfg=...` and not `#[cfg_attr]` is so that
+//! the HIR doesn't change as a result of the annotations, which might
+//! perturb the reuse results.
+
+use rustc::ty::TyCtxt;
+use syntax::ast;
+use syntax::attr::AttrMetaMethods;
+use syntax::parse::token::InternedString;
+
+use {ModuleSource, ModuleTranslation};
+
+const PARTITION_REUSED: &'static str = "rustc_partition_reused";
+const PARTITION_TRANSLATED: &'static str = "rustc_partition_translated";
+
+const MODULE: &'static str = "module";
+const CFG: &'static str = "cfg";
+
+#[derive(Debug, PartialEq)]
+enum Disposition { Reused, Translated }
+
+pub fn assert_module_sources<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ modules: &[ModuleTranslation]) {
+ let _ignore = tcx.dep_graph.in_ignore();
+
+ if tcx.sess.opts.incremental.is_none() {
+ return;
+ }
+
+ let ams = AssertModuleSource { tcx: tcx, modules: modules };
+ for attr in &tcx.map.krate().attrs {
+ ams.check_attr(attr);
+ }
+}
+
+struct AssertModuleSource<'a, 'tcx: 'a> {
+ tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ modules: &'a [ModuleTranslation],
+}
+
+impl<'a, 'tcx> AssertModuleSource<'a, 'tcx> {
+ fn check_attr(&self, attr: &ast::Attribute) {
+ let disposition = if attr.check_name(PARTITION_REUSED) {
+ Disposition::Reused
+ } else if attr.check_name(PARTITION_TRANSLATED) {
+ Disposition::Translated
+ } else {
+ return;
+ };
+
+ if !self.check_config(attr) {
+ debug!("check_attr: config does not match, ignoring attr");
+ return;
+ }
+
+ let mname = self.field(attr, MODULE);
+ let mtrans = self.modules.iter().find(|mtrans| &mtrans.name[..] == &mname[..]);
+ let mtrans = match mtrans {
+ Some(m) => m,
+ None => {
+ debug!("module name `{}` not found amongst:", mname);
+ for mtrans in self.modules {
+ debug!("module named `{}` with disposition {:?}",
+ mtrans.name,
+ self.disposition(mtrans));
+ }
+
+ self.tcx.sess.span_err(
+ attr.span,
+ &format!("no module named `{}`", mname));
+ return;
+ }
+ };
+
+ let mtrans_disposition = self.disposition(mtrans);
+ if disposition != mtrans_disposition {
+ self.tcx.sess.span_err(
+ attr.span,
+ &format!("expected module named `{}` to be {:?} but is {:?}",
+ mname,
+ disposition,
+ mtrans_disposition));
+ }
+ }
+
+ fn disposition(&self, mtrans: &ModuleTranslation) -> Disposition {
+ match mtrans.source {
+ ModuleSource::Preexisting(_) => Disposition::Reused,
+ ModuleSource::Translated(_) => Disposition::Translated,
+ }
+ }
+
+ fn field(&self, attr: &ast::Attribute, name: &str) -> InternedString {
+ for item in attr.meta_item_list().unwrap_or(&[]) {
+ if item.check_name(name) {
+ if let Some(value) = item.value_str() {
+ return value;
+ } else {
+ self.tcx.sess.span_fatal(
+ item.span,
+ &format!("associated value expected for `{}`", name));
+ }
+ }
+ }
+
+ self.tcx.sess.span_fatal(
+ attr.span,
+ &format!("no field `{}`", name));
+ }
+
+ /// Scan for a `cfg="foo"` attribute and check whether we have a
+ /// cfg flag called `foo`.
+ fn check_config(&self, attr: &ast::Attribute) -> bool {
+ let config = &self.tcx.map.krate().config;
+ let value = self.field(attr, CFG);
+ debug!("check_config(config={:?}, value={:?})", config, value);
+ if config.iter().any(|c| c.check_name(&value[..])) {
+ debug!("check_config: matched");
+ return true;
+ }
+ debug!("check_config: no match found");
+ return false;
+ }
+
+}
diff --git a/src/librustc_trans/attributes.rs b/src/librustc_trans/attributes.rs
index 01e9970..62eac35 100644
--- a/src/librustc_trans/attributes.rs
+++ b/src/librustc_trans/attributes.rs
@@ -9,8 +9,8 @@
// except according to those terms.
//! Set and unset common attributes on LLVM values.
-use libc::c_uint;
-use llvm::{self, ValueRef};
+use llvm::{self, Attribute, ValueRef};
+use llvm::AttributePlace::Function;
pub use syntax::attr::InlineAttr;
use syntax::ast;
use context::CrateContext;
@@ -20,14 +20,14 @@
pub fn inline(val: ValueRef, inline: InlineAttr) {
use self::InlineAttr::*;
match inline {
- Hint => llvm::SetFunctionAttribute(val, llvm::Attribute::InlineHint),
- Always => llvm::SetFunctionAttribute(val, llvm::Attribute::AlwaysInline),
- Never => llvm::SetFunctionAttribute(val, llvm::Attribute::NoInline),
+ Hint => Attribute::InlineHint.apply_llfn(Function, val),
+ Always => Attribute::AlwaysInline.apply_llfn(Function, val),
+ Never => Attribute::NoInline.apply_llfn(Function, val),
None => {
- let attr = llvm::Attribute::InlineHint |
- llvm::Attribute::AlwaysInline |
- llvm::Attribute::NoInline;
- llvm::RemoveFunctionAttributes(val, attr)
+ let attr = Attribute::InlineHint |
+ Attribute::AlwaysInline |
+ Attribute::NoInline;
+ attr.unapply_llfn(Function, val)
},
};
}
@@ -35,56 +35,37 @@
/// Tell LLVM to emit or not emit the information necessary to unwind the stack for the function.
#[inline]
pub fn emit_uwtable(val: ValueRef, emit: bool) {
- if emit {
- llvm::SetFunctionAttribute(val, llvm::Attribute::UWTable);
- } else {
- llvm::RemoveFunctionAttributes(val, llvm::Attribute::UWTable);
- }
+ Attribute::UWTable.toggle_llfn(Function, val, emit);
}
/// Tell LLVM whether the function can or cannot unwind.
#[inline]
pub fn unwind(val: ValueRef, can_unwind: bool) {
- if can_unwind {
- llvm::RemoveFunctionAttributes(val, llvm::Attribute::NoUnwind);
- } else {
- llvm::SetFunctionAttribute(val, llvm::Attribute::NoUnwind);
- }
+ Attribute::NoUnwind.toggle_llfn(Function, val, !can_unwind);
}
/// Tell LLVM whether it should optimise function for size.
#[inline]
#[allow(dead_code)] // possibly useful function
pub fn set_optimize_for_size(val: ValueRef, optimize: bool) {
- if optimize {
- llvm::SetFunctionAttribute(val, llvm::Attribute::OptimizeForSize);
- } else {
- llvm::RemoveFunctionAttributes(val, llvm::Attribute::OptimizeForSize);
- }
+ Attribute::OptimizeForSize.toggle_llfn(Function, val, optimize);
}
/// Tell LLVM if this function should be 'naked', i.e. skip the epilogue and prologue.
#[inline]
pub fn naked(val: ValueRef, is_naked: bool) {
- if is_naked {
- llvm::SetFunctionAttribute(val, llvm::Attribute::Naked);
- } else {
- llvm::RemoveFunctionAttributes(val, llvm::Attribute::Naked);
- }
+ Attribute::Naked.toggle_llfn(Function, val, is_naked);
}
pub fn set_frame_pointer_elimination(ccx: &CrateContext, llfn: ValueRef) {
// FIXME: #11906: Omitting frame pointers breaks retrieving the value of a
// parameter.
if ccx.sess().must_not_eliminate_frame_pointers() {
- unsafe {
- let attr = "no-frame-pointer-elim\0".as_ptr() as *const _;
- let val = "true\0".as_ptr() as *const _;
- llvm::LLVMAddFunctionAttrStringValue(llfn,
- llvm::FunctionIndex as c_uint,
- attr,
- val);
- }
+ llvm::AddFunctionAttrStringValue(
+ llfn,
+ llvm::AttributePlace::Function,
+ "no-frame-pointer-elim\0",
+ "true\0")
}
}
@@ -98,13 +79,12 @@
for attr in attrs {
if attr.check_name("cold") {
- llvm::Attributes::default().set(llvm::Attribute::Cold)
- .apply_llfn(llvm::FunctionIndex as usize, llfn)
+ Attribute::Cold.apply_llfn(Function, llfn);
} else if attr.check_name("naked") {
naked(llfn, true);
} else if attr.check_name("allocator") {
- llvm::Attributes::default().set(llvm::Attribute::NoAlias)
- .apply_llfn(llvm::ReturnIndex as usize, llfn)
+ Attribute::NoAlias.apply_llfn(
+ llvm::AttributePlace::ReturnValue(), llfn);
} else if attr.check_name("unwind") {
unwind(llfn, true);
}
diff --git a/src/librustc_trans/back/archive.rs b/src/librustc_trans/back/archive.rs
index 29019f3..e063209 100644
--- a/src/librustc_trans/back/archive.rs
+++ b/src/librustc_trans/back/archive.rs
@@ -293,7 +293,7 @@
members.as_ptr(),
self.should_update_symbols,
kind);
- let ret = if r != 0 {
+ let ret = if r.into_result().is_err() {
let err = llvm::LLVMRustGetLastError();
let msg = if err.is_null() {
"failed to write archive".to_string()
diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs
index 33cffa8..8ce2fa7 100644
--- a/src/librustc_trans/back/write.rs
+++ b/src/librustc_trans/back/write.rs
@@ -10,18 +10,21 @@
use back::lto;
use back::link::{get_linker, remove};
+use rustc_incremental::save_trans_partition;
use session::config::{OutputFilenames, Passes, SomePasses, AllPasses};
use session::Session;
use session::config::{self, OutputType};
use llvm;
use llvm::{ModuleRef, TargetMachineRef, PassManagerRef, DiagnosticInfoRef, ContextRef};
use llvm::SMDiagnosticRef;
-use {CrateTranslation, ModuleTranslation};
+use {CrateTranslation, ModuleLlvm, ModuleSource, ModuleTranslation};
use util::common::time;
use util::common::path2cstr;
+use util::fs::link_or_copy;
use errors::{self, Handler, Level, DiagnosticBuilder};
use errors::emitter::Emitter;
use syntax_pos::MultiSpan;
+use context::{is_pie_binary, get_reloc_model};
use std::collections::HashMap;
use std::ffi::{CStr, CString};
@@ -51,7 +54,7 @@
let output_c = path2cstr(output);
let result = llvm::LLVMRustWriteOutputFile(
target, pm, m, output_c.as_ptr(), file_type);
- if !result {
+ if result.into_result().is_err() {
llvm_err(handler, format!("could not write output to {}", output.display()));
}
}
@@ -135,11 +138,11 @@
fn get_llvm_opt_level(optimize: config::OptLevel) -> llvm::CodeGenOptLevel {
match optimize {
- config::OptLevel::No => llvm::CodeGenLevelNone,
- config::OptLevel::Less => llvm::CodeGenLevelLess,
- config::OptLevel::Default => llvm::CodeGenLevelDefault,
- config::OptLevel::Aggressive => llvm::CodeGenLevelAggressive,
- _ => llvm::CodeGenLevelDefault,
+ config::OptLevel::No => llvm::CodeGenOptLevel::None,
+ config::OptLevel::Less => llvm::CodeGenOptLevel::Less,
+ config::OptLevel::Default => llvm::CodeGenOptLevel::Default,
+ config::OptLevel::Aggressive => llvm::CodeGenOptLevel::Aggressive,
+ _ => llvm::CodeGenOptLevel::Default,
}
}
@@ -152,32 +155,11 @@
}
pub fn create_target_machine(sess: &Session) -> TargetMachineRef {
- let reloc_model_arg = match sess.opts.cg.relocation_model {
- Some(ref s) => &s[..],
- None => &sess.target.target.options.relocation_model[..],
- };
- let reloc_model = match reloc_model_arg {
- "pic" => llvm::RelocPIC,
- "static" => llvm::RelocStatic,
- "default" => llvm::RelocDefault,
- "dynamic-no-pic" => llvm::RelocDynamicNoPic,
- _ => {
- sess.err(&format!("{:?} is not a valid relocation mode",
- sess.opts
- .cg
- .relocation_model));
- sess.abort_if_errors();
- bug!();
- }
- };
+ let reloc_model = get_reloc_model(sess);
let opt_level = get_llvm_opt_level(sess.opts.optimize);
let use_softfp = sess.opts.cg.soft_float;
- let any_library = sess.crate_types.borrow().iter().any(|ty| {
- *ty != config::CrateTypeExecutable
- });
-
let ffunction_sections = sess.target.target.options.function_sections;
let fdata_sections = ffunction_sections;
@@ -187,11 +169,11 @@
};
let code_model = match code_model_arg {
- "default" => llvm::CodeModelDefault,
- "small" => llvm::CodeModelSmall,
- "kernel" => llvm::CodeModelKernel,
- "medium" => llvm::CodeModelMedium,
- "large" => llvm::CodeModelLarge,
+ "default" => llvm::CodeModel::Default,
+ "small" => llvm::CodeModel::Small,
+ "kernel" => llvm::CodeModel::Kernel,
+ "medium" => llvm::CodeModel::Medium,
+ "large" => llvm::CodeModel::Large,
_ => {
sess.err(&format!("{:?} is not a valid code model",
sess.opts
@@ -218,7 +200,7 @@
reloc_model,
opt_level,
use_softfp,
- !any_library && reloc_model == llvm::RelocPIC,
+ is_pie_binary(sess),
ffunction_sections,
fdata_sections,
)
@@ -335,6 +317,8 @@
remark: Passes,
// Worker thread number
worker: usize,
+ // Directory where incremental data is stored (if any)
+ incremental: Option<PathBuf>,
}
impl<'a> CodegenContext<'a> {
@@ -345,6 +329,7 @@
plugin_passes: sess.plugin_llvm_passes.borrow().clone(),
remark: sess.opts.cg.remark.clone(),
worker: 0,
+ incremental: sess.opts.incremental.clone(),
}
}
}
@@ -380,7 +365,7 @@
cookie: c_uint) {
let HandlerFreeVars { cgcx, .. } = *(user as *const HandlerFreeVars);
- let msg = llvm::build_string(|s| llvm::LLVMWriteSMDiagnosticToString(diag, s))
+ let msg = llvm::build_string(|s| llvm::LLVMRustWriteSMDiagnosticToString(diag, s))
.expect("non-UTF8 SMDiagnostic");
report_inline_asm(cgcx, &msg[..], cookie);
@@ -422,10 +407,11 @@
// Unsafe due to LLVM calls.
unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
mtrans: ModuleTranslation,
+ mllvm: ModuleLlvm,
config: ModuleConfig,
output_names: OutputFilenames) {
- let llmod = mtrans.llmod;
- let llcx = mtrans.llcx;
+ let llmod = mllvm.llmod;
+ let llcx = mllvm.llcx;
let tm = config.tm;
// llcx doesn't outlive this function, so we can put this on the stack.
@@ -435,7 +421,7 @@
};
let fv = &fv as *const HandlerFreeVars as *mut c_void;
- llvm::LLVMSetInlineAsmDiagnosticHandler(llcx, inline_asm_handler, fv);
+ llvm::LLVMRustSetInlineAsmDiagnosticHandler(llcx, inline_asm_handler, fv);
llvm::LLVMContextSetDiagnosticHandler(llcx, diagnostic_handler, fv);
let module_name = Some(&mtrans.name[..]);
@@ -463,9 +449,9 @@
return false;
}
let pass_manager = match llvm::LLVMRustPassKind(pass) {
- llvm::SupportedPassKind::Function => fpm,
- llvm::SupportedPassKind::Module => mpm,
- llvm::SupportedPassKind::Unsupported => {
+ llvm::PassKind::Function => fpm,
+ llvm::PassKind::Module => mpm,
+ llvm::PassKind::Other => {
cgcx.handler.err("Encountered LLVM pass kind we can't handle");
return true
},
@@ -593,7 +579,7 @@
};
with_codegen(tm, llmod, config.no_builtins, |cpm| {
write_output_file(cgcx.handler, tm, cpm, llmod, &path,
- llvm::AssemblyFileType);
+ llvm::FileType::AssemblyFile);
});
if config.emit_obj {
llvm::LLVMDisposeModule(llmod);
@@ -602,14 +588,15 @@
if write_obj {
with_codegen(tm, llmod, config.no_builtins, |cpm| {
- write_output_file(cgcx.handler, tm, cpm, llmod, &obj_out, llvm::ObjectFileType);
+ write_output_file(cgcx.handler, tm, cpm, llmod, &obj_out,
+ llvm::FileType::ObjectFile);
});
}
});
if copy_bc_to_obj {
debug!("copying bitcode {:?} to obj {:?}", bc_out, obj_out);
- if let Err(e) = fs::copy(&bc_out, &obj_out) {
+ if let Err(e) = link_or_copy(&bc_out, &obj_out) {
cgcx.handler.err(&format!("failed to copy bitcode to object file: {}", e));
}
}
@@ -628,8 +615,14 @@
pub fn cleanup_llvm(trans: &CrateTranslation) {
for module in trans.modules.iter() {
unsafe {
- llvm::LLVMDisposeModule(module.llmod);
- llvm::LLVMContextDispose(module.llcx);
+ match module.source {
+ ModuleSource::Translated(llvm) => {
+ llvm::LLVMDisposeModule(llvm.llmod);
+ llvm::LLVMContextDispose(llvm.llcx);
+ }
+ ModuleSource::Preexisting(_) => {
+ }
+ }
}
}
}
@@ -743,6 +736,23 @@
run_work_multithreaded(sess, work_items, num_workers);
}
+ // If in incr. comp. mode, preserve the `.o` files for potential re-use
+ for mtrans in trans.modules.iter() {
+ let mut files = vec![];
+
+ if modules_config.emit_obj {
+ let path = crate_output.temp_path(OutputType::Object, Some(&mtrans.name));
+ files.push((OutputType::Object, path));
+ }
+
+ if modules_config.emit_bc {
+ let path = crate_output.temp_path(OutputType::Bitcode, Some(&mtrans.name));
+ files.push((OutputType::Bitcode, path));
+ }
+
+ save_trans_partition(sess, &mtrans.name, mtrans.symbol_name_hash, &files);
+ }
+
// All codegen is finished.
unsafe {
llvm::LLVMRustDisposeTargetMachine(tm);
@@ -916,10 +926,37 @@
fn execute_work_item(cgcx: &CodegenContext,
work_item: WorkItem) {
unsafe {
- optimize_and_codegen(cgcx,
- work_item.mtrans,
- work_item.config,
- work_item.output_names);
+ match work_item.mtrans.source {
+ ModuleSource::Translated(mllvm) => {
+ debug!("llvm-optimizing {:?}", work_item.mtrans.name);
+ optimize_and_codegen(cgcx,
+ work_item.mtrans,
+ mllvm,
+ work_item.config,
+ work_item.output_names);
+ }
+ ModuleSource::Preexisting(wp) => {
+ let incremental = cgcx.incremental.as_ref().unwrap();
+ let name = &work_item.mtrans.name;
+ for (kind, saved_file) in wp.saved_files {
+ let obj_out = work_item.output_names.temp_path(kind, Some(name));
+ let source_file = incremental.join(&saved_file);
+ debug!("copying pre-existing module `{}` from {:?} to {}",
+ work_item.mtrans.name,
+ source_file,
+ obj_out.display());
+ match link_or_copy(&source_file, &obj_out) {
+ Ok(()) => { }
+ Err(err) => {
+ cgcx.handler.err(&format!("unable to copy {} to {}: {}",
+ source_file.display(),
+ obj_out.display(),
+ err));
+ }
+ }
+ }
+ }
+ }
}
}
@@ -955,6 +992,8 @@
let mut tx = Some(tx);
futures.push(rx);
+ let incremental = sess.opts.incremental.clone();
+
thread::Builder::new().name(format!("codegen-{}", i)).spawn(move || {
let diag_handler = Handler::with_emitter(true, false, box diag_emitter);
@@ -966,6 +1005,7 @@
plugin_passes: plugin_passes,
remark: remark,
worker: i,
+ incremental: incremental,
};
loop {
@@ -1039,7 +1079,7 @@
// reasonable defaults and prepare it to actually populate the pass
// manager.
let builder = llvm::LLVMPassManagerBuilderCreate();
- let opt_level = config.opt_level.unwrap_or(llvm::CodeGenLevelNone);
+ let opt_level = config.opt_level.unwrap_or(llvm::CodeGenOptLevel::None);
let opt_size = config.opt_size.unwrap_or(llvm::CodeGenOptSizeNone);
let inline_threshold = config.inline_threshold;
@@ -1063,7 +1103,7 @@
(_, _, Some(t)) => {
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, t as u32);
}
- (llvm::CodeGenLevelAggressive, _, _) => {
+ (llvm::CodeGenOptLevel::Aggressive, _, _) => {
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 275);
}
(_, llvm::CodeGenOptSizeDefault, _) => {
@@ -1072,15 +1112,18 @@
(_, llvm::CodeGenOptSizeAggressive, _) => {
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 25);
}
- (llvm::CodeGenLevelNone, _, _) => {
+ (llvm::CodeGenOptLevel::None, _, _) => {
llvm::LLVMRustAddAlwaysInlinePass(builder, false);
}
- (llvm::CodeGenLevelLess, _, _) => {
+ (llvm::CodeGenOptLevel::Less, _, _) => {
llvm::LLVMRustAddAlwaysInlinePass(builder, true);
}
- (llvm::CodeGenLevelDefault, _, _) => {
+ (llvm::CodeGenOptLevel::Default, _, _) => {
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 225);
}
+ (llvm::CodeGenOptLevel::Other, _, _) => {
+ bug!("CodeGenOptLevel::Other selected")
+ }
}
f(builder);
diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs
index ea8c248..1077cb2 100644
--- a/src/librustc_trans/base.rs
+++ b/src/librustc_trans/base.rs
@@ -26,8 +26,11 @@
#![allow(non_camel_case_types)]
use super::CrateTranslation;
+use super::ModuleLlvm;
+use super::ModuleSource;
use super::ModuleTranslation;
+use assert_module_sources;
use back::link;
use back::linker::LinkerInfo;
use llvm::{BasicBlockRef, Linkage, ValueRef, Vector, get_param};
@@ -40,7 +43,7 @@
use rustc::traits;
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
use rustc::ty::adjustment::CustomCoerceUnsized;
-use rustc::dep_graph::DepNode;
+use rustc::dep_graph::{DepNode, WorkProduct};
use rustc::hir::map as hir_map;
use rustc::util::common::time;
use rustc::mir::mir_map::MirMap;
@@ -1915,9 +1918,9 @@
}
pub fn trans_instance<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, instance: Instance<'tcx>) {
- let instance = inline::maybe_inline_instance(ccx, instance);
+ let local_instance = inline::maybe_inline_instance(ccx, instance);
- let fn_node_id = ccx.tcx().map.as_local_node_id(instance.def).unwrap();
+ let fn_node_id = ccx.tcx().map.as_local_node_id(local_instance.def).unwrap();
let _s = StatRecorder::new(ccx, ccx.tcx().node_path_str(fn_node_id));
debug!("trans_instance(instance={:?})", instance);
@@ -1933,7 +1936,7 @@
let sig = ccx.tcx().normalize_associated_type(&sig);
let abi = fn_ty.fn_abi();
- let lldecl = match ccx.instances().borrow().get(&instance) {
+ let lldecl = match ccx.instances().borrow().get(&local_instance) {
Some(&val) => val,
None => bug!("Instance `{:?}` not already declared", instance)
};
@@ -2133,7 +2136,7 @@
let instance = Instance::mono(ccx.shared(), main_def_id);
- if !ccx.codegen_unit().items.contains_key(&TransItem::Fn(instance)) {
+ if !ccx.codegen_unit().contains_item(&TransItem::Fn(instance)) {
// We want to create the wrapper in the same codegen unit as Rust's main
// function.
return;
@@ -2257,12 +2260,20 @@
/// Find any symbols that are defined in one compilation unit, but not declared
/// in any other compilation unit. Give these symbols internal linkage.
-fn internalize_symbols<'a, 'tcx>(ccxs: &CrateContextList<'a, 'tcx>,
+fn internalize_symbols<'a, 'tcx>(sess: &Session,
+ ccxs: &CrateContextList<'a, 'tcx>,
symbol_map: &SymbolMap<'tcx>,
reachable: &FnvHashSet<&str>) {
let scx = ccxs.shared();
let tcx = scx.tcx();
+ // In incr. comp. mode, we can't necessarily see all refs since we
+ // don't generate LLVM IR for reused modules, so skip this
+ // step. Later we should get smarter.
+ if sess.opts.debugging_opts.incremental.is_some() {
+ return;
+ }
+
// 'unsafe' because we are holding on to CStr's from the LLVM module within
// this block.
unsafe {
@@ -2270,7 +2281,7 @@
// Collect all symbols that need to stay externally visible because they
// are referenced via a declaration in some other codegen unit.
- for ccx in ccxs.iter() {
+ for ccx in ccxs.iter_need_trans() {
for val in iter_globals(ccx.llmod()).chain(iter_functions(ccx.llmod())) {
let linkage = llvm::LLVMGetLinkage(val);
// We only care about external declarations (not definitions)
@@ -2315,7 +2326,7 @@
// Examine each external definition. If the definition is not used in
// any other compilation unit, and is not reachable from other crates,
// then give it internal linkage.
- for ccx in ccxs.iter() {
+ for ccx in ccxs.iter_need_trans() {
for val in iter_globals(ccx.llmod()).chain(iter_functions(ccx.llmod())) {
let linkage = llvm::LLVMGetLinkage(val);
@@ -2336,8 +2347,9 @@
let has_fixed_linkage = linkage_fixed_explicitly.contains(&name_cow);
if !is_referenced_somewhere && !is_reachable && !has_fixed_linkage {
- llvm::SetLinkage(val, llvm::InternalLinkage);
- llvm::SetDLLStorageClass(val, llvm::DefaultStorageClass);
+ llvm::LLVMSetLinkage(val, llvm::InternalLinkage);
+ llvm::LLVMSetDLLStorageClass(val,
+ llvm::DLLStorageClass::Default);
llvm::UnsetComdat(val);
}
}
@@ -2362,7 +2374,7 @@
"\x01__imp_"
};
unsafe {
- for ccx in cx.iter() {
+ for ccx in cx.iter_need_trans() {
let exported: Vec<_> = iter_globals(ccx.llmod())
.filter(|&val| {
llvm::LLVMGetLinkage(val) ==
@@ -2382,7 +2394,7 @@
imp_name.as_ptr() as *const _);
let init = llvm::LLVMConstBitCast(val, i8p_ty.to_ref());
llvm::LLVMSetInitializer(imp, init);
- llvm::SetLinkage(imp, llvm::ExternalLinkage);
+ llvm::LLVMSetLinkage(imp, llvm::ExternalLinkage);
}
}
}
@@ -2514,8 +2526,11 @@
let metadata_module = ModuleTranslation {
name: "metadata".to_string(),
- llcx: shared_ccx.metadata_llcx(),
- llmod: shared_ccx.metadata_llmod(),
+ symbol_name_hash: 0, // we always rebuild metadata, at least for now
+ source: ModuleSource::Translated(ModuleLlvm {
+ llcx: shared_ccx.metadata_llcx(),
+ llmod: shared_ccx.metadata_llmod(),
+ }),
};
let no_builtins = attr::contains_name(&krate.attrs, "no_builtins");
@@ -2525,17 +2540,34 @@
let symbol_map = Rc::new(symbol_map);
+ let previous_work_products = trans_reuse_previous_work_products(tcx,
+ &codegen_units,
+ &symbol_map);
+
let crate_context_list = CrateContextList::new(&shared_ccx,
codegen_units,
+ previous_work_products,
symbol_map.clone());
- let modules = crate_context_list.iter()
- .map(|ccx| ModuleTranslation {
- name: String::from(&ccx.codegen_unit().name[..]),
- llcx: ccx.llcx(),
- llmod: ccx.llmod()
+ let modules: Vec<_> = crate_context_list.iter_all()
+ .map(|ccx| {
+ let source = match ccx.previous_work_product() {
+ Some(buf) => ModuleSource::Preexisting(buf.clone()),
+ None => ModuleSource::Translated(ModuleLlvm {
+ llcx: ccx.llcx(),
+ llmod: ccx.llmod(),
+ }),
+ };
+
+ ModuleTranslation {
+ name: String::from(ccx.codegen_unit().name()),
+ symbol_name_hash: ccx.codegen_unit().compute_symbol_name_hash(tcx, &symbol_map),
+ source: source,
+ }
})
.collect();
+ assert_module_sources::assert_module_sources(tcx, &modules);
+
// Skip crate items and just output metadata in -Z no-trans mode.
if tcx.sess.opts.no_trans {
let linker_info = LinkerInfo::new(&shared_ccx, &[]);
@@ -2551,41 +2583,44 @@
}
// Instantiate translation items without filling out definitions yet...
- for ccx in crate_context_list.iter() {
- let trans_items = ccx.codegen_unit()
- .items_in_deterministic_order(tcx, &symbol_map);
+ for ccx in crate_context_list.iter_need_trans() {
+ let cgu = ccx.codegen_unit();
+ let trans_items = cgu.items_in_deterministic_order(tcx, &symbol_map);
- for (trans_item, linkage) in trans_items {
- trans_item.predefine(&ccx, linkage);
- }
+ tcx.dep_graph.with_task(cgu.work_product_dep_node(), || {
+ for (trans_item, linkage) in trans_items {
+ trans_item.predefine(&ccx, linkage);
+ }
+ });
}
// ... and now that we have everything pre-defined, fill out those definitions.
- for ccx in crate_context_list.iter() {
- let trans_items = ccx.codegen_unit()
- .items_in_deterministic_order(tcx, &symbol_map);
-
- for (trans_item, _) in trans_items {
- trans_item.define(&ccx);
- }
-
- // If this codegen unit contains the main function, also create the
- // wrapper here
- maybe_create_entry_wrapper(&ccx);
-
- // Run replace-all-uses-with for statics that need it
- for &(old_g, new_g) in ccx.statics_to_rauw().borrow().iter() {
- unsafe {
- let bitcast = llvm::LLVMConstPointerCast(new_g, llvm::LLVMTypeOf(old_g));
- llvm::LLVMReplaceAllUsesWith(old_g, bitcast);
- llvm::LLVMDeleteGlobal(old_g);
+ for ccx in crate_context_list.iter_need_trans() {
+ let cgu = ccx.codegen_unit();
+ let trans_items = cgu.items_in_deterministic_order(tcx, &symbol_map);
+ tcx.dep_graph.with_task(cgu.work_product_dep_node(), || {
+ for (trans_item, _) in trans_items {
+ trans_item.define(&ccx);
}
- }
- // Finalize debuginfo
- if ccx.sess().opts.debuginfo != NoDebugInfo {
- debuginfo::finalize(&ccx);
- }
+ // If this codegen unit contains the main function, also create the
+ // wrapper here
+ maybe_create_entry_wrapper(&ccx);
+
+ // Run replace-all-uses-with for statics that need it
+ for &(old_g, new_g) in ccx.statics_to_rauw().borrow().iter() {
+ unsafe {
+ let bitcast = llvm::LLVMConstPointerCast(new_g, llvm::LLVMTypeOf(old_g));
+ llvm::LLVMReplaceAllUsesWith(old_g, bitcast);
+ llvm::LLVMDeleteGlobal(old_g);
+ }
+ }
+
+ // Finalize debuginfo
+ if ccx.sess().opts.debuginfo != NoDebugInfo {
+ debuginfo::finalize(&ccx);
+ }
+ });
}
symbol_names_test::report_symbol_names(&shared_ccx);
@@ -2654,7 +2689,8 @@
}
time(shared_ccx.sess().time_passes(), "internalize symbols", || {
- internalize_symbols(&crate_context_list,
+ internalize_symbols(sess,
+ &crate_context_list,
&symbol_map,
&reachable_symbols.iter()
.map(|s| &s[..])
@@ -2679,6 +2715,38 @@
}
}
+/// For each CGU, identify if we can reuse an existing object file (or
+/// maybe other context).
+fn trans_reuse_previous_work_products(tcx: TyCtxt,
+ codegen_units: &[CodegenUnit],
+ symbol_map: &SymbolMap)
+ -> Vec<Option<WorkProduct>> {
+ debug!("trans_reuse_previous_work_products()");
+ codegen_units
+ .iter()
+ .map(|cgu| {
+ let id = cgu.work_product_id();
+
+ let hash = cgu.compute_symbol_name_hash(tcx, symbol_map);
+
+ debug!("trans_reuse_previous_work_products: id={:?} hash={}", id, hash);
+
+ if let Some(work_product) = tcx.dep_graph.previous_work_product(&id) {
+ if work_product.input_hash == hash {
+ debug!("trans_reuse_previous_work_products: reusing {:?}", work_product);
+ return Some(work_product);
+ } else {
+ debug!("trans_reuse_previous_work_products: \
+ not reusing {:?} because hash changed to {:?}",
+ work_product, hash);
+ }
+ }
+
+ None
+ })
+ .collect()
+}
+
fn collect_and_partition_translation_items<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>)
-> (Vec<CodegenUnit<'tcx>>, SymbolMap<'tcx>) {
let time_passes = scx.sess().time_passes();
@@ -2739,10 +2807,10 @@
let mut item_to_cgus = HashMap::new();
for cgu in &codegen_units {
- for (&trans_item, &linkage) in &cgu.items {
+ for (&trans_item, &linkage) in cgu.items() {
item_to_cgus.entry(trans_item)
.or_insert(Vec::new())
- .push((cgu.name.clone(), linkage));
+ .push((cgu.name().clone(), linkage));
}
}
diff --git a/src/librustc_trans/build.rs b/src/librustc_trans/build.rs
index 4a7a573..8cd47bd 100644
--- a/src/librustc_trans/build.rs
+++ b/src/librustc_trans/build.rs
@@ -12,7 +12,7 @@
#![allow(non_snake_case)]
use llvm;
-use llvm::{AtomicBinOp, AtomicOrdering, SynchronizationScope, AsmDialect};
+use llvm::{AtomicRmwBinOp, AtomicOrdering, SynchronizationScope, AsmDialect};
use llvm::{Opcode, IntPredicate, RealPredicate};
use llvm::{ValueRef, BasicBlockRef};
use common::*;
@@ -1117,7 +1117,7 @@
weak: llvm::Bool) -> ValueRef {
B(cx).atomic_cmpxchg(dst, cmp, src, order, failure_order, weak)
}
-pub fn AtomicRMW(cx: Block, op: AtomicBinOp,
+pub fn AtomicRMW(cx: Block, op: AtomicRmwBinOp,
dst: ValueRef, src: ValueRef,
order: AtomicOrdering) -> ValueRef {
B(cx).atomic_rmw(op, dst, src, order)
diff --git a/src/librustc_trans/builder.rs b/src/librustc_trans/builder.rs
index e88257d..90f96af 100644
--- a/src/librustc_trans/builder.rs
+++ b/src/librustc_trans/builder.rs
@@ -11,7 +11,7 @@
#![allow(dead_code)] // FFI wrappers
use llvm;
-use llvm::{AtomicBinOp, AtomicOrdering, SynchronizationScope, AsmDialect};
+use llvm::{AtomicRmwBinOp, AtomicOrdering, SynchronizationScope, AsmDialect};
use llvm::{Opcode, IntPredicate, RealPredicate, False, OperandBundleDef};
use llvm::{ValueRef, BasicBlockRef, BuilderRef, ModuleRef};
use base;
@@ -503,8 +503,8 @@
unsafe {
let ty = Type::from_ref(llvm::LLVMTypeOf(ptr));
let align = llalign_of_pref(self.ccx, ty.element_type());
- llvm::LLVMBuildAtomicLoad(self.llbuilder, ptr, noname(), order,
- align as c_uint)
+ llvm::LLVMRustBuildAtomicLoad(self.llbuilder, ptr, noname(), order,
+ align as c_uint)
}
}
@@ -565,7 +565,7 @@
unsafe {
let ty = Type::from_ref(llvm::LLVMTypeOf(ptr));
let align = llalign_of_pref(self.ccx, ty.element_type());
- llvm::LLVMBuildAtomicStore(self.llbuilder, val, ptr, order, align as c_uint);
+ llvm::LLVMRustBuildAtomicStore(self.llbuilder, val, ptr, order, align as c_uint);
}
}
@@ -840,8 +840,8 @@
debug!("Asm Output Type: {:?}", output);
let fty = Type::func(&argtys[..], &output);
unsafe {
- let v = llvm::LLVMInlineAsm(
- fty.to_ref(), asm, cons, volatile, alignstack, dia as c_uint);
+ let v = llvm::LLVMRustInlineAsm(
+ fty.to_ref(), asm, cons, volatile, alignstack, dia);
self.call(v, inputs, None)
}
}
@@ -1083,11 +1083,11 @@
failure_order: AtomicOrdering,
weak: llvm::Bool) -> ValueRef {
unsafe {
- llvm::LLVMBuildAtomicCmpXchg(self.llbuilder, dst, cmp, src,
+ llvm::LLVMRustBuildAtomicCmpXchg(self.llbuilder, dst, cmp, src,
order, failure_order, weak)
}
}
- pub fn atomic_rmw(&self, op: AtomicBinOp,
+ pub fn atomic_rmw(&self, op: AtomicRmwBinOp,
dst: ValueRef, src: ValueRef,
order: AtomicOrdering) -> ValueRef {
unsafe {
@@ -1097,7 +1097,7 @@
pub fn atomic_fence(&self, order: AtomicOrdering, scope: SynchronizationScope) {
unsafe {
- llvm::LLVMBuildAtomicFence(self.llbuilder, order, scope);
+ llvm::LLVMRustBuildAtomicFence(self.llbuilder, order, scope);
}
}
}
diff --git a/src/librustc_trans/closure.rs b/src/librustc_trans/closure.rs
index 90443d9..e53a5ed 100644
--- a/src/librustc_trans/closure.rs
+++ b/src/librustc_trans/closure.rs
@@ -181,6 +181,41 @@
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,15 @@
// 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);
+
+ unsafe {
+ if ccx.sess().target.target.options.allows_weak_linkage {
+ llvm::LLVMSetLinkage(llfn, llvm::WeakODRLinkage);
+ llvm::SetUniqueComdat(ccx.llmod(), llfn);
+ } else {
+ llvm::LLVMSetLinkage(llfn, llvm::InternalLinkage);
+ }
+ }
// set an inline hint for all closures
attributes::inline(llfn, attributes::InlineAttr::Hint);
@@ -296,6 +338,39 @@
// 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);
diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs
index d057f62..a1783e9 100644
--- a/src/librustc_trans/common.rs
+++ b/src/librustc_trans/common.rs
@@ -980,7 +980,7 @@
});
llvm::LLVMSetInitializer(g, sc);
llvm::LLVMSetGlobalConstant(g, True);
- llvm::SetLinkage(g, llvm::InternalLinkage);
+ llvm::LLVMSetLinkage(g, llvm::InternalLinkage);
cx.const_cstr_cache().borrow_mut().insert(s, g);
g
@@ -1235,7 +1235,6 @@
inlined_vid: ast::NodeId)
-> ty::VariantDef<'tcx>
{
-
let ctor_ty = ccx.tcx().node_id_to_type(inlined_vid);
debug!("inlined_variant_def: ctor_ty={:?} inlined_vid={:?}", ctor_ty,
inlined_vid);
@@ -1245,13 +1244,18 @@
}), ..}) => ty,
_ => ctor_ty
}.ty_adt_def().unwrap();
- let inlined_vid_def_id = ccx.tcx().map.local_def_id(inlined_vid);
- adt_def.variants.iter().find(|v| {
- inlined_vid_def_id == v.did ||
- ccx.external().borrow().get(&v.did) == Some(&Some(inlined_vid))
- }).unwrap_or_else(|| {
- bug!("no variant for {:?}::{}", adt_def, inlined_vid)
- })
+ let variant_def_id = if ccx.tcx().map.is_inlined(inlined_vid) {
+ ccx.defid_for_inlined_node(inlined_vid).unwrap()
+ } else {
+ ccx.tcx().map.local_def_id(inlined_vid)
+ };
+
+ adt_def.variants
+ .iter()
+ .find(|v| variant_def_id == v.did)
+ .unwrap_or_else(|| {
+ bug!("no variant for {:?}::{}", adt_def, inlined_vid)
+ })
}
// To avoid UB from LLVM, these two functions mask RHS with an
diff --git a/src/librustc_trans/consts.rs b/src/librustc_trans/consts.rs
index 00feb2c..7afb525 100644
--- a/src/librustc_trans/consts.rs
+++ b/src/librustc_trans/consts.rs
@@ -10,11 +10,11 @@
use llvm;
-use llvm::{ConstFCmp, ConstICmp, SetLinkage, SetUnnamedAddr};
+use llvm::{SetUnnamedAddr};
use llvm::{InternalLinkage, ValueRef, Bool, True};
use middle::const_qualif::ConstQualif;
use rustc_const_eval::{ConstEvalErr, lookup_const_fn_by_id, lookup_const_by_id, ErrKind};
-use rustc_const_eval::eval_repeat_count;
+use rustc_const_eval::{eval_length, report_const_eval_err, note_const_eval_err};
use rustc::hir::def::Def;
use rustc::hir::def_id::DefId;
use rustc::hir::map as hir_map;
@@ -44,7 +44,6 @@
use rustc::hir;
use std::ffi::{CStr, CString};
-use std::borrow::Cow;
use libc::c_uint;
use syntax::ast::{self, LitKind};
use syntax::attr::{self, AttrMetaMethods};
@@ -126,7 +125,7 @@
});
llvm::LLVMSetInitializer(gv, cv);
llvm::LLVMSetAlignment(gv, align);
- SetLinkage(gv, InternalLinkage);
+ llvm::LLVMSetLinkage(gv, InternalLinkage);
SetUnnamedAddr(gv, true);
gv
}
@@ -250,10 +249,11 @@
Compiletime(e) => e,
}
}
- pub fn description(&self) -> Cow<str> {
+
+ pub fn as_inner(&self) -> &ConstEvalErr {
match self {
- &Runtime(ref e) => e.description(),
- &Compiletime(ref e) => e.description(),
+ &Runtime(ref e) => e,
+ &Compiletime(ref e) => e,
}
}
}
@@ -274,7 +274,7 @@
let empty_substs = ccx.tcx().mk_substs(Substs::empty());
match get_const_expr_as_global(ccx, expr, ConstQualif::empty(), empty_substs, TrueConst::Yes) {
Err(Runtime(err)) => {
- ccx.tcx().sess.span_err(expr.span, &err.description());
+ report_const_eval_err(ccx.tcx(), &err, expr.span, "expression").emit();
Err(Compiletime(err))
},
other => other,
@@ -526,12 +526,15 @@
(Ok(x), _) => Ok(x),
(Err(err), TrueConst::Yes) => {
let err = ConstEvalErr{ span: span, kind: err };
- cx.tcx().sess.span_err(span, &err.description());
+ report_const_eval_err(cx.tcx(), &err, span, "expression").emit();
Err(Compiletime(err))
},
(Err(err), TrueConst::No) => {
let err = ConstEvalErr{ span: span, kind: err };
- cx.tcx().sess.span_warn(span, &err.description());
+ let mut diag = cx.tcx().sess.struct_span_warn(
+ span, "this expression will panic at run-time");
+ note_const_eval_err(cx.tcx(), &err, span, "expression", &mut diag);
+ diag.emit();
Err(Runtime(err))
},
}
@@ -634,10 +637,10 @@
hir::BiEq | hir::BiNe | hir::BiLt | hir::BiLe | hir::BiGt | hir::BiGe => {
if is_float {
let cmp = base::bin_op_to_fcmp_predicate(b.node);
- ConstFCmp(cmp, te1, te2)
+ llvm::LLVMConstFCmp(cmp, te1, te2)
} else {
let cmp = base::bin_op_to_icmp_predicate(b.node, signed);
- ConstICmp(cmp, te1, te2)
+ llvm::LLVMConstICmp(cmp, te1, te2)
}
},
} } // unsafe { match b.node {
@@ -875,7 +878,7 @@
hir::ExprRepeat(ref elem, ref count) => {
let unit_ty = ety.sequence_element_type(cx.tcx());
let llunitty = type_of::type_of(cx, unit_ty);
- let n = eval_repeat_count(cx.tcx(), count);
+ let n = eval_length(cx.tcx(), count, "repeat count").unwrap();
let unit_val = const_expr(cx, &elem, param_substs, fn_args, trueconst)?.0;
let vs = vec![unit_val; n];
if val_ty(unit_val) != llunitty {
@@ -1023,10 +1026,10 @@
.get(TransItem::Static(id))
.expect("Local statics should always be in the SymbolMap");
// Make sure that this is never executed for something inlined.
- assert!(!ccx.external_srcs().borrow().contains_key(&id));
+ assert!(!ccx.tcx().map.is_inlined(id));
let defined_in_current_codegen_unit = ccx.codegen_unit()
- .items
+ .items()
.contains_key(&TransItem::Static(id));
if defined_in_current_codegen_unit {
if declare::get_declared_value(ccx, sym).is_none() {
@@ -1069,7 +1072,7 @@
unsafe {
// Declare a symbol `foo` with the desired linkage.
let g1 = declare::declare_global(ccx, &sym, llty2);
- llvm::SetLinkage(g1, linkage);
+ llvm::LLVMSetLinkage(g1, linkage);
// Declare an internal global `extern_with_linkage_foo` which
// is initialized with the address of `foo`. If `foo` is
@@ -1083,7 +1086,7 @@
ccx.sess().span_fatal(span,
&format!("symbol `{}` is already defined", &sym))
});
- llvm::SetLinkage(g2, llvm::InternalLinkage);
+ llvm::LLVMSetLinkage(g2, llvm::InternalLinkage);
llvm::LLVMSetInitializer(g2, g1);
g2
}
@@ -1123,7 +1126,9 @@
}
}
if ccx.use_dll_storage_attrs() {
- llvm::SetDLLStorageClass(g, llvm::DLLImportStorageClass);
+ unsafe {
+ llvm::LLVMSetDLLStorageClass(g, llvm::DLLStorageClass::DllImport);
+ }
}
g
};
@@ -1179,7 +1184,7 @@
let name_str_ref = CStr::from_ptr(llvm::LLVMGetValueName(datum.val));
let name_string = CString::new(name_str_ref.to_bytes()).unwrap();
llvm::LLVMSetValueName(datum.val, empty_string.as_ptr());
- let new_g = llvm::LLVMGetOrInsertGlobal(
+ let new_g = llvm::LLVMRustGetOrInsertGlobal(
ccx.llmod(), name_string.as_ptr(), val_llty.to_ref());
// To avoid breaking any invariants, we leave around the old
// global for the moment; we'll replace all references to it
diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs
index 8890372..166ce99 100644
--- a/src/librustc_trans/context.rs
+++ b/src/librustc_trans/context.rs
@@ -10,7 +10,7 @@
use llvm;
use llvm::{ContextRef, ModuleRef, ValueRef, BuilderRef};
-use rustc::dep_graph::{DepNode, DepTrackingMap, DepTrackingMapConfig};
+use rustc::dep_graph::{DepNode, DepTrackingMap, DepTrackingMapConfig, WorkProduct};
use middle::cstore::LinkMeta;
use rustc::hir::def::ExportMap;
use rustc::hir::def_id::DefId;
@@ -34,9 +34,10 @@
use rustc::ty::{self, Ty, TyCtxt};
use session::config::NoDebugInfo;
use session::Session;
+use session::config;
use symbol_map::SymbolMap;
use util::sha2::Sha256;
-use util::nodemap::{NodeMap, NodeSet, DefIdMap, FnvHashMap, FnvHashSet};
+use util::nodemap::{NodeSet, DefIdMap, FnvHashMap, FnvHashSet};
use std::ffi::{CStr, CString};
use std::cell::{Cell, RefCell};
@@ -95,16 +96,12 @@
pub struct LocalCrateContext<'tcx> {
llmod: ModuleRef,
llcx: ContextRef,
+ previous_work_product: Option<WorkProduct>,
tn: TypeNames, // FIXME: This seems to be largely unused.
codegen_unit: CodegenUnit<'tcx>,
needs_unwind_cleanup_cache: RefCell<FnvHashMap<Ty<'tcx>, bool>>,
fn_pointer_shims: RefCell<FnvHashMap<Ty<'tcx>, ValueRef>>,
drop_glues: RefCell<FnvHashMap<DropGlueKind<'tcx>, (ValueRef, FnType)>>,
- /// Track mapping of external ids to local items imported for inlining
- external: RefCell<DefIdMap<Option<ast::NodeId>>>,
- /// Backwards version of the `external` map (inlined items to where they
- /// came from)
- external_srcs: RefCell<NodeMap<DefId>>,
/// Cache instances of monomorphic and polymorphic items
instances: RefCell<FnvHashMap<Instance<'tcx>, ValueRef>>,
monomorphizing: RefCell<DefIdMap<usize>>,
@@ -198,24 +195,39 @@
}
impl<'a, 'tcx: 'a> CrateContextList<'a, 'tcx> {
-
pub fn new(shared_ccx: &'a SharedCrateContext<'a, 'tcx>,
codegen_units: Vec<CodegenUnit<'tcx>>,
+ previous_work_products: Vec<Option<WorkProduct>>,
symbol_map: Rc<SymbolMap<'tcx>>)
-> CrateContextList<'a, 'tcx> {
CrateContextList {
shared: shared_ccx,
- local_ccxs: codegen_units.into_iter().map(|codegen_unit| {
- LocalCrateContext::new(shared_ccx, codegen_unit, symbol_map.clone())
+ local_ccxs: codegen_units.into_iter().zip(previous_work_products).map(|(cgu, wp)| {
+ LocalCrateContext::new(shared_ccx, cgu, wp, symbol_map.clone())
}).collect()
}
}
- pub fn iter<'b>(&'b self) -> CrateContextIterator<'b, 'tcx> {
+ /// Iterate over all crate contexts, whether or not they need
+ /// translation. That is, whether or not a `.o` file is available
+ /// for re-use from a previous incr. comp.).
+ pub fn iter_all<'b>(&'b self) -> CrateContextIterator<'b, 'tcx> {
CrateContextIterator {
shared: self.shared,
index: 0,
- local_ccxs: &self.local_ccxs[..]
+ local_ccxs: &self.local_ccxs[..],
+ filter_to_previous_work_product_unavail: false,
+ }
+ }
+
+ /// Iterator over all CCX that need translation (cannot reuse results from
+ /// previous incr. comp.).
+ pub fn iter_need_trans<'b>(&'b self) -> CrateContextIterator<'b, 'tcx> {
+ CrateContextIterator {
+ shared: self.shared,
+ index: 0,
+ local_ccxs: &self.local_ccxs[..],
+ filter_to_previous_work_product_unavail: true,
}
}
@@ -239,24 +251,38 @@
shared: &'a SharedCrateContext<'a, 'tcx>,
local_ccxs: &'a [LocalCrateContext<'tcx>],
index: usize,
+
+ /// if true, only return results where `previous_work_product` is none
+ filter_to_previous_work_product_unavail: bool,
}
impl<'a, 'tcx> Iterator for CrateContextIterator<'a,'tcx> {
type Item = CrateContext<'a, 'tcx>;
fn next(&mut self) -> Option<CrateContext<'a, 'tcx>> {
- if self.index >= self.local_ccxs.len() {
- return None;
+ loop {
+ if self.index >= self.local_ccxs.len() {
+ return None;
+ }
+
+ let index = self.index;
+ self.index += 1;
+
+ let ccx = CrateContext {
+ shared: self.shared,
+ index: index,
+ local_ccxs: self.local_ccxs,
+ };
+
+ if
+ self.filter_to_previous_work_product_unavail &&
+ ccx.previous_work_product().is_some()
+ {
+ continue;
+ }
+
+ return Some(ccx);
}
-
- let index = self.index;
- self.index += 1;
-
- Some(CrateContext {
- shared: self.shared,
- index: index,
- local_ccxs: self.local_ccxs,
- })
}
}
@@ -292,6 +318,38 @@
}
}
+pub fn get_reloc_model(sess: &Session) -> llvm::RelocMode {
+ let reloc_model_arg = match sess.opts.cg.relocation_model {
+ Some(ref s) => &s[..],
+ None => &sess.target.target.options.relocation_model[..],
+ };
+
+ match reloc_model_arg {
+ "pic" => llvm::RelocMode::PIC,
+ "static" => llvm::RelocMode::Static,
+ "default" => llvm::RelocMode::Default,
+ "dynamic-no-pic" => llvm::RelocMode::DynamicNoPic,
+ _ => {
+ sess.err(&format!("{:?} is not a valid relocation mode",
+ sess.opts
+ .cg
+ .relocation_model));
+ sess.abort_if_errors();
+ bug!();
+ }
+ }
+}
+
+fn is_any_library(sess: &Session) -> bool {
+ sess.crate_types.borrow().iter().any(|ty| {
+ *ty != config::CrateTypeExecutable
+ })
+}
+
+pub fn is_pie_binary(sess: &Session) -> bool {
+ !is_any_library(sess) && get_reloc_model(sess) == llvm::RelocMode::PIC
+}
+
unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextRef, ModuleRef) {
let llcx = llvm::LLVMContextCreate();
let mod_name = CString::new(mod_name).unwrap();
@@ -307,7 +365,25 @@
let data_layout = str::from_utf8(CStr::from_ptr(data_layout).to_bytes())
.ok().expect("got a non-UTF8 data-layout from LLVM");
- if sess.target.target.data_layout != data_layout {
+ // Unfortunately LLVM target specs change over time, and right now we
+ // don't have proper support to work with any more than one
+ // `data_layout` than the one that is in the rust-lang/rust repo. If
+ // this compiler is configured against a custom LLVM, we may have a
+ // differing data layout, even though we should update our own to use
+ // that one.
+ //
+ // As an interim hack, if CFG_LLVM_ROOT is not an empty string then we
+ // disable this check entirely as we may be configured with something
+ // that has a different target layout.
+ //
+ // Unsure if this will actually cause breakage when rustc is configured
+ // as such.
+ //
+ // FIXME(#34960)
+ let cfg_llvm_root = option_env!("CFG_LLVM_ROOT").unwrap_or("");
+ let custom_llvm_used = cfg_llvm_root.trim() != "";
+
+ if !custom_llvm_used && sess.target.target.data_layout != data_layout {
bug!("data-layout for builtin `{}` target, `{}`, \
differs from LLVM default, `{}`",
sess.target.target.llvm_target,
@@ -322,6 +398,11 @@
let llvm_target = sess.target.target.llvm_target.as_bytes();
let llvm_target = CString::new(llvm_target).unwrap();
llvm::LLVMRustSetNormalizedTarget(llmod, llvm_target.as_ptr());
+
+ if is_pie_binary(sess) {
+ llvm::LLVMRustSetModulePIELevel(llmod);
+ }
+
(llcx, llmod)
}
@@ -510,6 +591,7 @@
impl<'tcx> LocalCrateContext<'tcx> {
fn new<'a>(shared: &SharedCrateContext<'a, 'tcx>,
codegen_unit: CodegenUnit<'tcx>,
+ previous_work_product: Option<WorkProduct>,
symbol_map: Rc<SymbolMap<'tcx>>)
-> LocalCrateContext<'tcx> {
unsafe {
@@ -521,13 +603,15 @@
// crashes if the module identifier is same as other symbols
// such as a function name in the module.
// 1. http://llvm.org/bugs/show_bug.cgi?id=11479
- let llmod_id = format!("{}.rs", codegen_unit.name);
+ let llmod_id = format!("{}.rs", codegen_unit.name());
let (llcx, llmod) = create_context_and_module(&shared.tcx.sess,
&llmod_id[..]);
let dbg_cx = if shared.tcx.sess.opts.debuginfo != NoDebugInfo {
- Some(debuginfo::CrateDebugContext::new(llmod))
+ let dctx = debuginfo::CrateDebugContext::new(llmod);
+ debuginfo::metadata::compile_unit_metadata(shared, &dctx, shared.tcx.sess);
+ Some(dctx)
} else {
None
};
@@ -535,13 +619,12 @@
let local_ccx = LocalCrateContext {
llmod: llmod,
llcx: llcx,
+ previous_work_product: previous_work_product,
codegen_unit: codegen_unit,
tn: TypeNames::new(),
needs_unwind_cleanup_cache: RefCell::new(FnvHashMap()),
fn_pointer_shims: RefCell::new(FnvHashMap()),
drop_glues: RefCell::new(FnvHashMap()),
- external: RefCell::new(DefIdMap()),
- external_srcs: RefCell::new(NodeMap()),
instances: RefCell::new(FnvHashMap()),
monomorphizing: RefCell::new(DefIdMap()),
vtables: RefCell::new(FnvHashMap()),
@@ -694,6 +777,10 @@
self.local().llcx
}
+ pub fn previous_work_product(&self) -> Option<&WorkProduct> {
+ self.local().previous_work_product.as_ref()
+ }
+
pub fn codegen_unit(&self) -> &CodegenUnit<'tcx> {
&self.local().codegen_unit
}
@@ -731,12 +818,12 @@
&self.local().drop_glues
}
- pub fn external<'a>(&'a self) -> &'a RefCell<DefIdMap<Option<ast::NodeId>>> {
- &self.local().external
+ pub fn local_node_for_inlined_defid<'a>(&'a self, def_id: DefId) -> Option<ast::NodeId> {
+ self.sess().cstore.local_node_for_inlined_defid(def_id)
}
- pub fn external_srcs<'a>(&'a self) -> &'a RefCell<NodeMap<DefId>> {
- &self.local().external_srcs
+ pub fn defid_for_inlined_node<'a>(&'a self, node_id: ast::NodeId) -> Option<DefId> {
+ self.sess().cstore.defid_for_inlined_node(node_id)
}
pub fn instances<'a>(&'a self) -> &'a RefCell<FnvHashMap<Instance<'tcx>, ValueRef>> {
diff --git a/src/librustc_trans/debuginfo/create_scope_map.rs b/src/librustc_trans/debuginfo/create_scope_map.rs
index 0b75402..fe6a48d 100644
--- a/src/librustc_trans/debuginfo/create_scope_map.rs
+++ b/src/librustc_trans/debuginfo/create_scope_map.rs
@@ -133,7 +133,7 @@
let loc = span_start(ccx, scope_data.span);
scopes[scope] = unsafe {
let file_metadata = file_metadata(ccx, &loc.file.name, &loc.file.abs_path);
- llvm::LLVMDIBuilderCreateLexicalBlock(
+ llvm::LLVMRustDIBuilderCreateLexicalBlock(
DIB(ccx),
parent_scope,
file_metadata,
@@ -156,7 +156,7 @@
let parent_scope = scope_stack.last().unwrap().scope_metadata;
let scope_metadata = unsafe {
- llvm::LLVMDIBuilderCreateLexicalBlock(
+ llvm::LLVMRustDIBuilderCreateLexicalBlock(
DIB(cx),
parent_scope,
file_metadata,
@@ -272,7 +272,7 @@
let parent_scope = scope_stack.last().unwrap().scope_metadata;
let scope_metadata = unsafe {
- llvm::LLVMDIBuilderCreateLexicalBlock(
+ llvm::LLVMRustDIBuilderCreateLexicalBlock(
DIB(cx),
parent_scope,
file_metadata,
diff --git a/src/librustc_trans/debuginfo/gdb.rs b/src/librustc_trans/debuginfo/gdb.rs
index cf31285..0a8d490 100644
--- a/src/librustc_trans/debuginfo/gdb.rs
+++ b/src/librustc_trans/debuginfo/gdb.rs
@@ -77,7 +77,7 @@
llvm::LLVMSetInitializer(section_var, C_bytes(ccx, section_contents));
llvm::LLVMSetGlobalConstant(section_var, llvm::True);
llvm::LLVMSetUnnamedAddr(section_var, llvm::True);
- llvm::SetLinkage(section_var, llvm::Linkage::LinkOnceODRLinkage);
+ llvm::LLVMSetLinkage(section_var, llvm::Linkage::LinkOnceODRLinkage);
// This should make sure that the whole section is not larger than
// the string it contains. Otherwise we get a warning from GDB.
llvm::LLVMSetAlignment(section_var, 1);
diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs
index 46813d9..8011347 100644
--- a/src/librustc_trans/debuginfo/metadata.rs
+++ b/src/librustc_trans/debuginfo/metadata.rs
@@ -18,7 +18,9 @@
fn_should_be_ignored, is_node_local_to_unit};
use super::namespace::mangled_name_of_item;
use super::type_names::{compute_debuginfo_type_name, push_debuginfo_type_name};
-use super::{declare_local, VariableKind, VariableAccess};
+use super::{declare_local, VariableKind, VariableAccess, CrateDebugContext};
+use context::SharedCrateContext;
+use session::Session;
use llvm::{self, ValueRef};
use llvm::debuginfo::{DIType, DIFile, DIScope, DIDescriptor, DICompositeType};
@@ -48,7 +50,6 @@
use syntax::parse::token;
use syntax_pos::{self, Span};
-
// From DWARF 5.
// See http://www.dwarfstd.org/ShowIssue.php?issue=140129.1
const DW_LANG_RUST: c_uint = 0x1c;
@@ -67,7 +68,6 @@
pub const UNKNOWN_COLUMN_NUMBER: c_uint = 0;
// ptr::null() doesn't work :(
-pub const NO_FILE_METADATA: DIFile = (0 as DIFile);
pub const NO_SCOPE_METADATA: DIScope = (0 as DIScope);
const FLAGS_NONE: c_uint = 0;
@@ -326,13 +326,12 @@
// First, find out the 'real' def_id of the type. Items inlined from
// other crates have to be mapped back to their source.
let def_id = if let Some(node_id) = cx.tcx().map.as_local_node_id(def_id) {
- match cx.external_srcs().borrow().get(&node_id).cloned() {
- Some(source_def_id) => {
- // The given def_id identifies the inlined copy of a
- // type definition, let's take the source of the copy.
- source_def_id
- }
- None => def_id
+ if cx.tcx().map.is_inlined(node_id) {
+ // The given def_id identifies the inlined copy of a
+ // type definition, let's take the source of the copy.
+ cx.defid_for_inlined_node(node_id).unwrap()
+ } else {
+ def_id
}
} else {
def_id
@@ -505,12 +504,12 @@
};
let subrange = unsafe {
- llvm::LLVMDIBuilderGetOrCreateSubrange(DIB(cx), 0, upper_bound)
+ llvm::LLVMRustDIBuilderGetOrCreateSubrange(DIB(cx), 0, upper_bound)
};
let subscripts = create_DIArray(DIB(cx), &[subrange]);
let metadata = unsafe {
- llvm::LLVMDIBuilderCreateArrayType(
+ llvm::LLVMRustDIBuilderCreateArrayType(
DIB(cx),
bytes_to_bits(array_size_in_bytes),
bytes_to_bits(element_type_align),
@@ -613,9 +612,9 @@
return MetadataCreationResult::new(
unsafe {
- llvm::LLVMDIBuilderCreateSubroutineType(
+ llvm::LLVMRustDIBuilderCreateSubroutineType(
DIB(cx),
- NO_FILE_METADATA,
+ unknown_file_metadata(cx),
create_DIArray(DIB(cx), &signature_metadata[..]))
},
false);
@@ -652,6 +651,7 @@
let (containing_scope, _) = get_namespace_and_span_for_item(cx, def_id);
let trait_llvm_type = type_of::type_of(cx, trait_object_type);
+ let file_metadata = unknown_file_metadata(cx);
composite_type_metadata(cx,
trait_llvm_type,
@@ -659,7 +659,7 @@
unique_type_id,
&[],
containing_scope,
- NO_FILE_METADATA,
+ file_metadata,
syntax_pos::DUMMY_SP)
}
@@ -885,8 +885,8 @@
let file_name = CString::new(file_name).unwrap();
let work_dir = CString::new(work_dir).unwrap();
let file_metadata = unsafe {
- llvm::LLVMDIBuilderCreateFile(DIB(cx), file_name.as_ptr(),
- work_dir.as_ptr())
+ llvm::LLVMRustDIBuilderCreateFile(DIB(cx), file_name.as_ptr(),
+ work_dir.as_ptr())
};
let mut created_files = debug_context(cx).created_files.borrow_mut();
@@ -916,7 +916,7 @@
pub fn diverging_type_metadata(cx: &CrateContext) -> DIType {
unsafe {
- llvm::LLVMDIBuilderCreateBasicType(
+ llvm::LLVMRustDIBuilderCreateBasicType(
DIB(cx),
"!\0".as_ptr() as *const _,
bytes_to_bits(0),
@@ -951,7 +951,7 @@
let (size, align) = size_and_align_of(cx, llvm_type);
let name = CString::new(name).unwrap();
let ty_metadata = unsafe {
- llvm::LLVMDIBuilderCreateBasicType(
+ llvm::LLVMRustDIBuilderCreateBasicType(
DIB(cx),
name.as_ptr(),
bytes_to_bits(size),
@@ -971,7 +971,7 @@
let name = compute_debuginfo_type_name(cx, pointer_type, false);
let name = CString::new(name).unwrap();
let ptr_metadata = unsafe {
- llvm::LLVMDIBuilderCreatePointerType(
+ llvm::LLVMRustDIBuilderCreatePointerType(
DIB(cx),
pointee_type_metadata,
bytes_to_bits(pointer_size),
@@ -981,14 +981,17 @@
return ptr_metadata;
}
-pub fn compile_unit_metadata(cx: &CrateContext) -> DIDescriptor {
- let work_dir = &cx.sess().working_dir;
- let compile_unit_name = match cx.sess().local_crate_source_file {
- None => fallback_path(cx),
+pub fn compile_unit_metadata(scc: &SharedCrateContext,
+ debug_context: &CrateDebugContext,
+ sess: &Session)
+ -> DIDescriptor {
+ let work_dir = &sess.working_dir;
+ let compile_unit_name = match sess.local_crate_source_file {
+ None => fallback_path(scc),
Some(ref abs_path) => {
if abs_path.is_relative() {
- cx.sess().warn("debuginfo: Invalid path to crate's local root source file!");
- fallback_path(cx)
+ sess.warn("debuginfo: Invalid path to crate's local root source file!");
+ fallback_path(scc)
} else {
match abs_path.strip_prefix(work_dir) {
Ok(ref p) if p.is_relative() => {
@@ -998,7 +1001,7 @@
path2cstr(&Path::new(".").join(p))
}
}
- _ => fallback_path(cx)
+ _ => fallback_path(scc)
}
}
}
@@ -1014,20 +1017,20 @@
let flags = "\0";
let split_name = "\0";
return unsafe {
- llvm::LLVMDIBuilderCreateCompileUnit(
- debug_context(cx).builder,
+ llvm::LLVMRustDIBuilderCreateCompileUnit(
+ debug_context.builder,
DW_LANG_RUST,
compile_unit_name,
work_dir.as_ptr(),
producer.as_ptr(),
- cx.sess().opts.optimize != config::OptLevel::No,
+ sess.opts.optimize != config::OptLevel::No,
flags.as_ptr() as *const _,
0,
split_name.as_ptr() as *const _)
};
- fn fallback_path(cx: &CrateContext) -> CString {
- CString::new(cx.link_meta().crate_name.clone()).unwrap()
+ fn fallback_path(scc: &SharedCrateContext) -> CString {
+ CString::new(scc.link_meta().crate_name.clone()).unwrap()
}
}
@@ -1593,7 +1596,7 @@
let token = v.name.as_str();
let name = CString::new(token.as_bytes()).unwrap();
unsafe {
- llvm::LLVMDIBuilderCreateEnumerator(
+ llvm::LLVMRustDIBuilderCreateEnumerator(
DIB(cx),
name.as_ptr(),
v.disr_val.to_u64_unchecked())
@@ -1620,11 +1623,11 @@
let name = CString::new(discriminant_name.as_bytes()).unwrap();
let discriminant_type_metadata = unsafe {
- llvm::LLVMDIBuilderCreateEnumerationType(
+ llvm::LLVMRustDIBuilderCreateEnumerationType(
DIB(cx),
containing_scope,
name.as_ptr(),
- NO_FILE_METADATA,
+ file_metadata,
UNKNOWN_LINE_NUMBER,
bytes_to_bits(discriminant_size),
bytes_to_bits(discriminant_align),
@@ -1664,7 +1667,7 @@
let enum_name = CString::new(enum_name).unwrap();
let unique_type_id_str = CString::new(unique_type_id_str.as_bytes()).unwrap();
let enum_metadata = unsafe {
- llvm::LLVMDIBuilderCreateUnionType(
+ llvm::LLVMRustDIBuilderCreateUnionType(
DIB(cx),
containing_scope,
enum_name.as_ptr(),
@@ -1766,11 +1769,11 @@
let member_name = member_description.name.as_bytes();
let member_name = CString::new(member_name).unwrap();
unsafe {
- llvm::LLVMDIBuilderCreateMemberType(
+ llvm::LLVMRustDIBuilderCreateMemberType(
DIB(cx),
composite_type_metadata,
member_name.as_ptr(),
- NO_FILE_METADATA,
+ unknown_file_metadata(cx),
UNKNOWN_LINE_NUMBER,
bytes_to_bits(member_size),
bytes_to_bits(member_align),
@@ -1783,13 +1786,14 @@
unsafe {
let type_array = create_DIArray(DIB(cx), &member_metadata[..]);
- llvm::LLVMDICompositeTypeSetTypeArray(DIB(cx), composite_type_metadata, type_array);
+ llvm::LLVMRustDICompositeTypeSetTypeArray(
+ DIB(cx), composite_type_metadata, type_array);
}
}
-// A convenience wrapper around LLVMDIBuilderCreateStructType(). Does not do any
-// caching, does not add any fields to the struct. This can be done later with
-// set_members_of_composite_type().
+// A convenience wrapper around LLVMRustDIBuilderCreateStructType(). Does not do
+// any caching, does not add any fields to the struct. This can be done later
+// with set_members_of_composite_type().
fn create_struct_stub(cx: &CrateContext,
struct_llvm_type: Type,
struct_type_name: &str,
@@ -1804,16 +1808,16 @@
let name = CString::new(struct_type_name).unwrap();
let unique_type_id = CString::new(unique_type_id_str.as_bytes()).unwrap();
let metadata_stub = unsafe {
- // LLVMDIBuilderCreateStructType() wants an empty array. A null
+ // LLVMRustDIBuilderCreateStructType() wants an empty array. A null
// pointer will lead to hard to trace and debug LLVM assertions
// later on in llvm/lib/IR/Value.cpp.
let empty_array = create_DIArray(DIB(cx), &[]);
- llvm::LLVMDIBuilderCreateStructType(
+ llvm::LLVMRustDIBuilderCreateStructType(
DIB(cx),
containing_scope,
name.as_ptr(),
- NO_FILE_METADATA,
+ unknown_file_metadata(cx),
UNKNOWN_LINE_NUMBER,
bytes_to_bits(struct_size),
bytes_to_bits(struct_align),
@@ -1842,7 +1846,7 @@
// crate should already contain debuginfo for it. More importantly, the
// global might not even exist in un-inlined form anywhere which would lead
// to a linker errors.
- if cx.external_srcs().borrow().contains_key(&node_id) {
+ if cx.tcx().map.is_inlined(node_id) {
return;
}
@@ -1853,7 +1857,7 @@
let loc = span_start(cx, span);
(file_metadata(cx, &loc.file.name, &loc.file.abs_path), loc.line as c_uint)
} else {
- (NO_FILE_METADATA, UNKNOWN_LINE_NUMBER)
+ (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER)
};
let is_local_to_unit = is_node_local_to_unit(cx, node_id);
@@ -1865,16 +1869,16 @@
let var_name = CString::new(var_name).unwrap();
let linkage_name = CString::new(linkage_name).unwrap();
unsafe {
- llvm::LLVMDIBuilderCreateStaticVariable(DIB(cx),
- var_scope,
- var_name.as_ptr(),
- linkage_name.as_ptr(),
- file_metadata,
- line_number,
- type_metadata,
- is_local_to_unit,
- global,
- ptr::null_mut());
+ llvm::LLVMRustDIBuilderCreateStaticVariable(DIB(cx),
+ var_scope,
+ var_name.as_ptr(),
+ linkage_name.as_ptr(),
+ file_metadata,
+ line_number,
+ type_metadata,
+ is_local_to_unit,
+ global,
+ ptr::null_mut());
}
}
@@ -1977,10 +1981,10 @@
env_index);
let address_operations = unsafe {
- [llvm::LLVMDIBuilderCreateOpDeref(),
- llvm::LLVMDIBuilderCreateOpPlus(),
+ [llvm::LLVMRustDIBuilderCreateOpDeref(),
+ llvm::LLVMRustDIBuilderCreateOpPlus(),
byte_offset_of_var_in_env as i64,
- llvm::LLVMDIBuilderCreateOpDeref()]
+ llvm::LLVMRustDIBuilderCreateOpDeref()]
};
let address_op_count = if captured_by_ref {
@@ -2018,7 +2022,7 @@
let scope_metadata = scope_metadata(bcx.fcx, binding.id, binding.span);
let aops = unsafe {
- [llvm::LLVMDIBuilderCreateOpDeref()]
+ [llvm::LLVMRustDIBuilderCreateOpDeref()]
};
// Regardless of the actual type (`T`) we're always passed the stack slot
// (alloca) for the binding. For ByRef bindings that's a `T*` but for ByMove
diff --git a/src/librustc_trans/debuginfo/mod.rs b/src/librustc_trans/debuginfo/mod.rs
index 8c5b3ed..464c32c 100644
--- a/src/librustc_trans/debuginfo/mod.rs
+++ b/src/librustc_trans/debuginfo/mod.rs
@@ -18,7 +18,7 @@
use self::namespace::mangled_name_of_item;
use self::type_names::compute_debuginfo_type_name;
use self::metadata::{type_metadata, diverging_type_metadata};
-use self::metadata::{file_metadata, scope_metadata, TypeMap, compile_unit_metadata};
+use self::metadata::{file_metadata, scope_metadata, TypeMap};
use self::source_loc::InternalDebugLocation::{self, UnknownLocation};
use llvm;
@@ -32,6 +32,7 @@
use abi::Abi;
use common::{NodeIdAndSpan, CrateContext, FunctionContext, Block, BlockAndBuilder};
+use inline;
use monomorphize::{self, Instance};
use rustc::ty::{self, Ty};
use session::config::{self, FullDebugInfo, LimitedDebugInfo, NoDebugInfo};
@@ -50,7 +51,7 @@
mod utils;
mod namespace;
mod type_names;
-mod metadata;
+pub mod metadata;
mod create_scope_map;
mod source_loc;
@@ -88,7 +89,7 @@
impl<'tcx> CrateDebugContext<'tcx> {
pub fn new(llmod: ModuleRef) -> CrateDebugContext<'tcx> {
debug!("CrateDebugContext::new");
- let builder = unsafe { llvm::LLVMDIBuilderCreate(llmod) };
+ let builder = unsafe { llvm::LLVMRustDIBuilderCreate(llmod) };
// DIBuilder inherits context from the module, so we'd better use the same one
let llcontext = unsafe { llvm::LLVMGetModuleContext(llmod) };
return CrateDebugContext {
@@ -168,7 +169,6 @@
}
debug!("finalize");
- let _ = compile_unit_metadata(cx);
if gdb::needs_gdb_debug_scripts_section(cx) {
// Add a .debug_gdb_scripts section to this compile-unit. This will
@@ -179,8 +179,8 @@
}
unsafe {
- llvm::LLVMDIBuilderFinalize(DIB(cx));
- llvm::LLVMDIBuilderDispose(DIB(cx));
+ llvm::LLVMRustDIBuilderFinalize(DIB(cx));
+ llvm::LLVMRustDIBuilderDispose(DIB(cx));
// Debuginfo generation in LLVM by default uses a higher
// version of dwarf than OS X currently understands. We can
// instruct LLVM to emit an older version of dwarf, however,
@@ -239,6 +239,7 @@
// Do this here already, in case we do an early exit from this function.
source_loc::set_debug_location(cx, None, UnknownLocation);
+ let instance = inline::maybe_inline_instance(cx, instance);
let (containing_scope, span) = get_containing_scope_and_span(cx, instance);
// This can be the case for functions inlined from another crate
@@ -251,7 +252,7 @@
let function_type_metadata = unsafe {
let fn_signature = get_function_signature(cx, sig, abi);
- llvm::LLVMDIBuilderCreateSubroutineType(DIB(cx), file_metadata, fn_signature)
+ llvm::LLVMRustDIBuilderCreateSubroutineType(DIB(cx), file_metadata, fn_signature)
};
// Find the enclosing function, in case this is a closure.
@@ -285,7 +286,7 @@
let linkage_name = CString::new(linkage_name).unwrap();
let fn_metadata = unsafe {
- llvm::LLVMDIBuilderCreateFunction(
+ llvm::LLVMRustDIBuilderCreateFunction(
DIB(cx),
containing_scope,
function_name.as_ptr(),
@@ -389,7 +390,7 @@
let actual_type_metadata = type_metadata(cx, actual_type, syntax_pos::DUMMY_SP);
let name = CString::new(param.name.as_str().as_bytes()).unwrap();
unsafe {
- llvm::LLVMDIBuilderCreateTemplateTypeParameter(
+ llvm::LLVMRustDIBuilderCreateTemplateTypeParameter(
DIB(cx),
ptr::null_mut(),
name.as_ptr(),
@@ -439,10 +440,9 @@
});
// Try to get some span information, if we have an inlined item.
- let definition_span = match cx.external().borrow().get(&instance.def) {
- Some(&Some(node_id)) => cx.tcx().map.span(node_id),
- _ => cx.tcx().map.def_id_span(instance.def, syntax_pos::DUMMY_SP)
- };
+ let definition_span = cx.tcx()
+ .map
+ .def_id_span(instance.def, syntax_pos::DUMMY_SP);
(containing_scope, definition_span)
}
@@ -494,7 +494,7 @@
(DirectVariable { alloca }, address_operations) |
(IndirectVariable {alloca, address_operations}, _) => {
let metadata = unsafe {
- llvm::LLVMDIBuilderCreateVariable(
+ llvm::LLVMRustDIBuilderCreateVariable(
DIB(cx),
dwarf_tag,
scope_metadata,
@@ -512,7 +512,7 @@
InternalDebugLocation::new(scope_metadata, loc.line, loc.col.to_usize()));
unsafe {
let debug_loc = llvm::LLVMGetCurrentDebugLocation(cx.raw_builder());
- let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd(
+ let instr = llvm::LLVMRustDIBuilderInsertDeclareAtEnd(
DIB(cx),
alloca,
metadata,
diff --git a/src/librustc_trans/debuginfo/namespace.rs b/src/librustc_trans/debuginfo/namespace.rs
index 167229d..5953ec4 100644
--- a/src/librustc_trans/debuginfo/namespace.rs
+++ b/src/librustc_trans/debuginfo/namespace.rs
@@ -10,7 +10,7 @@
// Namespace Handling.
-use super::metadata::{file_metadata, NO_FILE_METADATA, UNKNOWN_LINE_NUMBER};
+use super::metadata::{file_metadata, unknown_file_metadata, UNKNOWN_LINE_NUMBER};
use super::utils::{DIB, debug_context, span_start};
use llvm;
@@ -74,11 +74,11 @@
let loc = span_start(ccx, span);
(file_metadata(ccx, &loc.file.name, &loc.file.abs_path), loc.line as c_uint)
} else {
- (NO_FILE_METADATA, UNKNOWN_LINE_NUMBER)
+ (unknown_file_metadata(ccx), UNKNOWN_LINE_NUMBER)
};
let scope = unsafe {
- llvm::LLVMDIBuilderCreateNameSpace(
+ llvm::LLVMRustDIBuilderCreateNameSpace(
DIB(ccx),
parent_scope,
namespace_name.as_ptr(),
diff --git a/src/librustc_trans/debuginfo/source_loc.rs b/src/librustc_trans/debuginfo/source_loc.rs
index 9726001..d288b9d 100644
--- a/src/librustc_trans/debuginfo/source_loc.rs
+++ b/src/librustc_trans/debuginfo/source_loc.rs
@@ -206,7 +206,7 @@
debug!("setting debug location to {} {}", line, col);
unsafe {
- llvm::LLVMDIBuilderCreateDebugLocation(
+ llvm::LLVMRustDIBuilderCreateDebugLocation(
debug_context(cx).llcontext,
line as c_uint,
col as c_uint,
diff --git a/src/librustc_trans/debuginfo/utils.rs b/src/librustc_trans/debuginfo/utils.rs
index 1e0afa4..5734a12 100644
--- a/src/librustc_trans/debuginfo/utils.rs
+++ b/src/librustc_trans/debuginfo/utils.rs
@@ -40,7 +40,7 @@
#[allow(non_snake_case)]
pub fn create_DIArray(builder: DIBuilderRef, arr: &[DIDescriptor]) -> DIArray {
return unsafe {
- llvm::LLVMDIBuilderGetOrCreateArray(builder, arr.as_ptr(), arr.len() as u32)
+ llvm::LLVMRustDIBuilderGetOrCreateArray(builder, arr.as_ptr(), arr.len() as u32)
};
}
@@ -86,10 +86,7 @@
});
// Try to get some span information, if we have an inlined item.
- let definition_span = match cx.external().borrow().get(&def_id) {
- Some(&Some(node_id)) => cx.tcx().map.span(node_id),
- _ => cx.tcx().map.def_id_span(def_id, syntax_pos::DUMMY_SP)
- };
+ let definition_span = cx.tcx().map.def_id_span(def_id, syntax_pos::DUMMY_SP);
(containing_scope, definition_span)
}
diff --git a/src/librustc_trans/declare.rs b/src/librustc_trans/declare.rs
index 2746d3f..324e869 100644
--- a/src/librustc_trans/declare.rs
+++ b/src/librustc_trans/declare.rs
@@ -20,6 +20,7 @@
//! * Use define_* family of methods when you might be defining the ValueRef.
//! * When in doubt, define.
use llvm::{self, ValueRef};
+use llvm::AttributePlace::Function;
use rustc::ty;
use abi::{Abi, FnType};
use attributes;
@@ -40,7 +41,7 @@
bug!("name {:?} contains an interior null byte", name)
});
unsafe {
- llvm::LLVMGetOrInsertGlobal(ccx.llmod(), namebuf.as_ptr(), ty.to_ref())
+ llvm::LLVMRustGetOrInsertGlobal(ccx.llmod(), namebuf.as_ptr(), ty.to_ref())
}
}
@@ -55,7 +56,7 @@
bug!("name {:?} contains an interior null byte", name)
});
let llfn = unsafe {
- llvm::LLVMGetOrInsertFunction(ccx.llmod(), namebuf.as_ptr(), ty.to_ref())
+ llvm::LLVMRustGetOrInsertFunction(ccx.llmod(), namebuf.as_ptr(), ty.to_ref())
};
llvm::SetFunctionCallConv(llfn, callconv);
@@ -65,16 +66,16 @@
if ccx.tcx().sess.opts.cg.no_redzone
.unwrap_or(ccx.tcx().sess.target.target.options.disable_redzone) {
- llvm::SetFunctionAttribute(llfn, llvm::Attribute::NoRedZone)
+ llvm::Attribute::NoRedZone.apply_llfn(Function, llfn);
}
match ccx.tcx().sess.opts.cg.opt_level.as_ref().map(String::as_ref) {
Some("s") => {
- llvm::SetFunctionAttribute(llfn, llvm::Attribute::OptimizeForSize);
+ llvm::Attribute::OptimizeForSize.apply_llfn(Function, llfn);
},
Some("z") => {
- llvm::SetFunctionAttribute(llfn, llvm::Attribute::MinSize);
- llvm::SetFunctionAttribute(llfn, llvm::Attribute::OptimizeForSize);
+ llvm::Attribute::MinSize.apply_llfn(Function, llfn);
+ llvm::Attribute::OptimizeForSize.apply_llfn(Function, llfn);
},
_ => {},
}
@@ -111,7 +112,7 @@
let llfn = declare_raw_fn(ccx, name, fty.cconv, fty.llvm_type(ccx));
if sig.output == ty::FnDiverging {
- llvm::SetFunctionAttribute(llfn, llvm::Attribute::NoReturn);
+ llvm::Attribute::NoReturn.apply_llfn(Function, llfn);
}
if abi != Abi::Rust && abi != Abi::RustCall {
@@ -162,7 +163,7 @@
name: &str,
fn_type: ty::Ty<'tcx>) -> ValueRef {
let llfn = define_fn(ccx, name, fn_type);
- llvm::SetLinkage(llfn, llvm::InternalLinkage);
+ unsafe { llvm::LLVMSetLinkage(llfn, llvm::InternalLinkage) };
llfn
}
@@ -173,7 +174,7 @@
let namebuf = CString::new(name).unwrap_or_else(|_|{
bug!("name {:?} contains an interior null byte", name)
});
- let val = unsafe { llvm::LLVMGetNamedValue(ccx.llmod(), namebuf.as_ptr()) };
+ let val = unsafe { llvm::LLVMRustGetNamedValue(ccx.llmod(), namebuf.as_ptr()) };
if val.is_null() {
debug!("get_declared_value: {:?} value is null", name);
None
diff --git a/src/librustc_trans/glue.rs b/src/librustc_trans/glue.rs
index ef7d0ea..6bc4854 100644
--- a/src/librustc_trans/glue.rs
+++ b/src/librustc_trans/glue.rs
@@ -239,7 +239,7 @@
Falling back to on-demand instantiation.",
g,
TransItem::DropGlue(g).to_raw_string(),
- ccx.codegen_unit().name);
+ ccx.codegen_unit().name());
ccx.stats().n_fallback_instantiations.set(ccx.stats()
.n_fallback_instantiations
diff --git a/src/librustc_trans/inline.rs b/src/librustc_trans/inline.rs
index 4077b89..8581fcc 100644
--- a/src/librustc_trans/inline.rs
+++ b/src/librustc_trans/inline.rs
@@ -8,14 +8,12 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use middle::cstore::{FoundAst, InlinedItem};
use rustc::hir::def_id::DefId;
use base::push_ctxt;
use common::*;
use monomorphize::Instance;
use rustc::dep_graph::DepNode;
-use rustc::hir;
fn instantiate_inline(ccx: &CrateContext, fn_id: DefId) -> Option<DefId> {
debug!("instantiate_inline({:?})", fn_id);
@@ -23,104 +21,12 @@
let tcx = ccx.tcx();
let _task = tcx.dep_graph.in_task(DepNode::TransInlinedItem(fn_id));
- match ccx.external().borrow().get(&fn_id) {
- Some(&Some(node_id)) => {
- // Already inline
- debug!("instantiate_inline({}): already inline as node id {}",
- tcx.item_path_str(fn_id), node_id);
- let node_def_id = tcx.map.local_def_id(node_id);
- return Some(node_def_id);
- }
- Some(&None) => {
- return None; // Not inlinable
- }
- None => {
- // Not seen yet
- }
- }
-
- let inlined = tcx.sess.cstore.maybe_get_item_ast(tcx, fn_id);
- let inline_id = match inlined {
- FoundAst::NotFound => {
- ccx.external().borrow_mut().insert(fn_id, None);
- return None;
- }
- FoundAst::Found(&InlinedItem::Item(ref item)) => {
- ccx.external().borrow_mut().insert(fn_id, Some(item.id));
- ccx.external_srcs().borrow_mut().insert(item.id, fn_id);
-
- ccx.stats().n_inlines.set(ccx.stats().n_inlines.get() + 1);
-
- item.id
- }
- FoundAst::Found(&InlinedItem::Foreign(ref item)) => {
- ccx.external().borrow_mut().insert(fn_id, Some(item.id));
- ccx.external_srcs().borrow_mut().insert(item.id, fn_id);
- item.id
- }
- FoundAst::FoundParent(parent_id, item) => {
- ccx.external().borrow_mut().insert(parent_id, Some(item.id));
- ccx.external_srcs().borrow_mut().insert(item.id, parent_id);
-
- let mut my_id = 0;
- match item.node {
- hir::ItemEnum(ref ast_def, _) => {
- let ast_vs = &ast_def.variants;
- let ty_vs = &tcx.lookup_adt_def(parent_id).variants;
- assert_eq!(ast_vs.len(), ty_vs.len());
- for (ast_v, ty_v) in ast_vs.iter().zip(ty_vs.iter()) {
- if ty_v.did == fn_id { my_id = ast_v.node.data.id(); }
- ccx.external().borrow_mut().insert(ty_v.did, Some(ast_v.node.data.id()));
- ccx.external_srcs().borrow_mut().insert(ast_v.node.data.id(), ty_v.did);
- }
- }
- hir::ItemStruct(ref struct_def, _) => {
- if struct_def.is_struct() {
- bug!("instantiate_inline: called on a \
- non-tuple struct")
- } else {
- ccx.external().borrow_mut().insert(fn_id, Some(struct_def.id()));
- ccx.external_srcs().borrow_mut().insert(struct_def.id(), fn_id);
- my_id = struct_def.id();
- }
- }
- _ => bug!("instantiate_inline: item has a \
- non-enum, non-struct parent")
- }
- my_id
- }
- FoundAst::Found(&InlinedItem::TraitItem(_, ref trait_item)) => {
- ccx.external().borrow_mut().insert(fn_id, Some(trait_item.id));
- ccx.external_srcs().borrow_mut().insert(trait_item.id, fn_id);
-
- ccx.stats().n_inlines.set(ccx.stats().n_inlines.get() + 1);
-
- // Associated consts already have to be evaluated in `typeck`, so
- // the logic to do that already exists in `middle`. In order to
- // reuse that code, it needs to be able to look up the traits for
- // inlined items.
- let ty_trait_item = tcx.impl_or_trait_item(fn_id).clone();
- let trait_item_def_id = tcx.map.local_def_id(trait_item.id);
- tcx.impl_or_trait_items.borrow_mut()
- .insert(trait_item_def_id, ty_trait_item);
-
- // If this is a default method, we can't look up the
- // impl type. But we aren't going to translate anyways, so
- // don't.
- trait_item.id
- }
- FoundAst::Found(&InlinedItem::ImplItem(_, ref impl_item)) => {
- ccx.external().borrow_mut().insert(fn_id, Some(impl_item.id));
- ccx.external_srcs().borrow_mut().insert(impl_item.id, fn_id);
-
- ccx.stats().n_inlines.set(ccx.stats().n_inlines.get() + 1);
-
- impl_item.id
- }
- };
-
- let inline_def_id = tcx.map.local_def_id(inline_id);
- Some(inline_def_id)
+ tcx.sess
+ .cstore
+ .maybe_get_item_ast(tcx, fn_id)
+ .map(|(_, inline_id)| {
+ tcx.map.local_def_id(inline_id)
+ })
}
pub fn get_local_instance(ccx: &CrateContext, fn_id: DefId)
diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs
index f033b27..2f27aed 100644
--- a/src/librustc_trans/intrinsic.rs
+++ b/src/librustc_trans/intrinsic.rs
@@ -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,13 +36,13 @@
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;
use syntax::parse::token;
use rustc::session::Session;
+use rustc_const_eval::fatal_const_eval_err;
use syntax_pos::{Span, DUMMY_SP};
use std::cmp::Ordering;
@@ -641,28 +640,30 @@
// This requires that atomic intrinsics follow a specific naming pattern:
// "atomic_<operation>[_<ordering>]", and no ordering means SeqCst
(_, name) if name.starts_with("atomic_") => {
+ use llvm::AtomicOrdering::*;
+
let split: Vec<&str> = name.split('_').collect();
let is_cxchg = split[1] == "cxchg" || split[1] == "cxchgweak";
let (order, failorder) = match split.len() {
- 2 => (llvm::SequentiallyConsistent, llvm::SequentiallyConsistent),
+ 2 => (SequentiallyConsistent, SequentiallyConsistent),
3 => match split[2] {
- "unordered" => (llvm::Unordered, llvm::Unordered),
- "relaxed" => (llvm::Monotonic, llvm::Monotonic),
- "acq" => (llvm::Acquire, llvm::Acquire),
- "rel" => (llvm::Release, llvm::Monotonic),
- "acqrel" => (llvm::AcquireRelease, llvm::Acquire),
+ "unordered" => (Unordered, Unordered),
+ "relaxed" => (Monotonic, Monotonic),
+ "acq" => (Acquire, Acquire),
+ "rel" => (Release, Monotonic),
+ "acqrel" => (AcquireRelease, Acquire),
"failrelaxed" if is_cxchg =>
- (llvm::SequentiallyConsistent, llvm::Monotonic),
+ (SequentiallyConsistent, Monotonic),
"failacq" if is_cxchg =>
- (llvm::SequentiallyConsistent, llvm::Acquire),
+ (SequentiallyConsistent, Acquire),
_ => ccx.sess().fatal("unknown ordering in atomic intrinsic")
},
4 => match (split[2], split[3]) {
("acq", "failrelaxed") if is_cxchg =>
- (llvm::Acquire, llvm::Monotonic),
+ (Acquire, Monotonic),
("acqrel", "failrelaxed") if is_cxchg =>
- (llvm::AcquireRelease, llvm::Monotonic),
+ (AcquireRelease, Monotonic),
_ => ccx.sess().fatal("unknown ordering in atomic intrinsic")
},
_ => ccx.sess().fatal("Atomic intrinsic not in correct format"),
@@ -715,12 +716,12 @@
}
"fence" => {
- AtomicFence(bcx, order, llvm::CrossThread);
+ AtomicFence(bcx, order, llvm::SynchronizationScope::CrossThread);
C_nil(ccx)
}
"singlethreadfence" => {
- AtomicFence(bcx, order, llvm::SingleThread);
+ AtomicFence(bcx, order, llvm::SynchronizationScope::SingleThread);
C_nil(ccx)
}
@@ -1172,7 +1173,6 @@
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:
@@ -1192,20 +1192,6 @@
// 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");
@@ -1223,7 +1209,7 @@
// 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()));
@@ -1414,7 +1400,10 @@
// this should probably help simd error reporting
consts::TrueConst::Yes) {
Ok((vector, _)) => vector,
- Err(err) => bcx.sess().span_fatal(span, &err.description()),
+ Err(err) => {
+ fatal_const_eval_err(bcx.tcx(), err.as_inner(), span,
+ "shuffle indices");
+ }
}
}
None => llargs[2]
diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs
index fa0a1fd..81a1dbe 100644
--- a/src/librustc_trans/lib.rs
+++ b/src/librustc_trans/lib.rs
@@ -37,6 +37,8 @@
#![feature(unicode)]
#![feature(question_mark)]
+use rustc::dep_graph::WorkProduct;
+
extern crate arena;
extern crate flate;
extern crate getopts;
@@ -86,6 +88,7 @@
mod abi;
mod adt;
mod asm;
+mod assert_module_sources;
mod attributes;
mod base;
mod basic_block;
@@ -132,7 +135,27 @@
#[derive(Clone)]
pub struct ModuleTranslation {
+ /// The name of the module. When the crate may be saved between
+ /// compilations, incremental compilation requires that name be
+ /// unique amongst **all** crates. Therefore, it should contain
+ /// something unique to this crate (e.g., a module path) as well
+ /// as the crate name and disambiguator.
pub name: String,
+ pub symbol_name_hash: u64,
+ pub source: ModuleSource,
+}
+
+#[derive(Clone)]
+pub enum ModuleSource {
+ /// Copy the `.o` files or whatever from the incr. comp. directory.
+ Preexisting(WorkProduct),
+
+ /// Rebuild from this LLVM module.
+ Translated(ModuleLlvm),
+}
+
+#[derive(Copy, Clone)]
+pub struct ModuleLlvm {
pub llcx: llvm::ContextRef,
pub llmod: llvm::ModuleRef,
}
diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs
index 7a7f190..2d1769b 100644
--- a/src/librustc_trans/mir/block.rs
+++ b/src/librustc_trans/mir/block.rs
@@ -284,6 +284,7 @@
// After this point, bcx is the block for the call to panic.
bcx = panic_block.build();
+ debug_loc.apply_to_bcx(&bcx);
// Get the location information.
let loc = bcx.sess().codemap().lookup_char_pos(span.lo);
diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs
index da72793..00db19d 100644
--- a/src/librustc_trans/mir/constant.rs
+++ b/src/librustc_trans/mir/constant.rs
@@ -530,26 +530,10 @@
// 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 {
@@ -840,11 +824,11 @@
mir::BinOp::Gt | mir::BinOp::Ge => {
if is_float {
let cmp = base::bin_op_to_fcmp_predicate(op.to_hir_binop());
- llvm::ConstFCmp(cmp, lhs, rhs)
+ llvm::LLVMConstFCmp(cmp, lhs, rhs)
} else {
let cmp = base::bin_op_to_icmp_predicate(op.to_hir_binop(),
signed);
- llvm::ConstICmp(cmp, lhs, rhs)
+ llvm::LLVMConstICmp(cmp, lhs, rhs)
}
}
}
@@ -925,7 +909,7 @@
}
Err(ConstEvalFailure::Runtime(err)) => {
span_bug!(constant.span,
- "MIR constant {:?} results in runtime panic: {}",
+ "MIR constant {:?} results in runtime panic: {:?}",
constant, err.description())
}
}
diff --git a/src/librustc_trans/mir/mod.rs b/src/librustc_trans/mir/mod.rs
index 0221232..8f723d2 100644
--- a/src/librustc_trans/mir/mod.rs
+++ b/src/librustc_trans/mir/mod.rs
@@ -324,8 +324,8 @@
machine::llelement_offset(bcx.ccx(), lltuplety, i);
let ops = unsafe {
- [llvm::LLVMDIBuilderCreateOpDeref(),
- llvm::LLVMDIBuilderCreateOpPlus(),
+ [llvm::LLVMRustDIBuilderCreateOpDeref(),
+ llvm::LLVMRustDIBuilderCreateOpPlus(),
byte_offset_of_var_in_tuple as i64]
};
@@ -450,10 +450,10 @@
machine::llelement_offset(bcx.ccx(), llclosurety, i);
let ops = unsafe {
- [llvm::LLVMDIBuilderCreateOpDeref(),
- llvm::LLVMDIBuilderCreateOpPlus(),
+ [llvm::LLVMRustDIBuilderCreateOpDeref(),
+ llvm::LLVMRustDIBuilderCreateOpPlus(),
byte_offset_of_var_in_env as i64,
- llvm::LLVMDIBuilderCreateOpDeref()]
+ llvm::LLVMRustDIBuilderCreateOpDeref()]
};
// The environment and the capture can each be indirect.
diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs
index c3f2c4f..97d65ce 100644
--- a/src/librustc_trans/mir/rvalue.rs
+++ b/src/librustc_trans/mir/rvalue.rs
@@ -131,27 +131,11 @@
_ => {
// 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() {
@@ -260,18 +244,46 @@
}
}
}
- mir::CastKind::Misc if common::type_is_immediate(bcx.ccx(), operand.ty) => {
+ mir::CastKind::Misc if common::type_is_fat_ptr(bcx.tcx(), operand.ty) => {
+ let ll_cast_ty = type_of::immediate_type_of(bcx.ccx(), cast_ty);
+ let ll_from_ty = type_of::immediate_type_of(bcx.ccx(), operand.ty);
+ if let OperandValue::Pair(data_ptr, meta_ptr) = operand.val {
+ if common::type_is_fat_ptr(bcx.tcx(), cast_ty) {
+ let ll_cft = ll_cast_ty.field_types();
+ let ll_fft = ll_from_ty.field_types();
+ let data_cast = bcx.pointercast(data_ptr, ll_cft[0]);
+ assert_eq!(ll_cft[1].kind(), ll_fft[1].kind());
+ OperandValue::Pair(data_cast, meta_ptr)
+ } else { // cast to thin-ptr
+ // Cast of fat-ptr to thin-ptr is an extraction of data-ptr and
+ // pointer-cast of that pointer to desired pointer type.
+ let llval = bcx.pointercast(data_ptr, ll_cast_ty);
+ OperandValue::Immediate(llval)
+ }
+ } else {
+ bug!("Unexpected non-Pair operand")
+ }
+ }
+ mir::CastKind::Misc => {
debug_assert!(common::type_is_immediate(bcx.ccx(), cast_ty));
let r_t_in = CastTy::from_ty(operand.ty).expect("bad input type for cast");
let r_t_out = CastTy::from_ty(cast_ty).expect("bad output type for cast");
let ll_t_in = type_of::immediate_type_of(bcx.ccx(), operand.ty);
let ll_t_out = type_of::immediate_type_of(bcx.ccx(), cast_ty);
- let llval = operand.immediate();
- let signed = if let CastTy::Int(IntTy::CEnum) = r_t_in {
+ let (llval, signed) = if let CastTy::Int(IntTy::CEnum) = r_t_in {
let repr = adt::represent_type(bcx.ccx(), operand.ty);
- adt::is_discr_signed(&repr)
+ let discr = match operand.val {
+ OperandValue::Immediate(llval) => llval,
+ OperandValue::Ref(llptr) => {
+ bcx.with_block(|bcx| {
+ adt::trans_get_discr(bcx, &repr, llptr, None, true)
+ })
+ }
+ OperandValue::Pair(..) => bug!("Unexpected Pair operand")
+ };
+ (discr, adt::is_discr_signed(&repr))
} else {
- operand.ty.is_signed()
+ (operand.immediate(), operand.ty.is_signed())
};
let newval = match (r_t_in, r_t_out) {
@@ -320,26 +332,6 @@
};
OperandValue::Immediate(newval)
}
- mir::CastKind::Misc => { // Casts from a fat-ptr.
- let ll_cast_ty = type_of::immediate_type_of(bcx.ccx(), cast_ty);
- let ll_from_ty = type_of::immediate_type_of(bcx.ccx(), operand.ty);
- if let OperandValue::Pair(data_ptr, meta_ptr) = operand.val {
- if common::type_is_fat_ptr(bcx.tcx(), cast_ty) {
- let ll_cft = ll_cast_ty.field_types();
- let ll_fft = ll_from_ty.field_types();
- let data_cast = bcx.pointercast(data_ptr, ll_cft[0]);
- assert_eq!(ll_cft[1].kind(), ll_fft[1].kind());
- OperandValue::Pair(data_cast, meta_ptr)
- } else { // cast to thin-ptr
- // Cast of fat-ptr to thin-ptr is an extraction of data-ptr and
- // pointer-cast of that pointer to desired pointer type.
- let llval = bcx.pointercast(data_ptr, ll_cast_ty);
- OperandValue::Immediate(llval)
- }
- } else {
- bug!("Unexpected non-Pair operand")
- }
- }
};
let operand = OperandRef {
val: val,
diff --git a/src/librustc_trans/monomorphize.rs b/src/librustc_trans/monomorphize.rs
index 00c0e91..e9aacaa 100644
--- a/src/librustc_trans/monomorphize.rs
+++ b/src/librustc_trans/monomorphize.rs
@@ -52,7 +52,7 @@
debug!("leaving monomorphic fn {:?}", instance);
return (val, mono_ty);
} else {
- assert!(!ccx.codegen_unit().items.contains_key(&TransItem::Fn(instance)));
+ assert!(!ccx.codegen_unit().contains_item(&TransItem::Fn(instance)));
}
debug!("monomorphic_fn({:?})", instance);
@@ -125,7 +125,9 @@
if ccx.shared().translation_items().borrow().contains(&trans_item) {
attributes::from_fn_attrs(ccx, attrs, lldecl);
- llvm::SetLinkage(lldecl, llvm::ExternalLinkage);
+ unsafe {
+ llvm::LLVMSetLinkage(lldecl, llvm::ExternalLinkage);
+ }
} else {
// FIXME: #34151
// Normally, getting here would indicate a bug in trans::collector,
diff --git a/src/librustc_trans/partitioning.rs b/src/librustc_trans/partitioning.rs
index 8073359..ade6e8a 100644
--- a/src/librustc_trans/partitioning.rs
+++ b/src/librustc_trans/partitioning.rs
@@ -119,12 +119,15 @@
use collector::InliningMap;
use llvm;
use monomorphize;
+use rustc::dep_graph::{DepNode, WorkProductId};
use rustc::hir::def_id::DefId;
use rustc::hir::map::DefPathData;
use rustc::session::config::NUMBERED_CODEGEN_UNIT_MARKER;
use rustc::ty::TyCtxt;
use rustc::ty::item_path::characteristic_def_id_of_type;
use std::cmp::Ordering;
+use std::hash::{Hash, Hasher, SipHasher};
+use std::sync::Arc;
use symbol_map::SymbolMap;
use syntax::ast::NodeId;
use syntax::parse::token::{self, InternedString};
@@ -140,11 +143,59 @@
}
pub struct CodegenUnit<'tcx> {
- pub name: InternedString,
- pub items: FnvHashMap<TransItem<'tcx>, llvm::Linkage>,
+ /// A name for this CGU. Incremental compilation requires that
+ /// name be unique amongst **all** crates. Therefore, it should
+ /// contain something unique to this crate (e.g., a module path)
+ /// as well as the crate name and disambiguator.
+ name: InternedString,
+
+ items: FnvHashMap<TransItem<'tcx>, llvm::Linkage>,
}
impl<'tcx> CodegenUnit<'tcx> {
+ pub fn new(name: InternedString,
+ items: FnvHashMap<TransItem<'tcx>, llvm::Linkage>)
+ -> Self {
+ CodegenUnit {
+ name: name,
+ items: items,
+ }
+ }
+
+ pub fn empty(name: InternedString) -> Self {
+ Self::new(name, FnvHashMap())
+ }
+
+ pub fn contains_item(&self, item: &TransItem<'tcx>) -> bool {
+ self.items.contains_key(item)
+ }
+
+ pub fn name(&self) -> &str {
+ &self.name
+ }
+
+ pub fn items(&self) -> &FnvHashMap<TransItem<'tcx>, llvm::Linkage> {
+ &self.items
+ }
+
+ pub fn work_product_id(&self) -> Arc<WorkProductId> {
+ Arc::new(WorkProductId(self.name().to_string()))
+ }
+
+ pub fn work_product_dep_node(&self) -> DepNode<DefId> {
+ DepNode::WorkProduct(self.work_product_id())
+ }
+
+ pub fn compute_symbol_name_hash(&self, tcx: TyCtxt, symbol_map: &SymbolMap) -> u64 {
+ let mut state = SipHasher::new();
+ let all_items = self.items_in_deterministic_order(tcx, symbol_map);
+ for (item, _) in all_items {
+ let symbol_name = symbol_map.get(item).unwrap();
+ symbol_name.hash(&mut state);
+ }
+ state.finish()
+ }
+
pub fn items_in_deterministic_order(&self,
tcx: TyCtxt,
symbol_map: &SymbolMap)
@@ -277,10 +328,7 @@
};
let make_codegen_unit = || {
- CodegenUnit {
- name: codegen_unit_name.clone(),
- items: FnvHashMap(),
- }
+ CodegenUnit::empty(codegen_unit_name.clone())
};
let mut codegen_unit = codegen_units.entry(codegen_unit_name.clone())
@@ -319,10 +367,7 @@
if codegen_units.is_empty() {
let codegen_unit_name = InternedString::new(FALLBACK_CODEGEN_UNIT);
codegen_units.entry(codegen_unit_name.clone())
- .or_insert_with(|| CodegenUnit {
- name: codegen_unit_name.clone(),
- items: FnvHashMap(),
- });
+ .or_insert_with(|| CodegenUnit::empty(codegen_unit_name.clone()));
}
PreInliningPartitioning {
@@ -362,10 +407,8 @@
// we reach the target count
while codegen_units.len() < target_cgu_count {
let index = codegen_units.len();
- codegen_units.push(CodegenUnit {
- name: numbered_codegen_unit_name(crate_name, index),
- items: FnvHashMap()
- });
+ codegen_units.push(
+ CodegenUnit::empty(numbered_codegen_unit_name(crate_name, index)));
}
}
@@ -381,10 +424,8 @@
follow_inlining(*root, inlining_map, &mut reachable);
}
- let mut new_codegen_unit = CodegenUnit {
- name: codegen_unit.name.clone(),
- items: FnvHashMap(),
- };
+ let mut new_codegen_unit =
+ CodegenUnit::empty(codegen_unit.name.clone());
// Add all translation items that are not already there
for trans_item in reachable {
@@ -560,10 +601,9 @@
items.insert(trans_item, linkage);
}
- CodegenUnit {
- name: numbered_codegen_unit_name(&tcx.crate_name[..], 0),
- items: items
- }
+ CodegenUnit::new(
+ numbered_codegen_unit_name(&tcx.crate_name[..], 0),
+ items)
}
fn numbered_codegen_unit_name(crate_name: &str, index: usize) -> InternedString {
diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs
index 8b8e658..35bb048 100644
--- a/src/librustc_trans/trans_item.rs
+++ b/src/librustc_trans/trans_item.rs
@@ -23,12 +23,13 @@
use llvm;
use monomorphize::{self, Instance};
use inline;
+use rustc::dep_graph::DepNode;
use rustc::hir;
use rustc::hir::map as hir_map;
use rustc::hir::def_id::DefId;
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
use rustc::ty::subst;
-use rustc::dep_graph::DepNode;
+use rustc_const_eval::fatal_const_eval_err;
use std::hash::{Hash, Hasher};
use syntax::ast::{self, NodeId};
use syntax::{attr,errors};
@@ -67,27 +68,45 @@
impl<'a, 'tcx> TransItem<'tcx> {
pub fn define(&self, ccx: &CrateContext<'a, 'tcx>) {
-
debug!("BEGIN IMPLEMENTING '{} ({})' in cgu {}",
self.to_string(ccx.tcx()),
self.to_raw_string(),
- ccx.codegen_unit().name);
+ ccx.codegen_unit().name());
+
+ // (*) This code executes in the context of a dep-node for the
+ // entire CGU. In some cases, we introduce dep-nodes for
+ // particular items that we are translating (these nodes will
+ // have read edges coming into the CGU node). These smaller
+ // nodes are not needed for correctness -- we always
+ // invalidate an entire CGU at a time -- but they enable
+ // finer-grained testing, since you can write tests that check
+ // that the incoming edges to a particular fn are from a
+ // particular set.
self.register_reads(ccx);
match *self {
TransItem::Static(node_id) => {
+ let def_id = ccx.tcx().map.local_def_id(node_id);
+ let _task = ccx.tcx().dep_graph.in_task(DepNode::TransCrateItem(def_id)); // (*)
let item = ccx.tcx().map.expect_item(node_id);
if let hir::ItemStatic(_, m, ref expr) = item.node {
match consts::trans_static(&ccx, m, expr, item.id, &item.attrs) {
Ok(_) => { /* Cool, everything's alright. */ },
- Err(err) => ccx.tcx().sess.span_fatal(expr.span, &err.description()),
+ Err(err) => {
+ // FIXME: shouldn't this be a `span_err`?
+ fatal_const_eval_err(
+ ccx.tcx(), &err, expr.span, "static");
+ }
};
} else {
span_bug!(item.span, "Mismatch between hir::Item type and TransItem type")
}
}
TransItem::Fn(instance) => {
+ let _task = ccx.tcx().dep_graph.in_task(
+ DepNode::TransCrateItem(instance.def)); // (*)
+
base::trans_instance(&ccx, instance);
}
TransItem::DropGlue(dg) => {
@@ -98,7 +117,7 @@
debug!("END IMPLEMENTING '{} ({})' in cgu {}",
self.to_string(ccx.tcx()),
self.to_raw_string(),
- ccx.codegen_unit().name);
+ ccx.codegen_unit().name());
}
/// If necessary, creates a subtask for trans'ing a particular item and registers reads on
@@ -147,7 +166,7 @@
debug!("BEGIN PREDEFINING '{} ({})' in cgu {}",
self.to_string(ccx.tcx()),
self.to_raw_string(),
- ccx.codegen_unit().name);
+ ccx.codegen_unit().name());
let symbol_name = ccx.symbol_map()
.get_or_compute(ccx.shared(), *self);
@@ -169,7 +188,7 @@
debug!("END PREDEFINING '{} ({})' in cgu {}",
self.to_string(ccx.tcx()),
self.to_raw_string(),
- ccx.codegen_unit().name);
+ ccx.codegen_unit().name());
}
fn predefine_static(ccx: &CrateContext<'a, 'tcx>,
@@ -189,7 +208,7 @@
&format!("symbol `{}` is already defined", symbol_name))
});
- llvm::SetLinkage(g, linkage);
+ unsafe { llvm::LLVMSetLinkage(g, linkage) };
}
item => bug!("predefine_static: expected static, found {:?}", item)
@@ -231,7 +250,7 @@
ref attrs, node: hir::ImplItemKind::Method(..), ..
}) => {
let lldecl = declare::declare_fn(ccx, symbol_name, mono_ty);
- llvm::SetLinkage(lldecl, linkage);
+ unsafe { llvm::LLVMSetLinkage(lldecl, linkage) };
base::set_link_section(ccx, lldecl, attrs);
if linkage == llvm::LinkOnceODRLinkage ||
linkage == llvm::WeakODRLinkage {
@@ -268,7 +287,7 @@
assert!(declare::get_defined_value(ccx, symbol_name).is_none());
let llfn = declare::declare_cfn(ccx, symbol_name, llfnty);
- llvm::SetLinkage(llfn, linkage);
+ unsafe { llvm::LLVMSetLinkage(llfn, linkage) };
if linkage == llvm::LinkOnceODRLinkage ||
linkage == llvm::WeakODRLinkage {
llvm::SetUniqueComdat(ccx.llmod(), llfn);
diff --git a/src/librustc_trans/tvec.rs b/src/librustc_trans/tvec.rs
index f5b9bef..92a2d37 100644
--- a/src/librustc_trans/tvec.rs
+++ b/src/librustc_trans/tvec.rs
@@ -30,7 +30,7 @@
use rustc::ty::{self, Ty};
use rustc::hir;
-use rustc_const_eval::eval_repeat_count;
+use rustc_const_eval::eval_length;
use syntax::ast;
use syntax::parse::token::InternedString;
@@ -218,7 +218,7 @@
return expr::trans_into(bcx, &element, Ignore);
}
SaveIn(lldest) => {
- match eval_repeat_count(bcx.tcx(), &count_expr) {
+ match eval_length(bcx.tcx(), &count_expr, "repeat count").unwrap() {
0 => expr::trans_into(bcx, &element, Ignore),
1 => expr::trans_into(bcx, &element, SaveIn(lldest)),
count => {
@@ -268,7 +268,7 @@
},
hir::ExprVec(ref es) => es.len(),
hir::ExprRepeat(_, ref count_expr) => {
- eval_repeat_count(bcx.tcx(), &count_expr)
+ eval_length(bcx.tcx(), &count_expr, "repeat count").unwrap()
}
_ => span_bug!(content_expr.span, "unexpected vec content")
}
diff --git a/src/librustc_trans/type_.rs b/src/librustc_trans/type_.rs
index 001cd19..d191591 100644
--- a/src/librustc_trans/type_.rs
+++ b/src/librustc_trans/type_.rs
@@ -36,7 +36,7 @@
impl fmt::Debug for Type {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(&llvm::build_string(|s| unsafe {
- llvm::LLVMWriteTypeToString(self.to_ref(), s);
+ llvm::LLVMRustWriteTypeToString(self.to_ref(), s);
}).expect("non-UTF8 type description from LLVM"))
}
}
@@ -72,7 +72,7 @@
}
pub fn metadata(ccx: &CrateContext) -> Type {
- ty!(llvm::LLVMMetadataTypeInContext(ccx.llcx()))
+ ty!(llvm::LLVMRustMetadataTypeInContext(ccx.llcx()))
}
pub fn i1(ccx: &CrateContext) -> Type {
@@ -208,7 +208,7 @@
pub fn kind(&self) -> TypeKind {
unsafe {
- llvm::LLVMGetTypeKind(self.to_ref())
+ llvm::LLVMRustGetTypeKind(self.to_ref())
}
}
diff --git a/src/librustc_trans/value.rs b/src/librustc_trans/value.rs
index 00b316c..79e0c11 100644
--- a/src/librustc_trans/value.rs
+++ b/src/librustc_trans/value.rs
@@ -23,7 +23,7 @@
impl fmt::Debug for Value {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(&llvm::build_string(|s| unsafe {
- llvm::LLVMWriteValueToString(self.0, s);
+ llvm::LLVMRustWriteValueToString(self.0, s);
}).expect("nun-UTF8 value description from LLVM"))
}
}
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 9ff30f9..3b2bca4 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -48,10 +48,7 @@
//! case but `&a` in the second. Basically, defaults that appear inside
//! an rptr (`&r.T`) use the region `r` that appears in the rptr.
-use middle::const_val::ConstVal;
-use rustc_const_eval::{eval_const_expr_partial, ConstEvalErr};
-use rustc_const_eval::EvalHint::UncheckedExprHint;
-use rustc_const_eval::ErrKind::ErroneousReferencedConstant;
+use rustc_const_eval::eval_length;
use hir::{self, SelfKind};
use hir::def::{Def, PathResolution};
use hir::def_id::DefId;
@@ -70,7 +67,6 @@
use util::common::{ErrorReported, FN_OUTPUT_NAME};
use util::nodemap::{NodeMap, FnvHashSet};
-use rustc_const_math::ConstInt;
use std::cell::RefCell;
use syntax::{abi, ast};
use syntax::feature_gate::{GateIssue, emit_feature_err};
@@ -1317,6 +1313,12 @@
// item is declared.
let bound = match (&ty.sty, ty_path_def) {
(_, Def::SelfTy(Some(trait_did), Some(impl_id))) => {
+ // For Def::SelfTy() values inlined from another crate, the
+ // impl_id will be DUMMY_NODE_ID, which would cause problems
+ // here. But we should never run into an impl from another crate
+ // in this pass.
+ assert!(impl_id != ast::DUMMY_NODE_ID);
+
// `Self` in an impl of a trait - we have a concrete self type and a
// trait reference.
let trait_ref = tcx.impl_trait_ref(tcx.map.local_def_id(impl_id)).unwrap();
@@ -1522,6 +1524,13 @@
}
Def::SelfTy(_, Some(impl_id)) => {
// Self in impl (we know the concrete type).
+
+ // For Def::SelfTy() values inlined from another crate, the
+ // impl_id will be DUMMY_NODE_ID, which would cause problems
+ // here. But we should never run into an impl from another crate
+ // in this pass.
+ assert!(impl_id != ast::DUMMY_NODE_ID);
+
tcx.prohibit_type_params(base_segments);
let ty = tcx.node_id_to_type(impl_id);
if let Some(free_substs) = self.get_free_substs() {
@@ -1741,33 +1750,10 @@
ty
}
hir::TyFixedLengthVec(ref ty, ref e) => {
- let hint = UncheckedExprHint(tcx.types.usize);
- match eval_const_expr_partial(tcx.global_tcx(), &e, hint, None) {
- Ok(ConstVal::Integral(ConstInt::Usize(i))) => {
- let i = i.as_u64(tcx.sess.target.uint_type);
- assert_eq!(i as usize as u64, i);
- tcx.mk_array(self.ast_ty_to_ty(rscope, &ty), i as usize)
- },
- Ok(val) => {
- span_err!(tcx.sess, ast_ty.span, E0249,
- "expected usize value for array length, got {}",
- val.description());
- self.tcx().types.err
- },
- // array length errors happen before the global constant check
- // so we need to report the real error
- Err(ConstEvalErr { kind: ErroneousReferencedConstant(box r), ..}) |
- Err(r) => {
- let mut err = struct_span_err!(tcx.sess, r.span, E0250,
- "array length constant \
- evaluation error: {}",
- r.description());
- if !ast_ty.span.contains(r.span) {
- span_note!(&mut err, ast_ty.span, "for array length here")
- }
- err.emit();
- self.tcx().types.err
- }
+ if let Ok(length) = eval_length(tcx.global_tcx(), &e, "array length") {
+ tcx.mk_array(self.ast_ty_to_ty(rscope, &ty), length)
+ } else {
+ self.tcx().types.err
}
}
hir::TyTypeof(ref _e) => {
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index e90b32c..aae6e3a 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -103,15 +103,6 @@
return;
}
- // Check that the types of the end-points can be unified.
- let types_unify = self.require_same_types(pat.span, rhs_ty, lhs_ty,
- "mismatched types in range");
-
- // It's ok to return without a message as `require_same_types` prints an error.
- if !types_unify {
- return;
- }
-
// Now that we know the types can be unified we find the unified type and use
// it to type the entire expression.
let common_type = self.resolve_type_vars_if_possible(&lhs_ty);
@@ -120,6 +111,7 @@
// subtyping doesn't matter here, as the value is some kind of scalar
self.demand_eqtype(pat.span, expected, lhs_ty);
+ self.demand_eqtype(pat.span, expected, rhs_ty);
}
PatKind::Binding(bm, _, ref sub) => {
let typ = self.local_ty(pat.span, pat.id);
diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs
index 2c7e7d2..bd2c05b 100644
--- a/src/librustc_typeck/check/callee.rs
+++ b/src/librustc_typeck/check/callee.rs
@@ -27,33 +27,8 @@
/// to `trait_id` (this only cares about the trait, not the specific
/// method that is called)
pub fn check_legal_trait_for_method_call(ccx: &CrateCtxt, span: Span, trait_id: DefId) {
- let tcx = ccx.tcx;
- let did = Some(trait_id);
- let li = &tcx.lang_items;
-
- if did == li.drop_trait() {
- span_err!(tcx.sess, span, E0040, "explicit use of destructor method");
- } else if !tcx.sess.features.borrow().unboxed_closures {
- // the #[feature(unboxed_closures)] feature isn't
- // activated so we need to enforce the closure
- // restrictions.
-
- let method = if did == li.fn_trait() {
- "call"
- } else if did == li.fn_mut_trait() {
- "call_mut"
- } else if did == li.fn_once_trait() {
- "call_once"
- } else {
- return // not a closure method, everything is OK.
- };
-
- struct_span_err!(tcx.sess, span, E0174,
- "explicit use of unboxed closure method `{}` is experimental",
- method)
- .help("add `#![feature(unboxed_closures)]` to the crate \
- attributes to enable")
- .emit();
+ if ccx.tcx.lang_items.drop_trait() == Some(trait_id) {
+ span_err!(ccx.tcx.sess, span, E0040, "explicit use of destructor method");
}
}
@@ -216,7 +191,7 @@
_ => {
let mut err = self.type_error_struct(call_expr.span, |actual| {
format!("expected function, found `{}`", actual)
- }, callee_ty, None);
+ }, callee_ty);
if let hir::ExprCall(ref expr, _) = call_expr.node {
let tcx = self.tcx;
diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs
index 22ac8bc..7a4cc09 100644
--- a/src/librustc_typeck/check/cast.rs
+++ b/src/librustc_typeck/check/cast.rs
@@ -149,7 +149,7 @@
format!("casting `{}` as `{}` is invalid",
actual,
fcx.ty_to_string(self.cast_ty))
- }, self.expr_ty, None)
+ }, self.expr_ty)
.help(&format!("cast through {} first", match e {
CastError::NeedViaPtr => "a raw pointer",
CastError::NeedViaThinPtr => "a thin pointer",
@@ -167,35 +167,35 @@
CastError::CastToChar => {
fcx.type_error_message(self.span, |actual| {
format!("only `u8` can be cast as `char`, not `{}`", actual)
- }, self.expr_ty, None);
+ }, self.expr_ty);
}
CastError::NonScalar => {
fcx.type_error_message(self.span, |actual| {
format!("non-scalar cast: `{}` as `{}`",
actual,
fcx.ty_to_string(self.cast_ty))
- }, self.expr_ty, None);
+ }, self.expr_ty);
}
CastError::IllegalCast => {
fcx.type_error_message(self.span, |actual| {
format!("casting `{}` as `{}` is invalid",
actual,
fcx.ty_to_string(self.cast_ty))
- }, self.expr_ty, None);
+ }, self.expr_ty);
}
CastError::SizedUnsizedCast => {
fcx.type_error_message(self.span, |actual| {
format!("cannot cast thin pointer `{}` to fat pointer `{}`",
actual,
fcx.ty_to_string(self.cast_ty))
- }, self.expr_ty, None)
+ }, self.expr_ty)
}
CastError::DifferingKinds => {
fcx.type_error_struct(self.span, |actual| {
format!("casting `{}` as `{}` is invalid",
actual,
fcx.ty_to_string(self.cast_ty))
- }, self.expr_ty, None)
+ }, self.expr_ty)
.note("vtable kinds may not match")
.emit();
}
@@ -213,7 +213,7 @@
let tstr = fcx.ty_to_string(self.cast_ty);
let mut err = fcx.type_error_struct(self.span, |actual| {
format!("cast to unsized type: `{}` as `{}`", actual, tstr)
- }, self.expr_ty, None);
+ }, self.expr_ty);
match self.expr_ty.sty {
ty::TyRef(_, ty::TypeAndMut { mutbl: mt, .. }) => {
let mtstr = match mt {
@@ -484,4 +484,3 @@
traits::type_known_to_meet_builtin_bound(self, ty, ty::BoundSized, span)
}
}
-
diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs
index 35a5bc9..9844377 100644
--- a/src/librustc_typeck/check/compare_method.rs
+++ b/src/librustc_typeck/check/compare_method.rs
@@ -12,6 +12,7 @@
use rustc::infer::{self, InferOk, TypeOrigin};
use rustc::ty;
use rustc::traits::{self, ProjectionMode};
+use rustc::ty::error::ExpectedFound;
use rustc::ty::subst::{self, Subst, Substs, VecPerParamSpace};
use syntax::ast;
@@ -324,10 +325,19 @@
debug!("sub_types failed: impl ty {:?}, trait ty {:?}",
impl_fty,
trait_fty);
- span_err!(tcx.sess, impl_m_span, E0053,
- "method `{}` has an incompatible type for trait: {}",
- trait_m.name,
- terr);
+
+ let mut diag = struct_span_err!(
+ tcx.sess, origin.span(), E0053,
+ "method `{}` has an incompatible type for trait", trait_m.name
+ );
+ infcx.note_type_err(
+ &mut diag, origin,
+ Some(infer::ValuePairs::Types(ExpectedFound {
+ expected: trait_fty,
+ found: impl_fty
+ })), &terr
+ );
+ diag.emit();
return
}
@@ -437,10 +447,9 @@
// Compute skolemized form of impl and trait const tys.
let impl_ty = impl_c.ty.subst(tcx, impl_to_skol_substs);
let trait_ty = trait_c.ty.subst(tcx, &trait_to_skol_substs);
+ let origin = TypeOrigin::Misc(impl_c_span);
let err = infcx.commit_if_ok(|_| {
- let origin = TypeOrigin::Misc(impl_c_span);
-
// There is no "body" here, so just pass dummy id.
let impl_ty =
assoc::normalize_associated_types_in(&infcx,
@@ -473,11 +482,19 @@
debug!("checking associated const for compatibility: impl ty {:?}, trait ty {:?}",
impl_ty,
trait_ty);
- span_err!(tcx.sess, impl_c_span, E0326,
- "implemented const `{}` has an incompatible type for \
- trait: {}",
- trait_c.name,
- terr);
+ let mut diag = struct_span_err!(
+ tcx.sess, origin.span(), E0326,
+ "implemented const `{}` has an incompatible type for trait",
+ trait_c.name
+ );
+ infcx.note_type_err(
+ &mut diag, origin,
+ Some(infer::ValuePairs::Types(ExpectedFound {
+ expected: trait_ty,
+ found: impl_ty
+ })), &terr
+ );
+ diag.emit();
}
});
}
diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs
index eeebd6a..1f3a83e 100644
--- a/src/librustc_typeck/check/demand.rs
+++ b/src/librustc_typeck/check/demand.rs
@@ -33,7 +33,14 @@
}
pub fn demand_eqtype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) {
- let origin = TypeOrigin::Misc(sp);
+ self.demand_eqtype_with_origin(TypeOrigin::Misc(sp), expected, actual);
+ }
+
+ pub fn demand_eqtype_with_origin(&self,
+ origin: TypeOrigin,
+ expected: Ty<'tcx>,
+ actual: Ty<'tcx>)
+ {
match self.eq_types(false, origin, actual, expected) {
Ok(InferOk { obligations, .. }) => {
// FIXME(#32730) propagate obligations
@@ -54,16 +61,4 @@
self.report_mismatched_types(origin, expected, expr_ty, e);
}
}
-
- pub fn require_same_types(&self, span: Span, t1: Ty<'tcx>, t2: Ty<'tcx>, msg: &str)
- -> bool {
- if let Err(err) = self.eq_types(false, TypeOrigin::Misc(span), t1, t2) {
- let found_ty = self.resolve_type_vars_if_possible(&t1);
- let expected_ty = self.resolve_type_vars_if_possible(&t2);
- ::emit_type_err(self.tcx, span, found_ty, expected_ty, &err, msg);
- false
- } else {
- true
- }
- }
}
diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs
index 5a3268e..8a53c59 100644
--- a/src/librustc_typeck/check/intrinsic.rs
+++ b/src/librustc_typeck/check/intrinsic.rs
@@ -12,6 +12,7 @@
//! intrinsics that the compiler exposes.
use intrinsics;
+use rustc::infer::TypeOrigin;
use rustc::ty::subst::{self, Substs};
use rustc::ty::FnSig;
use rustc::ty::{self, Ty};
@@ -56,10 +57,9 @@
i_n_tps, n_tps);
} else {
require_same_types(ccx,
- it.span,
+ TypeOrigin::IntrinsicType(it.span),
i_ty.ty,
- fty,
- "intrinsic has wrong type");
+ fty);
}
}
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index f20dcdc..346449d 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -160,8 +160,7 @@
item_name,
actual)
},
- rcvr_ty,
- None);
+ rcvr_ty);
// If the item has the name of a field, give a help note
if let (&ty::TyStruct(def, substs), Some(expr)) = (&rcvr_ty.sty, rcvr_expr) {
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index fc1d223..6062bd0 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -126,7 +126,7 @@
use rustc::hir::{self, PatKind};
use rustc::hir::print as pprust;
use rustc_back::slice;
-use rustc_const_eval::eval_repeat_count;
+use rustc_const_eval::eval_length;
mod assoc;
mod autoderef;
@@ -2541,21 +2541,21 @@
self.type_error_message(arg.span, |t| {
format!("can't pass an `{}` to variadic \
function, cast to `c_double`", t)
- }, arg_ty, None);
+ }, arg_ty);
}
ty::TyInt(ast::IntTy::I8) | ty::TyInt(ast::IntTy::I16) | ty::TyBool => {
self.type_error_message(arg.span, |t| {
format!("can't pass `{}` to variadic \
function, cast to `c_int`",
t)
- }, arg_ty, None);
+ }, arg_ty);
}
ty::TyUint(ast::UintTy::U8) | ty::TyUint(ast::UintTy::U16) => {
self.type_error_message(arg.span, |t| {
format!("can't pass `{}` to variadic \
function, cast to `c_uint`",
t)
- }, arg_ty, None);
+ }, arg_ty);
}
ty::TyFnDef(_, _, f) => {
let ptr_ty = self.tcx.mk_fn_ptr(f);
@@ -2564,7 +2564,7 @@
|t| {
format!("can't pass `{}` to variadic \
function, cast to `{}`", t, ptr_ty)
- }, arg_ty, None);
+ }, arg_ty);
}
_ => {}
}
@@ -2908,9 +2908,8 @@
self.type_error_struct(field.span, |actual| {
format!("attempted to take value of method `{}` on type \
`{}`", field.node, actual)
- }, expr_t, None)
- .help(
- "maybe a `()` to call it is missing? \
+ }, expr_t)
+ .help("maybe a `()` to call it is missing? \
If not, try an anonymous function")
.emit();
self.write_error(expr.id);
@@ -2919,7 +2918,7 @@
format!("attempted access of field `{}` on type `{}`, \
but no field with that name was found",
field.node, actual)
- }, expr_t, None);
+ }, expr_t);
if let ty::TyStruct(def, _) = expr_t.sty {
Self::suggest_field_names(&mut err, def.struct_variant(), field, vec![]);
}
@@ -3019,7 +3018,7 @@
actual)
}
},
- expr_t, None);
+ expr_t);
self.write_error(expr.id);
}
@@ -3029,17 +3028,18 @@
variant: ty::VariantDef<'tcx>,
field: &hir::Field,
skip_fields: &[hir::Field]) {
- let mut err = self.type_error_struct(
+ let mut err = self.type_error_struct_with_diag(
field.name.span,
|actual| if let ty::TyEnum(..) = ty.sty {
- format!("struct variant `{}::{}` has no field named `{}`",
- actual, variant.name.as_str(), field.name.node)
+ struct_span_err!(self.tcx.sess, field.name.span, E0559,
+ "struct variant `{}::{}` has no field named `{}`",
+ actual, variant.name.as_str(), field.name.node)
} else {
- format!("structure `{}` has no field named `{}`",
- actual, field.name.node)
+ struct_span_err!(self.tcx.sess, field.name.span, E0560,
+ "structure `{}` has no field named `{}`",
+ actual, field.name.node)
},
- ty,
- None);
+ ty);
// prevent all specified fields from being suggested
let skip_fields = skip_fields.iter().map(|ref x| x.name.node.as_str());
Self::suggest_field_names(&mut err, variant, &field.name, skip_fields.collect());
@@ -3272,7 +3272,7 @@
self.type_error_message(expr.span, |actual| {
format!("type `{}` cannot be \
dereferenced", actual)
- }, oprnd_t, None);
+ }, oprnd_t);
oprnd_t = tcx.types.err;
}
}
@@ -3541,7 +3541,8 @@
}
hir::ExprRepeat(ref element, ref count_expr) => {
self.check_expr_has_type(&count_expr, tcx.types.usize);
- let count = eval_repeat_count(self.tcx.global_tcx(), &count_expr);
+ let count = eval_length(self.tcx.global_tcx(), &count_expr, "repeat count")
+ .unwrap_or(0);
let uty = match expected {
ExpectHasType(uty) => {
@@ -3647,8 +3648,7 @@
format!("cannot index a value of type `{}`",
actual)
},
- base_t,
- None);
+ base_t);
// Try to give some advice about indexing tuples.
if let ty::TyTuple(_) = base_t.sty {
let mut needs_note = true;
@@ -4523,7 +4523,7 @@
if !self.is_tainted_by_errors() {
self.type_error_message(sp, |_actual| {
"the type of this value must be known in this context".to_string()
- }, ty, None);
+ }, ty);
}
self.demand_suptype(sp, self.tcx.types.err, ty);
ty = self.tcx.types.err;
diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs
index 8604dad..d02f87d 100644
--- a/src/librustc_typeck/check/op.rs
+++ b/src/librustc_typeck/check/op.rs
@@ -239,7 +239,7 @@
self.type_error_message(ex.span, |actual| {
format!("cannot apply unary operator `{}` to type `{}`",
op_str, actual)
- }, operand_ty, None);
+ }, operand_ty);
self.tcx.types.err
}
}
diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs
index 702dd5f..030491b 100644
--- a/src/librustc_typeck/check/upvar.rs
+++ b/src/librustc_typeck/check/upvar.rs
@@ -47,11 +47,11 @@
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 @@
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_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 @@
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 @@
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 @@
{
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 @@
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 @@
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 @@
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 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_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 try_adjust_upvar_deref(&self,
+ fn try_adjust_upvar_deref(&mut self,
note: &mc::Note,
borrow_kind: ty::BorrowKind)
-> bool
@@ -430,7 +434,7 @@
/// 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_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;
- }
+ 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);
- 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();
+ 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
+ }
- 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
- }
-
- (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 @@
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);
}
}
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index d101381..34a91b2 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -13,6 +13,7 @@
use CrateCtxt;
use hir::def_id::DefId;
use middle::region::{CodeExtent};
+use rustc::infer::TypeOrigin;
use rustc::ty::subst::{self, TypeSpace, FnSpace, ParamSpace, SelfSpace};
use rustc::traits;
use rustc::ty::{self, Ty, TyCtxt};
@@ -157,7 +158,10 @@
}
}
- fn check_trait_or_impl_item(&mut self, item_id: ast::NodeId, span: Span) {
+ fn check_trait_or_impl_item(&mut self,
+ item_id: ast::NodeId,
+ span: Span,
+ sig_if_method: Option<&hir::MethodSig>) {
let code = self.code.clone();
self.for_id(item_id, span).with_fcx(|fcx, this| {
let free_substs = &fcx.parameter_environment.free_substs;
@@ -182,7 +186,8 @@
let predicates = fcx.instantiate_bounds(span, free_substs, &method.predicates);
this.check_fn_or_method(fcx, span, &method_ty, &predicates,
free_id_outlive, &mut implied_bounds);
- this.check_method_receiver(fcx, span, &method,
+ let sig_if_method = sig_if_method.expect("bad signature for method");
+ this.check_method_receiver(fcx, sig_if_method, &method,
free_id_outlive, self_ty);
}
ty::TypeTraitItem(assoc_type) => {
@@ -405,20 +410,15 @@
fn check_method_receiver<'fcx, 'tcx>(&mut self,
fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
- span: Span,
+ method_sig: &hir::MethodSig,
method: &ty::Method<'tcx>,
free_id_outlive: CodeExtent,
self_ty: ty::Ty<'tcx>)
{
// check that the type of the method's receiver matches the
// method's first parameter.
-
- let free_substs = &fcx.parameter_environment.free_substs;
- let fty = fcx.instantiate_type_scheme(span, free_substs, &method.fty);
- let sig = fcx.tcx.liberate_late_bound_regions(free_id_outlive, &fty.sig);
-
- debug!("check_method_receiver({:?},cat={:?},self_ty={:?},sig={:?})",
- method.name, method.explicit_self, self_ty, sig);
+ debug!("check_method_receiver({:?},cat={:?},self_ty={:?})",
+ method.name, method.explicit_self, self_ty);
let rcvr_ty = match method.explicit_self {
ty::ExplicitSelfCategory::Static => return,
@@ -431,20 +431,34 @@
}
ty::ExplicitSelfCategory::ByBox => fcx.tcx.mk_box(self_ty)
};
+
+ let span = method_sig.decl.inputs[0].pat.span;
+
+ let free_substs = &fcx.parameter_environment.free_substs;
+ let fty = fcx.instantiate_type_scheme(span, free_substs, &method.fty);
+ let sig = fcx.tcx.liberate_late_bound_regions(free_id_outlive, &fty.sig);
+
+ debug!("check_method_receiver: sig={:?}", sig);
+
let rcvr_ty = fcx.instantiate_type_scheme(span, free_substs, &rcvr_ty);
let rcvr_ty = fcx.tcx.liberate_late_bound_regions(free_id_outlive,
&ty::Binder(rcvr_ty));
debug!("check_method_receiver: receiver ty = {:?}", rcvr_ty);
- fcx.require_same_types(span, sig.inputs[0], rcvr_ty,
- "mismatched method receiver");
+ let origin = TypeOrigin::MethodReceiver(span);
+ fcx.demand_eqtype_with_origin(origin, rcvr_ty, sig.inputs[0]);
}
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);
@@ -553,13 +567,21 @@
fn visit_trait_item(&mut self, trait_item: &'v hir::TraitItem) {
debug!("visit_trait_item: {:?}", trait_item);
- self.check_trait_or_impl_item(trait_item.id, trait_item.span);
+ let method_sig = match trait_item.node {
+ hir::TraitItem_::MethodTraitItem(ref sig, _) => Some(sig),
+ _ => None
+ };
+ self.check_trait_or_impl_item(trait_item.id, trait_item.span, method_sig);
intravisit::walk_trait_item(self, trait_item)
}
fn visit_impl_item(&mut self, impl_item: &'v hir::ImplItem) {
debug!("visit_impl_item: {:?}", impl_item);
- self.check_trait_or_impl_item(impl_item.id, impl_item.span);
+ let method_sig = match impl_item.node {
+ hir::ImplItemKind::Method(ref sig, _) => Some(sig),
+ _ => None
+ };
+ self.check_trait_or_impl_item(impl_item.id, impl_item.span, method_sig);
intravisit::walk_impl_item(self, impl_item)
}
}
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 41e7a46..4486748 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -60,14 +60,11 @@
use astconv::{AstConv, ast_region_to_region, Bounds, PartitionedBounds, partition_bounds};
use lint;
-use hir::def::Def;
-use hir::def_id::DefId;
use constrained_type_params as ctp;
use middle::lang_items::SizedTraitLangItem;
use middle::const_val::ConstVal;
use rustc_const_eval::EvalHint::UncheckedExprHint;
-use rustc_const_eval::{eval_const_expr_partial, ConstEvalErr};
-use rustc_const_eval::ErrKind::ErroneousReferencedConstant;
+use rustc_const_eval::{eval_const_expr_partial, report_const_eval_err};
use rustc::ty::subst::{Substs, FnSpace, ParamSpace, SelfSpace, TypeSpace, VecPerParamSpace};
use rustc::ty::{ToPredicate, ImplContainer, ImplOrTraitItemContainer, TraitContainer};
use rustc::ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeScheme};
@@ -75,7 +72,6 @@
use rustc::ty::util::IntTypeExt;
use rscope::*;
use rustc::dep_graph::DepNode;
-use rustc::hir::map as hir_map;
use util::common::{ErrorReported, MemoizationMap};
use util::nodemap::{NodeMap, FnvHashMap};
use {CrateCtxt, write_ty_to_tcx};
@@ -92,9 +88,9 @@
use syntax::ptr::P;
use syntax_pos::Span;
-use rustc::hir::{self, PatKind};
-use rustc::hir::intravisit;
-use rustc::hir::print as pprust;
+use rustc::hir::{self, intravisit, map as hir_map, print as pprust};
+use rustc::hir::def::Def;
+use rustc::hir::def_id::DefId;
///////////////////////////////////////////////////////////////////////////
// Main entry point
@@ -1091,14 +1087,9 @@
},
// enum variant evaluation happens before the global constant check
// so we need to report the real error
- Err(ConstEvalErr { kind: ErroneousReferencedConstant(box err), ..}) |
Err(err) => {
- let mut diag = struct_span_err!(ccx.tcx.sess, err.span, E0080,
- "constant evaluation error: {}",
- err.description());
- if !e.span.contains(err.span) {
- diag.span_note(e.span, "for enum discriminant here");
- }
+ let mut diag = report_const_eval_err(
+ ccx.tcx, &err, e.span, "enum discriminant");
diag.emit();
None
}
@@ -2150,14 +2141,6 @@
abi: abi::Abi)
-> ty::TypeScheme<'tcx>
{
- for i in &decl.inputs {
- match i.pat.node {
- PatKind::Binding(..) | PatKind::Wild => {}
- _ => span_err!(ccx.tcx.sess, i.pat.span, E0130,
- "patterns aren't allowed in foreign function declarations")
- }
- }
-
let ty_generics = ty_generics_for_fn(ccx, ast_generics, &ty::Generics::empty());
let rb = BindingRscope::new();
@@ -2243,9 +2226,9 @@
// 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),
@@ -2273,9 +2256,9 @@
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);
@@ -2286,7 +2269,7 @@
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),
diff --git a/src/librustc_typeck/constrained_type_params.rs b/src/librustc_typeck/constrained_type_params.rs
index 08c1b5f..7909584 100644
--- a/src/librustc_typeck/constrained_type_params.rs
+++ b/src/librustc_typeck/constrained_type_params.rs
@@ -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 @@
}
/// 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()));
+ }
+ _ => {}
+ }
+
+ t.super_visit_with(self)
}
-}
-fn parameters_for_regions_in_substs(substs: &subst::Substs) -> Vec<Parameter> {
- substs.regions
- .iter()
- .filter_map(|r| parameters_for_region(r))
- .collect()
-}
-
-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 @@
// 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;
}
diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs
index 8769bc1..b655d95 100644
--- a/src/librustc_typeck/diagnostics.rs
+++ b/src/librustc_typeck/diagnostics.rs
@@ -1079,25 +1079,6 @@
```
"##,
-E0080: r##"
-This error indicates that the compiler was unable to sensibly evaluate an
-integer expression provided as an enum discriminant. Attempting to divide by 0
-or causing integer overflow are two ways to induce this error. For example:
-
-```compile_fail
-enum Enum {
- X = (1 << 500),
- Y = (1 / 0)
-}
-```
-
-Ensure that the expressions given can be evaluated as the desired integer type.
-See the FFI section of the Reference for more information about using a custom
-integer type:
-
-https://doc.rust-lang.org/reference.html#ffi-attributes
-"##,
-
E0081: r##"
Enum discriminants are used to differentiate enum variants stored in memory.
This error indicates that the same value was used for two or more variants,
@@ -1819,39 +1800,6 @@
parameter if so.
"##,
-E0130: r##"
-You declared a pattern as an argument in a foreign function declaration.
-Erroneous code example:
-
-```compile_fail
-extern {
- fn foo((a, b): (u32, u32)); // error: patterns aren't allowed in foreign
- // function declarations
-}
-```
-
-Please replace the pattern argument with a regular one. Example:
-
-```
-struct SomeStruct {
- a: u32,
- b: u32,
-}
-
-extern {
- fn foo(s: SomeStruct); // ok!
-}
-```
-
-Or:
-
-```
-extern {
- fn foo(a: (u32, u32)); // ok!
-}
-```
-"##,
-
E0131: r##"
It is not possible to define `main` with type parameters, or even with function
parameters. When `main` is present, it must take no arguments and return `()`.
@@ -1963,89 +1911,6 @@
https://doc.rust-lang.org/book/traits.html
"##,
-E0174: r##"
-This error occurs because of the explicit use of unboxed closure methods
-that are an experimental feature in current Rust version.
-
-Example of erroneous code:
-
-```compile_fail
-fn foo<F: Fn(&str)>(mut f: F) {
- f.call(("call",));
- // error: explicit use of unboxed closure method `call`
- f.call_mut(("call_mut",));
- // error: explicit use of unboxed closure method `call_mut`
- f.call_once(("call_once",));
- // error: explicit use of unboxed closure method `call_once`
-}
-
-fn bar(text: &str) {
- println!("Calling {} it works!", text);
-}
-
-fn main() {
- foo(bar);
-}
-```
-
-Rust's implementation of closures is a bit different than other languages.
-They are effectively syntax sugar for traits `Fn`, `FnMut` and `FnOnce`.
-To understand better how the closures are implemented see here:
-https://doc.rust-lang.org/book/closures.html#closure-implementation
-
-To fix this you can call them using parenthesis, like this: `foo()`.
-When you execute the closure with parenthesis, under the hood you are executing
-the method `call`, `call_mut` or `call_once`. However, using them explicitly is
-currently an experimental feature.
-
-Example of an implicit call:
-
-```
-fn foo<F: Fn(&str)>(f: F) {
- f("using ()"); // Calling using () it works!
-}
-
-fn bar(text: &str) {
- println!("Calling {} it works!", text);
-}
-
-fn main() {
- foo(bar);
-}
-```
-
-To enable the explicit calls you need to add `#![feature(unboxed_closures)]`.
-
-This feature is still unstable so you will also need to add
-`#![feature(fn_traits)]`.
-More details about this issue here:
-https://github.com/rust-lang/rust/issues/29625
-
-Example of use:
-
-```
-#![feature(fn_traits)]
-#![feature(unboxed_closures)]
-
-fn foo<F: Fn(&str)>(mut f: F) {
- f.call(("call",)); // Calling 'call' it works!
- f.call_mut(("call_mut",)); // Calling 'call_mut' it works!
- f.call_once(("call_once",)); // Calling 'call_once' it works!
-}
-
-fn bar(text: &str) {
- println!("Calling '{}' it works!", text);
-}
-
-fn main() {
- foo(bar);
-}
-```
-
-To see more about closures take a look here:
-https://doc.rust-lang.org/book/closures.html`
-"##,
-
E0178: r##"
In types, the `+` type operator has low precedence, so it is often necessary
to use parentheses.
@@ -2660,6 +2525,7 @@
[RFC 1023]: https://github.com/rust-lang/rfcs/pull/1023
"##,
+/*
E0211: r##"
You used a function or type which doesn't fit the requirements for where it was
used. Erroneous code examples:
@@ -2739,6 +2605,7 @@
}
```
"##,
+ */
E0214: r##"
A generic type was described using parentheses rather than angle brackets. For
@@ -2968,38 +2835,6 @@
behavior for specific enum variants.
"##,
-E0249: r##"
-This error indicates a constant expression for the array length was found, but
-it was not an integer (signed or unsigned) expression.
-
-Some examples of code that produces this error are:
-
-```compile_fail
-const A: [u32; "hello"] = []; // error
-const B: [u32; true] = []; // error
-const C: [u32; 0.0] = []; // error
-"##,
-
-E0250: r##"
-There was an error while evaluating the expression for the length of a fixed-
-size array type.
-
-Some examples of this error are:
-
-```compile_fail
-// divide by zero in the length expression
-const A: [u32; 1/0] = [];
-
-// Rust currently will not evaluate the function `foo` at compile time
-fn foo() -> usize { 12 }
-const B: [u32; foo()] = [];
-
-// it is an error to try to add `u8` and `f64`
-use std::{f64, u8};
-const C: [u32; u8::MAX + f64::EPSILON] = [];
-```
-"##,
-
E0318: r##"
Default impls for a trait must be located in the same crate where the trait was
defined. For more information see the [opt-in builtin traits RFC](https://github
@@ -4029,6 +3864,57 @@
```
"##,
+E0559: r##"
+An unknown field was specified into an enum's structure variant.
+
+Erroneous code example:
+
+```compile_fail,E0559
+enum Field {
+ Fool { x: u32 },
+}
+
+let s = Field::Fool { joke: 0 };
+// error: struct variant `Field::Fool` has no field named `joke`
+```
+
+Verify you didn't misspell the field's name or that the field exists. Example:
+
+```
+enum Field {
+ Fool { joke: u32 },
+}
+
+let s = Field::Fool { joke: 0 }; // ok!
+```
+"##,
+
+E0560: r##"
+An unknown field was specified into a structure.
+
+Erroneous code example:
+
+```compile_fail,E0560
+struct Simba {
+ mother: u32,
+}
+
+let s = Simba { mother: 1, father: 0 };
+// error: structure `Simba` has no field named `father`
+```
+
+Verify you didn't misspell the field's name or that the field exists. Example:
+
+```
+struct Simba {
+ mother: u32,
+ father: u32,
+}
+
+let s = Simba { mother: 1, father: 0 }; // ok!
+```
+"##,
+
}
register_diagnostics! {
@@ -4047,6 +3933,7 @@
E0167,
// E0168,
// E0173, // manual implementations of unboxed closure traits are experimental
+// E0174,
E0182,
E0183,
// E0187, // can't infer the kind of the closure
@@ -4086,6 +3973,7 @@
E0245, // not a trait
// E0246, // invalid recursive type
// E0247,
+// E0249,
// E0319, // trait impls for defaulted traits allowed just for structs/enums
E0320, // recursive overflow during dropck
E0328, // cannot implement Unsize explicitly
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index 8445258..3b2d02d 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -186,28 +186,14 @@
}
}
-pub fn emit_type_err<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
- span: Span,
- found_ty: Ty<'tcx>,
- expected_ty: Ty<'tcx>,
- terr: &ty::error::TypeError<'tcx>,
- msg: &str) {
- let mut err = struct_span_err!(tcx.sess, span, E0211, "{}", msg);
- err.span_label(span, &terr);
- err.note_expected_found(&"type", &expected_ty, &found_ty);
- tcx.note_and_explain_type_err(&mut err, terr, span);
- err.emit();
-}
-
fn require_same_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
- span: Span,
+ origin: TypeOrigin,
t1: Ty<'tcx>,
- t2: Ty<'tcx>,
- msg: &str)
+ t2: Ty<'tcx>)
-> bool {
ccx.tcx.infer_ctxt(None, None, ProjectionMode::AnyFinal).enter(|infcx| {
- if let Err(err) = infcx.eq_types(false, TypeOrigin::Misc(span), t1, t2) {
- emit_type_err(infcx.tcx, span, t1, t2, &err, msg);
+ if let Err(err) = infcx.eq_types(false, origin.clone(), t1, t2) {
+ infcx.report_mismatched_types(origin, t1, t2, err);
false
} else {
true
@@ -249,8 +235,11 @@
})
}));
- require_same_types(ccx, main_span, main_t, se_ty,
- "main function has wrong type");
+ require_same_types(
+ ccx,
+ TypeOrigin::MainFunctionType(main_span),
+ main_t,
+ se_ty);
}
_ => {
span_bug!(main_span,
@@ -298,8 +287,11 @@
}),
}));
- require_same_types(ccx, start_span, start_t, se_ty,
- "start function has wrong type");
+ require_same_types(
+ ccx,
+ TypeOrigin::StartFunctionType(start_span),
+ start_t,
+ se_ty);
}
_ => {
span_bug!(start_span,
diff --git a/src/librustc_unicode/char.rs b/src/librustc_unicode/char.rs
index 1ea0f8d..81856cb 100644
--- a/src/librustc_unicode/char.rs
+++ b/src/librustc_unicode/char.rs
@@ -36,7 +36,7 @@
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::char::{MAX, from_digit, from_u32, from_u32_unchecked};
#[stable(feature = "rust1", since = "1.0.0")]
-pub use core::char::{EncodeUtf16, EncodeUtf8, EscapeDefault, EscapeUnicode};
+pub use core::char::{EncodeUtf16, EncodeUtf8, EscapeDebug, EscapeDefault, EscapeUnicode};
// unstable reexports
#[unstable(feature = "decode_utf8", issue = "33906")]
@@ -269,6 +269,41 @@
/// Returns an iterator that yields the literal escape code of a `char`.
///
+ /// This will escape the characters similar to the `Debug` implementations
+ /// of `str` or `char`.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// for i in '\n'.escape_default() {
+ /// println!("{}", i);
+ /// }
+ /// ```
+ ///
+ /// This prints:
+ ///
+ /// ```text
+ /// \
+ /// n
+ /// ```
+ ///
+ /// Collecting into a `String`:
+ ///
+ /// ```
+ /// let quote: String = '\n'.escape_default().collect();
+ ///
+ /// assert_eq!(quote, "\\n");
+ /// ```
+ #[unstable(feature = "char_escape_debug", issue = "35068")]
+ #[inline]
+ pub fn escape_debug(self) -> EscapeDebug {
+ C::escape_debug(self)
+ }
+
+ /// Returns an iterator that yields the literal escape code of a `char`.
+ ///
/// The default is chosen with a bias toward producing literals that are
/// legal in a variety of languages, including C++11 and similar C-family
/// languages. The exact rules are:
diff --git a/src/librustc_unicode/lib.rs b/src/librustc_unicode/lib.rs
index f91a754..3ae905e 100644
--- a/src/librustc_unicode/lib.rs
+++ b/src/librustc_unicode/lib.rs
@@ -32,6 +32,7 @@
#![cfg_attr(not(stage0), deny(warnings))]
#![no_std]
+#![feature(char_escape_debug)]
#![feature(core_char_ext)]
#![feature(decode_utf8)]
#![feature(lang_items)]
diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml
index a41d3b0..3e510bd 100644
--- a/src/librustdoc/Cargo.toml
+++ b/src/librustdoc/Cargo.toml
@@ -28,4 +28,4 @@
[build-dependencies]
build_helper = { path = "../build_helper" }
-gcc = "0.3"
+gcc = "0.3.27"
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 0211b2c..d609ad8 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -498,21 +498,20 @@
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 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 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);
@@ -2690,7 +2691,12 @@
Def::Static(i, _) => (i, TypeStatic),
Def::Variant(i, _) => (i, TypeEnum),
Def::SelfTy(Some(def_id), _) => (def_id, TypeTrait),
- Def::SelfTy(_, Some(impl_id)) => return cx.map.local_def_id(impl_id),
+ Def::SelfTy(_, Some(impl_id)) => {
+ // For Def::SelfTy() values inlined from another crate, the
+ // impl_id will be DUMMY_NODE_ID, which would cause problems.
+ // But we should never run into an impl from another crate here.
+ return cx.map.local_def_id(impl_id)
+ }
_ => return def.def_id()
};
if did.is_local() { return did }
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index 2e2fc01..e4e886c 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -2409,10 +2409,13 @@
if structhead {"struct "} else {""},
it.name.as_ref().unwrap())?;
if let Some(g) = g {
- write!(w, "{}{}", *g, WhereClause(g))?
+ write!(w, "{}", g)?
}
match ty {
doctree::Plain => {
+ if let Some(g) = g {
+ write!(w, "{}", WhereClause(g))?
+ }
write!(w, " {{\n{}", tab)?;
for field in fields {
if let clean::StructFieldItem(ref ty) = field.inner {
@@ -2445,9 +2448,17 @@
_ => unreachable!()
}
}
- write!(w, ");")?;
+ write!(w, ")")?;
+ if let Some(g) = g {
+ write!(w, "{}", WhereClause(g))?
+ }
+ write!(w, ";")?;
}
doctree::Unit => {
+ // Needed for PhantomData.
+ if let Some(g) = g {
+ write!(w, "{}", WhereClause(g))?
+ }
write!(w, ";")?;
}
}
diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml
index eded6e2..3ce6841 100644
--- a/src/libstd/Cargo.toml
+++ b/src/libstd/Cargo.toml
@@ -24,8 +24,9 @@
[build-dependencies]
build_helper = { path = "../build_helper" }
-gcc = "0.3"
+gcc = "0.3.27"
[features]
+backtrace = []
jemalloc = ["alloc_jemalloc"]
debug-jemalloc = ["alloc_jemalloc/debug"]
diff --git a/src/libstd/build.rs b/src/libstd/build.rs
index 9c40836..9018e48 100644
--- a/src/libstd/build.rs
+++ b/src/libstd/build.rs
@@ -25,7 +25,8 @@
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);
}
diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs
index 48753cc..38fd935 100644
--- a/src/libstd/fs.rs
+++ b/src/libstd/fs.rs
@@ -694,6 +694,23 @@
///
/// 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 @@
///
/// 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 @@
///
/// 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)
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index d05a5a0..865d067 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -218,8 +218,9 @@
#![feature(associated_consts)]
#![feature(borrow_state)]
#![feature(box_syntax)]
-#![feature(cfg_target_vendor)]
#![feature(cfg_target_thread_local)]
+#![feature(cfg_target_vendor)]
+#![feature(char_escape_debug)]
#![feature(char_internals)]
#![feature(collections)]
#![feature(collections_bound)]
@@ -229,10 +230,10 @@
#![feature(dropck_parametricity)]
#![feature(float_extras)]
#![feature(float_from_str_radix)]
-#![feature(fnbox)]
#![feature(fn_traits)]
-#![feature(heap_api)]
+#![feature(fnbox)]
#![feature(hashmap_hasher)]
+#![feature(heap_api)]
#![feature(inclusive_range)]
#![feature(int_error_internals)]
#![feature(into_cow)]
@@ -242,6 +243,7 @@
#![feature(linkage)]
#![feature(macro_reexport)]
#![cfg_attr(test, feature(map_values_mut))]
+#![feature(needs_panic_runtime)]
#![feature(num_bits_bytes)]
#![feature(old_wrapping)]
#![feature(on_unimplemented)]
@@ -249,10 +251,11 @@
#![feature(optin_builtin_traits)]
#![feature(panic_unwind)]
#![feature(placement_in_syntax)]
+#![feature(question_mark)]
#![feature(rand)]
#![feature(raw)]
-#![feature(repr_simd)]
#![feature(reflect_marker)]
+#![feature(repr_simd)]
#![feature(rustc_attrs)]
#![feature(shared)]
#![feature(sip_hash_13)]
@@ -266,6 +269,7 @@
#![feature(str_utf16)]
#![feature(test, rustc_private)]
#![feature(thread_local)]
+#![feature(try_from)]
#![feature(unboxed_closures)]
#![feature(unicode)]
#![feature(unique)]
@@ -273,9 +277,6 @@
#![feature(unwind_attributes)]
#![feature(vec_push_all)]
#![feature(zero_one)]
-#![feature(question_mark)]
-#![feature(try_from)]
-#![feature(needs_panic_runtime)]
// Issue# 30592: Systematically use alloc_system during stage0 since jemalloc
// might be unavailable or disabled
diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs
index d73e954..57a4c3d 100644
--- a/src/libstd/panicking.rs
+++ b/src/libstd/panicking.rs
@@ -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 @@
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 @@
}
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 @@
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.");
+ }
}
};
diff --git a/src/libstd/sys/common/mod.rs b/src/libstd/sys/common/mod.rs
index c927988..a1f3f47 100644
--- a/src/libstd/sys/common/mod.rs
+++ b/src/libstd/sys/common/mod.rs
@@ -28,6 +28,7 @@
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 @@
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;
diff --git a/src/libstd/sys/common/wtf8.rs b/src/libstd/sys/common/wtf8.rs
index 2c1a656..c1b4f8a 100644
--- a/src/libstd/sys/common/wtf8.rs
+++ b/src/libstd/sys/common/wtf8.rs
@@ -390,7 +390,7 @@
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
fn write_str_escaped(f: &mut fmt::Formatter, s: &str) -> fmt::Result {
use fmt::Write;
- for c in s.chars().flat_map(|c| c.escape_default()) {
+ for c in s.chars().flat_map(|c| c.escape_debug()) {
f.write_char(c)?
}
Ok(())
@@ -408,7 +408,7 @@
&self.bytes[pos .. surrogate_pos]
)},
)?;
- write!(formatter, "\\u{{{:X}}}", surrogate)?;
+ write!(formatter, "\\u{{{:x}}}", surrogate)?;
pos = surrogate_pos + 3;
}
}
@@ -1064,9 +1064,9 @@
#[test]
fn wtf8buf_show() {
- let mut string = Wtf8Buf::from_str("a\té 💩\r");
+ let mut string = Wtf8Buf::from_str("a\té \u{7f}💩\r");
string.push(CodePoint::from_u32(0xD800).unwrap());
- assert_eq!(format!("{:?}", string), r#""a\t\u{e9} \u{1f4a9}\r\u{D800}""#);
+ assert_eq!(format!("{:?}", string), "\"a\\té \\u{7f}\u{1f4a9}\\r\\u{d800}\"");
}
#[test]
diff --git a/src/libstd/sys/unix/ext/fs.rs b/src/libstd/sys/unix/ext/fs.rs
index 5434077..7758791 100644
--- a/src/libstd/sys/unix/ext/fs.rs
+++ b/src/libstd/sys/unix/ext/fs.rs
@@ -25,15 +25,53 @@
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 @@
/// 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;
diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs
index f0fd42f..1c25c8f 100644
--- a/src/libstd/sys/unix/mod.rs
+++ b/src/libstd/sys/unix/mod.rs
@@ -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;
diff --git a/src/libstd/sys/unix/net.rs b/src/libstd/sys/unix/net.rs
index a784741..6f1b70a 100644
--- a/src/libstd/sys/unix/net.rs
+++ b/src/libstd/sys/unix/net.rs
@@ -67,7 +67,7 @@
// this option, however, was added in 2.6.27, and we still support
// 2.6.18 as a kernel, so if the returned error is EINVAL we
// fallthrough to the fallback.
- if cfg!(linux) {
+ if cfg!(target_os = "linux") {
match cvt(libc::socket(fam, ty | SOCK_CLOEXEC, 0)) {
Ok(fd) => return Ok(Socket(FileDesc::new(fd))),
Err(ref e) if e.raw_os_error() == Some(libc::EINVAL) => {}
@@ -87,7 +87,7 @@
let mut fds = [0, 0];
// Like above, see if we can set cloexec atomically
- if cfg!(linux) {
+ if cfg!(target_os = "linux") {
match cvt(libc::socketpair(fam, ty | SOCK_CLOEXEC, 0, fds.as_mut_ptr())) {
Ok(_) => {
return Ok((Socket(FileDesc::new(fds[0])), Socket(FileDesc::new(fds[1]))));
diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs
index 67f73d4..b622f68 100644
--- a/src/libsyntax/attr.rs
+++ b/src/libsyntax/attr.rs
@@ -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 @@
/// 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 @@
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 @@
_ => None
}
}
+
+ fn is_word(&self) -> bool {
+ match self.node {
+ MetaItemKind::Word(_) => true,
+ _ => false,
+ }
+ }
+
fn span(&self) -> Span { self.span }
}
@@ -150,6 +174,9 @@
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 @@
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 @@
/// 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,
})
}
diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs
index a8aca90..b176b8f 100644
--- a/src/libsyntax/codemap.rs
+++ b/src/libsyntax/codemap.rs
@@ -71,6 +71,23 @@
respan(DUMMY_SP, t)
}
+/// Build a span that covers the two provided spans.
+pub fn combine_spans(sp1: Span, sp2: Span) -> Span {
+ if sp1 == DUMMY_SP && sp2 == DUMMY_SP {
+ DUMMY_SP
+ } else if sp1 == DUMMY_SP {
+ sp2
+ } else if sp2 == DUMMY_SP {
+ sp1
+ } else {
+ Span {
+ lo: if sp1.lo < sp2.lo { sp1.lo } else { sp2.lo },
+ hi: if sp1.hi > sp2.hi { sp1.hi } else { sp2.hi },
+ expn_id: if sp1.expn_id == sp2.expn_id { sp1.expn_id } else { NO_EXPANSION },
+ }
+ }
+}
+
#[derive(Clone, Hash, Debug)]
pub struct NameAndSpan {
/// The format with which the macro was invoked.
diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs
index ff75149..a825cf8 100644
--- a/src/libsyntax/config.rs
+++ b/src/libsyntax/config.rs
@@ -124,7 +124,7 @@
};
let err_count = sess.span_diagnostic.err_count();
- let krate_attrs = strip_unconfigured.process_cfg_attrs(krate.attrs.clone());
+ let krate_attrs = strip_unconfigured.configure(krate.attrs.clone()).unwrap_or_default();
features = get_features(&sess.span_diagnostic, &krate_attrs);
if err_count < sess.span_diagnostic.err_count() {
krate.attrs = krate_attrs.clone(); // Avoid reconfiguring malformed `cfg_attr`s
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 435241f..5d6429f 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -1135,30 +1135,19 @@
}
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,
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 18342f2..5293d2a 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -302,9 +302,8 @@
};
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;
}
diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs
index 7c0d106..29a300b 100644
--- a/src/libsyntax/ext/tt/transcribe.rs
+++ b/src/libsyntax/ext/tt/transcribe.rs
@@ -14,7 +14,7 @@
use errors::{Handler, DiagnosticBuilder};
use ext::tt::macro_parser::{NamedMatch, MatchedSeq, MatchedNonterminal};
use parse::token::{DocComment, MatchNt, SubstNt};
-use parse::token::{Token, NtIdent, SpecialMacroVar};
+use parse::token::{Token, Interpolated, NtIdent, NtTT, SpecialMacroVar};
use parse::token;
use parse::lexer::TokenAndSpan;
use tokenstream::{self, TokenTree};
@@ -278,9 +278,9 @@
}
// FIXME #2887: think about span stuff here
TokenTree::Token(sp, SubstNt(ident)) => {
- r.stack.last_mut().unwrap().idx += 1;
match lookup_cur_matched(r, ident) {
None => {
+ r.stack.last_mut().unwrap().idx += 1;
r.cur_span = sp;
r.cur_tok = SubstNt(ident);
return ret_val;
@@ -292,14 +292,24 @@
// (a) idents can be in lots of places, so it'd be a pain
// (b) we actually can, since it's a token.
MatchedNonterminal(NtIdent(ref sn)) => {
+ r.stack.last_mut().unwrap().idx += 1;
r.cur_span = sn.span;
r.cur_tok = token::Ident(sn.node);
return ret_val;
}
+ MatchedNonterminal(NtTT(ref tt)) => {
+ r.stack.push(TtFrame {
+ forest: TokenTree::Token(sp, Interpolated(NtTT(tt.clone()))),
+ idx: 0,
+ dotdotdoted: false,
+ sep: None,
+ });
+ }
MatchedNonterminal(ref other_whole_nt) => {
+ r.stack.last_mut().unwrap().idx += 1;
// FIXME(pcwalton): Bad copy.
r.cur_span = sp;
- r.cur_tok = token::Interpolated((*other_whole_nt).clone());
+ r.cur_tok = Interpolated((*other_whole_nt).clone());
return ret_val;
}
MatchedSeq(..) => {
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 27485ee..29da0fb 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -481,6 +481,16 @@
is just used for rustc unit tests \
and will never be stable",
cfg_fn!(rustc_attrs))),
+ ("rustc_partition_reused", Whitelisted, Gated("rustc_attrs",
+ "this attribute \
+ is just used for rustc unit tests \
+ and will never be stable",
+ cfg_fn!(rustc_attrs))),
+ ("rustc_partition_translated", Whitelisted, Gated("rustc_attrs",
+ "this attribute \
+ is just used for rustc unit tests \
+ and will never be stable",
+ cfg_fn!(rustc_attrs))),
("rustc_symbol_name", Whitelisted, Gated("rustc_attrs",
"internal rustc attributes will never be stable",
cfg_fn!(rustc_attrs))),
@@ -800,6 +810,29 @@
}}
}
+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) {
@@ -831,21 +864,7 @@
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(..) => {
@@ -928,6 +947,16 @@
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(_) => {
@@ -1015,23 +1044,10 @@
}
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);
@@ -1044,7 +1060,10 @@
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");
}
@@ -1108,14 +1127,13 @@
}
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;
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index 2147e8e..7b28952 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -237,7 +237,7 @@
cfg: ast::CrateConfig,
ts: tokenstream::TokenStream)
-> Parser<'a> {
- tts_to_parser(sess, ts.tts, cfg)
+ tts_to_parser(sess, ts.to_tts(), cfg)
}
diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs
index 0ad09fd..89ead21 100644
--- a/src/libsyntax/tokenstream.rs
+++ b/src/libsyntax/tokenstream.rs
@@ -16,27 +16,27 @@
//! or a SequenceRepetition specifier (for the purpose of sequence generation during macro
//! expansion).
//!
-//! A TokenStream also has a slice view, `TokenSlice`, that is analogous to `str` for
-//! `String`: it allows the programmer to divvy up, explore, and otherwise partition a
-//! TokenStream as borrowed subsequences.
+//! ## Ownership
+//! TokenStreams are persistant data structures construced as ropes with reference
+//! counted-children. In general, this means that calling an operation on a TokenStream
+//! (such as `slice`) produces an entirely new TokenStream from the borrowed reference to
+//! the original. This essentially coerces TokenStreams into 'views' of their subparts,
+//! and a borrowed TokenStream is sufficient to build an owned TokenStream without taking
+//! ownership of the original.
use ast::{self, AttrStyle, LitKind};
use syntax_pos::{Span, DUMMY_SP, NO_EXPANSION};
-use codemap::Spanned;
+use codemap::{Spanned, combine_spans};
use ext::base;
use ext::tt::macro_parser;
use parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration};
use parse::lexer;
use parse;
-use parse::token::{self, Token, Lit, InternedString, Nonterminal};
-use parse::token::Lit as TokLit;
+use parse::token::{self, Token, Lit, Nonterminal};
use std::fmt;
-use std::mem;
-use std::ops::Index;
-use std::ops;
use std::iter::*;
-
+use std::ops::{self, Index};
use std::rc::Rc;
/// A delimited sequence of token trees
@@ -135,6 +135,7 @@
}
TokenTree::Token(_, token::SpecialVarNt(..)) => 2,
TokenTree::Token(_, token::MatchNt(..)) => 3,
+ TokenTree::Token(_, token::Interpolated(Nonterminal::NtTT(..))) => 1,
TokenTree::Delimited(_, ref delimed) => delimed.tts.len() + 2,
TokenTree::Sequence(_, ref seq) => seq.tts.len(),
TokenTree::Token(..) => 0,
@@ -197,6 +198,9 @@
TokenTree::Token(sp, token::Ident(kind))];
v[index].clone()
}
+ (&TokenTree::Token(_, token::Interpolated(Nonterminal::NtTT(ref tt))), _) => {
+ tt.clone().unwrap()
+ }
(&TokenTree::Sequence(_, ref seq), _) => seq.tts[index].clone(),
_ => panic!("Cannot expand a token tree"),
}
@@ -331,27 +335,51 @@
/// struct itself shouldn't be directly manipulated; the internal structure is not stable,
/// and may be changed at any time in the future. The operators will not, however (except
/// for signatures, later on).
-#[derive(Eq,Clone,Hash,RustcEncodable,RustcDecodable)]
+#[derive(Clone, Eq, Hash, RustcEncodable, RustcDecodable)]
pub struct TokenStream {
- pub span: Span,
- pub tts: Vec<TokenTree>,
+ ts: InternalTS,
+}
+
+// NB If Leaf access proves to be slow, inroducing a secondary Leaf without the bounds
+// for unsliced Leafs may lead to some performance improvemenet.
+#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
+pub enum InternalTS {
+ Empty(Span),
+ Leaf {
+ tts: Rc<Vec<TokenTree>>,
+ offset: usize,
+ len: usize,
+ sp: Span,
+ },
+ Node {
+ left: Rc<InternalTS>,
+ right: Rc<InternalTS>,
+ len: usize,
+ sp: Span,
+ },
}
impl fmt::Debug for TokenStream {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- if self.tts.len() == 0 {
- write!(f, "([empty")?;
- } else {
- write!(f, "([")?;
- write!(f, "{:?}", self.tts[0])?;
+ self.ts.fmt(f)
+ }
+}
- for tt in self.tts.iter().skip(1) {
- write!(f, ",{:?}", tt)?;
+impl fmt::Debug for InternalTS {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match *self {
+ InternalTS::Empty(..) => Ok(()),
+ InternalTS::Leaf { ref tts, offset, len, .. } => {
+ for t in tts.iter().skip(offset).take(len) {
+ try!(write!(f, "{:?}", t));
+ }
+ Ok(())
+ }
+ InternalTS::Node { ref left, ref right, .. } => {
+ try!(left.fmt(f));
+ right.fmt(f)
}
}
- write!(f, "|")?;
- self.span.fmt(f)?;
- write!(f, "])")
}
}
@@ -359,7 +387,7 @@
/// equality, see `eq_unspanned`.
impl PartialEq<TokenStream> for TokenStream {
fn eq(&self, other: &TokenStream) -> bool {
- self.tts == other.tts
+ self.iter().eq(other.iter())
}
}
@@ -404,6 +432,59 @@
}
}
+impl InternalTS {
+ fn len(&self) -> usize {
+ match *self {
+ InternalTS::Empty(..) => 0,
+ InternalTS::Leaf { len, .. } => len,
+ InternalTS::Node { len, .. } => len,
+ }
+ }
+
+ fn span(&self) -> Span {
+ match *self {
+ InternalTS::Empty(sp) |
+ InternalTS::Leaf { sp, .. } |
+ InternalTS::Node { sp, .. } => sp,
+ }
+ }
+
+ fn slice(&self, range: ops::Range<usize>) -> TokenStream {
+ let from = range.start;
+ let to = range.end;
+ if from == to {
+ return TokenStream::mk_empty();
+ }
+ if from > to {
+ panic!("Invalid range: {} to {}", from, to);
+ }
+ if from == 0 && to == self.len() {
+ return TokenStream { ts: self.clone() }; /* should be cheap */
+ }
+ match *self {
+ InternalTS::Empty(..) => panic!("Invalid index"),
+ InternalTS::Leaf { ref tts, offset, .. } => {
+ let offset = offset + from;
+ let len = to - from;
+ TokenStream::mk_sub_leaf(tts.clone(),
+ offset,
+ len,
+ covering_span(&tts[offset..offset + len]))
+ }
+ InternalTS::Node { ref left, ref right, .. } => {
+ let left_len = left.len();
+ if to <= left_len {
+ left.slice(range)
+ } else if from >= left_len {
+ right.slice(from - left_len..to - left_len)
+ } else {
+ TokenStream::concat(left.slice(from..left_len), right.slice(0..to - left_len))
+ }
+ }
+ }
+ }
+}
+
/// TokenStream operators include basic destructuring, boolean operations, `maybe_...`
/// operations, and `maybe_..._prefix` operations. Boolean operations are straightforward,
/// indicating information about the structure of the stream. The `maybe_...` operations
@@ -415,129 +496,149 @@
///
/// `maybe_path_prefix("a::b::c(a,b,c).foo()") -> (a::b::c, "(a,b,c).foo()")`
impl TokenStream {
- /// Convert a vector of `TokenTree`s into a `TokenStream`.
- pub fn from_tts(trees: Vec<TokenTree>) -> TokenStream {
- let span = covering_span(&trees);
+ pub fn mk_empty() -> TokenStream {
+ TokenStream { ts: InternalTS::Empty(DUMMY_SP) }
+ }
+
+ fn mk_spanned_empty(sp: Span) -> TokenStream {
+ TokenStream { ts: InternalTS::Empty(sp) }
+ }
+
+ fn mk_leaf(tts: Rc<Vec<TokenTree>>, sp: Span) -> TokenStream {
+ let len = tts.len();
TokenStream {
- tts: trees,
- span: span,
+ ts: InternalTS::Leaf {
+ tts: tts,
+ offset: 0,
+ len: len,
+ sp: sp,
+ },
}
}
- /// Copies all of the TokenTrees from the TokenSlice, appending them to the stream.
- pub fn append_stream(mut self, ts2: &TokenSlice) {
- for tt in ts2.iter() {
- self.tts.push(tt.clone());
+ fn mk_sub_leaf(tts: Rc<Vec<TokenTree>>, offset: usize, len: usize, sp: Span) -> TokenStream {
+ TokenStream {
+ ts: InternalTS::Leaf {
+ tts: tts,
+ offset: offset,
+ len: len,
+ sp: sp,
+ },
}
- self.span = covering_span(&self.tts[..]);
+ }
+
+ fn mk_int_node(left: Rc<InternalTS>,
+ right: Rc<InternalTS>,
+ len: usize,
+ sp: Span)
+ -> TokenStream {
+ TokenStream {
+ ts: InternalTS::Node {
+ left: left,
+ right: right,
+ len: len,
+ sp: sp,
+ },
+ }
+ }
+
+ /// Convert a vector of `TokenTree`s into a `TokenStream`.
+ pub fn from_tts(trees: Vec<TokenTree>) -> TokenStream {
+ let span = covering_span(&trees[..]);
+ TokenStream::mk_leaf(Rc::new(trees), span)
}
/// Manually change a TokenStream's span.
pub fn respan(self, span: Span) -> TokenStream {
- TokenStream {
- tts: self.tts,
- span: span,
- }
- }
-
- /// Construct a TokenStream from an ast literal.
- pub fn from_ast_lit_str(lit: ast::Lit) -> Option<TokenStream> {
- match lit.node {
- LitKind::Str(val, _) => {
- let val = TokLit::Str_(token::intern(&val));
- Some(TokenStream::from_tts(vec![TokenTree::Token(lit.span,
- Token::Literal(val, None))]))
+ match self.ts {
+ InternalTS::Empty(..) => TokenStream::mk_spanned_empty(span),
+ InternalTS::Leaf { tts, offset, len, .. } => {
+ TokenStream::mk_sub_leaf(tts, offset, len, span)
}
- _ => None,
+ InternalTS::Node { left, right, len, .. } => {
+ TokenStream::mk_int_node(left, right, len, span)
+ }
}
-
}
- /// Convert a vector of TokenTrees into a parentheses-delimited TokenStream.
- pub fn as_paren_delimited_stream(tts: Vec<TokenTree>) -> TokenStream {
- let new_sp = covering_span(&tts);
-
- let new_delim = Rc::new(Delimited {
- delim: token::DelimToken::Paren,
- open_span: DUMMY_SP,
- tts: tts,
- close_span: DUMMY_SP,
- });
-
- TokenStream::from_tts(vec![TokenTree::Delimited(new_sp, new_delim)])
+ /// Concatenates two TokenStreams into a new TokenStream
+ pub fn concat(left: TokenStream, right: TokenStream) -> TokenStream {
+ let new_len = left.len() + right.len();
+ let new_span = combine_spans(left.span(), right.span());
+ TokenStream::mk_int_node(Rc::new(left.ts), Rc::new(right.ts), new_len, new_span)
}
- /// Convert an interned string into a one-element TokenStream.
- pub fn from_interned_string_as_ident(s: InternedString) -> TokenStream {
- TokenStream::from_tts(vec![TokenTree::Token(DUMMY_SP,
- Token::Ident(token::str_to_ident(&s[..])))])
- }
-}
-
-/// TokenSlices are 'views' of `TokenStream's; they fit the same role as `str`s do for
-/// `String`s. In general, most TokenStream manipulations will be refocusing their internal
-/// contents by taking a TokenSlice and then using indexing and the provided operators.
-#[derive(PartialEq, Eq, Debug)]
-pub struct TokenSlice([TokenTree]);
-
-impl ops::Deref for TokenStream {
- type Target = TokenSlice;
-
- fn deref(&self) -> &TokenSlice {
- let tts: &[TokenTree] = &*self.tts;
- unsafe { mem::transmute(tts) }
- }
-}
-
-impl TokenSlice {
- /// Convert a borrowed TokenTree slice into a borrowed TokenSlice.
- fn from_tts(tts: &[TokenTree]) -> &TokenSlice {
- unsafe { mem::transmute(tts) }
- }
-
- /// Indicates whether the `TokenStream` is empty.
+ /// Indicate if the TokenStream is empty.
pub fn is_empty(&self) -> bool {
self.len() == 0
}
- /// Return the `TokenSlice`'s length.
+ /// Return a TokenStream's length.
pub fn len(&self) -> usize {
- self.0.len()
+ self.ts.len()
}
- /// Check equality versus another TokenStream, ignoring span information.
- pub fn eq_unspanned(&self, other: &TokenSlice) -> bool {
- if self.len() != other.len() {
- return false;
- }
- for (tt1, tt2) in self.iter().zip(other.iter()) {
- if !tt1.eq_unspanned(tt2) {
- return false;
+ /// Convert a TokenStream into a vector of borrowed TokenTrees.
+ pub fn to_vec(&self) -> Vec<&TokenTree> {
+ fn internal_to_vec(ts: &InternalTS) -> Vec<&TokenTree> {
+ match *ts {
+ InternalTS::Empty(..) => Vec::new(),
+ InternalTS::Leaf { ref tts, offset, len, .. } => {
+ tts[offset..offset + len].iter().collect()
+ }
+ InternalTS::Node { ref left, ref right, .. } => {
+ let mut v1 = internal_to_vec(left);
+ let mut v2 = internal_to_vec(right);
+ v1.append(&mut v2);
+ v1
+ }
}
}
- true
+ internal_to_vec(&self.ts)
}
- /// Compute a span that covers the entire TokenSlice (eg, one wide enough to include
- /// the entire slice). If the inputs share expansion identification, it is preserved.
- /// If they do not, it is discarded.
- pub fn covering_span(&self) -> Span {
- covering_span(&self.0)
+ /// Convert a TokenStream into a vector of TokenTrees (by cloning the TokenTrees).
+ /// (This operation is an O(n) deep copy of the underlying structure.)
+ pub fn to_tts(&self) -> Vec<TokenTree> {
+ self.to_vec().into_iter().cloned().collect::<Vec<TokenTree>>()
}
- /// Indicates where the stream is of the form `= <ts>`, where `<ts>` is a continued
- /// `TokenStream`.
- pub fn is_assignment(&self) -> bool {
- self.maybe_assignment().is_some()
+ /// Return the TokenStream's span.
+ pub fn span(&self) -> Span {
+ self.ts.span()
}
- /// Returns the RHS of an assigment.
- pub fn maybe_assignment(&self) -> Option<&TokenSlice> {
- if !(self.len() > 1) {
- return None;
+ /// Returns an iterator over a TokenStream (as a sequence of TokenTrees).
+ pub fn iter<'a>(&self) -> Iter {
+ Iter { vs: self, idx: 0 }
+ }
+
+ /// Splits a TokenStream based on the provided `&TokenTree -> bool` predicate.
+ pub fn split<P>(&self, pred: P) -> Split<P>
+ where P: FnMut(&TokenTree) -> bool
+ {
+ Split {
+ vs: self,
+ pred: pred,
+ finished: false,
+ idx: 0,
}
+ }
- Some(&self[1..])
+ /// Produce a slice of the input TokenStream from the `from` index, inclusive, to the
+ /// `to` index, non-inclusive.
+ pub fn slice(&self, range: ops::Range<usize>) -> TokenStream {
+ self.ts.slice(range)
+ }
+
+ /// Slice starting at the provided index, inclusive.
+ pub fn slice_from(&self, from: ops::RangeFrom<usize>) -> TokenStream {
+ self.slice(from.start..self.len())
+ }
+
+ /// Slice up to the provided index, non-inclusive.
+ pub fn slice_to(&self, to: ops::RangeTo<usize>) -> TokenStream {
+ self.slice(0..to.end)
}
/// Indicates where the stream is a single, delimited expression (e.g., `(a,b,c)` or
@@ -547,50 +648,15 @@
}
/// Returns the inside of the delimited term as a new TokenStream.
- pub fn maybe_delimited(&self) -> Option<&TokenSlice> {
+ pub fn maybe_delimited(&self) -> Option<TokenStream> {
if !(self.len() == 1) {
return None;
}
+ // FIXME It would be nice to change Delimited to move the Rc around the TokenTree
+ // vector directly in order to avoid the clone here.
match self[0] {
- TokenTree::Delimited(_, ref rc) => Some(TokenSlice::from_tts(&*rc.tts)),
- _ => None,
- }
- }
-
- /// Returns a list of `TokenSlice`s if the stream is a delimited list, breaking the
- /// stream on commas.
- pub fn maybe_comma_list(&self) -> Option<Vec<&TokenSlice>> {
- let maybe_tts = self.maybe_delimited();
-
- let ts: &TokenSlice;
- match maybe_tts {
- Some(t) => {
- ts = t;
- }
- None => {
- return None;
- }
- }
-
- let splits: Vec<&TokenSlice> = ts.split(|x| match *x {
- TokenTree::Token(_, Token::Comma) => true,
- _ => false,
- })
- .filter(|x| x.len() > 0)
- .collect();
-
- Some(splits)
- }
-
- /// Returns a Nonterminal if it is Interpolated.
- pub fn maybe_interpolated_nonterminal(&self) -> Option<Nonterminal> {
- if !(self.len() == 1) {
- return None;
- }
-
- match self[0] {
- TokenTree::Token(_, Token::Interpolated(ref nt)) => Some(nt.clone()),
+ TokenTree::Delimited(_, ref rc) => Some(TokenStream::from_tts(rc.tts.clone())),
_ => None,
}
}
@@ -606,180 +672,54 @@
return None;
}
- let tok = if let Some(tts) = self.maybe_delimited() {
- if tts.len() != 1 {
- return None;
- }
- &tts[0]
- } else {
- &self[0]
- };
-
- match *tok {
+ match self[0] {
TokenTree::Token(_, Token::Ident(t)) => Some(t),
_ => None,
}
}
- /// Indicates if the stream is exactly one literal
- pub fn is_lit(&self) -> bool {
- self.maybe_lit().is_some()
- }
-
- /// Returns a literal
- pub fn maybe_lit(&self) -> Option<token::Lit> {
- if !(self.len() == 1) {
- return None;
- }
-
- let tok = if let Some(tts) = self.maybe_delimited() {
- if tts.len() != 1 {
- return None;
- }
- &tts[0]
- } else {
- &self[0]
- };
-
- match *tok {
- TokenTree::Token(_, Token::Literal(l, _)) => Some(l),
- _ => None,
- }
- }
-
- /// Returns an AST string literal if the TokenStream is either a normal ('cooked') or
- /// raw string literal.
- pub fn maybe_str(&self) -> Option<ast::Lit> {
- if !(self.len() == 1) {
- return None;
- }
-
- match self[0] {
- TokenTree::Token(sp, Token::Literal(Lit::Str_(s), _)) => {
- let l = LitKind::Str(token::intern_and_get_ident(&parse::str_lit(&s.as_str())),
- ast::StrStyle::Cooked);
- Some(Spanned {
- node: l,
- span: sp,
- })
- }
- TokenTree::Token(sp, Token::Literal(Lit::StrRaw(s, n), _)) => {
- let l = LitKind::Str(token::intern_and_get_ident(&parse::raw_str_lit(&s.as_str())),
- ast::StrStyle::Raw(n));
- Some(Spanned {
- node: l,
- span: sp,
- })
- }
- _ => None,
- }
- }
-
- /// This operation extracts the path prefix , returning an AST path struct and the remainder
- /// of the stream (if it finds one). To be more specific, a tokenstream that has a valid,
- /// non-global path as a prefix (eg `foo(bar, baz)`, `foo::bar(bar)`, but *not*
- /// `::foo::bar(baz)`) will yield the path and the remaining tokens (as a slice). The previous
- /// examples will yield
- /// `Some((Path { segments = vec![foo], ... }, [(bar, baz)]))`,
- /// `Some((Path { segments = vec![foo, bar] }, [(baz)]))`,
- /// and `None`, respectively.
- pub fn maybe_path_prefix(&self) -> Option<(ast::Path, &TokenSlice)> {
- let mut segments: Vec<ast::PathSegment> = Vec::new();
-
- let path: Vec<&TokenTree> = self.iter()
- .take_while(|x| x.is_ident() || x.eq_token(Token::ModSep))
- .collect::<Vec<&TokenTree>>();
-
- let path_size = path.len();
- if path_size == 0 {
- return None;
- }
-
- let cov_span = self[..path_size].covering_span();
- let rst = &self[path_size..];
-
- let fst_id = path[0];
-
- if let Some(id) = fst_id.maybe_ident() {
- segments.push(ast::PathSegment {
- identifier: id,
- parameters: ast::PathParameters::none(),
- });
- } else {
- return None;
- }
-
- // Let's use a state machine to parse out the rest.
- enum State {
- Mod, // Expect a `::`, or return None otherwise.
- Ident, // Expect an ident, or return None otherwise.
- }
- let mut state = State::Mod;
-
- for p in &path[1..] {
- match state {
- State::Mod => {
- // State 0: ['::' -> state 1, else return None]
- if p.eq_token(Token::ModSep) {
- state = State::Ident;
- } else {
- return None;
- }
- }
- State::Ident => {
- // State 1: [ident -> state 0, else return None]
- if let Some(id) = p.maybe_ident() {
- segments.push(ast::PathSegment {
- identifier: id,
- parameters: ast::PathParameters::none(),
- });
- state = State::Mod;
- } else {
- return None;
- }
- }
+ /// Compares two TokenStreams, checking equality without regarding span information.
+ pub fn eq_unspanned(&self, other: &TokenStream) -> bool {
+ for (t1, t2) in self.iter().zip(other.iter()) {
+ if !t1.eq_unspanned(t2) {
+ return false;
}
}
-
- let path = ast::Path {
- span: cov_span,
- global: false,
- segments: segments,
- };
- Some((path, rst))
+ true
}
- /// Returns an iterator over a TokenSlice (as a sequence of TokenStreams).
- fn iter(&self) -> Iter {
- Iter { vs: self }
- }
+ /// Convert a vector of TokenTrees into a parentheses-delimited TokenStream.
+ pub fn as_delimited_stream(tts: Vec<TokenTree>, delim: token::DelimToken) -> TokenStream {
+ let new_sp = covering_span(&tts);
- /// Splits a TokenSlice based on the provided `&TokenTree -> bool` predicate.
- fn split<P>(&self, pred: P) -> Split<P>
- where P: FnMut(&TokenTree) -> bool
- {
- Split {
- vs: self,
- pred: pred,
- finished: false,
- }
+ let new_delim = Rc::new(Delimited {
+ delim: delim,
+ open_span: DUMMY_SP,
+ tts: tts,
+ close_span: DUMMY_SP,
+ });
+
+ TokenStream::from_tts(vec![TokenTree::Delimited(new_sp, new_delim)])
}
}
+// FIXME Reimplement this iterator to hold onto a slice iterator for a leaf, getting the
+// next leaf's iterator when the current one is exhausted.
pub struct Iter<'a> {
- vs: &'a TokenSlice,
+ vs: &'a TokenStream,
+ idx: usize,
}
impl<'a> Iterator for Iter<'a> {
type Item = &'a TokenTree;
fn next(&mut self) -> Option<&'a TokenTree> {
- if self.vs.is_empty() {
+ if self.vs.is_empty() || self.idx >= self.vs.len() {
return None;
}
- let ret = Some(&self.vs[0]);
- self.vs = &self.vs[1..];
+ let ret = Some(&self.vs[self.idx]);
+ self.idx = self.idx + 1;
ret
}
}
@@ -787,29 +727,35 @@
pub struct Split<'a, P>
where P: FnMut(&TokenTree) -> bool
{
- vs: &'a TokenSlice,
+ vs: &'a TokenStream,
pred: P,
finished: bool,
+ idx: usize,
}
impl<'a, P> Iterator for Split<'a, P>
where P: FnMut(&TokenTree) -> bool
{
- type Item = &'a TokenSlice;
+ type Item = TokenStream;
- fn next(&mut self) -> Option<&'a TokenSlice> {
+ fn next(&mut self) -> Option<TokenStream> {
if self.finished {
return None;
}
+ if self.idx >= self.vs.len() {
+ self.finished = true;
+ return None;
+ }
- match self.vs.iter().position(|x| (self.pred)(x)) {
+ let mut lookup = self.vs.iter().skip(self.idx);
+ match lookup.position(|x| (self.pred)(&x)) {
None => {
self.finished = true;
- Some(&self.vs[..])
+ Some(self.vs.slice_from(self.idx..))
}
- Some(idx) => {
- let ret = Some(&self.vs[..idx]);
- self.vs = &self.vs[idx + 1..];
+ Some(edx) => {
+ let ret = Some(self.vs.slice(self.idx..self.idx + edx));
+ self.idx += edx + 1;
ret
}
}
@@ -820,79 +766,29 @@
type Output = TokenTree;
fn index(&self, index: usize) -> &TokenTree {
- Index::index(&**self, index)
+ &self.ts[index]
}
}
-impl ops::Index<ops::Range<usize>> for TokenStream {
- type Output = TokenSlice;
-
- fn index(&self, index: ops::Range<usize>) -> &TokenSlice {
- Index::index(&**self, index)
- }
-}
-
-impl ops::Index<ops::RangeTo<usize>> for TokenStream {
- type Output = TokenSlice;
-
- fn index(&self, index: ops::RangeTo<usize>) -> &TokenSlice {
- Index::index(&**self, index)
- }
-}
-
-impl ops::Index<ops::RangeFrom<usize>> for TokenStream {
- type Output = TokenSlice;
-
- fn index(&self, index: ops::RangeFrom<usize>) -> &TokenSlice {
- Index::index(&**self, index)
- }
-}
-
-impl ops::Index<ops::RangeFull> for TokenStream {
- type Output = TokenSlice;
-
- fn index(&self, _index: ops::RangeFull) -> &TokenSlice {
- Index::index(&**self, _index)
- }
-}
-
-impl Index<usize> for TokenSlice {
+impl Index<usize> for InternalTS {
type Output = TokenTree;
fn index(&self, index: usize) -> &TokenTree {
- &self.0[index]
- }
-}
-
-impl ops::Index<ops::Range<usize>> for TokenSlice {
- type Output = TokenSlice;
-
- fn index(&self, index: ops::Range<usize>) -> &TokenSlice {
- TokenSlice::from_tts(&self.0[index])
- }
-}
-
-impl ops::Index<ops::RangeTo<usize>> for TokenSlice {
- type Output = TokenSlice;
-
- fn index(&self, index: ops::RangeTo<usize>) -> &TokenSlice {
- TokenSlice::from_tts(&self.0[index])
- }
-}
-
-impl ops::Index<ops::RangeFrom<usize>> for TokenSlice {
- type Output = TokenSlice;
-
- fn index(&self, index: ops::RangeFrom<usize>) -> &TokenSlice {
- TokenSlice::from_tts(&self.0[index])
- }
-}
-
-impl ops::Index<ops::RangeFull> for TokenSlice {
- type Output = TokenSlice;
-
- fn index(&self, _index: ops::RangeFull) -> &TokenSlice {
- TokenSlice::from_tts(&self.0[_index])
+ if self.len() <= index {
+ panic!("Index {} too large for {:?}", index, self);
+ }
+ match *self {
+ InternalTS::Empty(..) => panic!("Invalid index"),
+ InternalTS::Leaf { ref tts, offset, .. } => tts.get(index + offset).unwrap(),
+ InternalTS::Node { ref left, ref right, .. } => {
+ let left_len = left.len();
+ if index < left_len {
+ Index::index(&**left, index)
+ } else {
+ Index::index(&**right, index - left_len)
+ }
+ }
+ }
}
}
@@ -900,9 +796,8 @@
#[cfg(test)]
mod tests {
use super::*;
- use ast;
use syntax_pos::{Span, BytePos, NO_EXPANSION, DUMMY_SP};
- use parse::token::{self, str_to_ident, Token, Lit};
+ use parse::token::{self, str_to_ident, Token};
use util::parser_testing::string_to_tts;
use std::rc::Rc;
@@ -914,6 +809,93 @@
}
}
+ fn as_paren_delimited_stream(tts: Vec<TokenTree>) -> TokenStream {
+ TokenStream::as_delimited_stream(tts, token::DelimToken::Paren)
+ }
+
+ #[test]
+ fn test_concat() {
+ let test_res = TokenStream::from_tts(string_to_tts("foo::bar::baz".to_string()));
+ let test_fst = TokenStream::from_tts(string_to_tts("foo::bar".to_string()));
+ let test_snd = TokenStream::from_tts(string_to_tts("::baz".to_string()));
+ let eq_res = TokenStream::concat(test_fst, test_snd);
+ assert_eq!(test_res.len(), 5);
+ assert_eq!(eq_res.len(), 5);
+ assert_eq!(test_res.eq_unspanned(&eq_res), true);
+ }
+
+ #[test]
+ fn test_from_to_bijection() {
+ let test_start = string_to_tts("foo::bar(baz)".to_string());
+ let test_end = TokenStream::from_tts(string_to_tts("foo::bar(baz)".to_string())).to_tts();
+ assert_eq!(test_start, test_end)
+ }
+
+ #[test]
+ fn test_to_from_bijection() {
+ let test_start = TokenStream::from_tts(string_to_tts("foo::bar(baz)".to_string()));
+ let test_end = TokenStream::from_tts(test_start.clone().to_tts());
+ assert_eq!(test_start, test_end)
+ }
+
+ #[test]
+ fn test_eq_0() {
+ let test_res = TokenStream::from_tts(string_to_tts("foo".to_string()));
+ let test_eqs = TokenStream::from_tts(string_to_tts("foo".to_string()));
+ assert_eq!(test_res, test_eqs)
+ }
+
+ #[test]
+ fn test_eq_1() {
+ let test_res = TokenStream::from_tts(string_to_tts("::bar::baz".to_string()));
+ let test_eqs = TokenStream::from_tts(string_to_tts("::bar::baz".to_string()));
+ assert_eq!(test_res, test_eqs)
+ }
+
+ #[test]
+ fn test_eq_2() {
+ let test_res = TokenStream::from_tts(string_to_tts("foo::bar".to_string()));
+ let test_eqs = TokenStream::from_tts(string_to_tts("foo::bar::baz".to_string()));
+ assert_eq!(test_res, test_eqs.slice(0..3))
+ }
+
+ #[test]
+ fn test_eq_3() {
+ let test_res = TokenStream::from_tts(string_to_tts("".to_string()));
+ let test_eqs = TokenStream::from_tts(string_to_tts("".to_string()));
+ assert_eq!(test_res, test_eqs)
+ }
+
+ #[test]
+ fn test_diseq_0() {
+ let test_res = TokenStream::from_tts(string_to_tts("::bar::baz".to_string()));
+ let test_eqs = TokenStream::from_tts(string_to_tts("bar::baz".to_string()));
+ assert_eq!(test_res == test_eqs, false)
+ }
+
+ #[test]
+ fn test_diseq_1() {
+ let test_res = TokenStream::from_tts(string_to_tts("(bar,baz)".to_string()));
+ let test_eqs = TokenStream::from_tts(string_to_tts("bar,baz".to_string()));
+ assert_eq!(test_res == test_eqs, false)
+ }
+
+ #[test]
+ fn test_slice_0() {
+ let test_res = TokenStream::from_tts(string_to_tts("foo::bar".to_string()));
+ let test_eqs = TokenStream::from_tts(string_to_tts("foo::bar::baz".to_string()));
+ assert_eq!(test_res, test_eqs.slice(0..3))
+ }
+
+ #[test]
+ fn test_slice_1() {
+ let test_res = TokenStream::from_tts(string_to_tts("foo::bar::baz".to_string()))
+ .slice(2..3);
+ let test_eqs = TokenStream::from_tts(vec![TokenTree::Token(sp(5,8),
+ token::Ident(str_to_ident("bar")))]);
+ assert_eq!(test_res, test_eqs)
+ }
+
#[test]
fn test_is_empty() {
let test0 = TokenStream::from_tts(Vec::new());
@@ -944,38 +926,6 @@
}
#[test]
- fn test_is_assign() {
- let test0 = TokenStream::from_tts(string_to_tts("= bar::baz".to_string()));
- let test1 = TokenStream::from_tts(string_to_tts("= \"5\"".to_string()));
- let test2 = TokenStream::from_tts(string_to_tts("= 5".to_string()));
- let test3 = TokenStream::from_tts(string_to_tts("(foo = 10)".to_string()));
- let test4 = TokenStream::from_tts(string_to_tts("= (foo,bar,baz)".to_string()));
- let test5 = TokenStream::from_tts(string_to_tts("".to_string()));
-
- assert_eq!(test0.is_assignment(), true);
- assert_eq!(test1.is_assignment(), true);
- assert_eq!(test2.is_assignment(), true);
- assert_eq!(test3.is_assignment(), false);
- assert_eq!(test4.is_assignment(), true);
- assert_eq!(test5.is_assignment(), false);
- }
-
- #[test]
- fn test_is_lit() {
- let test0 = TokenStream::from_tts(string_to_tts("\"foo\"".to_string()));
- let test1 = TokenStream::from_tts(string_to_tts("5".to_string()));
- let test2 = TokenStream::from_tts(string_to_tts("foo".to_string()));
- let test3 = TokenStream::from_tts(string_to_tts("foo::bar".to_string()));
- let test4 = TokenStream::from_tts(string_to_tts("foo(bar)".to_string()));
-
- assert_eq!(test0.is_lit(), true);
- assert_eq!(test1.is_lit(), true);
- assert_eq!(test2.is_lit(), false);
- assert_eq!(test3.is_lit(), false);
- assert_eq!(test4.is_lit(), false);
- }
-
- #[test]
fn test_is_ident() {
let test0 = TokenStream::from_tts(string_to_tts("\"foo\"".to_string()));
let test1 = TokenStream::from_tts(string_to_tts("5".to_string()));
@@ -991,62 +941,6 @@
}
#[test]
- fn test_maybe_assignment() {
- let test0_input = TokenStream::from_tts(string_to_tts("= bar::baz".to_string()));
- let test1_input = TokenStream::from_tts(string_to_tts("= \"5\"".to_string()));
- let test2_input = TokenStream::from_tts(string_to_tts("= 5".to_string()));
- let test3_input = TokenStream::from_tts(string_to_tts("(foo = 10)".to_string()));
- let test4_input = TokenStream::from_tts(string_to_tts("= (foo,bar,baz)".to_string()));
- let test5_input = TokenStream::from_tts(string_to_tts("".to_string()));
-
- let test0 = test0_input.maybe_assignment();
- let test1 = test1_input.maybe_assignment();
- let test2 = test2_input.maybe_assignment();
- let test3 = test3_input.maybe_assignment();
- let test4 = test4_input.maybe_assignment();
- let test5 = test5_input.maybe_assignment();
-
- let test0_expected = TokenStream::from_tts(vec![TokenTree::Token(sp(2, 5),
- token::Ident(str_to_ident("bar"))),
- TokenTree::Token(sp(5, 7), token::ModSep),
- TokenTree::Token(sp(7, 10),
- token::Ident(str_to_ident("baz")))]);
- assert_eq!(test0, Some(&test0_expected[..]));
-
- let test1_expected = TokenStream::from_tts(vec![TokenTree::Token(sp(2, 5),
- token::Literal(Lit::Str_(token::intern("5")), None))]);
- assert_eq!(test1, Some(&test1_expected[..]));
-
- let test2_expected = TokenStream::from_tts(vec![TokenTree::Token( sp(2,3)
- , token::Literal(
- Lit::Integer(
- token::intern(&(5.to_string()))),
- None))]);
- assert_eq!(test2, Some(&test2_expected[..]));
-
- assert_eq!(test3, None);
-
-
- let test4_tts = vec![TokenTree::Token(sp(3, 6), token::Ident(str_to_ident("foo"))),
- TokenTree::Token(sp(6, 7), token::Comma),
- TokenTree::Token(sp(7, 10), token::Ident(str_to_ident("bar"))),
- TokenTree::Token(sp(10, 11), token::Comma),
- TokenTree::Token(sp(11, 14), token::Ident(str_to_ident("baz")))];
-
- let test4_expected = TokenStream::from_tts(vec![TokenTree::Delimited(sp(2, 15),
- Rc::new(Delimited {
- delim: token::DelimToken::Paren,
- open_span: sp(2, 3),
- tts: test4_tts,
- close_span: sp(14, 15),
- }))]);
- assert_eq!(test4, Some(&test4_expected[..]));
-
- assert_eq!(test5, None);
-
- }
-
- #[test]
fn test_maybe_delimited() {
let test0_input = TokenStream::from_tts(string_to_tts("foo(bar::baz)".to_string()));
let test1_input = TokenStream::from_tts(string_to_tts("(bar::baz)".to_string()));
@@ -1070,7 +964,7 @@
TokenTree::Token(sp(4, 6), token::ModSep),
TokenTree::Token(sp(6, 9),
token::Ident(str_to_ident("baz")))]);
- assert_eq!(test1, Some(&test1_expected[..]));
+ assert_eq!(test1, Some(test1_expected));
let test2_expected = TokenStream::from_tts(vec![TokenTree::Token(sp(1, 4),
token::Ident(str_to_ident("foo"))),
@@ -1080,7 +974,7 @@
TokenTree::Token(sp(8, 9), token::Comma),
TokenTree::Token(sp(9, 12),
token::Ident(str_to_ident("baz")))]);
- assert_eq!(test2, Some(&test2_expected[..]));
+ assert_eq!(test2, Some(test2_expected));
assert_eq!(test3, None);
@@ -1089,72 +983,6 @@
assert_eq!(test5, None);
}
- #[test]
- fn test_maybe_comma_list() {
- let test0_input = TokenStream::from_tts(string_to_tts("foo(bar::baz)".to_string()));
- let test1_input = TokenStream::from_tts(string_to_tts("(bar::baz)".to_string()));
- let test2_input = TokenStream::from_tts(string_to_tts("(foo,bar,baz)".to_string()));
- let test3_input = TokenStream::from_tts(string_to_tts("(foo::bar,bar,baz)".to_string()));
- let test4_input = TokenStream::from_tts(string_to_tts("(foo,bar,baz)(zab,rab)"
- .to_string()));
- let test5_input = TokenStream::from_tts(string_to_tts("(foo,bar,baz)foo".to_string()));
- let test6_input = TokenStream::from_tts(string_to_tts("".to_string()));
- // The following is supported behavior!
- let test7_input = TokenStream::from_tts(string_to_tts("(foo,bar,)".to_string()));
-
- let test0 = test0_input.maybe_comma_list();
- let test1 = test1_input.maybe_comma_list();
- let test2 = test2_input.maybe_comma_list();
- let test3 = test3_input.maybe_comma_list();
- let test4 = test4_input.maybe_comma_list();
- let test5 = test5_input.maybe_comma_list();
- let test6 = test6_input.maybe_comma_list();
- let test7 = test7_input.maybe_comma_list();
-
- assert_eq!(test0, None);
-
- let test1_stream = TokenStream::from_tts(vec![TokenTree::Token(sp(1, 4),
- token::Ident(str_to_ident("bar"))),
- TokenTree::Token(sp(4, 6), token::ModSep),
- TokenTree::Token(sp(6, 9),
- token::Ident(str_to_ident("baz")))]);
-
- let test1_expected: Vec<&TokenSlice> = vec![&test1_stream[..]];
- assert_eq!(test1, Some(test1_expected));
-
- let test2_foo = TokenStream::from_tts(vec![TokenTree::Token(sp(1, 4),
- token::Ident(str_to_ident("foo")))]);
- let test2_bar = TokenStream::from_tts(vec![TokenTree::Token(sp(5, 8),
- token::Ident(str_to_ident("bar")))]);
- let test2_baz = TokenStream::from_tts(vec![TokenTree::Token(sp(9, 12),
- token::Ident(str_to_ident("baz")))]);
- let test2_expected: Vec<&TokenSlice> = vec![&test2_foo[..], &test2_bar[..], &test2_baz[..]];
- assert_eq!(test2, Some(test2_expected));
-
- let test3_path = TokenStream::from_tts(vec![TokenTree::Token(sp(1, 4),
- token::Ident(str_to_ident("foo"))),
- TokenTree::Token(sp(4, 6), token::ModSep),
- TokenTree::Token(sp(6, 9),
- token::Ident(str_to_ident("bar")))]);
- let test3_bar = TokenStream::from_tts(vec![TokenTree::Token(sp(10, 13),
- token::Ident(str_to_ident("bar")))]);
- let test3_baz = TokenStream::from_tts(vec![TokenTree::Token(sp(14, 17),
- token::Ident(str_to_ident("baz")))]);
- let test3_expected: Vec<&TokenSlice> =
- vec![&test3_path[..], &test3_bar[..], &test3_baz[..]];
- assert_eq!(test3, Some(test3_expected));
-
- assert_eq!(test4, None);
-
- assert_eq!(test5, None);
-
- assert_eq!(test6, None);
-
-
- let test7_expected: Vec<&TokenSlice> = vec![&test2_foo[..], &test2_bar[..]];
- assert_eq!(test7, Some(test7_expected));
- }
-
// pub fn maybe_ident(&self) -> Option<ast::Ident>
#[test]
fn test_maybe_ident() {
@@ -1171,86 +999,10 @@
assert_eq!(test4, None);
}
- // pub fn maybe_lit(&self) -> Option<token::Lit>
#[test]
- fn test_maybe_lit() {
- let test0 = TokenStream::from_tts(string_to_tts("\"foo\"".to_string())).maybe_lit();
- let test1 = TokenStream::from_tts(string_to_tts("5".to_string())).maybe_lit();
- let test2 = TokenStream::from_tts(string_to_tts("foo".to_string())).maybe_lit();
- let test3 = TokenStream::from_tts(string_to_tts("foo::bar".to_string())).maybe_lit();
- let test4 = TokenStream::from_tts(string_to_tts("foo(bar)".to_string())).maybe_lit();
-
- assert_eq!(test0, Some(Lit::Str_(token::intern("foo"))));
- assert_eq!(test1, Some(Lit::Integer(token::intern(&(5.to_string())))));
- assert_eq!(test2, None);
- assert_eq!(test3, None);
- assert_eq!(test4, None);
- }
-
- #[test]
- fn test_maybe_path_prefix() {
- let test0_input = TokenStream::from_tts(string_to_tts("foo(bar::baz)".to_string()));
- let test1_input = TokenStream::from_tts(string_to_tts("(bar::baz)".to_string()));
- let test2_input = TokenStream::from_tts(string_to_tts("(foo,bar,baz)".to_string()));
- let test3_input = TokenStream::from_tts(string_to_tts("foo::bar(bar,baz)".to_string()));
-
- let test0 = test0_input.maybe_path_prefix();
- let test1 = test1_input.maybe_path_prefix();
- let test2 = test2_input.maybe_path_prefix();
- let test3 = test3_input.maybe_path_prefix();
-
- let test0_tts = vec![TokenTree::Token(sp(4, 7), token::Ident(str_to_ident("bar"))),
- TokenTree::Token(sp(7, 9), token::ModSep),
- TokenTree::Token(sp(9, 12), token::Ident(str_to_ident("baz")))];
-
- let test0_stream = TokenStream::from_tts(vec![TokenTree::Delimited(sp(3, 13),
- Rc::new(Delimited {
- delim: token::DelimToken::Paren,
- open_span: sp(3, 4),
- tts: test0_tts,
- close_span: sp(12, 13),
- }))]);
-
- let test0_expected = Some((ast::Path::from_ident(sp(0, 3), str_to_ident("foo")),
- &test0_stream[..]));
- assert_eq!(test0, test0_expected);
-
- assert_eq!(test1, None);
- assert_eq!(test2, None);
-
- let test3_path = ast::Path {
- span: sp(0, 8),
- global: false,
- segments: vec![ast::PathSegment {
- identifier: str_to_ident("foo"),
- parameters: ast::PathParameters::none(),
- },
- ast::PathSegment {
- identifier: str_to_ident("bar"),
- parameters: ast::PathParameters::none(),
- }],
- };
-
- let test3_tts = vec![TokenTree::Token(sp(9, 12), token::Ident(str_to_ident("bar"))),
- TokenTree::Token(sp(12, 13), token::Comma),
- TokenTree::Token(sp(13, 16), token::Ident(str_to_ident("baz")))];
-
- let test3_stream = TokenStream::from_tts(vec![TokenTree::Delimited(sp(8, 17),
- Rc::new(Delimited {
- delim: token::DelimToken::Paren,
- open_span: sp(8, 9),
- tts: test3_tts,
- close_span: sp(16, 17),
- }))]);
- let test3_expected = Some((test3_path, &test3_stream[..]));
- assert_eq!(test3, test3_expected);
- }
-
- #[test]
- fn test_as_paren_delimited_stream() {
- let test0 = TokenStream::as_paren_delimited_stream(string_to_tts("foo,bar,".to_string()));
- let test1 = TokenStream::as_paren_delimited_stream(string_to_tts("baz(foo,bar)"
- .to_string()));
+ fn test_as_delimited_stream() {
+ let test0 = as_paren_delimited_stream(string_to_tts("foo,bar,".to_string()));
+ let test1 = as_paren_delimited_stream(string_to_tts("baz(foo,bar)".to_string()));
let test0_tts = vec![TokenTree::Token(sp(0, 3), token::Ident(str_to_ident("foo"))),
TokenTree::Token(sp(3, 4), token::Comma),
@@ -1290,5 +1042,4 @@
assert_eq!(test1, test1_stream);
}
-
}
diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs
index 80e2a92..e09a64e 100644
--- a/src/libsyntax_ext/deriving/mod.rs
+++ b/src/libsyntax_ext/deriving/mod.rs
@@ -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 @@
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;
- }
- };
+ 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()) {
+ if !(is_builtin_trait(&tname) || cx.ecfg.enable_custom_derive()) {
feature_gate::emit_feature_err(&cx.parse_sess.span_diagnostic,
"custom_derive",
titem.span,
diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs
index 94bb78e..1f6f57c 100644
--- a/src/libsyntax_ext/format.rs
+++ b/src/libsyntax_ext/format.rs
@@ -406,7 +406,9 @@
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
}
diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs
index c96be8f..0f17180 100644
--- a/src/libsyntax_pos/lib.rs
+++ b/src/libsyntax_pos/lib.rs
@@ -193,6 +193,20 @@
}
}
+ 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 @@
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 @@
// 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)
diff --git a/src/libunwind/build.rs b/src/libunwind/build.rs
index ebe6fd5..fd446f5 100644
--- a/src/libunwind/build.rs
+++ b/src/libunwind/build.rs
@@ -16,7 +16,7 @@
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");
diff --git a/src/libunwind/libunwind.rs b/src/libunwind/libunwind.rs
index d9b6c9e..5e242db 100644
--- a/src/libunwind/libunwind.rs
+++ b/src/libunwind/libunwind.rs
@@ -10,38 +10,15 @@
#![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 @@
_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,6 +74,164 @@
pub type _Unwind_Exception_Cleanup_Fn = extern "C" fn(unwind_code: _Unwind_Reason_Code,
exception: *mut _Unwind_Exception);
+extern "C" {
+ #[unwind]
+ pub fn _Unwind_Resume(exception: *mut _Unwind_Exception) -> !;
+ 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;
+}
+
+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::*;
+
+ #[repr(C)]
+ enum _Unwind_VRS_Result {
+ _UVRSR_OK = 0,
+ _UVRSR_NOT_IMPLEMENTED = 1,
+ _UVRSR_FAILED = 2,
+ }
+ #[repr(C)]
+ enum _Unwind_VRS_RegClass {
+ _UVRSC_CORE = 0,
+ _UVRSC_VFP = 1,
+ _UVRSC_FPA = 2,
+ _UVRSC_WMMXD = 3,
+ _UVRSC_WMMXC = 4,
+ }
+ use self::_Unwind_VRS_RegClass::*;
+ #[repr(C)]
+ enum _Unwind_VRS_DataRepresentation {
+ _UVRSD_UINT32 = 0,
+ _UVRSD_VFPX = 1,
+ _UVRSD_FPAX = 2,
+ _UVRSD_UINT64 = 3,
+ _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;
+
+ extern "C" {
+ fn _Unwind_VRS_Get(ctx: *mut _Unwind_Context,
+ 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 c_void)
+ -> _Unwind_VRS_Result;
+ }
+
+ // 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
+ }
+
+ 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
+ }
+}
+
+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",
@@ -127,122 +260,3 @@
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_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)
-}
-
-// 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,
- _UVRSR_NOT_IMPLEMENTED = 1,
- _UVRSR_FAILED = 2,
- }
- #[repr(C)]
- enum _Unwind_VRS_RegClass {
- _UVRSC_CORE = 0,
- _UVRSC_VFP = 1,
- _UVRSC_FPA = 2,
- _UVRSC_WMMXD = 3,
- _UVRSC_WMMXC = 4,
- }
- #[repr(C)]
- enum _Unwind_VRS_DataRepresentation {
- _UVRSD_UINT32 = 0,
- _UVRSD_VFPX = 1,
- _UVRSD_FPAX = 2,
- _UVRSD_UINT64 = 3,
- _UVRSD_FLOAT = 4,
- _UVRSD_DOUBLE = 5,
- }
-
- type _Unwind_Word = libc::c_uint;
- extern "C" {
- fn _Unwind_VRS_Get(ctx: *mut _Unwind_Context,
- klass: _Unwind_VRS_RegClass,
- word: _Unwind_Word,
- repr: _Unwind_VRS_DataRepresentation,
- data: *mut libc::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
-}
-
-// 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)
-}
-
-// 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
-}
diff --git a/src/llvm b/src/llvm
index 7ca76af..d1cc489 160000
--- a/src/llvm
+++ b/src/llvm
@@ -1 +1 @@
-Subproject commit 7ca76af03bb04659562890d6b4f223fffe0d748f
+Subproject commit d1cc48989b13780f21c408fef17dceb104a09c9d
diff --git a/src/rustc/Cargo.lock b/src/rustc/Cargo.lock
index 4def60e..0b2287c 100644
--- a/src/rustc/Cargo.lock
+++ b/src/rustc/Cargo.lock
@@ -105,6 +105,7 @@
"rustc 0.0.0",
"rustc_back 0.0.0",
"rustc_const_math 0.0.0",
+ "rustc_errors 0.0.0",
"serialize 0.0.0",
"syntax 0.0.0",
"syntax_pos 0.0.0",
diff --git a/src/rustc/std_shim/Cargo.lock b/src/rustc/std_shim/Cargo.lock
index bad4696..70aef55 100644
--- a/src/rustc/std_shim/Cargo.lock
+++ b/src/rustc/std_shim/Cargo.lock
@@ -18,7 +18,7 @@
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 @@
[[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 @@
"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",
diff --git a/src/rustc/std_shim/Cargo.toml b/src/rustc/std_shim/Cargo.toml
index 5602ef8..693cbe0 100644
--- a/src/rustc/std_shim/Cargo.toml
+++ b/src/rustc/std_shim/Cargo.toml
@@ -46,3 +46,4 @@
[features]
jemalloc = ["std/jemalloc"]
debug-jemalloc = ["std/debug-jemalloc"]
+backtrace = ["std/backtrace"]
diff --git a/src/rustllvm/ArchiveWrapper.cpp b/src/rustllvm/ArchiveWrapper.cpp
index 1e7b04c..1e873b5 100644
--- a/src/rustllvm/ArchiveWrapper.cpp
+++ b/src/rustllvm/ArchiveWrapper.cpp
@@ -16,24 +16,62 @@
using namespace llvm;
using namespace llvm::object;
-struct LLVMRustArchiveMember {
+struct RustArchiveMember {
const char *filename;
const char *name;
Archive::Child child;
- LLVMRustArchiveMember(): filename(NULL), name(NULL),
+ RustArchiveMember(): filename(NULL), name(NULL),
#if LLVM_VERSION_MINOR >= 8
child(NULL, NULL, NULL)
#else
child(NULL, NULL)
#endif
{}
- ~LLVMRustArchiveMember() {}
+ ~RustArchiveMember() {}
};
-typedef OwningBinary<Archive> RustArchive;
-extern "C" void*
+struct RustArchiveIterator {
+ Archive::child_iterator cur;
+ Archive::child_iterator end;
+#if LLVM_VERSION_MINOR >= 9
+ Error err;
+#endif
+};
+
+enum class LLVMRustArchiveKind {
+ Other,
+ GNU,
+ MIPS64,
+ BSD,
+ COFF,
+};
+
+static Archive::Kind
+from_rust(LLVMRustArchiveKind kind)
+{
+ switch (kind) {
+ case LLVMRustArchiveKind::GNU:
+ return Archive::K_GNU;
+ case LLVMRustArchiveKind::MIPS64:
+ return Archive::K_MIPS64;
+ case LLVMRustArchiveKind::BSD:
+ return Archive::K_BSD;
+ case LLVMRustArchiveKind::COFF:
+ return Archive::K_COFF;
+ default:
+ llvm_unreachable("Bad ArchiveKind.");
+ }
+}
+
+typedef OwningBinary<Archive> *LLVMRustArchiveRef;
+typedef RustArchiveMember *LLVMRustArchiveMemberRef;
+typedef Archive::Child *LLVMRustArchiveChildRef;
+typedef Archive::Child const *LLVMRustArchiveChildConstRef;
+typedef RustArchiveIterator *LLVMRustArchiveIteratorRef;
+
+extern "C" LLVMRustArchiveRef
LLVMRustOpenArchive(char *path) {
ErrorOr<std::unique_ptr<MemoryBuffer>> buf_or = MemoryBuffer::getFile(path,
-1,
@@ -43,11 +81,19 @@
return nullptr;
}
+#if LLVM_VERSION_MINOR <= 8
ErrorOr<std::unique_ptr<Archive>> archive_or =
+#else
+ Expected<std::unique_ptr<Archive>> archive_or =
+#endif
Archive::create(buf_or.get()->getMemBufferRef());
if (!archive_or) {
+#if LLVM_VERSION_MINOR <= 8
LLVMRustSetLastError(archive_or.getError().message().c_str());
+#else
+ LLVMRustSetLastError(toString(archive_or.takeError()).c_str());
+#endif
return nullptr;
}
@@ -58,29 +104,38 @@
}
extern "C" void
-LLVMRustDestroyArchive(RustArchive *ar) {
+LLVMRustDestroyArchive(LLVMRustArchiveRef ar) {
delete ar;
}
-struct RustArchiveIterator {
- Archive::child_iterator cur;
- Archive::child_iterator end;
-};
-
-extern "C" RustArchiveIterator*
-LLVMRustArchiveIteratorNew(RustArchive *ra) {
+extern "C" LLVMRustArchiveIteratorRef
+LLVMRustArchiveIteratorNew(LLVMRustArchiveRef ra) {
Archive *ar = ra->getBinary();
RustArchiveIterator *rai = new RustArchiveIterator();
+#if LLVM_VERSION_MINOR <= 8
rai->cur = ar->child_begin();
+#else
+ rai->cur = ar->child_begin(rai->err);
+ if (rai->err) {
+ LLVMRustSetLastError(toString(std::move(rai->err)).c_str());
+ return NULL;
+ }
+#endif
rai->end = ar->child_end();
return rai;
}
-extern "C" const Archive::Child*
-LLVMRustArchiveIteratorNext(RustArchiveIterator *rai) {
+extern "C" LLVMRustArchiveChildConstRef
+LLVMRustArchiveIteratorNext(LLVMRustArchiveIteratorRef rai) {
+#if LLVM_VERSION_MINOR >= 9
+ if (rai->err) {
+ LLVMRustSetLastError(toString(std::move(rai->err)).c_str());
+ return NULL;
+ }
+#endif
if (rai->cur == rai->end)
return NULL;
-#if LLVM_VERSION_MINOR >= 8
+#if LLVM_VERSION_MINOR == 8
const ErrorOr<Archive::Child>* cur = rai->cur.operator->();
if (!*cur) {
LLVMRustSetLastError(cur->getError().message().c_str());
@@ -97,17 +152,17 @@
}
extern "C" void
-LLVMRustArchiveChildFree(Archive::Child *child) {
+LLVMRustArchiveChildFree(LLVMRustArchiveChildRef child) {
delete child;
}
extern "C" void
-LLVMRustArchiveIteratorFree(RustArchiveIterator *rai) {
+LLVMRustArchiveIteratorFree(LLVMRustArchiveIteratorRef rai) {
delete rai;
}
extern "C" const char*
-LLVMRustArchiveChildName(const Archive::Child *child, size_t *size) {
+LLVMRustArchiveChildName(LLVMRustArchiveChildConstRef child, size_t *size) {
ErrorOr<StringRef> name_or_err = child->getName();
if (name_or_err.getError())
return NULL;
@@ -117,7 +172,7 @@
}
extern "C" const char*
-LLVMRustArchiveChildData(Archive::Child *child, size_t *size) {
+LLVMRustArchiveChildData(LLVMRustArchiveChildRef child, size_t *size) {
StringRef buf;
ErrorOr<StringRef> buf_or_err = child->getBuffer();
if (buf_or_err.getError()) {
@@ -129,9 +184,10 @@
return buf.data();
}
-extern "C" LLVMRustArchiveMember*
-LLVMRustArchiveMemberNew(char *Filename, char *Name, Archive::Child *child) {
- LLVMRustArchiveMember *Member = new LLVMRustArchiveMember;
+extern "C" LLVMRustArchiveMemberRef
+LLVMRustArchiveMemberNew(char *Filename, char *Name,
+ LLVMRustArchiveChildRef child) {
+ RustArchiveMember *Member = new RustArchiveMember;
Member->filename = Filename;
Member->name = Name;
if (child)
@@ -140,29 +196,51 @@
}
extern "C" void
-LLVMRustArchiveMemberFree(LLVMRustArchiveMember *Member) {
+LLVMRustArchiveMemberFree(LLVMRustArchiveMemberRef Member) {
delete Member;
}
-extern "C" int
+extern "C" LLVMRustResult
LLVMRustWriteArchive(char *Dst,
size_t NumMembers,
- const LLVMRustArchiveMember **NewMembers,
+ const LLVMRustArchiveMemberRef *NewMembers,
bool WriteSymbtab,
- Archive::Kind Kind) {
+ LLVMRustArchiveKind rust_kind) {
+
+#if LLVM_VERSION_MINOR <= 8
std::vector<NewArchiveIterator> Members;
+#else
+ std::vector<NewArchiveMember> Members;
+#endif
+ auto Kind = from_rust(rust_kind);
for (size_t i = 0; i < NumMembers; i++) {
auto Member = NewMembers[i];
assert(Member->name);
if (Member->filename) {
-#if LLVM_VERSION_MINOR >= 8
+#if LLVM_VERSION_MINOR >= 9
+ Expected<NewArchiveMember> MOrErr = NewArchiveMember::getFile(Member->filename, true);
+ if (!MOrErr) {
+ LLVMRustSetLastError(toString(MOrErr.takeError()).c_str());
+ return LLVMRustResult::Failure;
+ }
+ Members.push_back(std::move(*MOrErr));
+#elif LLVM_VERSION_MINOR == 8
Members.push_back(NewArchiveIterator(Member->filename));
#else
Members.push_back(NewArchiveIterator(Member->filename, Member->name));
#endif
} else {
+#if LLVM_VERSION_MINOR <= 8
Members.push_back(NewArchiveIterator(Member->child, Member->name));
+#else
+ Expected<NewArchiveMember> MOrErr = NewArchiveMember::getOldMember(Member->child, true);
+ if (!MOrErr) {
+ LLVMRustSetLastError(toString(MOrErr.takeError()).c_str());
+ return LLVMRustResult::Failure;
+ }
+ Members.push_back(std::move(*MOrErr));
+#endif
}
}
#if LLVM_VERSION_MINOR >= 8
@@ -171,7 +249,7 @@
auto pair = writeArchive(Dst, Members, WriteSymbtab, Kind, true);
#endif
if (!pair.second)
- return 0;
+ return LLVMRustResult::Success;
LLVMRustSetLastError(pair.second.message().c_str());
- return -1;
+ return LLVMRustResult::Failure;
}
diff --git a/src/rustllvm/ExecutionEngineWrapper.cpp b/src/rustllvm/ExecutionEngineWrapper.cpp
deleted file mode 100644
index b26ab44..0000000
--- a/src/rustllvm/ExecutionEngineWrapper.cpp
+++ /dev/null
@@ -1,111 +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.
-
-#include "rustllvm.h"
-
-#include "llvm/ExecutionEngine/SectionMemoryManager.h"
-
-using namespace llvm;
-using namespace llvm::sys;
-using namespace llvm::object;
-
-class RustJITMemoryManager : public SectionMemoryManager
-{
- typedef SectionMemoryManager Base;
-
- public:
-
- RustJITMemoryManager() {}
-
- uint64_t getSymbolAddress(const std::string &Name) override
- {
- return Base::getSymbolAddress(Name);
- }
-};
-
-DEFINE_SIMPLE_CONVERSION_FUNCTIONS(RustJITMemoryManager, LLVMRustJITMemoryManagerRef)
-
-extern "C" LLVMBool LLVMRustLoadDynamicLibrary(const char *path)
-{
- std::string err;
- DynamicLibrary lib = DynamicLibrary::getPermanentLibrary(path, &err);
-
- if (!lib.isValid())
- LLVMRustSetLastError(err.c_str());
-
- return lib.isValid();
-}
-
-// Calls LLVMAddModule;
-// exists for consistency with LLVMExecutionEngineRemoveModule
-extern "C" void LLVMExecutionEngineAddModule(
- LLVMExecutionEngineRef eeref, LLVMModuleRef mref)
-{
-#ifdef _WIN32
- // On Windows, MCJIT must generate ELF objects
- std::string target = getProcessTriple();
- target += "-elf";
- target = Triple::normalize(target);
- unwrap(mref)->setTargetTriple(target);
-#endif
- LLVMAddModule(eeref, mref);
-}
-
-// LLVMRemoveModule exists in LLVM's C bindings,
-// but it requires pointless parameters
-extern "C" LLVMBool LLVMExecutionEngineRemoveModule(
- LLVMExecutionEngineRef eeref, LLVMModuleRef mref)
-{
- ExecutionEngine *ee = unwrap(eeref);
- Module *m = unwrap(mref);
-
- return ee->removeModule(m);
-}
-
-extern "C" LLVMExecutionEngineRef LLVMBuildExecutionEngine(LLVMModuleRef mod)
-{
- // These are necessary for code generation to work properly.
- InitializeNativeTarget();
- InitializeNativeTargetAsmPrinter();
- InitializeNativeTargetAsmParser();
-
-#ifdef _WIN32
- // On Windows, MCJIT must generate ELF objects
- std::string target = getProcessTriple();
- target += "-elf";
- target = Triple::normalize(target);
- unwrap(mod)->setTargetTriple(target);
-#endif
-
- std::string error_str;
- TargetOptions options;
-
- RustJITMemoryManager *mm = new RustJITMemoryManager;
-
- ExecutionEngine *ee =
- EngineBuilder(std::unique_ptr<Module>(unwrap(mod)))
- .setMCJITMemoryManager(std::unique_ptr<RustJITMemoryManager>(mm))
- .setEngineKind(EngineKind::JIT)
- .setErrorStr(&error_str)
- .setTargetOptions(options)
- .create();
-
- if (!ee)
- LLVMRustSetLastError(error_str.c_str());
-
- return wrap(ee);
-}
-
-extern "C" void LLVMExecutionEngineFinalizeObject(LLVMExecutionEngineRef eeref)
-{
- ExecutionEngine *ee = unwrap(eeref);
-
- ee->finalizeObject();
-}
diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp
index 3564f33..3a20bb2 100644
--- a/src/rustllvm/PassWrapper.cpp
+++ b/src/rustllvm/PassWrapper.cpp
@@ -17,6 +17,7 @@
#include "llvm/Support/Host.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/TargetTransformInfo.h"
+#include "llvm/IR/AutoUpgrade.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetSubtargetInfo.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
@@ -54,41 +55,48 @@
initializeTarget(Registry);
}
-
-enum class SupportedPassKind {
+enum class LLVMRustPassKind {
+ Other,
Function,
Module,
- Unsupported
};
-extern "C" Pass*
+static LLVMRustPassKind
+to_rust(PassKind kind)
+{
+ switch (kind) {
+ case PT_Function:
+ return LLVMRustPassKind::Function;
+ case PT_Module:
+ return LLVMRustPassKind::Module;
+ default:
+ return LLVMRustPassKind::Other;
+ }
+}
+
+extern "C" LLVMPassRef
LLVMRustFindAndCreatePass(const char *PassName) {
StringRef SR(PassName);
PassRegistry *PR = PassRegistry::getPassRegistry();
const PassInfo *PI = PR->getPassInfo(SR);
if (PI) {
- return PI->createPass();
+ return wrap(PI->createPass());
}
return NULL;
}
-extern "C" SupportedPassKind
-LLVMRustPassKind(Pass *pass) {
- assert(pass);
- PassKind passKind = pass->getPassKind();
- if (passKind == PT_Module) {
- return SupportedPassKind::Module;
- } else if (passKind == PT_Function) {
- return SupportedPassKind::Function;
- } else {
- return SupportedPassKind::Unsupported;
- }
+extern "C" LLVMRustPassKind
+LLVMRustPassKind(LLVMPassRef rust_pass) {
+ assert(rust_pass);
+ Pass *pass = unwrap(rust_pass);
+ return to_rust(pass->getPassKind());
}
extern "C" void
-LLVMRustAddPass(LLVMPassManagerRef PM, Pass *pass) {
- assert(pass);
+LLVMRustAddPass(LLVMPassManagerRef PM, LLVMPassRef rust_pass) {
+ assert(rust_pass);
+ Pass *pass = unwrap(rust_pass);
PassManagerBase *pm = unwrap(PM);
pm->add(pass);
}
@@ -162,17 +170,99 @@
return (Bits & FeatureEntry->Value) == FeatureEntry->Value;
}
+enum class LLVMRustCodeModel {
+ Other,
+ Default,
+ JITDefault,
+ Small,
+ Kernel,
+ Medium,
+ Large,
+};
+
+static CodeModel::Model
+from_rust(LLVMRustCodeModel model)
+{
+ switch (model) {
+ case LLVMRustCodeModel::Default:
+ return CodeModel::Default;
+ case LLVMRustCodeModel::JITDefault:
+ return CodeModel::JITDefault;
+ case LLVMRustCodeModel::Small:
+ return CodeModel::Small;
+ case LLVMRustCodeModel::Kernel:
+ return CodeModel::Kernel;
+ case LLVMRustCodeModel::Medium:
+ return CodeModel::Medium;
+ case LLVMRustCodeModel::Large:
+ return CodeModel::Large;
+ default:
+ llvm_unreachable("Bad CodeModel.");
+ }
+}
+
+enum class LLVMRustCodeGenOptLevel {
+ Other,
+ None,
+ Less,
+ Default,
+ Aggressive,
+};
+
+static CodeGenOpt::Level
+from_rust(LLVMRustCodeGenOptLevel level)
+{
+ switch (level) {
+ case LLVMRustCodeGenOptLevel::None:
+ return CodeGenOpt::None;
+ case LLVMRustCodeGenOptLevel::Less:
+ return CodeGenOpt::Less;
+ case LLVMRustCodeGenOptLevel::Default:
+ return CodeGenOpt::Default;
+ case LLVMRustCodeGenOptLevel::Aggressive:
+ return CodeGenOpt::Aggressive;
+ default:
+ llvm_unreachable("Bad CodeGenOptLevel.");
+ }
+}
+
extern "C" LLVMTargetMachineRef
LLVMRustCreateTargetMachine(const char *triple,
const char *cpu,
const char *feature,
- CodeModel::Model CM,
- Reloc::Model RM,
- CodeGenOpt::Level OptLevel,
+ LLVMRustCodeModel rust_CM,
+ LLVMRelocMode Reloc,
+ LLVMRustCodeGenOptLevel rust_OptLevel,
bool UseSoftFloat,
bool PositionIndependentExecutable,
bool FunctionSections,
bool DataSections) {
+
+#if LLVM_VERSION_MINOR <= 8
+ Reloc::Model RM;
+#else
+ Optional<Reloc::Model> RM;
+#endif
+ auto CM = from_rust(rust_CM);
+ auto OptLevel = from_rust(rust_OptLevel);
+
+ switch (Reloc){
+ case LLVMRelocStatic:
+ RM = Reloc::Static;
+ break;
+ case LLVMRelocPIC:
+ RM = Reloc::PIC_;
+ break;
+ case LLVMRelocDynamicNoPic:
+ RM = Reloc::DynamicNoPIC;
+ break;
+ default:
+#if LLVM_VERSION_MINOR <= 8
+ RM = Reloc::Default;
+#endif
+ break;
+ }
+
std::string Error;
Triple Trip(Triple::normalize(triple));
const llvm::Target *TheTarget = TargetRegistry::lookupTarget(Trip.getTriple(),
@@ -188,7 +278,10 @@
}
TargetOptions Options;
+#if LLVM_VERSION_MINOR <= 8
Options.PositionIndependentExecutable = PositionIndependentExecutable;
+#endif
+
Options.FloatABIType = FloatABI::Default;
if (UseSoftFloat) {
Options.FloatABIType = FloatABI::Soft;
@@ -225,14 +318,14 @@
extern "C" void
LLVMRustConfigurePassManagerBuilder(LLVMPassManagerBuilderRef PMB,
- CodeGenOpt::Level OptLevel,
+ LLVMRustCodeGenOptLevel OptLevel,
bool MergeFunctions,
bool SLPVectorize,
bool LoopVectorize) {
// Ignore mergefunc for now as enabling it causes crashes.
//unwrap(PMB)->MergeFunctions = MergeFunctions;
unwrap(PMB)->SLPVectorize = SLPVectorize;
- unwrap(PMB)->OptLevel = OptLevel;
+ unwrap(PMB)->OptLevel = from_rust(OptLevel);
unwrap(PMB)->LoopVectorize = LoopVectorize;
}
@@ -267,12 +360,19 @@
// similar code in clang's BackendUtil.cpp file.
extern "C" void
LLVMRustRunFunctionPassManager(LLVMPassManagerRef PM, LLVMModuleRef M) {
- FunctionPassManager *P = unwrap<FunctionPassManager>(PM);
+ llvm::legacy::FunctionPassManager *P = unwrap<llvm::legacy::FunctionPassManager>(PM);
P->doInitialization();
+
+ // Upgrade all calls to old intrinsics first.
+ for (Module::iterator I = unwrap(M)->begin(),
+ E = unwrap(M)->end(); I != E;)
+ UpgradeCallsToIntrinsic(&*I++); // must be post-increment, as we remove
+
for (Module::iterator I = unwrap(M)->begin(),
E = unwrap(M)->end(); I != E; ++I)
if (!I->isDeclaration())
P->run(*I);
+
P->doFinalization();
}
@@ -288,13 +388,33 @@
cl::ParseCommandLineOptions(Argc, Argv);
}
-extern "C" bool
+enum class LLVMRustFileType {
+ Other,
+ AssemblyFile,
+ ObjectFile,
+};
+
+static TargetMachine::CodeGenFileType
+from_rust(LLVMRustFileType type)
+{
+ switch (type) {
+ case LLVMRustFileType::AssemblyFile:
+ return TargetMachine::CGFT_AssemblyFile;
+ case LLVMRustFileType::ObjectFile:
+ return TargetMachine::CGFT_ObjectFile;
+ default:
+ llvm_unreachable("Bad FileType.");
+ }
+}
+
+extern "C" LLVMRustResult
LLVMRustWriteOutputFile(LLVMTargetMachineRef Target,
LLVMPassManagerRef PMR,
LLVMModuleRef M,
const char *path,
- TargetMachine::CodeGenFileType FileType) {
- PassManager *PM = unwrap<PassManager>(PMR);
+ LLVMRustFileType rust_FileType) {
+ llvm::legacy::PassManager *PM = unwrap<llvm::legacy::PassManager>(PMR);
+ auto FileType = from_rust(rust_FileType);
std::string ErrorInfo;
std::error_code EC;
@@ -303,7 +423,7 @@
ErrorInfo = EC.message();
if (ErrorInfo != "") {
LLVMRustSetLastError(ErrorInfo.c_str());
- return false;
+ return LLVMRustResult::Failure;
}
unwrap(Target)->addPassesToEmitFile(*PM, OS, FileType, false);
@@ -313,14 +433,14 @@
// stream (OS), so the only real safe place to delete this is here? Don't we
// wish this was written in Rust?
delete PM;
- return true;
+ return LLVMRustResult::Success;
}
extern "C" void
LLVMRustPrintModule(LLVMPassManagerRef PMR,
LLVMModuleRef M,
const char* path) {
- PassManager *PM = unwrap<PassManager>(PMR);
+ llvm::legacy::PassManager *PM = unwrap<llvm::legacy::PassManager>(PMR);
std::string ErrorInfo;
std::error_code EC;
@@ -358,9 +478,24 @@
extern "C" void
LLVMRustRunRestrictionPass(LLVMModuleRef M, char **symbols, size_t len) {
- PassManager passes;
+ llvm::legacy::PassManager passes;
+
+#if LLVM_VERSION_MINOR <= 8
ArrayRef<const char*> ref(symbols, len);
passes.add(llvm::createInternalizePass(ref));
+#else
+ auto PreserveFunctions = [=](const GlobalValue &GV) {
+ for (size_t i=0; i<len; i++) {
+ if (GV.getName() == symbols[i]) {
+ return true;
+ }
+ }
+ return false;
+ };
+
+ passes.add(llvm::createInternalizePass(PreserveFunctions));
+#endif
+
passes.run(*unwrap(M));
}
@@ -396,3 +531,10 @@
LLVMRustGetModuleDataLayout(LLVMModuleRef M) {
return wrap(&unwrap(M)->getDataLayout());
}
+
+extern "C" void
+LLVMRustSetModulePIELevel(LLVMModuleRef M) {
+#if LLVM_VERSION_MINOR >= 9
+ unwrap(M)->setPIELevel(PIELevel::Level::Large);
+#endif
+}
diff --git a/src/rustllvm/README b/src/rustllvm/README
index c0db3f6..e1c6dd0 100644
--- a/src/rustllvm/README
+++ b/src/rustllvm/README
@@ -1,2 +1,16 @@
This directory currently contains some LLVM support code. This will generally
be sent upstream to LLVM in time; for now it lives here.
+
+NOTE: the LLVM C++ ABI is subject to between-version breakage and must *never*
+be exposed to Rust. To allow for easy auditing of that, all Rust-exposed types
+must be typedef-ed as "LLVMXyz", or "LLVMRustXyz" if they were defined here.
+
+Functions that return a failure status and leave the error in
+the LLVM last error should return an LLVMRustResult rather than an
+int or anything to avoid confusion.
+
+When translating enums, add a single `Other` variant as the first
+one to allow for new variants to be added. It should abort when used
+as an input.
+
+All other types must not be typedef-ed as such.
diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp
index fadd95c..0da25e7 100644
--- a/src/rustllvm/RustWrapper.cpp
+++ b/src/rustllvm/RustWrapper.cpp
@@ -13,6 +13,7 @@
#include "llvm/Object/ObjectFile.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/DiagnosticPrinter.h"
+#include "llvm/IR/Instructions.h"
#include "llvm/IR/CallSite.h"
@@ -27,6 +28,30 @@
using namespace llvm::sys;
using namespace llvm::object;
+// LLVMAtomicOrdering is already an enum - don't create another
+// one.
+static AtomicOrdering from_rust(LLVMAtomicOrdering Ordering) {
+ switch (Ordering) {
+ case LLVMAtomicOrderingNotAtomic:
+ return AtomicOrdering::NotAtomic;
+ case LLVMAtomicOrderingUnordered:
+ return AtomicOrdering::Unordered;
+ case LLVMAtomicOrderingMonotonic:
+ return AtomicOrdering::Monotonic;
+ case LLVMAtomicOrderingAcquire:
+ return AtomicOrdering::Acquire;
+ case LLVMAtomicOrderingRelease:
+ return AtomicOrdering::Release;
+ case LLVMAtomicOrderingAcquireRelease:
+ return AtomicOrdering::AcquireRelease;
+ case LLVMAtomicOrderingSequentiallyConsistent:
+ return AtomicOrdering::SequentiallyConsistent;
+ }
+
+ llvm_unreachable("Invalid LLVMAtomicOrdering value!");
+}
+
+
static char *LastError;
extern "C" LLVMMemoryBufferRef
@@ -57,49 +82,34 @@
unwrap(M)->setTargetTriple(Triple::normalize(triple));
}
-extern "C" LLVMValueRef LLVMRustConstSmallInt(LLVMTypeRef IntTy, unsigned N,
- LLVMBool SignExtend) {
- return LLVMConstInt(IntTy, (unsigned long long)N, SignExtend);
-}
-
-extern "C" LLVMValueRef LLVMRustConstInt(LLVMTypeRef IntTy,
- unsigned N_hi,
- unsigned N_lo,
- LLVMBool SignExtend) {
- unsigned long long N = N_hi;
- N <<= 32;
- N |= N_lo;
- return LLVMConstInt(IntTy, N, SignExtend);
-}
-
extern "C" void LLVMRustPrintPassTimings() {
raw_fd_ostream OS (2, false); // stderr.
TimerGroup::printAll(OS);
}
-extern "C" LLVMValueRef LLVMGetNamedValue(LLVMModuleRef M,
- const char* Name) {
+extern "C" LLVMValueRef LLVMRustGetNamedValue(LLVMModuleRef M,
+ const char* Name) {
return wrap(unwrap(M)->getNamedValue(Name));
}
-extern "C" LLVMValueRef LLVMGetOrInsertFunction(LLVMModuleRef M,
- const char* Name,
- LLVMTypeRef FunctionTy) {
+extern "C" LLVMValueRef LLVMRustGetOrInsertFunction(LLVMModuleRef M,
+ const char* Name,
+ LLVMTypeRef FunctionTy) {
return wrap(unwrap(M)->getOrInsertFunction(Name,
unwrap<FunctionType>(FunctionTy)));
}
-extern "C" LLVMValueRef LLVMGetOrInsertGlobal(LLVMModuleRef M,
- const char* Name,
- LLVMTypeRef Ty) {
+extern "C" LLVMValueRef LLVMRustGetOrInsertGlobal(LLVMModuleRef M,
+ const char* Name,
+ LLVMTypeRef Ty) {
return wrap(unwrap(M)->getOrInsertGlobal(Name, unwrap(Ty)));
}
-extern "C" LLVMTypeRef LLVMMetadataTypeInContext(LLVMContextRef C) {
+extern "C" LLVMTypeRef LLVMRustMetadataTypeInContext(LLVMContextRef C) {
return wrap(Type::getMetadataTy(*unwrap(C)));
}
-extern "C" void LLVMAddCallSiteAttribute(LLVMValueRef Instr, unsigned index, uint64_t Val) {
+extern "C" void LLVMRustAddCallSiteAttribute(LLVMValueRef Instr, unsigned index, uint64_t Val) {
CallSite Call = CallSite(unwrap<Instruction>(Instr));
AttrBuilder B;
B.addRawValue(Val);
@@ -110,7 +120,10 @@
}
-extern "C" void LLVMAddDereferenceableCallSiteAttr(LLVMValueRef Instr, unsigned idx, uint64_t b) {
+extern "C" void LLVMRustAddDereferenceableCallSiteAttr(LLVMValueRef Instr,
+ unsigned idx,
+ uint64_t b)
+{
CallSite Call = CallSite(unwrap<Instruction>(Instr));
AttrBuilder B;
B.addDereferenceableAttr(b);
@@ -120,38 +133,50 @@
idx, B)));
}
-extern "C" void LLVMAddFunctionAttribute(LLVMValueRef Fn, unsigned index,
- uint64_t Val) {
+extern "C" void LLVMRustAddFunctionAttribute(LLVMValueRef Fn,
+ unsigned index,
+ uint64_t Val)
+{
Function *A = unwrap<Function>(Fn);
AttrBuilder B;
B.addRawValue(Val);
A->addAttributes(index, AttributeSet::get(A->getContext(), index, B));
}
-extern "C" void LLVMAddDereferenceableAttr(LLVMValueRef Fn, unsigned index, uint64_t bytes) {
+extern "C" void LLVMRustAddDereferenceableAttr(LLVMValueRef Fn,
+ unsigned index,
+ uint64_t bytes)
+{
Function *A = unwrap<Function>(Fn);
AttrBuilder B;
B.addDereferenceableAttr(bytes);
A->addAttributes(index, AttributeSet::get(A->getContext(), index, B));
}
-extern "C" void LLVMAddFunctionAttrString(LLVMValueRef Fn, unsigned index, const char *Name) {
+extern "C" void LLVMRustAddFunctionAttrString(LLVMValueRef Fn,
+ unsigned index,
+ const char *Name)
+{
Function *F = unwrap<Function>(Fn);
AttrBuilder B;
B.addAttribute(Name);
F->addAttributes(index, AttributeSet::get(F->getContext(), index, B));
}
-extern "C" void LLVMAddFunctionAttrStringValue(LLVMValueRef Fn, unsigned index,
- const char *Name,
- const char *Value) {
+extern "C" void LLVMRustAddFunctionAttrStringValue(LLVMValueRef Fn,
+ unsigned index,
+ const char *Name,
+ const char *Value) {
Function *F = unwrap<Function>(Fn);
AttrBuilder B;
B.addAttribute(Name, Value);
F->addAttributes(index, AttributeSet::get(F->getContext(), index, B));
}
-extern "C" void LLVMRemoveFunctionAttributes(LLVMValueRef Fn, unsigned index, uint64_t Val) {
+extern "C" void LLVMRustRemoveFunctionAttributes(LLVMValueRef Fn,
+ unsigned index,
+ uint64_t Val)
+{
Function *A = unwrap<Function>(Fn);
const AttributeSet PAL = A->getAttributes();
AttrBuilder B(Val);
@@ -161,7 +186,10 @@
A->setAttributes(PALnew);
}
-extern "C" void LLVMRemoveFunctionAttrString(LLVMValueRef fn, unsigned index, const char *Name) {
+extern "C" void LLVMRustRemoveFunctionAttrString(LLVMValueRef fn,
+ unsigned index,
+ const char *Name)
+{
Function *f = unwrap<Function>(fn);
LLVMContext &C = f->getContext();
AttrBuilder B;
@@ -181,80 +209,122 @@
}
}
-extern "C" LLVMValueRef LLVMBuildAtomicLoad(LLVMBuilderRef B,
- LLVMValueRef source,
- const char* Name,
- AtomicOrdering order,
- unsigned alignment) {
+extern "C" LLVMValueRef LLVMRustBuildAtomicLoad(LLVMBuilderRef B,
+ LLVMValueRef source,
+ const char* Name,
+ LLVMAtomicOrdering order,
+ unsigned alignment) {
LoadInst* li = new LoadInst(unwrap(source),0);
- li->setAtomic(order);
+ li->setAtomic(from_rust(order));
li->setAlignment(alignment);
return wrap(unwrap(B)->Insert(li, Name));
}
-extern "C" LLVMValueRef LLVMBuildAtomicStore(LLVMBuilderRef B,
- LLVMValueRef val,
- LLVMValueRef target,
- AtomicOrdering order,
- unsigned alignment) {
+extern "C" LLVMValueRef LLVMRustBuildAtomicStore(LLVMBuilderRef B,
+ LLVMValueRef val,
+ LLVMValueRef target,
+ LLVMAtomicOrdering order,
+ unsigned alignment) {
StoreInst* si = new StoreInst(unwrap(val),unwrap(target));
- si->setAtomic(order);
+ si->setAtomic(from_rust(order));
si->setAlignment(alignment);
return wrap(unwrap(B)->Insert(si));
}
-extern "C" LLVMValueRef LLVMBuildAtomicCmpXchg(LLVMBuilderRef B,
+extern "C" LLVMValueRef LLVMRustBuildAtomicCmpXchg(LLVMBuilderRef B,
LLVMValueRef target,
LLVMValueRef old,
LLVMValueRef source,
- AtomicOrdering order,
- AtomicOrdering failure_order,
+ LLVMAtomicOrdering order,
+ LLVMAtomicOrdering failure_order,
LLVMBool weak) {
- AtomicCmpXchgInst* acxi = unwrap(B)->CreateAtomicCmpXchg(unwrap(target),
- unwrap(old),
- unwrap(source),
- order,
- failure_order);
+ AtomicCmpXchgInst* acxi = unwrap(B)->CreateAtomicCmpXchg(
+ unwrap(target),
+ unwrap(old),
+ unwrap(source),
+ from_rust(order),
+ from_rust(failure_order));
acxi->setWeak(weak);
return wrap(acxi);
}
-extern "C" LLVMValueRef LLVMBuildAtomicFence(LLVMBuilderRef B,
- AtomicOrdering order,
- SynchronizationScope scope) {
- return wrap(unwrap(B)->CreateFence(order, scope));
+
+enum class LLVMRustSynchronizationScope {
+ Other,
+ SingleThread,
+ CrossThread,
+};
+
+static SynchronizationScope
+from_rust(LLVMRustSynchronizationScope scope)
+{
+ switch (scope) {
+ case LLVMRustSynchronizationScope::SingleThread:
+ return SingleThread;
+ case LLVMRustSynchronizationScope::CrossThread:
+ return CrossThread;
+ default:
+ llvm_unreachable("bad SynchronizationScope.");
+ }
}
-extern "C" void LLVMSetDebug(int Enabled) {
+extern "C" LLVMValueRef LLVMRustBuildAtomicFence(
+ LLVMBuilderRef B,
+ LLVMAtomicOrdering order,
+ LLVMRustSynchronizationScope scope)
+{
+ return wrap(unwrap(B)->CreateFence(from_rust(order), from_rust(scope)));
+}
+
+extern "C" void LLVMRustSetDebug(int Enabled) {
#ifndef NDEBUG
DebugFlag = Enabled;
#endif
}
-extern "C" LLVMValueRef LLVMInlineAsm(LLVMTypeRef Ty,
- char *AsmString,
- char *Constraints,
- LLVMBool HasSideEffects,
- LLVMBool IsAlignStack,
- unsigned Dialect) {
- return wrap(InlineAsm::get(unwrap<FunctionType>(Ty), AsmString,
- Constraints, HasSideEffects,
- IsAlignStack, (InlineAsm::AsmDialect) Dialect));
+enum class LLVMRustAsmDialect {
+ Other,
+ Att,
+ Intel,
+};
+
+static InlineAsm::AsmDialect
+from_rust(LLVMRustAsmDialect dialect)
+{
+ switch (dialect) {
+ case LLVMRustAsmDialect::Att:
+ return InlineAsm::AD_ATT;
+ case LLVMRustAsmDialect::Intel:
+ return InlineAsm::AD_Intel;
+ default:
+ llvm_unreachable("bad AsmDialect.");
+ }
}
-typedef DIBuilder* DIBuilderRef;
+extern "C" LLVMValueRef LLVMRustInlineAsm(LLVMTypeRef Ty,
+ char *AsmString,
+ char *Constraints,
+ LLVMBool HasSideEffects,
+ LLVMBool IsAlignStack,
+ LLVMRustAsmDialect Dialect) {
+ return wrap(InlineAsm::get(unwrap<FunctionType>(Ty), AsmString,
+ Constraints, HasSideEffects,
+ IsAlignStack, from_rust(Dialect)));
+}
-typedef struct LLVMOpaqueMetadata *LLVMMetadataRef;
+typedef DIBuilder* LLVMRustDIBuilderRef;
+
+typedef struct LLVMOpaqueMetadata *LLVMRustMetadataRef;
namespace llvm {
-DEFINE_ISA_CONVERSION_FUNCTIONS(Metadata, LLVMMetadataRef)
+DEFINE_ISA_CONVERSION_FUNCTIONS(Metadata, LLVMRustMetadataRef)
-inline Metadata **unwrap(LLVMMetadataRef *Vals) {
+inline Metadata **unwrap(LLVMRustMetadataRef *Vals) {
return reinterpret_cast<Metadata**>(Vals);
}
}
template<typename DIT>
-DIT* unwrapDIptr(LLVMMetadataRef ref) {
+DIT* unwrapDIptr(LLVMRustMetadataRef ref) {
return (DIT*) (ref ? unwrap<MDNode>(ref) : NULL);
}
@@ -266,11 +336,11 @@
return DEBUG_METADATA_VERSION;
}
-extern "C" uint32_t LLVMVersionMinor() {
+extern "C" uint32_t LLVMRustVersionMinor() {
return LLVM_VERSION_MINOR;
}
-extern "C" uint32_t LLVMVersionMajor() {
+extern "C" uint32_t LLVMRustVersionMajor() {
return LLVM_VERSION_MAJOR;
}
@@ -280,20 +350,20 @@
unwrap(M)->addModuleFlag(Module::Warning, name, value);
}
-extern "C" DIBuilderRef LLVMDIBuilderCreate(LLVMModuleRef M) {
+extern "C" LLVMRustDIBuilderRef LLVMRustDIBuilderCreate(LLVMModuleRef M) {
return new DIBuilder(*unwrap(M));
}
-extern "C" void LLVMDIBuilderDispose(DIBuilderRef Builder) {
+extern "C" void LLVMRustDIBuilderDispose(LLVMRustDIBuilderRef Builder) {
delete Builder;
}
-extern "C" void LLVMDIBuilderFinalize(DIBuilderRef Builder) {
+extern "C" void LLVMRustDIBuilderFinalize(LLVMRustDIBuilderRef Builder) {
Builder->finalize();
}
-extern "C" LLVMMetadataRef LLVMDIBuilderCreateCompileUnit(
- DIBuilderRef Builder,
+extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateCompileUnit(
+ LLVMRustDIBuilderRef Builder,
unsigned Lang,
const char* File,
const char* Dir,
@@ -312,17 +382,17 @@
SplitName));
}
-extern "C" LLVMMetadataRef LLVMDIBuilderCreateFile(
- DIBuilderRef Builder,
+extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateFile(
+ LLVMRustDIBuilderRef Builder,
const char* Filename,
const char* Directory) {
return wrap(Builder->createFile(Filename, Directory));
}
-extern "C" LLVMMetadataRef LLVMDIBuilderCreateSubroutineType(
- DIBuilderRef Builder,
- LLVMMetadataRef File,
- LLVMMetadataRef ParameterTypes) {
+extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateSubroutineType(
+ LLVMRustDIBuilderRef Builder,
+ LLVMRustMetadataRef File,
+ LLVMRustMetadataRef ParameterTypes) {
return wrap(Builder->createSubroutineType(
#if LLVM_VERSION_MINOR == 7
unwrapDI<DIFile>(File),
@@ -330,22 +400,22 @@
DITypeRefArray(unwrap<MDTuple>(ParameterTypes))));
}
-extern "C" LLVMMetadataRef LLVMDIBuilderCreateFunction(
- DIBuilderRef Builder,
- LLVMMetadataRef Scope,
+extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateFunction(
+ LLVMRustDIBuilderRef Builder,
+ LLVMRustMetadataRef Scope,
const char* Name,
const char* LinkageName,
- LLVMMetadataRef File,
+ LLVMRustMetadataRef File,
unsigned LineNo,
- LLVMMetadataRef Ty,
+ LLVMRustMetadataRef Ty,
bool isLocalToUnit,
bool isDefinition,
unsigned ScopeLine,
unsigned Flags,
bool isOptimized,
LLVMValueRef Fn,
- LLVMMetadataRef TParam,
- LLVMMetadataRef Decl) {
+ LLVMRustMetadataRef TParam,
+ LLVMRustMetadataRef Decl) {
#if LLVM_VERSION_MINOR >= 8
DITemplateParameterArray TParams =
DITemplateParameterArray(unwrap<MDTuple>(TParam));
@@ -370,8 +440,8 @@
#endif
}
-extern "C" LLVMMetadataRef LLVMDIBuilderCreateBasicType(
- DIBuilderRef Builder,
+extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateBasicType(
+ LLVMRustDIBuilderRef Builder,
const char* Name,
uint64_t SizeInBits,
uint64_t AlignInBits,
@@ -381,9 +451,9 @@
AlignInBits, Encoding));
}
-extern "C" LLVMMetadataRef LLVMDIBuilderCreatePointerType(
- DIBuilderRef Builder,
- LLVMMetadataRef PointeeTy,
+extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreatePointerType(
+ LLVMRustDIBuilderRef Builder,
+ LLVMRustMetadataRef PointeeTy,
uint64_t SizeInBits,
uint64_t AlignInBits,
const char* Name) {
@@ -391,19 +461,19 @@
unwrapDI<DIType>(PointeeTy), SizeInBits, AlignInBits, Name));
}
-extern "C" LLVMMetadataRef LLVMDIBuilderCreateStructType(
- DIBuilderRef Builder,
- LLVMMetadataRef Scope,
+extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateStructType(
+ LLVMRustDIBuilderRef Builder,
+ LLVMRustMetadataRef Scope,
const char* Name,
- LLVMMetadataRef File,
+ LLVMRustMetadataRef File,
unsigned LineNumber,
uint64_t SizeInBits,
uint64_t AlignInBits,
unsigned Flags,
- LLVMMetadataRef DerivedFrom,
- LLVMMetadataRef Elements,
+ LLVMRustMetadataRef DerivedFrom,
+ LLVMRustMetadataRef Elements,
unsigned RunTimeLang,
- LLVMMetadataRef VTableHolder,
+ LLVMRustMetadataRef VTableHolder,
const char *UniqueId) {
return wrap(Builder->createStructType(
unwrapDI<DIDescriptor>(Scope),
@@ -421,17 +491,17 @@
));
}
-extern "C" LLVMMetadataRef LLVMDIBuilderCreateMemberType(
- DIBuilderRef Builder,
- LLVMMetadataRef Scope,
+extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateMemberType(
+ LLVMRustDIBuilderRef Builder,
+ LLVMRustMetadataRef Scope,
const char* Name,
- LLVMMetadataRef File,
+ LLVMRustMetadataRef File,
unsigned LineNo,
uint64_t SizeInBits,
uint64_t AlignInBits,
uint64_t OffsetInBits,
unsigned Flags,
- LLVMMetadataRef Ty) {
+ LLVMRustMetadataRef Ty) {
return wrap(Builder->createMemberType(
unwrapDI<DIDescriptor>(Scope), Name,
unwrapDI<DIFile>(File), LineNo,
@@ -439,10 +509,10 @@
unwrapDI<DIType>(Ty)));
}
-extern "C" LLVMMetadataRef LLVMDIBuilderCreateLexicalBlock(
- DIBuilderRef Builder,
- LLVMMetadataRef Scope,
- LLVMMetadataRef File,
+extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateLexicalBlock(
+ LLVMRustDIBuilderRef Builder,
+ LLVMRustMetadataRef Scope,
+ LLVMRustMetadataRef File,
unsigned Line,
unsigned Col) {
return wrap(Builder->createLexicalBlock(
@@ -451,17 +521,17 @@
));
}
-extern "C" LLVMMetadataRef LLVMDIBuilderCreateStaticVariable(
- DIBuilderRef Builder,
- LLVMMetadataRef Context,
+extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateStaticVariable(
+ LLVMRustDIBuilderRef Builder,
+ LLVMRustMetadataRef Context,
const char* Name,
const char* LinkageName,
- LLVMMetadataRef File,
+ LLVMRustMetadataRef File,
unsigned LineNo,
- LLVMMetadataRef Ty,
+ LLVMRustMetadataRef Ty,
bool isLocalToUnit,
LLVMValueRef Val,
- LLVMMetadataRef Decl = NULL) {
+ LLVMRustMetadataRef Decl = NULL) {
return wrap(Builder->createGlobalVariable(unwrapDI<DIDescriptor>(Context),
Name,
LinkageName,
@@ -473,14 +543,14 @@
unwrapDIptr<MDNode>(Decl)));
}
-extern "C" LLVMMetadataRef LLVMDIBuilderCreateVariable(
- DIBuilderRef Builder,
+extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateVariable(
+ LLVMRustDIBuilderRef Builder,
unsigned Tag,
- LLVMMetadataRef Scope,
+ LLVMRustMetadataRef Scope,
const char* Name,
- LLVMMetadataRef File,
+ LLVMRustMetadataRef File,
unsigned LineNo,
- LLVMMetadataRef Ty,
+ LLVMRustMetadataRef Ty,
bool AlwaysPreserve,
unsigned Flags,
int64_t* AddrOps,
@@ -509,50 +579,50 @@
#endif
}
-extern "C" LLVMMetadataRef LLVMDIBuilderCreateArrayType(
- DIBuilderRef Builder,
+extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateArrayType(
+ LLVMRustDIBuilderRef Builder,
uint64_t Size,
uint64_t AlignInBits,
- LLVMMetadataRef Ty,
- LLVMMetadataRef Subscripts) {
+ LLVMRustMetadataRef Ty,
+ LLVMRustMetadataRef Subscripts) {
return wrap(Builder->createArrayType(Size, AlignInBits,
unwrapDI<DIType>(Ty),
DINodeArray(unwrapDI<MDTuple>(Subscripts))
));
}
-extern "C" LLVMMetadataRef LLVMDIBuilderCreateVectorType(
- DIBuilderRef Builder,
+extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateVectorType(
+ LLVMRustDIBuilderRef Builder,
uint64_t Size,
uint64_t AlignInBits,
- LLVMMetadataRef Ty,
- LLVMMetadataRef Subscripts) {
+ LLVMRustMetadataRef Ty,
+ LLVMRustMetadataRef Subscripts) {
return wrap(Builder->createVectorType(Size, AlignInBits,
unwrapDI<DIType>(Ty),
DINodeArray(unwrapDI<MDTuple>(Subscripts))
));
}
-extern "C" LLVMMetadataRef LLVMDIBuilderGetOrCreateSubrange(
- DIBuilderRef Builder,
+extern "C" LLVMRustMetadataRef LLVMRustDIBuilderGetOrCreateSubrange(
+ LLVMRustDIBuilderRef Builder,
int64_t Lo,
int64_t Count) {
return wrap(Builder->getOrCreateSubrange(Lo, Count));
}
-extern "C" LLVMMetadataRef LLVMDIBuilderGetOrCreateArray(
- DIBuilderRef Builder,
- LLVMMetadataRef* Ptr,
+extern "C" LLVMRustMetadataRef LLVMRustDIBuilderGetOrCreateArray(
+ LLVMRustDIBuilderRef Builder,
+ LLVMRustMetadataRef* Ptr,
unsigned Count) {
Metadata **DataValue = unwrap(Ptr);
return wrap(Builder->getOrCreateArray(
ArrayRef<Metadata*>(DataValue, Count)).get());
}
-extern "C" LLVMValueRef LLVMDIBuilderInsertDeclareAtEnd(
- DIBuilderRef Builder,
+extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareAtEnd(
+ LLVMRustDIBuilderRef Builder,
LLVMValueRef Val,
- LLVMMetadataRef VarInfo,
+ LLVMRustMetadataRef VarInfo,
int64_t* AddrOps,
unsigned AddrOpsCount,
LLVMValueRef DL,
@@ -566,10 +636,10 @@
unwrap(InsertAtEnd)));
}
-extern "C" LLVMValueRef LLVMDIBuilderInsertDeclareBefore(
- DIBuilderRef Builder,
+extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareBefore(
+ LLVMRustDIBuilderRef Builder,
LLVMValueRef Val,
- LLVMMetadataRef VarInfo,
+ LLVMRustMetadataRef VarInfo,
int64_t* AddrOps,
unsigned AddrOpsCount,
LLVMValueRef DL,
@@ -583,24 +653,24 @@
unwrap<Instruction>(InsertBefore)));
}
-extern "C" LLVMMetadataRef LLVMDIBuilderCreateEnumerator(
- DIBuilderRef Builder,
+extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateEnumerator(
+ LLVMRustDIBuilderRef Builder,
const char* Name,
uint64_t Val)
{
return wrap(Builder->createEnumerator(Name, Val));
}
-extern "C" LLVMMetadataRef LLVMDIBuilderCreateEnumerationType(
- DIBuilderRef Builder,
- LLVMMetadataRef Scope,
+extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateEnumerationType(
+ LLVMRustDIBuilderRef Builder,
+ LLVMRustMetadataRef Scope,
const char* Name,
- LLVMMetadataRef File,
+ LLVMRustMetadataRef File,
unsigned LineNumber,
uint64_t SizeInBits,
uint64_t AlignInBits,
- LLVMMetadataRef Elements,
- LLVMMetadataRef ClassType)
+ LLVMRustMetadataRef Elements,
+ LLVMRustMetadataRef ClassType)
{
return wrap(Builder->createEnumerationType(
unwrapDI<DIDescriptor>(Scope),
@@ -613,16 +683,16 @@
unwrapDI<DIType>(ClassType)));
}
-extern "C" LLVMMetadataRef LLVMDIBuilderCreateUnionType(
- DIBuilderRef Builder,
- LLVMMetadataRef Scope,
+extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateUnionType(
+ LLVMRustDIBuilderRef Builder,
+ LLVMRustMetadataRef Scope,
const char* Name,
- LLVMMetadataRef File,
+ LLVMRustMetadataRef File,
unsigned LineNumber,
uint64_t SizeInBits,
uint64_t AlignInBits,
unsigned Flags,
- LLVMMetadataRef Elements,
+ LLVMRustMetadataRef Elements,
unsigned RunTimeLang,
const char* UniqueId)
{
@@ -640,12 +710,12 @@
));
}
-extern "C" LLVMMetadataRef LLVMDIBuilderCreateTemplateTypeParameter(
- DIBuilderRef Builder,
- LLVMMetadataRef Scope,
+extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateTemplateTypeParameter(
+ LLVMRustDIBuilderRef Builder,
+ LLVMRustMetadataRef Scope,
const char* Name,
- LLVMMetadataRef Ty,
- LLVMMetadataRef File,
+ LLVMRustMetadataRef Ty,
+ LLVMRustMetadataRef File,
unsigned LineNo,
unsigned ColumnNo)
{
@@ -656,21 +726,11 @@
));
}
-extern "C" int64_t LLVMDIBuilderCreateOpDeref()
-{
- return dwarf::DW_OP_deref;
-}
-
-extern "C" int64_t LLVMDIBuilderCreateOpPlus()
-{
- return dwarf::DW_OP_plus;
-}
-
-extern "C" LLVMMetadataRef LLVMDIBuilderCreateNameSpace(
- DIBuilderRef Builder,
- LLVMMetadataRef Scope,
+extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateNameSpace(
+ LLVMRustDIBuilderRef Builder,
+ LLVMRustMetadataRef Scope,
const char* Name,
- LLVMMetadataRef File,
+ LLVMRustMetadataRef File,
unsigned LineNo)
{
return wrap(Builder->createNameSpace(
@@ -680,22 +740,22 @@
LineNo));
}
-extern "C" void LLVMDICompositeTypeSetTypeArray(
- DIBuilderRef Builder,
- LLVMMetadataRef CompositeType,
- LLVMMetadataRef TypeArray)
+extern "C" void LLVMRustDICompositeTypeSetTypeArray(
+ LLVMRustDIBuilderRef Builder,
+ LLVMRustMetadataRef CompositeType,
+ LLVMRustMetadataRef TypeArray)
{
DICompositeType *tmp = unwrapDI<DICompositeType>(CompositeType);
Builder->replaceArrays(tmp, DINodeArray(unwrap<MDTuple>(TypeArray)));
}
-extern "C" LLVMValueRef LLVMDIBuilderCreateDebugLocation(
+extern "C" LLVMValueRef LLVMRustDIBuilderCreateDebugLocation(
LLVMContextRef Context,
unsigned Line,
unsigned Column,
- LLVMMetadataRef Scope,
- LLVMMetadataRef InlinedAt) {
-
+ LLVMRustMetadataRef Scope,
+ LLVMRustMetadataRef InlinedAt)
+{
LLVMContext& context = *unwrap(Context);
DebugLoc debug_loc = DebugLoc::get(Line,
@@ -706,12 +766,22 @@
return wrap(MetadataAsValue::get(context, debug_loc.getAsMDNode()));
}
-extern "C" void LLVMWriteTypeToString(LLVMTypeRef Type, RustStringRef str) {
+extern "C" int64_t LLVMRustDIBuilderCreateOpDeref()
+{
+ return dwarf::DW_OP_deref;
+}
+
+extern "C" int64_t LLVMRustDIBuilderCreateOpPlus()
+{
+ return dwarf::DW_OP_plus;
+}
+
+extern "C" void LLVMRustWriteTypeToString(LLVMTypeRef Type, RustStringRef str) {
raw_rust_string_ostream os(str);
unwrap<llvm::Type>(Type)->print(os);
}
-extern "C" void LLVMWriteValueToString(LLVMValueRef Value, RustStringRef str) {
+extern "C" void LLVMRustWriteValueToString(LLVMValueRef Value, RustStringRef str) {
raw_rust_string_ostream os(str);
os << "(";
unwrap<llvm::Value>(Value)->getType()->print(os);
@@ -746,13 +816,6 @@
return true;
}
-extern "C" void
-LLVMRustSetDLLStorageClass(LLVMValueRef Value,
- GlobalValue::DLLStorageClassTypes Class) {
- GlobalValue *V = unwrap<GlobalValue>(Value);
- V->setDLLStorageClass(Class);
-}
-
// Note that the two following functions look quite similar to the
// LLVMGetSectionName function. Sadly, it appears that this function only
// returns a char* pointer, which isn't guaranteed to be null-terminated. The
@@ -768,7 +831,7 @@
return reinterpret_cast<section_iterator*>(SI);
}
-extern "C" int
+extern "C" size_t
LLVMRustGetSectionName(LLVMSectionIteratorRef SI, const char **ptr) {
StringRef ret;
if (std::error_code ec = (*unwrap(SI))->getName(ret))
@@ -787,13 +850,13 @@
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DebugLoc, LLVMDebugLocRef)
extern "C" void
-LLVMWriteTwineToString(LLVMTwineRef T, RustStringRef str) {
+LLVMRustWriteTwineToString(LLVMTwineRef T, RustStringRef str) {
raw_rust_string_ostream os(str);
unwrap(T)->print(os);
}
extern "C" void
-LLVMUnpackOptimizationDiagnostic(
+LLVMRustUnpackOptimizationDiagnostic(
LLVMDiagnosticInfoRef di,
const char **pass_name_out,
LLVMValueRef *function_out,
@@ -811,7 +874,7 @@
}
extern "C" void
-LLVMUnpackInlineAsmDiagnostic(
+LLVMRustUnpackInlineAsmDiagnostic(
LLVMDiagnosticInfoRef di,
unsigned *cookie_out,
LLVMTwineRef *message_out,
@@ -826,17 +889,111 @@
*instruction_out = wrap(ia->getInstruction());
}
-extern "C" void LLVMWriteDiagnosticInfoToString(LLVMDiagnosticInfoRef di, RustStringRef str) {
+extern "C" void LLVMRustWriteDiagnosticInfoToString(LLVMDiagnosticInfoRef di, RustStringRef str) {
raw_rust_string_ostream os(str);
DiagnosticPrinterRawOStream dp(os);
unwrap(di)->print(dp);
}
-extern "C" int LLVMGetDiagInfoKind(LLVMDiagnosticInfoRef di) {
- return unwrap(di)->getKind();
+enum class LLVMRustDiagnosticKind {
+ Other,
+ InlineAsm,
+ StackSize,
+ DebugMetadataVersion,
+ SampleProfile,
+ OptimizationRemark,
+ OptimizationRemarkMissed,
+ OptimizationRemarkAnalysis,
+ OptimizationRemarkAnalysisFPCommute,
+ OptimizationRemarkAnalysisAliasing,
+ OptimizationRemarkOther,
+ OptimizationFailure,
+};
+
+static LLVMRustDiagnosticKind
+to_rust(DiagnosticKind kind)
+{
+ switch (kind) {
+ case DK_InlineAsm:
+ return LLVMRustDiagnosticKind::InlineAsm;
+ case DK_StackSize:
+ return LLVMRustDiagnosticKind::StackSize;
+ case DK_DebugMetadataVersion:
+ return LLVMRustDiagnosticKind::DebugMetadataVersion;
+ case DK_SampleProfile:
+ return LLVMRustDiagnosticKind::SampleProfile;
+ case DK_OptimizationRemark:
+ return LLVMRustDiagnosticKind::OptimizationRemark;
+ case DK_OptimizationRemarkMissed:
+ return LLVMRustDiagnosticKind::OptimizationRemarkMissed;
+ case DK_OptimizationRemarkAnalysis:
+ return LLVMRustDiagnosticKind::OptimizationRemarkAnalysis;
+#if LLVM_VERSION_MINOR >= 8
+ case DK_OptimizationRemarkAnalysisFPCommute:
+ return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisFPCommute;
+ case DK_OptimizationRemarkAnalysisAliasing:
+ return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisAliasing;
+#endif
+ default:
+#if LLVM_VERSION_MINOR >= 9
+ return (kind >= DK_FirstRemark && kind <= DK_LastRemark) ?
+ LLVMRustDiagnosticKind::OptimizationRemarkOther :
+ LLVMRustDiagnosticKind::Other;
+#else
+ return LLVMRustDiagnosticKind::Other;
+#endif
+ }
}
-extern "C" void LLVMWriteDebugLocToString(
+extern "C" LLVMRustDiagnosticKind LLVMRustGetDiagInfoKind(LLVMDiagnosticInfoRef di) {
+ return to_rust((DiagnosticKind) unwrap(di)->getKind());
+}
+// This is kept distinct from LLVMGetTypeKind, because when
+// a new type kind is added, the Rust-side enum must be
+// updated or UB will result.
+extern "C" LLVMTypeKind LLVMRustGetTypeKind(LLVMTypeRef Ty) {
+ switch (unwrap(Ty)->getTypeID()) {
+ case Type::VoidTyID:
+ return LLVMVoidTypeKind;
+ case Type::HalfTyID:
+ return LLVMHalfTypeKind;
+ case Type::FloatTyID:
+ return LLVMFloatTypeKind;
+ case Type::DoubleTyID:
+ return LLVMDoubleTypeKind;
+ case Type::X86_FP80TyID:
+ return LLVMX86_FP80TypeKind;
+ case Type::FP128TyID:
+ return LLVMFP128TypeKind;
+ case Type::PPC_FP128TyID:
+ return LLVMPPC_FP128TypeKind;
+ case Type::LabelTyID:
+ return LLVMLabelTypeKind;
+ case Type::MetadataTyID:
+ return LLVMMetadataTypeKind;
+ case Type::IntegerTyID:
+ return LLVMIntegerTypeKind;
+ case Type::FunctionTyID:
+ return LLVMFunctionTypeKind;
+ case Type::StructTyID:
+ return LLVMStructTypeKind;
+ case Type::ArrayTyID:
+ return LLVMArrayTypeKind;
+ case Type::PointerTyID:
+ return LLVMPointerTypeKind;
+ case Type::VectorTyID:
+ return LLVMVectorTypeKind;
+ case Type::X86_MMXTyID:
+ return LLVMX86_MMXTypeKind;
+#if LLVM_VERSION_MINOR >= 8
+ case Type::TokenTyID:
+ return LLVMTokenTypeKind;
+#endif
+ }
+ llvm_unreachable("Unhandled TypeID.");
+}
+
+extern "C" void LLVMRustWriteDebugLocToString(
LLVMContextRef C,
LLVMDebugLocRef dl,
RustStringRef str)
@@ -847,7 +1004,7 @@
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef)
-extern "C" void LLVMSetInlineAsmDiagnosticHandler(
+extern "C" void LLVMRustSetInlineAsmDiagnosticHandler(
LLVMContextRef C,
LLVMContext::InlineAsmDiagHandlerTy H,
void *CX)
@@ -855,7 +1012,8 @@
unwrap(C)->setInlineAsmDiagnosticHandler(H, CX);
}
-extern "C" void LLVMWriteSMDiagnosticToString(LLVMSMDiagnosticRef d, RustStringRef str) {
+extern "C" void LLVMRustWriteSMDiagnosticToString(LLVMSMDiagnosticRef d,
+ RustStringRef str) {
raw_rust_string_ostream os(str);
unwrap(d)->print("", os);
}
diff --git a/src/rustllvm/llvm-auto-clean-trigger b/src/rustllvm/llvm-auto-clean-trigger
index 1953fc5..e871763 100644
--- a/src/rustllvm/llvm-auto-clean-trigger
+++ b/src/rustllvm/llvm-auto-clean-trigger
@@ -1,4 +1,4 @@
# If this file is modified, then llvm will be forcibly cleaned and then rebuilt.
# The actual contents of this file do not matter, but to trigger a change on the
# build bots then the contents should be changed so git updates the mtime.
-2016-06-23
+2016-07-25b
diff --git a/src/rustllvm/rustllvm.h b/src/rustllvm/rustllvm.h
index 2a47e8b..5aae11f 100644
--- a/src/rustllvm/rustllvm.h
+++ b/src/rustllvm/rustllvm.h
@@ -58,6 +58,11 @@
void LLVMRustSetLastError(const char*);
+enum class LLVMRustResult {
+ Success,
+ Failure
+};
+
typedef struct OpaqueRustString *RustStringRef;
typedef struct LLVMOpaqueTwine *LLVMTwineRef;
typedef struct LLVMOpaqueDebugLoc *LLVMDebugLocRef;
diff --git a/src/test/compile-fail-fulldeps/lint-plugin-forbid-attrs.rs b/src/test/compile-fail-fulldeps/lint-plugin-forbid-attrs.rs
index 83c845b..61a8ee8 100644
--- a/src/test/compile-fail-fulldeps/lint-plugin-forbid-attrs.rs
+++ b/src/test/compile-fail-fulldeps/lint-plugin-forbid-attrs.rs
@@ -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'
diff --git a/src/test/compile-fail/E0045.rs b/src/test/compile-fail/E0045.rs
index edec911..2a73159 100644
--- a/src/test/compile-fail/E0045.rs
+++ b/src/test/compile-fail/E0045.rs
@@ -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() {
}
diff --git a/src/test/compile-fail/array-not-vector.rs b/src/test/compile-fail/array-not-vector.rs
index 1bbccae..47e1c09 100644
--- a/src/test/compile-fail/array-not-vector.rs
+++ b/src/test/compile-fail/array-not-vector.rs
@@ -12,7 +12,7 @@
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];
diff --git a/src/test/compile-fail/array_const_index-0.rs b/src/test/compile-fail/array_const_index-0.rs
index e652303..501c66e 100644
--- a/src/test/compile-fail/array_const_index-0.rs
+++ b/src/test/compile-fail/array_const_index-0.rs
@@ -10,7 +10,8 @@
const A: &'static [i32] = &[];
const B: i32 = (&A)[1];
-//~^ ERROR index out of bounds: the len is 0 but the index is 1
+//~^ ERROR constant evaluation error
+//~| index out of bounds: the len is 0 but the index is 1
fn main() {
let _ = B;
diff --git a/src/test/compile-fail/array_const_index-1.rs b/src/test/compile-fail/array_const_index-1.rs
index 69d84e2..d3b43e8 100644
--- a/src/test/compile-fail/array_const_index-1.rs
+++ b/src/test/compile-fail/array_const_index-1.rs
@@ -10,7 +10,8 @@
const A: [i32; 0] = [];
const B: i32 = A[1];
-//~^ ERROR index out of bounds: the len is 0 but the index is 1
+//~^ ERROR constant evaluation error
+//~| index out of bounds: the len is 0 but the index is 1
fn main() {
let _ = B;
diff --git a/src/test/compile-fail/associated-const-array-len.rs b/src/test/compile-fail/associated-const-array-len.rs
index 5d8007d..0239986 100644
--- a/src/test/compile-fail/associated-const-array-len.rs
+++ b/src/test/compile-fail/associated-const-array-len.rs
@@ -14,7 +14,7 @@
const ID: usize;
}
-const X: [i32; <i32 as Foo>::ID] = [0, 1, 2]; //~ ERROR E0250
+const X: [i32; <i32 as Foo>::ID] = [0, 1, 2]; //~ ERROR E0080
fn main() {
assert_eq!(1, X);
diff --git a/src/test/compile-fail/associated-const-impl-wrong-type.rs b/src/test/compile-fail/associated-const-impl-wrong-type.rs
index 4658d0f..95508a3 100644
--- a/src/test/compile-fail/associated-const-impl-wrong-type.rs
+++ b/src/test/compile-fail/associated-const-impl-wrong-type.rs
@@ -18,9 +18,8 @@
impl Foo for SignedBar {
const BAR: i32 = -1;
- //~^ ERROR implemented const `BAR` has an incompatible type for trait
- //~| expected u32,
- //~| found i32 [E0326]
+ //~^ ERROR implemented const `BAR` has an incompatible type for trait [E0326]
+ //~| expected u32, found i32
}
fn main() {}
diff --git a/src/test/compile-fail/associated-const-type-parameter-arrays-2.rs b/src/test/compile-fail/associated-const-type-parameter-arrays-2.rs
index 2f68735..c3fa396 100644
--- a/src/test/compile-fail/associated-const-type-parameter-arrays-2.rs
+++ b/src/test/compile-fail/associated-const-type-parameter-arrays-2.rs
@@ -25,7 +25,8 @@
}
pub fn test<A: Foo, B: Foo>() {
- let _array = [4; <A as Foo>::Y]; //~ error: expected constant integer
+ let _array = [4; <A as Foo>::Y]; //~ ERROR E0080
+ //~| non-constant path in constant
}
fn main() {
diff --git a/src/test/compile-fail/associated-types-eq-3.rs b/src/test/compile-fail/associated-types-eq-3.rs
index 8c66160..cb952f6 100644
--- a/src/test/compile-fail/associated-types-eq-3.rs
+++ b/src/test/compile-fail/associated-types-eq-3.rs
@@ -47,10 +47,8 @@
let a = 42;
foo1(a);
//~^ ERROR type mismatch resolving
- //~| expected usize
- //~| found struct `Bar`
+ //~| expected usize, found struct `Bar`
baz(&a);
//~^ ERROR type mismatch resolving
- //~| expected usize
- //~| found struct `Bar`
+ //~| expected usize, found struct `Bar`
}
diff --git a/src/test/compile-fail/associated-types/bound-lifetime-constrained.rs b/src/test/compile-fail/associated-types/bound-lifetime-constrained.rs
index f60f06b..de6ce79 100644
--- a/src/test/compile-fail/associated-types/bound-lifetime-constrained.rs
+++ b/src/test/compile-fail/associated-types/bound-lifetime-constrained.rs
@@ -12,7 +12,6 @@
#![allow(dead_code)]
#![feature(rustc_attrs)]
-#![feature(unboxed_closures)]
#![deny(hr_lifetime_in_assoc_type)]
trait Foo<'a> {
diff --git a/src/test/compile-fail/associated-types/cache/wasm-issue-32330.rs b/src/test/compile-fail/associated-types/cache/wasm-issue-32330.rs
index 01db477..6ba09ac 100644
--- a/src/test/compile-fail/associated-types/cache/wasm-issue-32330.rs
+++ b/src/test/compile-fail/associated-types/cache/wasm-issue-32330.rs
@@ -13,7 +13,6 @@
#![allow(dead_code, unused_variables)]
#![deny(hr_lifetime_in_assoc_type)]
-#![feature(unboxed_closures)]
use std::str::Chars;
diff --git a/src/test/compile-fail/associated-types/higher-ranked-projection.rs b/src/test/compile-fail/associated-types/higher-ranked-projection.rs
new file mode 100644
index 0000000..12341fa
--- /dev/null
+++ b/src/test/compile-fail/associated-types/higher-ranked-projection.rs
@@ -0,0 +1,38 @@
+// 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.
+
+#![feature(rustc_attrs)]
+
+// revisions: good bad
+
+trait Mirror {
+ type Image;
+}
+
+impl<T> Mirror for T {
+ type Image = T;
+}
+
+#[cfg(bad)]
+fn foo<U, T>(_t: T)
+ where for<'a> &'a T: Mirror<Image=U>
+{}
+
+#[cfg(good)]
+fn foo<U, T>(_t: T)
+ where for<'a> &'a T: Mirror<Image=&'a U>
+{}
+
+#[rustc_error]
+fn main() { //[good]~ ERROR compilation successful
+ foo(());
+ //[bad]~^ ERROR type mismatch resolving `for<'a> <&'a _ as Mirror>::Image == _`
+ //[bad]~| expected bound lifetime parameter 'a, found concrete lifetime
+}
diff --git a/src/test/compile-fail/bad-const-type.rs b/src/test/compile-fail/bad-const-type.rs
index ee6ac33..5547d19 100644
--- a/src/test/compile-fail/bad-const-type.rs
+++ b/src/test/compile-fail/bad-const-type.rs
@@ -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); }
diff --git a/src/test/compile-fail/borrowck/borrowck-call-is-borrow-issue-12224.rs b/src/test/compile-fail/borrowck/borrowck-call-is-borrow-issue-12224.rs
index 7626f35..e4ae565 100644
--- a/src/test/compile-fail/borrowck/borrowck-call-is-borrow-issue-12224.rs
+++ b/src/test/compile-fail/borrowck/borrowck-call-is-borrow-issue-12224.rs
@@ -10,8 +10,6 @@
// Ensure that invoking a closure counts as a unique immutable borrow
-#![feature(unboxed_closures)]
-
type Fn<'a> = Box<FnMut() + 'a>;
struct Test<'a> {
diff --git a/src/test/compile-fail/borrowck/borrowck-unboxed-closures.rs b/src/test/compile-fail/borrowck/borrowck-unboxed-closures.rs
index 1c12ca9c..0f9829a 100644
--- a/src/test/compile-fail/borrowck/borrowck-unboxed-closures.rs
+++ b/src/test/compile-fail/borrowck/borrowck-unboxed-closures.rs
@@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(overloaded_calls, unboxed_closures)]
-
fn a<F:Fn(isize, isize) -> isize>(mut f: F) {
let g = &mut f;
f(1, 2); //~ ERROR cannot borrow `f` as immutable
diff --git a/src/test/compile-fail/coerce-mut.rs b/src/test/compile-fail/coerce-mut.rs
index 634d124..86702a7 100644
--- a/src/test/compile-fail/coerce-mut.rs
+++ b/src/test/compile-fail/coerce-mut.rs
@@ -15,6 +15,6 @@
f(&x);
//~^ ERROR mismatched types
//~| expected type `&mut i32`
- //~| found type `&_`
+ //~| found type `&{integer}`
//~| values differ in mutability
}
diff --git a/src/test/compile-fail/coercion-slice.rs b/src/test/compile-fail/coercion-slice.rs
index bd7e6c2..a619f33 100644
--- a/src/test/compile-fail/coercion-slice.rs
+++ b/src/test/compile-fail/coercion-slice.rs
@@ -14,6 +14,6 @@
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/const-array-oob.rs b/src/test/compile-fail/const-array-oob.rs
index faabed4..b980bc0 100644
--- a/src/test/compile-fail/const-array-oob.rs
+++ b/src/test/compile-fail/const-array-oob.rs
@@ -16,7 +16,8 @@
const BAR: u32 = FOO[5]; // no error, because the error below occurs before regular const eval
const BLUB: [u32; FOO[4]] = [5, 6];
-//~^ ERROR array length constant evaluation error: index out of bounds: the len is 3 but the index is 4 [E0250]
+//~^ ERROR constant evaluation error [E0080]
+//~| index out of bounds: the len is 3 but the index is 4
fn main() {
let _ = BAR;
diff --git a/src/test/compile-fail/const-call.rs b/src/test/compile-fail/const-call.rs
index 1143d3b..7e2eabf 100644
--- a/src/test/compile-fail/const-call.rs
+++ b/src/test/compile-fail/const-call.rs
@@ -15,5 +15,6 @@
}
fn main() {
- let _ = [0; f(2)]; //~ ERROR: non-constant path in constant expression [E0307]
+ let _ = [0; f(2)]; //~ ERROR constant evaluation error [E0080]
+ //~| non-constant path in constant expression
}
diff --git a/src/test/compile-fail/const-err.rs b/src/test/compile-fail/const-err.rs
index a1d3888..f207980 100644
--- a/src/test/compile-fail/const-err.rs
+++ b/src/test/compile-fail/const-err.rs
@@ -22,21 +22,29 @@
// Make sure that the two uses get two errors.
const FOO: u8 = [5u8][1];
-//~^ ERROR index out of bounds: the len is 1 but the index is 1
-//~^^ ERROR index out of bounds: the len is 1 but the index is 1
+//~^ ERROR constant evaluation error
+//~| index out of bounds: the len is 1 but the index is 1
+//~^^^ ERROR constant evaluation error
+//~| index out of bounds: the len is 1 but the index is 1
fn main() {
let a = -std::i8::MIN;
- //~^ WARN attempted to negate with overflow
+ //~^ WARN this expression will panic at run-time
+ //~| attempted to negate with overflow
let b = 200u8 + 200u8 + 200u8;
- //~^ WARN attempted to add with overflow
- //~| WARN attempted to add with overflow
+ //~^ WARN this expression will panic at run-time
+ //~| attempted to add with overflow
+ //~^^^ WARN this expression will panic at run-time
+ //~| attempted to add with overflow
let c = 200u8 * 4;
- //~^ WARN attempted to multiply with overflow
+ //~^ WARN this expression will panic at run-time
+ //~| attempted to multiply with overflow
let d = 42u8 - (42u8 + 1);
- //~^ WARN attempted to subtract with overflow
+ //~^ WARN this expression will panic at run-time
+ //~| attempted to subtract with overflow
let _e = [5u8][1];
- //~^ WARN index out of bounds: the len is 1 but the index is 1
+ //~^ WARN this expression will panic at run-time
+ //~| index out of bounds: the len is 1 but the index is 1
black_box(a);
black_box(b);
black_box(c);
diff --git a/src/test/compile-fail/const-eval-overflow-2.rs b/src/test/compile-fail/const-eval-overflow-2.rs
index 07e27a7..4749457 100644
--- a/src/test/compile-fail/const-eval-overflow-2.rs
+++ b/src/test/compile-fail/const-eval-overflow-2.rs
@@ -19,13 +19,16 @@
const NEG_128: i8 = -128;
const NEG_NEG_128: i8 = -NEG_128;
-//~^ ERROR constant evaluation error: attempted to negate with overflow
-//~| ERROR attempted to negate with overflow
-//~| ERROR attempted to negate with overflow
+//~^ ERROR constant evaluation error
+//~| attempted to negate with overflow
+//~| ERROR constant evaluation error
+//~| attempted to negate with overflow
+//~| ERROR constant evaluation error
+//~| attempted to negate with overflow
fn main() {
match -128i8 {
- NEG_NEG_128 => println!("A"), //~ NOTE in pattern here
+ NEG_NEG_128 => println!("A"), //~ NOTE for pattern here
_ => println!("B"),
}
}
diff --git a/src/test/compile-fail/const-eval-overflow-3.rs b/src/test/compile-fail/const-eval-overflow-3.rs
index c90ae04..c78c74e 100644
--- a/src/test/compile-fail/const-eval-overflow-3.rs
+++ b/src/test/compile-fail/const-eval-overflow-3.rs
@@ -17,7 +17,7 @@
// self-hosted and a cross-compiled setup; therefore resorting to
// error-pattern for now.
-// error-pattern: expected constant integer for repeat count, but attempted to add with overflow
+// error-pattern: attempted to add with overflow
#![allow(unused_imports)]
diff --git a/src/test/compile-fail/const-eval-overflow-4b.rs b/src/test/compile-fail/const-eval-overflow-4b.rs
index 31e1a72..9e7a5ec 100644
--- a/src/test/compile-fail/const-eval-overflow-4b.rs
+++ b/src/test/compile-fail/const-eval-overflow-4b.rs
@@ -20,9 +20,8 @@
const A_I8_T
: [u32; (i8::MAX as i8 + 1u8) as usize]
- //~^ ERROR mismatched types:
- //~| expected `i8`,
- //~| found `u8` [E0250]
+ //~^ ERROR constant evaluation error [E0080]
+ //~| expected i8, found u8
= [0; (i8::MAX as usize) + 1];
@@ -33,7 +32,8 @@
const A_BAD_CHAR_USIZE
: [u32; 5i8 as char as usize]
- //~^ ERROR only `u8` can be cast as `char`, not `i8`
+ //~^ ERROR constant evaluation error
+ //~| only `u8` can be cast as `char`, not `i8`
= [0; 5];
fn main() {}
diff --git a/src/test/compile-fail/const-eval-overflow.rs b/src/test/compile-fail/const-eval-overflow.rs
index 3dfcb5b..c1c6935 100644
--- a/src/test/compile-fail/const-eval-overflow.rs
+++ b/src/test/compile-fail/const-eval-overflow.rs
@@ -21,86 +21,114 @@
const VALS_I8: (i8, i8, i8, i8) =
(-i8::MIN,
- //~^ ERROR attempted to negate with overflow
+ //~^ ERROR constant evaluation error
+ //~| attempted to negate with overflow
i8::MIN - 1,
- //~^ ERROR attempted to subtract with overflow
+ //~^ ERROR constant evaluation error
+ //~| attempted to subtract with overflow
i8::MAX + 1,
- //~^ ERROR attempted to add with overflow
+ //~^ ERROR constant evaluation error
+ //~| attempted to add with overflow
i8::MIN * 2,
- //~^ ERROR attempted to multiply with overflow
+ //~^ ERROR constant evaluation error
+ //~| attempted to multiply with overflow
);
const VALS_I16: (i16, i16, i16, i16) =
(-i16::MIN,
- //~^ ERROR attempted to negate with overflow
+ //~^ ERROR constant evaluation error
+ //~| attempted to negate with overflow
i16::MIN - 1,
- //~^ ERROR attempted to subtract with overflow
+ //~^ ERROR constant evaluation error
+ //~| attempted to subtract with overflow
i16::MAX + 1,
- //~^ ERROR attempted to add with overflow
+ //~^ ERROR constant evaluation error
+ //~| attempted to add with overflow
i16::MIN * 2,
- //~^ ERROR attempted to multiply with overflow
+ //~^ ERROR constant evaluation error
+ //~| attempted to multiply with overflow
);
const VALS_I32: (i32, i32, i32, i32) =
(-i32::MIN,
- //~^ ERROR attempted to negate with overflow
+ //~^ ERROR constant evaluation error
+ //~| attempted to negate with overflow
i32::MIN - 1,
- //~^ ERROR attempted to subtract with overflow
+ //~^ ERROR constant evaluation error
+ //~| attempted to subtract with overflow
i32::MAX + 1,
- //~^ ERROR attempted to add with overflow
+ //~^ ERROR constant evaluation error
+ //~| attempted to add with overflow
i32::MIN * 2,
- //~^ ERROR attempted to multiply with overflow
+ //~^ ERROR constant evaluation error
+ //~| attempted to multiply with overflow
);
const VALS_I64: (i64, i64, i64, i64) =
(-i64::MIN,
- //~^ ERROR attempted to negate with overflow
+ //~^ ERROR constant evaluation error
+ //~| attempted to negate with overflow
i64::MIN - 1,
- //~^ ERROR attempted to subtract with overflow
+ //~^ ERROR constant evaluation error
+ //~| attempted to subtract with overflow
i64::MAX + 1,
- //~^ ERROR attempted to add with overflow
+ //~^ ERROR constant evaluation error
+ //~| attempted to add with overflow
i64::MAX * 2,
- //~^ ERROR attempted to multiply with overflow
+ //~^ ERROR constant evaluation error
+ //~| attempted to multiply with overflow
);
const VALS_U8: (u8, u8, u8, u8) =
(-(u8::MIN as i8) as u8,
u8::MIN - 1,
- //~^ ERROR attempted to subtract with overflow
+ //~^ ERROR constant evaluation error
+ //~| attempted to subtract with overflow
u8::MAX + 1,
- //~^ ERROR attempted to add with overflow
+ //~^ ERROR constant evaluation error
+ //~| attempted to add with overflow
u8::MAX * 2,
- //~^ ERROR attempted to multiply with overflow
+ //~^ ERROR constant evaluation error
+ //~| attempted to multiply with overflow
);
const VALS_U16: (u16, u16, u16, u16) =
(-(u16::MIN as i16) as u16,
u16::MIN - 1,
- //~^ ERROR attempted to subtract with overflow
+ //~^ ERROR constant evaluation error
+ //~| attempted to subtract with overflow
u16::MAX + 1,
- //~^ ERROR attempted to add with overflow
+ //~^ ERROR constant evaluation error
+ //~| attempted to add with overflow
u16::MAX * 2,
- //~^ ERROR attempted to multiply with overflow
+ //~^ ERROR constant evaluation error
+ //~| attempted to multiply with overflow
);
const VALS_U32: (u32, u32, u32, u32) =
(-(u32::MIN as i32) as u32,
u32::MIN - 1,
- //~^ ERROR attempted to subtract with overflow
+ //~^ ERROR constant evaluation error
+ //~| attempted to subtract with overflow
u32::MAX + 1,
- //~^ ERROR attempted to add with overflow
+ //~^ ERROR constant evaluation error
+ //~| attempted to add with overflow
u32::MAX * 2,
- //~^ ERROR attempted to multiply with overflow
+ //~^ ERROR constant evaluation error
+ //~| attempted to multiply with overflow
);
const VALS_U64: (u64, u64, u64, u64) =
(-(u64::MIN as i64) as u64,
u64::MIN - 1,
- //~^ ERROR attempted to subtract with overflow
+ //~^ ERROR constant evaluation error
+ //~| attempted to subtract with overflow
u64::MAX + 1,
- //~^ ERROR attempted to add with overflow
+ //~^ ERROR constant evaluation error
+ //~| attempted to add with overflow
u64::MAX * 2,
- //~^ ERROR attempted to multiply with overflow
+ //~^ ERROR constant evaluation error
+ //~| attempted to multiply with overflow
);
fn main() {
diff --git a/src/test/compile-fail/const-eval-span.rs b/src/test/compile-fail/const-eval-span.rs
index 9fdd24c..7335142 100644
--- a/src/test/compile-fail/const-eval-span.rs
+++ b/src/test/compile-fail/const-eval-span.rs
@@ -14,7 +14,8 @@
struct S(i32);
const CONSTANT: S = S(0);
-//~^ ERROR: unimplemented constant expression: tuple struct constructors [E0080]
+//~^ ERROR E0080
+//~| unimplemented constant expression: tuple struct constructors
enum E {
V = CONSTANT,
diff --git a/src/test/compile-fail/const-fn-error.rs b/src/test/compile-fail/const-fn-error.rs
index 45a00de..dd0f058 100644
--- a/src/test/compile-fail/const-fn-error.rs
+++ b/src/test/compile-fail/const-fn-error.rs
@@ -17,10 +17,11 @@
for i in 0..x {
sum += i;
}
- sum //~ ERROR: E0250
+ sum //~ ERROR E0080
+ //~| non-constant path in constant
}
#[allow(unused_variables)]
fn main() {
- let a : [i32; f(X)];
+ let a : [i32; f(X)]; //~ NOTE for array length here
}
diff --git a/src/test/compile-fail/const-index-feature-gate.rs b/src/test/compile-fail/const-index-feature-gate.rs
index 09822e4..4f92770 100644
--- a/src/test/compile-fail/const-index-feature-gate.rs
+++ b/src/test/compile-fail/const-index-feature-gate.rs
@@ -9,7 +9,8 @@
// except according to those terms.
const ARR: [usize; 1] = [2];
-const ARR2: [i32; ARR[0]] = [5, 6]; //~ ERROR unstable
+const ARR2: [i32; ARR[0]] = [5, 6]; //~ ERROR E0080
+ //~| unstable
fn main() {
}
diff --git a/src/test/compile-fail/const-integer-bool-ops.rs b/src/test/compile-fail/const-integer-bool-ops.rs
index 0d6cf3b..5dadd89 100644
--- a/src/test/compile-fail/const-integer-bool-ops.rs
+++ b/src/test/compile-fail/const-integer-bool-ops.rs
@@ -8,30 +8,34 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-const X: usize = 42 && 39; //~ ERROR: can't do this op on integrals
+const X: usize = 42 && 39; //~ ERROR E0080
+ //~| can't do this op on integrals
const ARR: [i32; X] = [99; 34]; //~ NOTE: for array length here
-const X1: usize = 42 || 39; //~ ERROR: can't do this op on integrals
+const X1: usize = 42 || 39; //~ ERROR E0080
+ //~| can't do this op on integrals
const ARR1: [i32; X1] = [99; 47]; //~ NOTE: for array length here
-const X2: usize = -42 || -39; //~ ERROR: unary negation of unsigned integer
+const X2: usize = -42 || -39; //~ ERROR E0080
+ //~| unary negation of unsigned integer
const ARR2: [i32; X2] = [99; 18446744073709551607]; //~ NOTE: for array length here
-const X3: usize = -42 && -39; //~ ERROR: unary negation of unsigned integer
+const X3: usize = -42 && -39; //~ ERROR E0080
+ //~| unary negation of unsigned integer
const ARR3: [i32; X3] = [99; 6]; //~ NOTE: for array length here
const Y: usize = 42.0 == 42.0;
-const ARRR: [i32; Y] = [99; 1]; //~ ERROR: expected usize value for array length
+const ARRR: [i32; Y] = [99; 1]; //~ ERROR: expected usize for array length
const Y1: usize = 42.0 >= 42.0;
-const ARRR1: [i32; Y] = [99; 1]; //~ ERROR: expected usize value for array length
+const ARRR1: [i32; Y] = [99; 1]; //~ ERROR: expected usize for array length
const Y2: usize = 42.0 <= 42.0;
-const ARRR2: [i32; Y] = [99; 1]; //~ ERROR: expected usize value for array length
+const ARRR2: [i32; Y] = [99; 1]; //~ ERROR: expected usize for array length
const Y3: usize = 42.0 > 42.0;
-const ARRR3: [i32; Y] = [99; 0]; //~ ERROR: expected usize value for array length
+const ARRR3: [i32; Y] = [99; 0]; //~ ERROR: expected usize for array length
const Y4: usize = 42.0 < 42.0;
-const ARRR4: [i32; Y] = [99; 0]; //~ ERROR: expected usize value for array length
+const ARRR4: [i32; Y] = [99; 0]; //~ ERROR: expected usize for array length
const Y5: usize = 42.0 != 42.0;
-const ARRR5: [i32; Y] = [99; 0]; //~ ERROR: expected usize value for array length
+const ARRR5: [i32; Y] = [99; 0]; //~ ERROR: expected usize for array length
fn main() {
let _ = ARR;
diff --git a/src/test/compile-fail/const-len-underflow-separate-spans.rs b/src/test/compile-fail/const-len-underflow-separate-spans.rs
index 9c6b774..43375ee 100644
--- a/src/test/compile-fail/const-len-underflow-separate-spans.rs
+++ b/src/test/compile-fail/const-len-underflow-separate-spans.rs
@@ -15,7 +15,8 @@
const ONE: usize = 1;
const TWO: usize = 2;
const LEN: usize = ONE - TWO;
-//~^ ERROR array length constant evaluation error: attempted to subtract with overflow [E0250]
+//~^ ERROR E0080
+//~| attempted to subtract with overflow
fn main() {
let a: [i8; LEN] = unimplemented!();
diff --git a/src/test/compile-fail/const-len-underflow-subspans.rs b/src/test/compile-fail/const-len-underflow-subspans.rs
index d51f310..e338f20 100644
--- a/src/test/compile-fail/const-len-underflow-subspans.rs
+++ b/src/test/compile-fail/const-len-underflow-subspans.rs
@@ -16,5 +16,6 @@
fn main() {
let a: [i8; ONE - TWO] = unimplemented!();
- //~^ ERROR array length constant evaluation error: attempted to subtract with overflow [E0250]
+ //~^ ERROR constant evaluation error [E0080]
+ //~| attempted to subtract with overflow
}
diff --git a/src/test/compile-fail/const-pattern-not-const-evaluable.rs b/src/test/compile-fail/const-pattern-not-const-evaluable.rs
index 4567cd4..d68d636 100644
--- a/src/test/compile-fail/const-pattern-not-const-evaluable.rs
+++ b/src/test/compile-fail/const-pattern-not-const-evaluable.rs
@@ -17,22 +17,26 @@
use Cake::*;
const BOO: (Cake, Cake) = (Marmor, BlackForest);
-//~^ ERROR: constant evaluation error: unimplemented constant expression: enum variants [E0471]
+//~^ ERROR: constant evaluation error [E0080]
+//~| unimplemented constant expression: enum variants
const FOO: Cake = BOO.1;
const fn foo() -> Cake {
- Marmor //~ ERROR: constant evaluation error: unimplemented constant expression: enum variants
- //~^ ERROR: unimplemented constant expression: enum variants
+ Marmor
+ //~^ ERROR: constant evaluation error [E0080]
+ //~| unimplemented constant expression: enum variants
+ //~^^^ ERROR: constant evaluation error [E0080]
+ //~| unimplemented constant expression: enum variants
}
const WORKS: Cake = Marmor;
-const GOO: Cake = foo();
+const GOO: Cake = foo(); //~ NOTE for expression here
fn main() {
match BlackForest {
- FOO => println!("hi"), //~ NOTE: in pattern here
- GOO => println!("meh"), //~ NOTE: in pattern here
+ FOO => println!("hi"), //~ NOTE: for pattern here
+ GOO => println!("meh"), //~ NOTE: for pattern here
WORKS => println!("möp"),
_ => println!("bye"),
}
diff --git a/src/test/compile-fail/const-slice-oob.rs b/src/test/compile-fail/const-slice-oob.rs
index d63b009..b1b4bfe 100644
--- a/src/test/compile-fail/const-slice-oob.rs
+++ b/src/test/compile-fail/const-slice-oob.rs
@@ -10,7 +10,8 @@
const FOO: &'static[u32] = &[1, 2, 3];
const BAR: u32 = FOO[5];
-//~^ ERROR index out of bounds: the len is 3 but the index is 5
+//~^ ERROR constant evaluation error [E0080]
+//~| index out of bounds: the len is 3 but the index is 5
fn main() {
let _ = BAR;
diff --git a/src/test/compile-fail/const-tup-index-span.rs b/src/test/compile-fail/const-tup-index-span.rs
index 9d3c432..6f095b3 100644
--- a/src/test/compile-fail/const-tup-index-span.rs
+++ b/src/test/compile-fail/const-tup-index-span.rs
@@ -11,7 +11,8 @@
// Test spans of errors
const TUP: (usize,) = 5 << 64;
-//~^ ERROR: attempted to shift left with overflow [E0250]
+//~^ ERROR E0080
+//~| attempted to shift left with overflow
const ARR: [i32; TUP.0] = [];
fn main() {
diff --git a/src/test/compile-fail/discrim-ill-typed.rs b/src/test/compile-fail/discrim-ill-typed.rs
index 23106c9..c73b7e8 100644
--- a/src/test/compile-fail/discrim-ill-typed.rs
+++ b/src/test/compile-fail/discrim-ill-typed.rs
@@ -25,7 +25,8 @@
Ok = i8::MAX - 1,
Ok2,
OhNo = 0_u8,
- //~^ ERROR mismatched types
+ //~^ ERROR E0080
+ //~| expected i8, found u8
}
let x = A::Ok;
@@ -37,7 +38,8 @@
Ok = u8::MAX - 1,
Ok2,
OhNo = 0_i8,
- //~^ ERROR mismatched types
+ //~^ ERROR E0080
+ //~| expected u8, found i8
}
let x = A::Ok;
@@ -49,7 +51,8 @@
Ok = i16::MAX - 1,
Ok2,
OhNo = 0_u16,
- //~^ ERROR mismatched types
+ //~^ ERROR E0080
+ //~| expected i16, found u16
}
let x = A::Ok;
@@ -61,7 +64,8 @@
Ok = u16::MAX - 1,
Ok2,
OhNo = 0_i16,
- //~^ ERROR mismatched types
+ //~^ ERROR E0080
+ //~| expected u16, found i16
}
let x = A::Ok;
@@ -73,7 +77,8 @@
Ok = i32::MAX - 1,
Ok2,
OhNo = 0_u32,
- //~^ ERROR mismatched types
+ //~^ ERROR E0080
+ //~| expected i32, found u32
}
let x = A::Ok;
@@ -85,7 +90,8 @@
Ok = u32::MAX - 1,
Ok2,
OhNo = 0_i32,
- //~^ ERROR mismatched types
+ //~^ ERROR E0080
+ //~| expected u32, found i32
}
let x = A::Ok;
@@ -97,7 +103,8 @@
Ok = i64::MAX - 1,
Ok2,
OhNo = 0_u64,
- //~^ ERROR mismatched types
+ //~^ ERROR E0080
+ //~| expected i64, found u64
}
let x = A::Ok;
@@ -109,7 +116,8 @@
Ok = u64::MAX - 1,
Ok2,
OhNo = 0_i64,
- //~^ ERROR mismatched types
+ //~^ ERROR E0080
+ //~| expected u64, found i64
}
let x = A::Ok;
diff --git a/src/test/compile-fail/enable-orbit-for-incr-comp.rs b/src/test/compile-fail/enable-orbit-for-incr-comp.rs
new file mode 100644
index 0000000..eec6bad
--- /dev/null
+++ b/src/test/compile-fail/enable-orbit-for-incr-comp.rs
@@ -0,0 +1,20 @@
+// 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.
+
+// ignore-pretty
+// compile-flags:-Zincremental=tmp/cfail-tests/enable-orbit-for-incr-comp -Zorbit=off
+// error-pattern:Automatically enabling `-Z orbit` because `-Z incremental` was specified
+
+#![deny(warnings)]
+
+fn main() {
+ FAIL! // We just need some compilation error. What we really care about is
+ // that the error pattern above is checked.
+}
diff --git a/src/test/compile-fail/enum-discrim-too-small.rs b/src/test/compile-fail/enum-discrim-too-small.rs
index d6ba09b..bbdb389 100644
--- a/src/test/compile-fail/enum-discrim-too-small.rs
+++ b/src/test/compile-fail/enum-discrim-too-small.rs
@@ -13,28 +13,32 @@
enum Eu8 {
Au8 = 23,
Bu8 = 223,
- Cu8 = -23, //~ ERROR unary negation of unsigned integer
+ Cu8 = -23, //~ ERROR E0080
+ //~| unary negation of unsigned integer
}
#[repr(u16)]
enum Eu16 {
Au16 = 23,
Bu16 = 55555,
- Cu16 = -22333, //~ ERROR unary negation of unsigned integer
+ Cu16 = -22333, //~ ERROR E0080
+ //~| unary negation of unsigned integer
}
#[repr(u32)]
enum Eu32 {
Au32 = 23,
Bu32 = 3_000_000_000,
- Cu32 = -2_000_000_000, //~ ERROR unary negation of unsigned integer
+ Cu32 = -2_000_000_000, //~ ERROR E0080
+ //~| unary negation of unsigned integer
}
#[repr(u64)]
enum Eu64 {
Au32 = 23,
Bu32 = 3_000_000_000,
- Cu32 = -2_000_000_000, //~ ERROR unary negation of unsigned integer
+ Cu32 = -2_000_000_000, //~ ERROR E0080
+ //~| unary negation of unsigned integer
}
// u64 currently allows negative numbers, and i64 allows numbers greater than `1<<63`. This is a
diff --git a/src/test/compile-fail/eval-enum.rs b/src/test/compile-fail/eval-enum.rs
index 7ca274b..57db583 100644
--- a/src/test/compile-fail/eval-enum.rs
+++ b/src/test/compile-fail/eval-enum.rs
@@ -9,9 +9,11 @@
// except according to those terms.
enum test {
- div_zero = 1/0, //~ERROR constant evaluation error: attempted to divide by zero
+ div_zero = 1/0, //~ ERROR E0080
+ //~| attempted to divide by zero
rem_zero = 1%0,
-//~^ ERROR constant evaluation error: attempted to calculate the remainder with a divisor of zero
+ //~^ ERROR E0080
+ //~| attempted to calculate the remainder with a divisor of zero
}
fn main() {}
diff --git a/src/test/compile-fail/explicit-self-lifetime-mismatch.rs b/src/test/compile-fail/explicit-self-lifetime-mismatch.rs
index b5432fa..f8aa1ea 100644
--- a/src/test/compile-fail/explicit-self-lifetime-mismatch.rs
+++ b/src/test/compile-fail/explicit-self-lifetime-mismatch.rs
@@ -14,15 +14,17 @@
}
impl<'a,'b> Foo<'a,'b> {
- fn bar(self: Foo<'b,'a>) {}
- //~^ ERROR mismatched types
+ fn bar(
+ self
+ //~^ ERROR mismatched method receiver
//~| expected type `Foo<'a, 'b>`
//~| found type `Foo<'b, 'a>`
//~| lifetime mismatch
- //~| ERROR mismatched types
+ //~| ERROR mismatched method receiver
//~| expected type `Foo<'a, 'b>`
//~| found type `Foo<'b, 'a>`
//~| lifetime mismatch
+ : Foo<'b,'a>) {}
}
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
index 0000000..0c01f95
--- /dev/null
+++ b/src/test/compile-fail/feature-gate-abi.rs
@@ -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-negate-unsigned0.rs b/src/test/compile-fail/feature-gate-negate-unsigned0.rs
index 05b1943..89ae1a0 100644
--- a/src/test/compile-fail/feature-gate-negate-unsigned0.rs
+++ b/src/test/compile-fail/feature-gate-negate-unsigned0.rs
@@ -18,14 +18,17 @@
fn main() {
let a = -1;
- //~^ ERROR unary negation of unsigned integer
+ //~^ ERROR E0080
+ //~| unary negation of unsigned integer
let _b : u8 = a; // for infering variable a to u8.
let _d = -1u8;
- //~^ ERROR unary negation of unsigned integer
+ //~^ ERROR E0080
+ //~| unary negation of unsigned integer
for _ in -10..10u8 {}
- //~^ ERROR unary negation of unsigned integer
+ //~^ ERROR E0080
+ //~| unary negation of unsigned integer
-S; // should not trigger the gate; issue 26840
}
diff --git a/src/test/compile-fail/feature-gate-unboxed-closures-method-calls.rs b/src/test/compile-fail/feature-gate-unboxed-closures-method-calls.rs
index eea1f61..253d163 100644
--- a/src/test/compile-fail/feature-gate-unboxed-closures-method-calls.rs
+++ b/src/test/compile-fail/feature-gate-unboxed-closures-method-calls.rs
@@ -11,9 +11,9 @@
#![allow(dead_code)]
fn foo<F: Fn()>(mut f: F) {
- f.call(()); //~ ERROR explicit use of unboxed closure method `call`
- f.call_mut(()); //~ ERROR explicit use of unboxed closure method `call_mut`
- f.call_once(()); //~ ERROR explicit use of unboxed closure method `call_once`
+ f.call(()); //~ ERROR use of unstable library feature 'fn_traits'
+ f.call_mut(()); //~ ERROR use of unstable library feature 'fn_traits'
+ f.call_once(()); //~ ERROR use of unstable library feature 'fn_traits'
}
fn main() {}
diff --git a/src/test/compile-fail/feature-gate-unboxed-closures-ufcs-calls.rs b/src/test/compile-fail/feature-gate-unboxed-closures-ufcs-calls.rs
index f15c5c4..902b3c1 100644
--- a/src/test/compile-fail/feature-gate-unboxed-closures-ufcs-calls.rs
+++ b/src/test/compile-fail/feature-gate-unboxed-closures-ufcs-calls.rs
@@ -10,10 +10,10 @@
#![allow(dead_code)]
-fn foo<F: Fn()>(mut f: F, mut g: F) {
- Fn::call(&g, ()); //~ ERROR explicit use of unboxed closure method `call`
- FnMut::call_mut(&mut g, ()); //~ ERROR explicit use of unboxed closure method `call_mut`
- FnOnce::call_once(g, ()); //~ ERROR explicit use of unboxed closure method `call_once`
+fn foo<F: Fn()>(mut f: F) {
+ Fn::call(&f, ()); //~ ERROR use of unstable library feature 'fn_traits'
+ FnMut::call_mut(&mut f, ()); //~ ERROR use of unstable library feature 'fn_traits'
+ FnOnce::call_once(f, ()); //~ ERROR use of unstable library feature 'fn_traits'
}
fn main() {}
diff --git a/src/test/compile-fail/fn-trait-formatting.rs b/src/test/compile-fail/fn-trait-formatting.rs
index fd140cd..e01a041 100644
--- a/src/test/compile-fail/fn-trait-formatting.rs
+++ b/src/test/compile-fail/fn-trait-formatting.rs
@@ -8,7 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(unboxed_closures)]
#![feature(box_syntax)]
fn needs_fn<F>(x: F) where F: Fn(isize) -> isize {}
diff --git a/src/test/compile-fail/fully-qualified-type-name1.rs b/src/test/compile-fail/fully-qualified-type-name1.rs
index 5ea8ce2..1a7ceb2 100644
--- a/src/test/compile-fail/fully-qualified-type-name1.rs
+++ b/src/test/compile-fail/fully-qualified-type-name1.rs
@@ -15,6 +15,6 @@
x = 5;
//~^ ERROR mismatched types
//~| expected type `std::option::Option<usize>`
- //~| found type `_`
+ //~| found type `{integer}`
//~| expected enum `std::option::Option`, found integral variable
}
diff --git a/src/test/compile-fail/if-let-arm-types.rs b/src/test/compile-fail/if-let-arm-types.rs
index c7b1e1a..40013a7 100644
--- a/src/test/compile-fail/if-let-arm-types.rs
+++ b/src/test/compile-fail/if-let-arm-types.rs
@@ -12,7 +12,7 @@
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
diff --git a/src/test/compile-fail/ifmt-bad-arg.rs b/src/test/compile-fail/ifmt-bad-arg.rs
index 272ad98..59c61a4 100644
--- a/src/test/compile-fail/ifmt-bad-arg.rs
+++ b/src/test/compile-fail/ifmt-bad-arg.rs
@@ -41,6 +41,12 @@
//~^ 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
diff --git a/src/test/compile-fail/indexing-requires-a-uint.rs b/src/test/compile-fail/indexing-requires-a-uint.rs
index 354d7b9..61d54b3 100644
--- a/src/test/compile-fail/indexing-requires-a-uint.rs
+++ b/src/test/compile-fail/indexing-requires-a-uint.rs
@@ -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
diff --git a/src/test/compile-fail/integral-variable-unification-error.rs b/src/test/compile-fail/integral-variable-unification-error.rs
index 99f2d25..f2686ae 100644
--- a/src/test/compile-fail/integral-variable-unification-error.rs
+++ b/src/test/compile-fail/integral-variable-unification-error.rs
@@ -12,7 +12,7 @@
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
}
diff --git a/src/test/compile-fail/invalid-path-in-const.rs b/src/test/compile-fail/invalid-path-in-const.rs
index 3c4ad5a..9a9358b 100644
--- a/src/test/compile-fail/invalid-path-in-const.rs
+++ b/src/test/compile-fail/invalid-path-in-const.rs
@@ -10,5 +10,6 @@
fn main() {
fn f(a: [u8; u32::DOESNOTEXIST]) {}
- //~^ ERROR unresolved path in constant expression
+ //~^ ERROR constant evaluation error
+ //~| unresolved path in constant expression
}
diff --git a/src/test/compile-fail/issue-13033.rs b/src/test/compile-fail/issue-13033.rs
index 43cf70e..3d9d814 100644
--- a/src/test/compile-fail/issue-13033.rs
+++ b/src/test/compile-fail/issue-13033.rs
@@ -16,7 +16,9 @@
impl Foo for Baz {
fn bar(&mut self, other: &Foo) {}
- //~^ ERROR method `bar` has an incompatible type for trait: values differ in mutability [E0053]
+ //~^ ERROR method `bar` has an incompatible type for trait
+ //~| expected type `fn(&mut Baz, &mut Foo)`
+ //~| found type `fn(&mut Baz, &Foo)`
}
fn main() {}
diff --git a/src/test/compile-fail/issue-13466.rs b/src/test/compile-fail/issue-13466.rs
index 17b9641..abddf6b 100644
--- a/src/test/compile-fail/issue-13466.rs
+++ b/src/test/compile-fail/issue-13466.rs
@@ -17,13 +17,13 @@
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`
};
diff --git a/src/test/compile-fail/issue-15094.rs b/src/test/compile-fail/issue-15094.rs
index 42e3456..da48bbb 100644
--- a/src/test/compile-fail/issue-15094.rs
+++ b/src/test/compile-fail/issue-15094.rs
@@ -20,8 +20,8 @@
type Output = ();
fn call_once(self, _args: ()) {
//~^ ERROR `call_once` has an incompatible type for trait
- //~| expected "rust-call" fn,
- //~| found "Rust" fn
+ //~| expected type `extern "rust-call" fn
+ //~| found type `fn
println!("{:?}", self.x);
}
}
diff --git a/src/test/compile-fail/issue-16939.rs b/src/test/compile-fail/issue-16939.rs
index 7ec3fef..e16c58b 100644
--- a/src/test/compile-fail/issue-16939.rs
+++ b/src/test/compile-fail/issue-16939.rs
@@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(overloaded_calls, unboxed_closures)]
-
// Make sure we don't ICE when making an overloaded call with the
// wrong arity.
diff --git a/src/test/compile-fail/issue-17033.rs b/src/test/compile-fail/issue-17033.rs
index f0fe01b..0ec05b9 100644
--- a/src/test/compile-fail/issue-17033.rs
+++ b/src/test/compile-fail/issue-17033.rs
@@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(overloaded_calls)]
-
fn f<'r>(p: &'r mut fn(p: &mut ())) {
(*p)(()) //~ ERROR mismatched types
//~| expected type `&mut ()`
diff --git a/src/test/compile-fail/issue-17545.rs b/src/test/compile-fail/issue-17545.rs
index 8480021..49435f8 100644
--- a/src/test/compile-fail/issue-17545.rs
+++ b/src/test/compile-fail/issue-17545.rs
@@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(unboxed_closures)]
-
pub fn foo<'a, F: Fn(&'a ())>(bar: F) {
bar.call((
&(), //~ ERROR borrowed value does not live long enough
diff --git a/src/test/compile-fail/issue-17551.rs b/src/test/compile-fail/issue-17551.rs
index 5781cb7..5e69553d 100644
--- a/src/test/compile-fail/issue-17551.rs
+++ b/src/test/compile-fail/issue-17551.rs
@@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(unboxed_closures)]
-
use std::marker;
struct B<T>(marker::PhantomData<T>);
diff --git a/src/test/compile-fail/issue-17651.rs b/src/test/compile-fail/issue-17651.rs
index 0fe01ec..3ea136a 100644
--- a/src/test/compile-fail/issue-17651.rs
+++ b/src/test/compile-fail/issue-17651.rs
@@ -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
}
diff --git a/src/test/compile-fail/issue-17740.rs b/src/test/compile-fail/issue-17740.rs
index 6b9294b..664d62e 100644
--- a/src/test/compile-fail/issue-17740.rs
+++ b/src/test/compile-fail/issue-17740.rs
@@ -14,11 +14,11 @@
impl <'a> Foo<'a>{
fn bar(self: &mut Foo) {
- //~^ mismatched types
+ //~^ mismatched method receiver
//~| expected type `&mut Foo<'a>`
//~| found type `&mut Foo<'_>`
//~| lifetime mismatch
- //~| mismatched types
+ //~| mismatched method receiver
//~| expected type `&mut Foo<'a>`
//~| found type `&mut Foo<'_>`
//~| lifetime mismatch
diff --git a/src/test/compile-fail/issue-18532.rs b/src/test/compile-fail/issue-18532.rs
index 9cf922a..94eab97c 100644
--- a/src/test/compile-fail/issue-18532.rs
+++ b/src/test/compile-fail/issue-18532.rs
@@ -12,8 +12,6 @@
// when a type error or unconstrained type variable propagates
// into it.
-#![feature(unboxed_closures)]
-
fn main() {
(return)((),());
//~^ ERROR the type of this value must be known
diff --git a/src/test/compile-fail/issue-19521.rs b/src/test/compile-fail/issue-19521.rs
index 58a95e9..93d95ca 100644
--- a/src/test/compile-fail/issue-19521.rs
+++ b/src/test/compile-fail/issue-19521.rs
@@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(unboxed_closures)]
-
fn main() {
"".homura()(); //~ ERROR no method named `homura` found
}
diff --git a/src/test/compile-fail/issue-19707.rs b/src/test/compile-fail/issue-19707.rs
index 9affb44..beeb7da 100644
--- a/src/test/compile-fail/issue-19707.rs
+++ b/src/test/compile-fail/issue-19707.rs
@@ -8,7 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(unboxed_closures)]
#![allow(dead_code)]
type foo = fn(&u8, &u8) -> &u8; //~ ERROR missing lifetime specifier
diff --git a/src/test/compile-fail/issue-19991.rs b/src/test/compile-fail/issue-19991.rs
index b368daa..e07dfaf 100644
--- a/src/test/compile-fail/issue-19991.rs
+++ b/src/test/compile-fail/issue-19991.rs
@@ -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
};
diff --git a/src/test/compile-fail/issue-21332.rs b/src/test/compile-fail/issue-21332.rs
index b369181..db33348 100644
--- a/src/test/compile-fail/issue-21332.rs
+++ b/src/test/compile-fail/issue-21332.rs
@@ -14,8 +14,7 @@
type Item = i32;
fn next(&mut self) -> Result<i32, i32> { Ok(7) }
//~^ ERROR method `next` has an incompatible type for trait
- //~| expected enum `std::option::Option`
- //~| found enum `std::result::Result` [E0053]
+ //~| expected enum `std::option::Option`, found enum `std::result::Result`
}
fn main() {}
diff --git a/src/test/compile-fail/issue-22933-2.rs b/src/test/compile-fail/issue-22933-2.rs
index 7d619c2..54a2408 100644
--- a/src/test/compile-fail/issue-22933-2.rs
+++ b/src/test/compile-fail/issue-22933-2.rs
@@ -12,10 +12,12 @@
Pie = 0x1,
Apple = 0x2,
ApplePie = Delicious::Apple as isize | Delicious::PIE as isize,
- //~^ ERROR constant evaluation error: unresolved path in constant expression
+ //~^ ERROR constant evaluation error
+ //~| unresolved path in constant expression
}
const FOO: [u32; u8::MIN as usize] = [];
-//~^ ERROR array length constant evaluation error: unresolved path in constant expression
+//~^ ERROR constant evaluation error
+//~| unresolved path in constant expression
fn main() {}
diff --git a/src/test/compile-fail/issue-23217.rs b/src/test/compile-fail/issue-23217.rs
index 32cdd6b..c2bcbb9 100644
--- a/src/test/compile-fail/issue-23217.rs
+++ b/src/test/compile-fail/issue-23217.rs
@@ -10,7 +10,8 @@
pub enum SomeEnum {
B = SomeEnum::A,
- //~^ ERROR constant evaluation error: unresolved path in constant expression
+ //~^ ERROR constant evaluation error
+ //~| unresolved path in constant expression
}
fn main() {}
diff --git a/src/test/compile-fail/issue-24356.rs b/src/test/compile-fail/issue-24356.rs
index 27d46be..ede81be 100644
--- a/src/test/compile-fail/issue-24356.rs
+++ b/src/test/compile-fail/issue-24356.rs
@@ -30,9 +30,6 @@
impl Deref for Thing {
//~^ ERROR not all trait items implemented, missing: `Target` [E0046]
fn deref(&self) -> i8 { self.0 }
- //~^ ERROR method `deref` has an incompatible type for trait
- //~| expected &-ptr
- //~| found i8 [E0053]
}
let thing = Thing(72);
diff --git a/src/test/compile-fail/issue-25145.rs b/src/test/compile-fail/issue-25145.rs
index e8a9c8d..93f75e9 100644
--- a/src/test/compile-fail/issue-25145.rs
+++ b/src/test/compile-fail/issue-25145.rs
@@ -17,6 +17,7 @@
}
static STUFF: [u8; S::N] = [0; S::N];
-//~^ ERROR array length constant evaluation error: unresolved path in constant expression
+//~^ ERROR constant evaluation error
+//~| unresolved path in constant expression
fn main() {}
diff --git a/src/test/compile-fail/issue-26237.rs b/src/test/compile-fail/issue-26237.rs
index 11e236d..22772e5 100644
--- a/src/test/compile-fail/issue-26237.rs
+++ b/src/test/compile-fail/issue-26237.rs
@@ -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-27008.rs b/src/test/compile-fail/issue-27008.rs
index bdcbaf0..ee6ec52 100644
--- a/src/test/compile-fail/issue-27008.rs
+++ b/src/test/compile-fail/issue-27008.rs
@@ -16,5 +16,5 @@
//~| expected type `usize`
//~| found type `S`
//~| expected usize, found struct `S`
- //~| ERROR expected positive integer for repeat count, found struct
+ //~| ERROR expected usize for repeat count, found struct
}
diff --git a/src/test/compile-fail/issue-27895.rs b/src/test/compile-fail/issue-27895.rs
index 3b3abc9..ca8d5a1 100644
--- a/src/test/compile-fail/issue-27895.rs
+++ b/src/test/compile-fail/issue-27895.rs
@@ -14,7 +14,8 @@
match i {
0...index => println!("winner"),
- //~^ ERROR non-constant path in constant expression
+ //~^ ERROR constant evaluation error
+ //~| non-constant path in constant expression
_ => println!("hello"),
}
}
diff --git a/src/test/compile-fail/issue-28586.rs b/src/test/compile-fail/issue-28586.rs
index c8a1e424d..1dfd146 100644
--- a/src/test/compile-fail/issue-28586.rs
+++ b/src/test/compile-fail/issue-28586.rs
@@ -11,6 +11,6 @@
// Regression test for issue #28586
pub trait Foo {}
-impl Foo for [u8; usize::BYTES] {} //~ ERROR E0250
+impl Foo for [u8; usize::BYTES] {} //~ ERROR E0080
fn main() { }
diff --git a/src/test/compile-fail/issue-31173.rs b/src/test/compile-fail/issue-31173.rs
new file mode 100644
index 0000000..fb1e3cc
--- /dev/null
+++ b/src/test/compile-fail/issue-31173.rs
@@ -0,0 +1,27 @@
+// 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::vec::IntoIter;
+
+pub fn get_tok(it: &mut IntoIter<u8>) {
+ let mut found_e = false;
+
+ let temp: Vec<u8> = it.take_while(|&x| {
+ found_e = true;
+ false
+ })
+ .cloned()
+ //~^ ERROR type mismatch resolving
+ //~| expected type `u8`
+ //~| found type `&_`
+ .collect(); //~ ERROR no method named `collect`
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/issue-34349.rs b/src/test/compile-fail/issue-34349.rs
new file mode 100644
index 0000000..5917531
--- /dev/null
+++ b/src/test/compile-fail/issue-34349.rs
@@ -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/feature-gate-abi-vectorcall.rs b/src/test/compile-fail/issue-35075.rs
similarity index 69%
rename from src/test/compile-fail/feature-gate-abi-vectorcall.rs
rename to src/test/compile-fail/issue-35075.rs
index 79f3c8d..a70452d 100644
--- a/src/test/compile-fail/feature-gate-abi-vectorcall.rs
+++ b/src/test/compile-fail/issue-35075.rs
@@ -8,12 +8,12 @@
// 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();
+struct Bar<T> {
+ inner: Foo<T> //~ ERROR type name `Foo` is undefined or not in scope
}
-extern "vectorcall" fn baz() { //~ ERROR vectorcall is experimental and subject to change
+enum Baz<T> {
+ Foo(Foo<T>) //~ ERROR type name `Foo` is undefined or not in scope
}
-fn main() {
-}
+fn main() {}
diff --git a/src/test/compile-fail/issue-35139.rs b/src/test/compile-fail/issue-35139.rs
new file mode 100644
index 0000000..67f0e7a
--- /dev/null
+++ b/src/test/compile-fail/issue-35139.rs
@@ -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);
+}
diff --git a/src/test/compile-fail/issue-3521.rs b/src/test/compile-fail/issue-3521.rs
index 52375ef..1b6e4b1 100644
--- a/src/test/compile-fail/issue-3521.rs
+++ b/src/test/compile-fail/issue-3521.rs
@@ -15,7 +15,8 @@
enum Stuff {
Bar = foo
//~^ ERROR attempt to use a non-constant value in a constant
- //~^^ ERROR constant evaluation error: non-constant path in constant expression
+ //~^^ ERROR constant evaluation error
+ //~| non-constant path in constant expression
}
println!("{}", Stuff::Bar);
diff --git a/src/test/compile-fail/issue-3907.rs b/src/test/compile-fail/issue-3907.rs
index c99ff18..cbc09a0 100644
--- a/src/test/compile-fail/issue-3907.rs
+++ b/src/test/compile-fail/issue-3907.rs
@@ -11,14 +11,14 @@
// aux-build:issue_3907.rs
extern crate issue_3907;
-type Foo = issue_3907::Foo; //~ NOTE: type aliases cannot be used for traits
+type Foo = issue_3907::Foo;
struct S {
name: isize
}
impl Foo for S { //~ ERROR: `Foo` is not a trait
- //~| `Foo` is not a trait
+ //~| NOTE: type aliases cannot be used for traits
fn bar() { }
}
diff --git a/src/test/compile-fail/issue-4201.rs b/src/test/compile-fail/issue-4201.rs
index 5842334..b1f668d 100644
--- a/src/test/compile-fail/issue-4201.rs
+++ b/src/test/compile-fail/issue-4201.rs
@@ -14,7 +14,7 @@
} else if false {
//~^ ERROR if may be missing an else clause
//~| expected type `()`
-//~| found type `_`
+//~| found type `{integer}`
//~| expected (), found integral variable
1
};
diff --git a/src/test/compile-fail/issue-4335.rs b/src/test/compile-fail/issue-4335.rs
index 0089bff..9a1b5d9 100644
--- a/src/test/compile-fail/issue-4335.rs
+++ b/src/test/compile-fail/issue-4335.rs
@@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(unboxed_closures)]
-
fn id<T>(t: T) -> T { t }
fn f<'r, T>(v: &'r T) -> Box<FnMut() -> T + 'r> {
diff --git a/src/test/compile-fail/issue-4968.rs b/src/test/compile-fail/issue-4968.rs
index 7c09058..77588e5 100644
--- a/src/test/compile-fail/issue-4968.rs
+++ b/src/test/compile-fail/issue-4968.rs
@@ -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
}
diff --git a/src/test/compile-fail/issue-5035.rs b/src/test/compile-fail/issue-5035.rs
index a186a39..9648d64 100644
--- a/src/test/compile-fail/issue-5035.rs
+++ b/src/test/compile-fail/issue-5035.rs
@@ -10,7 +10,10 @@
trait I {}
type K = I;
-//~^ NOTE: aliases cannot be used for traits
impl K for isize {} //~ ERROR: `K` is not a trait
-//~| is not a trait
+ //~| NOTE: aliases cannot be used for traits
+
+use ImportError; //~ ERROR unresolved
+impl ImportError for () {} // check that this is not an additional error (c.f. #35142)
+
fn main() {}
diff --git a/src/test/compile-fail/issue-7867.rs b/src/test/compile-fail/issue-7867.rs
index e0de860..ed46511 100644
--- a/src/test/compile-fail/issue-7867.rs
+++ b/src/test/compile-fail/issue-7867.rs
@@ -25,12 +25,12 @@
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`
}
diff --git a/src/test/compile-fail/issue-8761.rs b/src/test/compile-fail/issue-8761.rs
index 1c98abc..91a07dd 100644
--- a/src/test/compile-fail/issue-8761.rs
+++ b/src/test/compile-fail/issue-8761.rs
@@ -10,13 +10,11 @@
enum Foo {
A = 1i64,
- //~^ ERROR mismatched types:
- //~| expected `isize`,
- //~| found `i64` [E0080]
+ //~^ ERROR constant evaluation error
+ //~| expected isize, found i64
B = 2u8
- //~^ ERROR mismatched types:
- //~| expected `isize`,
- //~| found `u8` [E0080]
+ //~^ ERROR constant evaluation error
+ //~| expected isize, found u8
}
fn main() {}
diff --git a/src/test/compile-fail/kindck-impl-type-params-2.rs b/src/test/compile-fail/kindck-impl-type-params-2.rs
index 1cf970e..a455a7b 100644
--- a/src/test/compile-fail/kindck-impl-type-params-2.rs
+++ b/src/test/compile-fail/kindck-impl-type-params-2.rs
@@ -21,5 +21,5 @@
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
}
diff --git a/src/test/compile-fail/lint-forbid-attr.rs b/src/test/compile-fail/lint-forbid-attr.rs
index fcc8fb6..fd2513c 100644
--- a/src/test/compile-fail/lint-forbid-attr.rs
+++ b/src/test/compile-fail/lint-forbid-attr.rs
@@ -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() {
diff --git a/src/test/compile-fail/feature-gate-abi-vectorcall.rs b/src/test/compile-fail/macro-tt-matchers.rs
similarity index 69%
copy from src/test/compile-fail/feature-gate-abi-vectorcall.rs
copy to src/test/compile-fail/macro-tt-matchers.rs
index 79f3c8d..f41da77 100644
--- a/src/test/compile-fail/feature-gate-abi-vectorcall.rs
+++ b/src/test/compile-fail/macro-tt-matchers.rs
@@ -8,12 +8,13 @@
// 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();
+#![feature(rustc_attrs)]
+
+macro_rules! foo {
+ ($x:tt) => (type Alias = $x<i32>;)
}
-extern "vectorcall" fn baz() { //~ ERROR vectorcall is experimental and subject to change
-}
+foo!(Box);
-fn main() {
-}
+#[rustc_error]
+fn main() {} //~ ERROR compilation successful
diff --git a/src/test/compile-fail/match-range-fail.rs b/src/test/compile-fail/match-range-fail.rs
index 526aa83..f89b3e39 100644
--- a/src/test/compile-fail/match-range-fail.rs
+++ b/src/test/compile-fail/match-range-fail.rs
@@ -20,13 +20,14 @@
10 ... "what" => ()
};
//~^^ ERROR only char and numeric types are allowed in range
- //~| start type: _
+ //~| start type: {integer}
//~| end type: &'static str
match 5 {
'c' ... 100 => { }
_ => { }
};
- //~^^^ ERROR mismatched types in range
- //~| expected char, found integral variable
+ //~^^^ ERROR mismatched types
+ //~| expected type `{integer}`
+ //~| found type `char`
}
diff --git a/src/test/compile-fail/match-vec-mismatch.rs b/src/test/compile-fail/match-vec-mismatch.rs
index 3ac4958..596cec1 100644
--- a/src/test/compile-fail/match-vec-mismatch.rs
+++ b/src/test/compile-fail/match-vec-mismatch.rs
@@ -18,7 +18,7 @@
};
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] {
diff --git a/src/test/compile-fail/method-self-arg-1.rs b/src/test/compile-fail/method-self-arg-1.rs
index ffa5287..0381636 100644
--- a/src/test/compile-fail/method-self-arg-1.rs
+++ b/src/test/compile-fail/method-self-arg-1.rs
@@ -24,6 +24,6 @@
//~| 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
}
diff --git a/src/test/compile-fail/moves-based-on-type-no-recursive-stack-closure.rs b/src/test/compile-fail/moves-based-on-type-no-recursive-stack-closure.rs
index 5af326b..df9a351 100644
--- a/src/test/compile-fail/moves-based-on-type-no-recursive-stack-closure.rs
+++ b/src/test/compile-fail/moves-based-on-type-no-recursive-stack-closure.rs
@@ -12,8 +12,6 @@
// bound must be noncopyable. For details see
// http://smallcultfollowing.com/babysteps/blog/2013/04/30/the-case-of-the-recurring-closure/
-#![feature(unboxed_closures)]
-
struct R<'a> {
// This struct is needed to create the
// otherwise infinite type of a fn that
diff --git a/src/test/compile-fail/mut-pattern-mismatched.rs b/src/test/compile-fail/mut-pattern-mismatched.rs
index 63e7dbd..318d121 100644
--- a/src/test/compile-fail/mut-pattern-mismatched.rs
+++ b/src/test/compile-fail/mut-pattern-mismatched.rs
@@ -14,7 +14,7 @@
// (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 @@
let bar = &1;
let &_ = bar;
let &mut _ //~ ERROR mismatched types
- //~| expected type `&_`
+ //~| expected type `&{integer}`
//~| found type `&mut _`
//~| values differ in mutability
= bar;
diff --git a/src/test/compile-fail/no-patterns-in-args.rs b/src/test/compile-fail/no-patterns-in-args.rs
new file mode 100644
index 0000000..3edbdf4
--- /dev/null
+++ b/src/test/compile-fail/no-patterns-in-args.rs
@@ -0,0 +1,30 @@
+// 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 {
+ fn f1(mut arg: u8); //~ ERROR patterns aren't allowed in foreign function declarations
+ //~^ NOTE this is a recent error
+ fn f2(&arg: u8); //~ ERROR patterns aren't allowed in foreign function declarations
+ fn f3(arg @ _: u8); //~ ERROR patterns aren't allowed in foreign function declarations
+ //~^ NOTE this is a recent error
+ fn g1(arg: u8); // OK
+ fn g2(_: u8); // OK
+ // fn g3(u8); // Not yet
+}
+
+type A1 = fn(mut arg: u8); //~ ERROR patterns aren't allowed in function pointer types
+ //~^ NOTE this is a recent error
+type A2 = fn(&arg: u8); //~ ERROR patterns aren't allowed in function pointer types
+ //~^ NOTE this is a recent error
+type B1 = fn(arg: u8); // OK
+type B2 = fn(_: u8); // OK
+type B3 = fn(u8); // OK
+
+fn main() {}
diff --git a/src/test/compile-fail/no_send-rc.rs b/src/test/compile-fail/no_send-rc.rs
index 69f6fcd..f31d378 100644
--- a/src/test/compile-fail/no_send-rc.rs
+++ b/src/test/compile-fail/no_send-rc.rs
@@ -15,5 +15,5 @@
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
}
diff --git a/src/test/compile-fail/non-constant-enum-for-vec-repeat.rs b/src/test/compile-fail/non-constant-enum-for-vec-repeat.rs
index 9564a08..cadfec5 100644
--- a/src/test/compile-fail/non-constant-enum-for-vec-repeat.rs
+++ b/src/test/compile-fail/non-constant-enum-for-vec-repeat.rs
@@ -15,5 +15,6 @@
fn main() {
[State::ST_NULL; (State::ST_WHITESPACE as usize)];
- //~^ ERROR expected constant integer for repeat count, but unimplemented constant expression
+ //~^ ERROR constant evaluation error
+ //~| unimplemented constant expression: enum variants
}
diff --git a/src/test/compile-fail/non-constant-expr-for-vec-repeat.rs b/src/test/compile-fail/non-constant-expr-for-vec-repeat.rs
index 3ce206f..a6f88a5 100644
--- a/src/test/compile-fail/non-constant-expr-for-vec-repeat.rs
+++ b/src/test/compile-fail/non-constant-expr-for-vec-repeat.rs
@@ -13,6 +13,8 @@
fn main() {
fn bar(n: usize) {
let _x = [0; n];
- //~^ ERROR expected constant integer for repeat count, found variable
+ //~^ ERROR constant evaluation error
+ //~| non-constant path in constant expression
+ //~| NOTE `n` is a variable
}
}
diff --git a/src/test/compile-fail/non-constant-in-const-path.rs b/src/test/compile-fail/non-constant-in-const-path.rs
index ee88168..737f803 100644
--- a/src/test/compile-fail/non-constant-in-const-path.rs
+++ b/src/test/compile-fail/non-constant-in-const-path.rs
@@ -12,6 +12,7 @@
let x = 0;
match 1 {
0 ... x => {}
- //~^ ERROR non-constant path in constant expression
+ //~^ ERROR constant evaluation error
+ //~| non-constant path in constant expression
};
}
diff --git a/src/test/compile-fail/privacy-ns2.rs b/src/test/compile-fail/privacy-ns2.rs
index bf29622..7accf0c 100644
--- a/src/test/compile-fail/privacy-ns2.rs
+++ b/src/test/compile-fail/privacy-ns2.rs
@@ -25,15 +25,15 @@
}
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 @@
}
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
diff --git a/src/test/compile-fail/range-1.rs b/src/test/compile-fail/range-1.rs
index c00be91..dc68331 100644
--- a/src/test/compile-fail/range-1.rs
+++ b/src/test/compile-fail/range-1.rs
@@ -23,5 +23,5 @@
// 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
}
diff --git a/src/test/compile-fail/regionck-unboxed-closure-lifetimes.rs b/src/test/compile-fail/regionck-unboxed-closure-lifetimes.rs
index 5db9a01..8ec6036 100644
--- a/src/test/compile-fail/regionck-unboxed-closure-lifetimes.rs
+++ b/src/test/compile-fail/regionck-unboxed-closure-lifetimes.rs
@@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(unboxed_closures, overloaded_calls)]
-
use std::ops::FnMut;
fn main() {
diff --git a/src/test/compile-fail/regions-escape-unboxed-closure.rs b/src/test/compile-fail/regions-escape-unboxed-closure.rs
index abbefd2..cf41fad 100644
--- a/src/test/compile-fail/regions-escape-unboxed-closure.rs
+++ b/src/test/compile-fail/regions-escape-unboxed-closure.rs
@@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(unboxed_closures)]
-
fn with_int(f: &mut FnMut(&isize)) {
}
diff --git a/src/test/compile-fail/regions-return-ref-to-upvar-issue-17403.rs b/src/test/compile-fail/regions-return-ref-to-upvar-issue-17403.rs
index 1e2224e..99e5cc0 100644
--- a/src/test/compile-fail/regions-return-ref-to-upvar-issue-17403.rs
+++ b/src/test/compile-fail/regions-return-ref-to-upvar-issue-17403.rs
@@ -10,8 +10,6 @@
// Test that closures cannot subvert aliasing restrictions
-#![feature(overloaded_calls, unboxed_closures)]
-
fn main() {
// Unboxed closure case
{
diff --git a/src/test/compile-fail/regions-steal-closure.rs b/src/test/compile-fail/regions-steal-closure.rs
index a30d847..8ade8b2 100644
--- a/src/test/compile-fail/regions-steal-closure.rs
+++ b/src/test/compile-fail/regions-steal-closure.rs
@@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(unboxed_closures)]
-
struct closure_box<'a> {
cl: Box<FnMut() + 'a>,
}
diff --git a/src/test/compile-fail/repeat_count.rs b/src/test/compile-fail/repeat_count.rs
index ab5af64..1758b28 100644
--- a/src/test/compile-fail/repeat_count.rs
+++ b/src/test/compile-fail/repeat_count.rs
@@ -13,39 +13,38 @@
fn main() {
let n = 1;
let a = [0; n];
- //~^ ERROR expected constant integer for repeat count, found variable [E0307]
+ //~^ ERROR constant evaluation error
+ //~| non-constant path in constant expression
let b = [0; ()];
//~^ ERROR mismatched types
//~| expected type `usize`
//~| found type `()`
//~| expected usize, found ()
- //~| ERROR expected positive integer for repeat count, found tuple [E0306]
+ //~| ERROR expected usize for repeat count, found tuple [E0306]
let c = [0; true];
//~^ ERROR mismatched types
//~| expected usize, found bool
- //~| ERROR expected positive integer for repeat count, found boolean [E0306]
+ //~| ERROR expected usize for repeat count, found boolean [E0306]
let d = [0; 0.5];
//~^ ERROR mismatched types
//~| expected type `usize`
- //~| found type `_`
+ //~| found type `{float}`
//~| expected usize, found floating-point variable
- //~| ERROR expected positive integer for repeat count, found float [E0306]
+ //~| ERROR expected usize for repeat count, found float [E0306]
let e = [0; "foo"];
//~^ ERROR mismatched types
//~| expected type `usize`
//~| found type `&'static str`
//~| expected usize, found &-ptr
- //~| ERROR expected positive integer for repeat count, found string literal [E0306]
+ //~| ERROR expected usize for repeat count, found string literal [E0306]
let f = [0; -4_isize];
- //~^ ERROR mismatched types
- //~| expected `usize`
- //~| found `isize`
- //~| ERROR mismatched types:
+ //~^ ERROR constant evaluation error
+ //~| expected usize, found isize
+ //~| ERROR mismatched types
//~| expected usize, found isize
let f = [0_usize; -1_isize];
- //~^ ERROR mismatched types
- //~| expected `usize`
- //~| found `isize`
+ //~^ ERROR constant evaluation error
+ //~| expected usize, found isize
//~| ERROR mismatched types
//~| expected usize, found isize
struct G {
@@ -56,5 +55,5 @@
//~| expected type `usize`
//~| found type `main::G`
//~| expected usize, found struct `main::G`
- //~| ERROR expected positive integer for repeat count, found struct [E0306]
+ //~| ERROR expected usize for repeat count, found struct [E0306]
}
diff --git a/src/test/compile-fail/resolve-type-param-in-item-in-trait.rs b/src/test/compile-fail/resolve-type-param-in-item-in-trait.rs
index 30ff1ed..a1572b8 100644
--- a/src/test/compile-fail/resolve-type-param-in-item-in-trait.rs
+++ b/src/test/compile-fail/resolve-type-param-in-item-in-trait.rs
@@ -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 @@
}
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
}
diff --git a/src/test/compile-fail/slightly-nice-generic-literal-messages.rs b/src/test/compile-fail/slightly-nice-generic-literal-messages.rs
index 3140bb6..2eba7c2 100644
--- a/src/test/compile-fail/slightly-nice-generic-literal-messages.rs
+++ b/src/test/compile-fail/slightly-nice-generic-literal-messages.rs
@@ -16,8 +16,8 @@
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
}
diff --git a/src/test/compile-fail/str-idx.rs b/src/test/compile-fail/str-idx.rs
index b972a09..2b2c23a 100644
--- a/src/test/compile-fail/str-idx.rs
+++ b/src/test/compile-fail/str-idx.rs
@@ -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
}
diff --git a/src/test/compile-fail/struct-base-wrong-type-2.rs b/src/test/compile-fail/struct-base-wrong-type-2.rs
index 1250d0d..7e5510ed 100644
--- a/src/test/compile-fail/struct-base-wrong-type-2.rs
+++ b/src/test/compile-fail/struct-base-wrong-type-2.rs
@@ -24,6 +24,6 @@
//~| 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
}
diff --git a/src/test/compile-fail/struct-base-wrong-type.rs b/src/test/compile-fail/struct-base-wrong-type.rs
index 4503e46..3703b15 100644
--- a/src/test/compile-fail/struct-base-wrong-type.rs
+++ b/src/test/compile-fail/struct-base-wrong-type.rs
@@ -23,7 +23,7 @@
//~| 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() {
diff --git a/src/test/compile-fail/trait-impl-method-mismatch.rs b/src/test/compile-fail/trait-impl-method-mismatch.rs
index f86d9b7..a05e007 100644
--- a/src/test/compile-fail/trait-impl-method-mismatch.rs
+++ b/src/test/compile-fail/trait-impl-method-mismatch.rs
@@ -17,8 +17,8 @@
// Cannot have a larger effect than the trait:
unsafe fn jumbo(&self, x: &usize) { *self + *x; }
//~^ ERROR method `jumbo` has an incompatible type for trait
- //~| expected normal fn,
- //~| found unsafe fn
+ //~| expected type `fn
+ //~| found type `unsafe fn
}
fn main() {}
diff --git a/src/test/compile-fail/traits-inductive-overflow-simultaneous.rs b/src/test/compile-fail/traits-inductive-overflow-simultaneous.rs
index 2968e8a..777746a 100644
--- a/src/test/compile-fail/traits-inductive-overflow-simultaneous.rs
+++ b/src/test/compile-fail/traits-inductive-overflow-simultaneous.rs
@@ -26,5 +26,5 @@
fn main() {
is_ee(4);
- //~^ ERROR overflow evaluating the requirement `_: Tweedle
+ //~^ ERROR overflow evaluating the requirement `{integer}: Tweedle
}
diff --git a/src/test/compile-fail/tuple-arity-mismatch.rs b/src/test/compile-fail/tuple-arity-mismatch.rs
index e62255a..a71f441 100644
--- a/src/test/compile-fail/tuple-arity-mismatch.rs
+++ b/src/test/compile-fail/tuple-arity-mismatch.rs
@@ -16,7 +16,7 @@
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,));
diff --git a/src/test/compile-fail/tuple-index-out-of-bounds.rs b/src/test/compile-fail/tuple-index-out-of-bounds.rs
index c2c41fb..4597cf3 100644
--- a/src/test/compile-fail/tuple-index-out-of-bounds.rs
+++ b/src/test/compile-fail/tuple-index-out-of-bounds.rs
@@ -20,5 +20,5 @@
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})`
}
diff --git a/src/test/compile-fail/type-mismatch-multiple.rs b/src/test/compile-fail/type-mismatch-multiple.rs
index 0f174d9..9359c03 100644
--- a/src/test/compile-fail/type-mismatch-multiple.rs
+++ b/src/test/compile-fail/type-mismatch-multiple.rs
@@ -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
diff --git a/src/test/compile-fail/typeck-unsafe-always-share.rs b/src/test/compile-fail/typeck-unsafe-always-share.rs
index 6047f67..f017277 100644
--- a/src/test/compile-fail/typeck-unsafe-always-share.rs
+++ b/src/test/compile-fail/typeck-unsafe-always-share.rs
@@ -27,7 +27,7 @@
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);
diff --git a/src/test/compile-fail/ufcs-explicit-self-bad.rs b/src/test/compile-fail/ufcs-explicit-self-bad.rs
index f14a350..a98b7cd 100644
--- a/src/test/compile-fail/ufcs-explicit-self-bad.rs
+++ b/src/test/compile-fail/ufcs-explicit-self-bad.rs
@@ -41,14 +41,14 @@
impl<'a, T> SomeTrait for &'a Bar<T> {
fn dummy1(self: &&'a Bar<T>) { }
- fn dummy2(self: &Bar<T>) {} //~ ERROR mismatched types
- //~^ ERROR mismatched types
+ fn dummy2(self: &Bar<T>) {} //~ ERROR mismatched method receiver
+ //~^ ERROR mismatched method receiver
fn dummy3(self: &&Bar<T>) {}
- //~^ ERROR mismatched types
+ //~^ ERROR mismatched method receiver
//~| expected type `&&'a Bar<T>`
//~| found type `&&Bar<T>`
//~| lifetime mismatch
- //~| ERROR mismatched types
+ //~| ERROR mismatched method receiver
//~| expected type `&&'a Bar<T>`
//~| found type `&&Bar<T>`
//~| lifetime mismatch
diff --git a/src/test/compile-fail/unboxed-closure-immutable-capture.rs b/src/test/compile-fail/unboxed-closure-immutable-capture.rs
index 5be2738b..2d99837 100644
--- a/src/test/compile-fail/unboxed-closure-immutable-capture.rs
+++ b/src/test/compile-fail/unboxed-closure-immutable-capture.rs
@@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(unboxed_closures)]
-
// Test that even unboxed closures that are capable of mutating their
// environment cannot mutate captured variables that have not been
// declared mutable (#18335)
diff --git a/src/test/compile-fail/unboxed-closure-region.rs b/src/test/compile-fail/unboxed-closure-region.rs
index eee1b6c..1c86dda 100644
--- a/src/test/compile-fail/unboxed-closure-region.rs
+++ b/src/test/compile-fail/unboxed-closure-region.rs
@@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(unboxed_closures)]
-
// Test that an unboxed closure that captures a free variable by
// reference cannot escape the region of that variable.
fn main() {
diff --git a/src/test/compile-fail/unboxed-closure-sugar-nonexistent-trait.rs b/src/test/compile-fail/unboxed-closure-sugar-nonexistent-trait.rs
index 2145085..465bddd 100644
--- a/src/test/compile-fail/unboxed-closure-sugar-nonexistent-trait.rs
+++ b/src/test/compile-fail/unboxed-closure-sugar-nonexistent-trait.rs
@@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(unboxed_closures)]
-
fn f<F:Nonexist(isize) -> isize>(x: F) {} //~ ERROR trait `Nonexist` is not in scope
type Typedef = isize;
diff --git a/src/test/compile-fail/unboxed-closures-borrow-conflict.rs b/src/test/compile-fail/unboxed-closures-borrow-conflict.rs
index 372f327..ad7e678 100644
--- a/src/test/compile-fail/unboxed-closures-borrow-conflict.rs
+++ b/src/test/compile-fail/unboxed-closures-borrow-conflict.rs
@@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(unboxed_closures)]
-
// Test that an unboxed closure that mutates a free variable will
// cause borrow conflicts.
diff --git a/src/test/compile-fail/unboxed-closures-infer-argument-types-two-region-pointers.rs b/src/test/compile-fail/unboxed-closures-infer-argument-types-two-region-pointers.rs
index 1e2b018..5436a85 100644
--- a/src/test/compile-fail/unboxed-closures-infer-argument-types-two-region-pointers.rs
+++ b/src/test/compile-fail/unboxed-closures-infer-argument-types-two-region-pointers.rs
@@ -11,8 +11,6 @@
// That a closure whose expected argument types include two distinct
// bound regions.
-#![feature(unboxed_closures)]
-
use std::cell::Cell;
fn doit<T,F>(val: T, f: &F)
diff --git a/src/test/compile-fail/unboxed-closures-infer-explicit-call-too-early.rs b/src/test/compile-fail/unboxed-closures-infer-explicit-call-too-early.rs
index 226b516..62f6ee5 100644
--- a/src/test/compile-fail/unboxed-closures-infer-explicit-call-too-early.rs
+++ b/src/test/compile-fail/unboxed-closures-infer-explicit-call-too-early.rs
@@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(unboxed_closures)]
-
fn main() {
let mut zero = || {};
let () = zero.call_mut(());
diff --git a/src/test/compile-fail/unboxed-closures-type-mismatch.rs b/src/test/compile-fail/unboxed-closures-type-mismatch.rs
index 9118239..dba4c8c 100644
--- a/src/test/compile-fail/unboxed-closures-type-mismatch.rs
+++ b/src/test/compile-fail/unboxed-closures-type-mismatch.rs
@@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(unboxed_closures)]
-
use std::ops::FnMut;
pub fn main() {
diff --git a/src/test/compile-fail/unboxed-closures-unsafe-extern-fn.rs b/src/test/compile-fail/unboxed-closures-unsafe-extern-fn.rs
index cba7ad8..2b0a8ba 100644
--- a/src/test/compile-fail/unboxed-closures-unsafe-extern-fn.rs
+++ b/src/test/compile-fail/unboxed-closures-unsafe-extern-fn.rs
@@ -10,8 +10,6 @@
// Tests that unsafe extern fn pointers do not implement any Fn traits.
-#![feature(unboxed_closures)]
-
use std::ops::{Fn,FnMut,FnOnce};
unsafe fn square(x: &isize) -> isize { (*x) * (*x) }
diff --git a/src/test/compile-fail/unboxed-closures-wrong-abi.rs b/src/test/compile-fail/unboxed-closures-wrong-abi.rs
index dd891bc..f6ba25f 100644
--- a/src/test/compile-fail/unboxed-closures-wrong-abi.rs
+++ b/src/test/compile-fail/unboxed-closures-wrong-abi.rs
@@ -10,8 +10,6 @@
// Tests that unsafe extern fn pointers do not implement any Fn traits.
-#![feature(unboxed_closures)]
-
use std::ops::{Fn,FnMut,FnOnce};
extern "C" fn square(x: &isize) -> isize { (*x) * (*x) }
diff --git a/src/test/compile-fail/unboxed-closures-wrong-arg-type-extern-fn.rs b/src/test/compile-fail/unboxed-closures-wrong-arg-type-extern-fn.rs
index f9edd5d..9d907ff 100644
--- a/src/test/compile-fail/unboxed-closures-wrong-arg-type-extern-fn.rs
+++ b/src/test/compile-fail/unboxed-closures-wrong-arg-type-extern-fn.rs
@@ -10,8 +10,6 @@
// Tests that unsafe extern fn pointers do not implement any Fn traits.
-#![feature(unboxed_closures)]
-
use std::ops::{Fn,FnMut,FnOnce};
unsafe fn square(x: isize) -> isize { x * x }
diff --git a/src/test/compile-fail/unresolved-import-recovery.rs b/src/test/compile-fail/unresolved-import-recovery.rs
new file mode 100644
index 0000000..8173f69
--- /dev/null
+++ b/src/test/compile-fail/unresolved-import-recovery.rs
@@ -0,0 +1,27 @@
+// 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.
+
+// Check that unresolved imports do not create additional errors and ICEs
+
+mod m {
+ pub use unresolved; //~ ERROR unresolved import `unresolved`
+
+ fn f() {
+ let unresolved = 0; // OK
+ }
+}
+
+fn main() {
+ match 0u8 {
+ m::unresolved => {} // OK
+ m::unresolved(..) => {} // OK
+ m::unresolved{..} => {} // OK
+ }
+}
diff --git a/src/test/compile-fail/unsafe-trait-impl.rs b/src/test/compile-fail/unsafe-trait-impl.rs
index 51f8766..fb4652a 100644
--- a/src/test/compile-fail/unsafe-trait-impl.rs
+++ b/src/test/compile-fail/unsafe-trait-impl.rs
@@ -17,8 +17,8 @@
impl Foo for u32 {
fn len(&self) -> u32 { *self }
//~^ ERROR method `len` has an incompatible type for trait
- //~| expected unsafe fn,
- //~| found normal fn
+ //~| expected type `unsafe fn(&u32) -> u32`
+ //~| found type `fn(&u32) -> u32`
}
fn main() { }
diff --git a/src/test/compile-fail/vtable-res-trait-param.rs b/src/test/compile-fail/vtable-res-trait-param.rs
index eb0baff..8b3e936 100644
--- a/src/test/compile-fail/vtable-res-trait-param.rs
+++ b/src/test/compile-fail/vtable-res-trait-param.rs
@@ -24,7 +24,7 @@
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/debuginfo/var-captured-in-sendable-closure.rs b/src/test/debuginfo/var-captured-in-sendable-closure.rs
index aa269ed..b415546 100644
--- a/src/test/debuginfo/var-captured-in-sendable-closure.rs
+++ b/src/test/debuginfo/var-captured-in-sendable-closure.rs
@@ -40,7 +40,7 @@
// lldb-check:[...]$2 = 5
#![allow(unused_variables)]
-#![feature(unboxed_closures, box_syntax)]
+#![feature(box_syntax)]
#![feature(omit_gdb_pretty_printer_section)]
#![omit_gdb_pretty_printer_section]
diff --git a/src/test/debuginfo/var-captured-in-stack-closure.rs b/src/test/debuginfo/var-captured-in-stack-closure.rs
index 6def5cf..e60f964 100644
--- a/src/test/debuginfo/var-captured-in-stack-closure.rs
+++ b/src/test/debuginfo/var-captured-in-stack-closure.rs
@@ -69,7 +69,7 @@
// lldb-command:print *owned
// lldb-check:[...]$9 = 6
-#![feature(unboxed_closures, box_syntax)]
+#![feature(box_syntax)]
#![allow(unused_variables)]
#![feature(omit_gdb_pretty_printer_section)]
#![omit_gdb_pretty_printer_section]
diff --git a/src/test/compile-fail/feature-gate-rust-call.rs b/src/test/incremental/rlib_cross_crate/auxiliary/a.rs
similarity index 65%
rename from src/test/compile-fail/feature-gate-rust-call.rs
rename to src/test/incremental/rlib_cross_crate/auxiliary/a.rs
index 029a9ca..ff5fd63 100644
--- a/src/test/compile-fail/feature-gate-rust-call.rs
+++ b/src/test/incremental/rlib_cross_crate/auxiliary/a.rs
@@ -8,14 +8,18 @@
// 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
+// no-prefer-dynamic
-trait Foo {
- extern "rust-call" fn foo();
-}
+#![crate_type="rlib"]
-impl Foo for i32 {
- extern "rust-call" fn foo() { } //~ ERROR rust-call ABI is subject to change
-}
+#[cfg(rpass1)]
+pub type X = u32;
-fn main() { }
+#[cfg(rpass2)]
+pub type X = i32;
+
+// this version doesn't actually change anything:
+#[cfg(rpass3)]
+pub type X = i32;
+
+pub type Y = char;
diff --git a/src/test/incremental/rlib_cross_crate/b.rs b/src/test/incremental/rlib_cross_crate/b.rs
new file mode 100644
index 0000000..5539837
--- /dev/null
+++ b/src/test/incremental/rlib_cross_crate/b.rs
@@ -0,0 +1,38 @@
+// 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.
+
+// Same test as `type_alias_cross_crate`, but with
+// `no-prefer-dynamic`, ensuring that we test what happens when we
+// build rlibs (before we were only testing dylibs, which meant we
+// didn't realize we had to preserve a `bc` file as well).
+
+// aux-build:a.rs
+// revisions:rpass1 rpass2 rpass3
+// no-prefer-dynamic
+
+
+#![feature(rustc_attrs)]
+
+extern crate a;
+
+#[rustc_dirty(label="TypeckItemBody", cfg="rpass2")]
+#[rustc_clean(label="TypeckItemBody", cfg="rpass3")]
+pub fn use_X() -> u32 {
+ let x: a::X = 22;
+ x as u32
+}
+
+#[rustc_clean(label="TypeckItemBody", cfg="rpass2")]
+#[rustc_clean(label="TypeckItemBody", cfg="rpass3")]
+pub fn use_Y() {
+ let x: a::Y = 'c';
+}
+
+pub fn main() { }
diff --git a/src/test/incremental/spike-neg1.rs b/src/test/incremental/spike-neg1.rs
new file mode 100644
index 0000000..b00c68a
--- /dev/null
+++ b/src/test/incremental/spike-neg1.rs
@@ -0,0 +1,62 @@
+// 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.
+
+// A variant of the first "spike" test that serves to test the
+// `rustc_partition_reused` and `rustc_partition_translated` tests.
+// Here we change and say that the `x` module will be reused (when in
+// fact it will not), and then indicate that the test itself
+// should-fail (because an error will be reported, and hence the
+// revision rpass2 will not compile, despite being named rpass).
+
+// revisions:rpass1 rpass2
+// should-fail
+
+#![feature(rustc_attrs)]
+
+#![rustc_partition_reused(module="spike_neg1", cfg="rpass2")]
+#![rustc_partition_reused(module="spike_neg1-x", cfg="rpass2")] // this is wrong!
+#![rustc_partition_reused(module="spike_neg1-y", cfg="rpass2")]
+
+mod x {
+ pub struct X {
+ x: u32, y: u32,
+ }
+
+ #[cfg(rpass1)]
+ fn make() -> X {
+ X { x: 22, y: 0 }
+ }
+
+ #[cfg(rpass2)]
+ fn make() -> X {
+ X { x: 11, y: 11 }
+ }
+
+ pub fn new() -> X {
+ make()
+ }
+
+ pub fn sum(x: &X) -> u32 {
+ x.x + x.y
+ }
+}
+
+mod y {
+ use x;
+
+ pub fn assert_sum() -> bool {
+ let x = x::new();
+ x::sum(&x) == 22
+ }
+}
+
+pub fn main() {
+ y::assert_sum();
+}
diff --git a/src/test/incremental/spike-neg2.rs b/src/test/incremental/spike-neg2.rs
new file mode 100644
index 0000000..472d11d
--- /dev/null
+++ b/src/test/incremental/spike-neg2.rs
@@ -0,0 +1,62 @@
+// 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.
+
+// A variant of the first "spike" test that serves to test the
+// `rustc_partition_reused` and `rustc_partition_translated` tests.
+// Here we change and say that the `y` module will be translated (when
+// in fact it will not), and then indicate that the test itself
+// should-fail (because an error will be reported, and hence the
+// revision rpass2 will not compile, despite being named rpass).
+
+// revisions:rpass1 rpass2
+// should-fail
+
+#![feature(rustc_attrs)]
+
+#![rustc_partition_reused(module="spike_neg2", cfg="rpass2")]
+#![rustc_partition_translated(module="spike_neg2-x", cfg="rpass2")]
+#![rustc_partition_translated(module="spike_neg2-y", cfg="rpass2")] // this is wrong!
+
+mod x {
+ pub struct X {
+ x: u32, y: u32,
+ }
+
+ #[cfg(rpass1)]
+ fn make() -> X {
+ X { x: 22, y: 0 }
+ }
+
+ #[cfg(rpass2)]
+ fn make() -> X {
+ X { x: 11, y: 11 }
+ }
+
+ pub fn new() -> X {
+ make()
+ }
+
+ pub fn sum(x: &X) -> u32 {
+ x.x + x.y
+ }
+}
+
+mod y {
+ use x;
+
+ pub fn assert_sum() -> bool {
+ let x = x::new();
+ x::sum(&x) == 22
+ }
+}
+
+pub fn main() {
+ y::assert_sum();
+}
diff --git a/src/test/incremental/spike.rs b/src/test/incremental/spike.rs
new file mode 100644
index 0000000..68af20d
--- /dev/null
+++ b/src/test/incremental/spike.rs
@@ -0,0 +1,63 @@
+// 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.
+
+// A first "spike" for incremental compilation: here, we change the
+// content of the `make` function, and we find that we can reuse the
+// `y` module entirely (but not the `x` module).
+
+// revisions:rpass1 rpass2
+
+#![feature(rustc_attrs)]
+
+#![rustc_partition_reused(module="spike", cfg="rpass2")]
+#![rustc_partition_translated(module="spike-x", cfg="rpass2")]
+#![rustc_partition_reused(module="spike-y", cfg="rpass2")]
+
+mod x {
+ pub struct X {
+ x: u32, y: u32,
+ }
+
+ #[cfg(rpass1)]
+ fn make() -> X {
+ X { x: 22, y: 0 }
+ }
+
+ #[cfg(rpass2)]
+ fn make() -> X {
+ X { x: 11, y: 11 }
+ }
+
+ #[rustc_dirty(label="TypeckItemBody", cfg="rpass2")]
+ #[rustc_clean(label="ItemSignature", cfg="rpass2")]
+ pub fn new() -> X {
+ make()
+ }
+
+ #[rustc_clean(label="TypeckItemBody", cfg="rpass2")]
+ #[rustc_clean(label="ItemSignature", cfg="rpass2")]
+ pub fn sum(x: &X) -> u32 {
+ x.x + x.y
+ }
+}
+
+mod y {
+ use x;
+
+ #[rustc_clean(label="TypeckItemBody", cfg="rpass2")]
+ pub fn assert_sum() -> bool {
+ let x = x::new();
+ x::sum(&x) == 22
+ }
+}
+
+pub fn main() {
+ y::assert_sum();
+}
diff --git a/src/test/run-make/execution-engine/Makefile b/src/test/run-make/execution-engine/Makefile
deleted file mode 100644
index 4c818cd..0000000
--- a/src/test/run-make/execution-engine/Makefile
+++ /dev/null
@@ -1,21 +0,0 @@
--include ../tools.mk
-
-# FIXME: ignore freebsd
-# This is a basic test of LLVM ExecutionEngine functionality using compiled
-# Rust code built using the `rustc` crate.
-
-ifeq ($(filter executionengine,$(LLVM_COMPONENTS)),executionengine)
-
-ifneq ($(shell uname),FreeBSD)
-all:
- $(RUSTC) test.rs
- $(call RUN,test $(RUSTC))
-else
-all:
-
-endif
-
-else
-all:
-
-endif
diff --git a/src/test/run-make/execution-engine/test.rs b/src/test/run-make/execution-engine/test.rs
deleted file mode 100644
index 2e90b51..0000000
--- a/src/test/run-make/execution-engine/test.rs
+++ /dev/null
@@ -1,277 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![feature(rustc_private)]
-#![feature(libc)]
-
-extern crate libc;
-extern crate rustc;
-extern crate rustc_driver;
-extern crate rustc_lint;
-extern crate rustc_llvm as llvm;
-extern crate rustc_metadata;
-extern crate rustc_resolve;
-extern crate rustc_errors;
-extern crate rustc_errors as errors;
-#[macro_use] extern crate syntax;
-
-use std::ffi::{CStr, CString};
-use std::mem::transmute;
-use std::path::PathBuf;
-use std::rc::Rc;
-use std::thread::Builder;
-
-use rustc::dep_graph::DepGraph;
-use rustc::hir::map as ast_map;
-use rustc::middle::cstore::LinkagePreference;
-use rustc::ty;
-use rustc::session::config::{self, basic_options, build_configuration, Input, Options};
-use rustc::session::build_session;
-use rustc_driver::{driver, abort_on_err};
-use rustc_resolve::MakeGlobMap;
-use rustc_metadata::cstore::CStore;
-use libc::c_void;
-
-use rustc_errors::registry::Registry;
-
-fn main() {
- // Currently trips an assertion on i686-msvc, presumably because the support
- // in LLVM is a little young.
- if cfg!(target_env = "msvc") && cfg!(target_arch = "x86") {
- return
- }
-
- let program = r#"
- #[no_mangle]
- pub static TEST_STATIC: i32 = 42;
- "#;
-
- let program2 = r#"
- #[no_mangle]
- pub fn test_add(a: i32, b: i32) -> i32 { a + b }
- "#;
-
- let mut path = match std::env::args().nth(2) {
- Some(path) => PathBuf::from(&path),
- None => panic!("missing rustc path")
- };
-
- // Remove two segments from rustc path to get sysroot.
- path.pop();
- path.pop();
-
- let mut ee = ExecutionEngine::new(program, path);
-
- let test_static = match ee.get_global("TEST_STATIC") {
- Some(g) => g as *const i32,
- None => panic!("failed to get global")
- };
-
- assert_eq!(unsafe { *test_static }, 42);
-
- ee.add_module(program2);
-
- let test_add: fn(i32, i32) -> i32;
-
- test_add = match ee.get_function("test_add") {
- Some(f) => unsafe { transmute(f) },
- None => panic!("failed to get function")
- };
-
- assert_eq!(test_add(1, 2), 3);
-}
-
-struct ExecutionEngine {
- ee: llvm::ExecutionEngineRef,
- modules: Vec<llvm::ModuleRef>,
- sysroot: PathBuf,
-}
-
-impl ExecutionEngine {
- pub fn new(program: &str, sysroot: PathBuf) -> ExecutionEngine {
- let (llmod, deps) = compile_program(program, sysroot.clone())
- .expect("failed to compile program");
-
- let ee = unsafe { llvm::LLVMBuildExecutionEngine(llmod) };
-
- if ee.is_null() {
- panic!("Failed to create ExecutionEngine: {}", llvm_error());
- }
-
- let ee = ExecutionEngine{
- ee: ee,
- modules: vec![llmod],
- sysroot: sysroot,
- };
-
- ee.load_deps(&deps);
- ee
- }
-
- pub fn add_module(&mut self, program: &str) {
- let (llmod, deps) = compile_program(program, self.sysroot.clone())
- .expect("failed to compile program in add_module");
-
- unsafe { llvm::LLVMExecutionEngineAddModule(self.ee, llmod); }
-
- self.modules.push(llmod);
- self.load_deps(&deps);
- }
-
- /// Returns a raw pointer to the named function.
- pub fn get_function(&mut self, name: &str) -> Option<*const c_void> {
- let s = CString::new(name.as_bytes()).unwrap();
-
- for &m in &self.modules {
- let fv = unsafe { llvm::LLVMGetNamedFunction(m, s.as_ptr()) };
-
- if !fv.is_null() {
- let fp = unsafe { llvm::LLVMGetPointerToGlobal(self.ee, fv) };
-
- assert!(!fp.is_null());
- return Some(fp);
- }
- }
- None
- }
-
- /// Returns a raw pointer to the named global item.
- pub fn get_global(&mut self, name: &str) -> Option<*const c_void> {
- let s = CString::new(name.as_bytes()).unwrap();
-
- for &m in &self.modules {
- let gv = unsafe { llvm::LLVMGetNamedGlobal(m, s.as_ptr()) };
-
- if !gv.is_null() {
- let gp = unsafe { llvm::LLVMGetPointerToGlobal(self.ee, gv) };
-
- assert!(!gp.is_null());
- return Some(gp);
- }
- }
- None
- }
-
- /// Loads all dependencies of compiled code.
- /// Expects a series of paths to dynamic library files.
- fn load_deps(&self, deps: &[PathBuf]) {
- for path in deps {
- let s = match path.as_os_str().to_str() {
- Some(s) => s,
- None => panic!(
- "Could not convert crate path to UTF-8 string: {:?}", path)
- };
- let cs = CString::new(s).unwrap();
-
- let res = unsafe { llvm::LLVMRustLoadDynamicLibrary(cs.as_ptr()) };
-
- if res == 0 {
- panic!("Failed to load crate {:?}: {}",
- path.display(), llvm_error());
- }
- }
- }
-}
-
-impl Drop for ExecutionEngine {
- fn drop(&mut self) {
- unsafe { llvm::LLVMDisposeExecutionEngine(self.ee) };
- }
-}
-
-/// Returns last error from LLVM wrapper code.
-fn llvm_error() -> String {
- String::from_utf8_lossy(
- unsafe { CStr::from_ptr(llvm::LLVMRustGetLastError()).to_bytes() })
- .into_owned()
-}
-
-fn build_exec_options(sysroot: PathBuf) -> Options {
- let mut opts = basic_options();
-
- // librustc derives sysroot from the executable name.
- // Since we are not rustc, we must specify it.
- opts.maybe_sysroot = Some(sysroot);
-
- // Prefer faster build time
- opts.optimize = config::OptLevel::No;
-
- // Don't require a `main` function
- opts.crate_types = vec![config::CrateTypeDylib];
-
- opts
-}
-
-/// Compiles input up to phase 4, translation to LLVM.
-///
-/// Returns the LLVM `ModuleRef` and a series of paths to dynamic libraries
-/// for crates used in the given input.
-fn compile_program(input: &str, sysroot: PathBuf)
- -> Option<(llvm::ModuleRef, Vec<PathBuf>)> {
- let input = Input::Str {
- name: driver::anon_src(),
- input: input.to_string(),
- };
- let thread = Builder::new().name("compile_program".to_string());
-
- let handle = thread.spawn(move || {
- let opts = build_exec_options(sysroot);
- let dep_graph = DepGraph::new(opts.build_dep_graph());
- let cstore = Rc::new(CStore::new(&dep_graph));
- let sess = build_session(opts,
- &dep_graph,
- None,
- Registry::new(&rustc::DIAGNOSTICS),
- cstore.clone());
- rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
-
- let cfg = build_configuration(&sess);
-
- let id = "input".to_string();
-
- let krate = panictry!(driver::phase_1_parse_input(&sess, cfg, &input));
-
- let driver::ExpansionResult { defs, analysis, resolutions, mut hir_forest, .. } = {
- driver::phase_2_configure_and_expand(
- &sess, &cstore, krate, &id, None, MakeGlobMap::No, |_| Ok(()),
- ).expect("phase_2 returned `None`")
- };
-
- let arenas = ty::CtxtArenas::new();
- let ast_map = ast_map::map_crate(&mut hir_forest, defs);
-
- abort_on_err(driver::phase_3_run_analysis_passes(
- &sess, ast_map, analysis, resolutions, &arenas, &id,
- |tcx, mir_map, analysis, _| {
-
- let trans = driver::phase_4_translate_to_llvm(tcx, mir_map.unwrap(), analysis);
-
- let crates = tcx.sess.cstore.used_crates(LinkagePreference::RequireDynamic);
-
- // Collect crates used in the session.
- // Reverse order finds dependencies first.
- let deps = crates.into_iter().rev()
- .filter_map(|(_, p)| p).collect();
-
- assert_eq!(trans.modules.len(), 1);
- let llmod = trans.modules[0].llmod;
-
- // Workaround because raw pointers do not impl Send
- let modp = llmod as usize;
-
- (modp, deps)
- }), &sess)
- }).unwrap();
-
- match handle.join() {
- Ok((llmod, deps)) => Some((llmod as llvm::ModuleRef, deps)),
- Err(_) => None
- }
-}
diff --git a/src/test/run-make/llvm-phase/test.rs b/src/test/run-make/llvm-phase/test.rs
index 402b5ed..19e410f 100644
--- a/src/test/run-make/llvm-phase/test.rs
+++ b/src/test/run-make/llvm-phase/test.rs
@@ -13,11 +13,13 @@
extern crate rustc;
extern crate rustc_driver;
extern crate rustc_llvm;
+extern crate rustc_trans;
#[macro_use] extern crate syntax;
extern crate getopts;
use rustc_driver::{CompilerCalls, Compilation};
use rustc_driver::driver::CompileController;
+use rustc_trans::ModuleSource;
use rustc::session::Session;
use syntax::codemap::FileLoader;
use std::io;
@@ -51,7 +53,10 @@
state.session.abort_if_errors();
let trans = state.trans.unwrap();
assert_eq!(trans.modules.len(), 1);
- let rs_llmod = trans.modules[0].llmod;
+ let rs_llmod = match trans.modules[0].source {
+ ModuleSource::Preexisting(_) => unimplemented!(),
+ ModuleSource::Translated(llvm) => llvm.llmod,
+ };
unsafe { rustc_llvm::LLVMDumpModule(rs_llmod) };
});
cc
diff --git a/src/test/run-pass/coerce-match-calls.rs b/src/test/run-pass-valgrind/coerce-match-calls.rs
similarity index 100%
rename from src/test/run-pass/coerce-match-calls.rs
rename to src/test/run-pass-valgrind/coerce-match-calls.rs
diff --git a/src/test/run-pass/coerce-match.rs b/src/test/run-pass-valgrind/coerce-match.rs
similarity index 100%
rename from src/test/run-pass/coerce-match.rs
rename to src/test/run-pass-valgrind/coerce-match.rs
diff --git a/src/test/run-pass/assignability-trait.rs b/src/test/run-pass/assignability-trait.rs
index 0ee4600..c364240 100644
--- a/src/test/run-pass/assignability-trait.rs
+++ b/src/test/run-pass/assignability-trait.rs
@@ -12,9 +12,6 @@
// making method calls, but only if there aren't any matches without
// it.
-
-#![feature(unboxed_closures)]
-
trait iterable<A> {
fn iterate<F>(&self, blk: F) -> bool where F: FnMut(&A) -> bool;
}
diff --git a/src/test/run-pass/associated-types-impl-redirect.rs b/src/test/run-pass/associated-types-impl-redirect.rs
index 4082580..3e34367 100644
--- a/src/test/run-pass/associated-types-impl-redirect.rs
+++ b/src/test/run-pass/associated-types-impl-redirect.rs
@@ -14,7 +14,7 @@
// for `ByRef`. The right answer was to consider the result ambiguous
// until more type information was available.
-#![feature(lang_items, unboxed_closures)]
+#![feature(lang_items)]
#![no_implicit_prelude]
use std::marker::Sized;
diff --git a/src/test/run-pass/associated-types-where-clause-impl-ambiguity.rs b/src/test/run-pass/associated-types-where-clause-impl-ambiguity.rs
index 082ad53..ef1225d 100644
--- a/src/test/run-pass/associated-types-where-clause-impl-ambiguity.rs
+++ b/src/test/run-pass/associated-types-where-clause-impl-ambiguity.rs
@@ -14,7 +14,7 @@
// for `ByRef`. The right answer was to consider the result ambiguous
// until more type information was available.
-#![feature(lang_items, unboxed_closures)]
+#![feature(lang_items)]
#![no_implicit_prelude]
use std::marker::Sized;
diff --git a/src/test/run-pass/auxiliary/issue-18711.rs b/src/test/run-pass/auxiliary/issue-18711.rs
index a29dcc0..c247c02 100644
--- a/src/test/run-pass/auxiliary/issue-18711.rs
+++ b/src/test/run-pass/auxiliary/issue-18711.rs
@@ -8,7 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(unboxed_closures)]
#![crate_type = "rlib"]
pub fn inner<F>(f: F) -> F {
diff --git a/src/test/run-pass/auxiliary/unboxed-closures-cross-crate.rs b/src/test/run-pass/auxiliary/unboxed-closures-cross-crate.rs
index dac20dd..dc9798a 100644
--- a/src/test/run-pass/auxiliary/unboxed-closures-cross-crate.rs
+++ b/src/test/run-pass/auxiliary/unboxed-closures-cross-crate.rs
@@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(unboxed_closures)]
-
use std::ops::Add;
#[inline]
diff --git a/src/test/run-pass/backtrace.rs b/src/test/run-pass/backtrace.rs
index ad38dc8..f1ce17c 100644
--- a/src/test/run-pass/backtrace.rs
+++ b/src/test/run-pass/backtrace.rs
@@ -46,19 +46,7 @@
}
fn expected(fn_name: &str) -> String {
- // FIXME(#32481)
- //
- // On windows, we read the function name from debuginfo using some
- // system APIs. For whatever reason, these APIs seem to use the
- // "name" field, which is only the "relative" name, not the full
- // name with namespace info, so we just see `foo` and not
- // `backtrace::foo` as we see on linux (which uses the linkage
- // name).
- if cfg!(windows) && cfg!(target_env = "msvc") {
- format!(" - {}", fn_name)
- } else {
- format!(" - backtrace::{}", fn_name)
- }
+ format!(" - backtrace::{}", fn_name)
}
fn runtest(me: &str) {
diff --git a/src/test/run-pass/bare-fn-implements-fn-mut.rs b/src/test/run-pass/bare-fn-implements-fn-mut.rs
index e8118e9..30a11ca 100644
--- a/src/test/run-pass/bare-fn-implements-fn-mut.rs
+++ b/src/test/run-pass/bare-fn-implements-fn-mut.rs
@@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(unboxed_closures)]
-
use std::ops::FnMut;
fn call_f<F:FnMut()>(mut f: F) {
diff --git a/src/test/run-pass/borrowck/borrowck-move-by-capture-ok.rs b/src/test/run-pass/borrowck/borrowck-move-by-capture-ok.rs
index bbc668f..158594d 100644
--- a/src/test/run-pass/borrowck/borrowck-move-by-capture-ok.rs
+++ b/src/test/run-pass/borrowck/borrowck-move-by-capture-ok.rs
@@ -11,7 +11,6 @@
#![allow(unknown_features)]
#![feature(box_syntax)]
-#![feature(unboxed_closures)]
pub fn main() {
let bar: Box<_> = box 3;
diff --git a/src/test/run-pass/capture-clauses-unboxed-closures.rs b/src/test/run-pass/capture-clauses-unboxed-closures.rs
index 5e7d5aa..e8a9dc7 100644
--- a/src/test/run-pass/capture-clauses-unboxed-closures.rs
+++ b/src/test/run-pass/capture-clauses-unboxed-closures.rs
@@ -8,9 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-#![feature(unboxed_closures)]
-
fn each<'a,T,F:FnMut(&'a T)>(x: &'a [T], mut f: F) {
for val in x {
f(val)
diff --git a/src/test/run-pass/closure-bounds-can-capture-chan.rs b/src/test/run-pass/closure-bounds-can-capture-chan.rs
index dbbac8a..5268e85 100644
--- a/src/test/run-pass/closure-bounds-can-capture-chan.rs
+++ b/src/test/run-pass/closure-bounds-can-capture-chan.rs
@@ -10,8 +10,6 @@
// pretty-expanded FIXME #23616
-#![feature(unboxed_closures)]
-
use std::sync::mpsc::channel;
fn foo<F:FnOnce()+Send>(blk: F) {
diff --git a/src/test/run-pass/closure-reform.rs b/src/test/run-pass/closure-reform.rs
index 0fa67e8..a37733b 100644
--- a/src/test/run-pass/closure-reform.rs
+++ b/src/test/run-pass/closure-reform.rs
@@ -11,8 +11,6 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
-#![feature(unboxed_closures)]
-
fn call_it<F>(f: F)
where F : FnOnce(String) -> String
{
diff --git a/src/test/run-pass/hashmap-memory.rs b/src/test/run-pass/hashmap-memory.rs
index 4dae113..3f6f1aa 100644
--- a/src/test/run-pass/hashmap-memory.rs
+++ b/src/test/run-pass/hashmap-memory.rs
@@ -9,7 +9,7 @@
// except according to those terms.
#![allow(unknown_features)]
-#![feature(unboxed_closures, std_misc)]
+#![feature(std_misc)]
/**
A somewhat reduced test case to expose some Valgrind issues.
diff --git a/src/test/run-pass/hrtb-parse.rs b/src/test/run-pass/hrtb-parse.rs
index ecd0bc6..cdffaef 100644
--- a/src/test/run-pass/hrtb-parse.rs
+++ b/src/test/run-pass/hrtb-parse.rs
@@ -13,7 +13,6 @@
// pretty-expanded FIXME #23616
-#![feature(unboxed_closures)]
#![allow(unused_variables)]
#![allow(dead_code)]
diff --git a/src/test/run-pass/hrtb-precedence-of-plus-where-clause.rs b/src/test/run-pass/hrtb-precedence-of-plus-where-clause.rs
index bc00a07..46ea256 100644
--- a/src/test/run-pass/hrtb-precedence-of-plus-where-clause.rs
+++ b/src/test/run-pass/hrtb-precedence-of-plus-where-clause.rs
@@ -10,8 +10,6 @@
// pretty-expanded FIXME #23616
-#![feature(unboxed_closures)]
-
// Test that `F : Fn(isize) -> isize + Send` is interpreted as two
// distinct bounds on `F`.
diff --git a/src/test/run-pass/hrtb-precedence-of-plus.rs b/src/test/run-pass/hrtb-precedence-of-plus.rs
index 892f2f1..d93e52a 100644
--- a/src/test/run-pass/hrtb-precedence-of-plus.rs
+++ b/src/test/run-pass/hrtb-precedence-of-plus.rs
@@ -11,7 +11,6 @@
// pretty-expanded FIXME #23616
#![allow(unknown_features)]
-#![feature(unboxed_closures)]
// Test that `Fn(isize) -> isize + 'static` parses as `(Fn(isize) -> isize) +
// 'static` and not `Fn(isize) -> (isize + 'static)`. The latter would
diff --git a/src/test/run-pass/hrtb-trait-object-paren-notation.rs b/src/test/run-pass/hrtb-trait-object-paren-notation.rs
index fefbd00..5b9d4a8 100644
--- a/src/test/run-pass/hrtb-trait-object-paren-notation.rs
+++ b/src/test/run-pass/hrtb-trait-object-paren-notation.rs
@@ -8,9 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-#![feature(unboxed_closures)]
-
// A basic test of using a higher-ranked trait bound.
trait FnLike<A,R> {
diff --git a/src/test/run-pass/hrtb-unboxed-closure-trait.rs b/src/test/run-pass/hrtb-unboxed-closure-trait.rs
index 008e7dd..6666b61 100644
--- a/src/test/run-pass/hrtb-unboxed-closure-trait.rs
+++ b/src/test/run-pass/hrtb-unboxed-closure-trait.rs
@@ -10,8 +10,6 @@
// Test HRTB used with the `Fn` trait.
-#![feature(unboxed_closures)]
-
fn foo<F:Fn(&isize)>(f: F) {
let x = 22;
f(&x);
diff --git a/src/test/run-pass/ifmt.rs b/src/test/run-pass/ifmt.rs
index ed56519..8b5536d 100644
--- a/src/test/run-pass/ifmt.rs
+++ b/src/test/run-pass/ifmt.rs
@@ -70,15 +70,15 @@
t!(format!("{}", '☃'), "☃");
t!(format!("{}", 10), "10");
t!(format!("{}", 10_usize), "10");
- t!(format!("{:?}", '☃'), "'\\u{2603}'");
+ t!(format!("{:?}", '☃'), "'☃'");
t!(format!("{:?}", 10), "10");
t!(format!("{:?}", 10_usize), "10");
t!(format!("{:?}", "true"), "\"true\"");
t!(format!("{:?}", "foo\nbar"), "\"foo\\nbar\"");
t!(format!("{:?}", "foo\n\"bar\"\r\n\'baz\'\t\\qux\\"),
r#""foo\n\"bar\"\r\n\'baz\'\t\\qux\\""#);
- t!(format!("{:?}", "foo\0bar\x01baz\u{3b1}q\u{75}x"),
- r#""foo\u{0}bar\u{1}baz\u{3b1}qux""#);
+ t!(format!("{:?}", "foo\0bar\x01baz\u{7f}q\u{75}x"),
+ r#""foo\u{0}bar\u{1}baz\u{7f}qux""#);
t!(format!("{:o}", 10_usize), "12");
t!(format!("{:x}", 10_usize), "a");
t!(format!("{:X}", 10_usize), "A");
diff --git a/src/test/run-pass/issue-10718.rs b/src/test/run-pass/issue-10718.rs
index 0a6e454..fedd94e 100644
--- a/src/test/run-pass/issue-10718.rs
+++ b/src/test/run-pass/issue-10718.rs
@@ -10,8 +10,6 @@
// pretty-expanded FIXME #23616
-#![feature(unboxed_closures)]
-
fn f<F:FnOnce()>(p: F) {
p();
}
diff --git a/src/test/run-pass/issue-14936.rs b/src/test/run-pass/issue-14936.rs
index 5f8e7cb..428d4e4 100644
--- a/src/test/run-pass/issue-14936.rs
+++ b/src/test/run-pass/issue-14936.rs
@@ -28,7 +28,8 @@
unsafe {
asm!("mov ($1), $0"
: $output_constraint (*wrap(&mut x, "out", &mut history))
- : "r"(&wrap(y, "in", &mut history)));
+ : "r"(&wrap(y, "in", &mut history))
+ :: "volatile");
}
assert_eq!((x,y), (1,1));
let b: &[_] = &["out", "in"];
diff --git a/src/test/run-pass/issue-16560.rs b/src/test/run-pass/issue-16560.rs
index 596f0d2..e91569f 100644
--- a/src/test/run-pass/issue-16560.rs
+++ b/src/test/run-pass/issue-16560.rs
@@ -10,8 +10,6 @@
// ignore-emscripten no threads support
-#![feature(unboxed_closures)]
-
use std::thread;
use std::mem;
diff --git a/src/test/run-pass/issue-16668.rs b/src/test/run-pass/issue-16668.rs
index 786c701..0fd9965 100644
--- a/src/test/run-pass/issue-16668.rs
+++ b/src/test/run-pass/issue-16668.rs
@@ -11,7 +11,6 @@
// ignore-pretty
#![allow(unknown_features)]
-#![feature(unboxed_closures)]
struct Parser<'a, I, O> {
parse: Box<FnMut(I) -> Result<O, String> + 'a>
diff --git a/src/test/run-pass/issue-16774.rs b/src/test/run-pass/issue-16774.rs
index 627717a..9ec5910 100644
--- a/src/test/run-pass/issue-16774.rs
+++ b/src/test/run-pass/issue-16774.rs
@@ -12,7 +12,6 @@
#![allow(unknown_features)]
#![feature(box_syntax)]
#![feature(box_patterns)]
-#![feature(unboxed_closures)]
use std::ops::{Deref, DerefMut};
diff --git a/src/test/run-pass/issue-17816.rs b/src/test/run-pass/issue-17816.rs
index 8e3cb41..a9aa4cd 100644
--- a/src/test/run-pass/issue-17816.rs
+++ b/src/test/run-pass/issue-17816.rs
@@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(unboxed_closures)]
-
use std::marker::PhantomData;
fn main() {
diff --git a/src/test/run-pass/issue-18652.rs b/src/test/run-pass/issue-18652.rs
index 8ab645e..cea0bea 100644
--- a/src/test/run-pass/issue-18652.rs
+++ b/src/test/run-pass/issue-18652.rs
@@ -12,9 +12,6 @@
// once closure as an optimization by trans. This used to hit an
// incorrect assert.
-
-#![feature(unboxed_closures)]
-
fn main() {
let x = 2u8;
let y = 3u8;
diff --git a/src/test/run-pass/issue-18685.rs b/src/test/run-pass/issue-18685.rs
index e4537e1..b569dbc 100644
--- a/src/test/run-pass/issue-18685.rs
+++ b/src/test/run-pass/issue-18685.rs
@@ -13,8 +13,6 @@
// pretty-expanded FIXME #23616
-#![feature(unboxed_closures)]
-
trait Tr {
fn foo(&self);
diff --git a/src/test/run-pass/issue-18711.rs b/src/test/run-pass/issue-18711.rs
index 277ad32..8239d74 100644
--- a/src/test/run-pass/issue-18711.rs
+++ b/src/test/run-pass/issue-18711.rs
@@ -13,8 +13,6 @@
// pretty-expanded FIXME #23616
-#![feature(unboxed_closures)]
-
// aux-build:issue-18711.rs
extern crate issue_18711 as issue;
diff --git a/src/test/run-pass/issue-19127.rs b/src/test/run-pass/issue-19127.rs
index c5eb506..8d16991 100644
--- a/src/test/run-pass/issue-19127.rs
+++ b/src/test/run-pass/issue-19127.rs
@@ -10,8 +10,6 @@
// pretty-expanded FIXME #23616
-#![feature(unboxed_closures)]
-
fn foo<T, F: FnOnce(T) -> T>(f: F) {}
fn id<'a>(input: &'a u8) -> &'a u8 { input }
diff --git a/src/test/run-pass/issue-19135.rs b/src/test/run-pass/issue-19135.rs
index 5e6dd56..ca20981 100644
--- a/src/test/run-pass/issue-19135.rs
+++ b/src/test/run-pass/issue-19135.rs
@@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(unboxed_closures)]
-
use std::marker::PhantomData;
#[derive(Debug)]
diff --git a/src/test/run-pass/issue-28950.rs b/src/test/run-pass/issue-28950.rs
index f01ce46..efce148 100644
--- a/src/test/run-pass/issue-28950.rs
+++ b/src/test/run-pass/issue-28950.rs
@@ -8,6 +8,9 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// compile-flags: -Z orbit=off
+// (blows the stack with MIR trans and no optimizations)
+
// Tests that the `vec!` macro does not overflow the stack when it is
// given data larger than the stack.
diff --git a/src/test/run-pass/issue-34932.rs b/src/test/run-pass/issue-34932.rs
new file mode 100644
index 0000000..e83939e
--- /dev/null
+++ b/src/test/run-pass/issue-34932.rs
@@ -0,0 +1,23 @@
+// 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.
+
+// compile-flags:--test
+// rustc-env:RUSTC_BOOTSTRAP_KEY=
+// ignore-pretty : (#23623) problems when ending with // comments
+
+#![cfg(any())] // This test should be configured away
+#![feature(rustc_attrs)] // Test that this is allowed on stable/beta
+#![feature(iter_arith_traits)] // Test that this is not unused
+#![deny(unused_features)]
+
+#[test]
+fn dummy() {
+ let () = "this should not reach type-checking";
+}
diff --git a/src/test/compile-fail/feature-gate-abi-vectorcall.rs b/src/test/run-pass/mir_cross_crate.rs
similarity index 60%
copy from src/test/compile-fail/feature-gate-abi-vectorcall.rs
copy to src/test/run-pass/mir_cross_crate.rs
index 79f3c8d..cc239d9 100644
--- a/src/test/compile-fail/feature-gate-abi-vectorcall.rs
+++ b/src/test/run-pass/mir_cross_crate.rs
@@ -8,12 +8,21 @@
// 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();
-}
+// compile-flags: -Z orbit
+// Tests that -Z orbit affects functions from other crates.
-extern "vectorcall" fn baz() { //~ ERROR vectorcall is experimental and subject to change
+#![feature(unsafe_no_drop_flag)]
+
+#[unsafe_no_drop_flag]
+struct Foo;
+
+impl Drop for Foo {
+ fn drop(&mut self) {
+ panic!("MIR trans is not enabled for mem::forget");
+ }
}
fn main() {
+ let x = Foo;
+ std::mem::forget(x);
}
diff --git a/src/test/run-pass/mir_trans_calls.rs b/src/test/run-pass/mir_trans_calls.rs
index ca3294a..7ff684a 100644
--- a/src/test/run-pass/mir_trans_calls.rs
+++ b/src/test/run-pass/mir_trans_calls.rs
@@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(rustc_attrs, unboxed_closures, fn_traits)]
+#![feature(rustc_attrs, fn_traits)]
#[rustc_mir]
fn test1(a: isize, b: (i32, i32), c: &[i32]) -> (isize, (i32, i32), &[i32]) {
diff --git a/src/test/run-pass/myriad-closures.rs b/src/test/run-pass/myriad-closures.rs
new file mode 100644
index 0000000..d2c9a5d
--- /dev/null
+++ b/src/test/run-pass/myriad-closures.rs
@@ -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);
+}
diff --git a/src/test/run-pass/simd-upgraded.rs b/src/test/run-pass/simd-upgraded.rs
new file mode 100644
index 0000000..821a505
--- /dev/null
+++ b/src/test/run-pass/simd-upgraded.rs
@@ -0,0 +1,30 @@
+// 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.
+
+// Test that removed LLVM SIMD intrinsics continue
+// to work via the "AutoUpgrade" mechanism.
+
+#![feature(cfg_target_feature, repr_simd)]
+#![feature(platform_intrinsics, stmt_expr_attributes)]
+
+#[repr(simd)]
+#[derive(PartialEq, Debug)]
+struct i16x8(i16, i16, i16, i16, i16, i16, i16, i16);
+
+fn main() {
+ #[cfg(target_feature = "sse2")] unsafe {
+ extern "platform-intrinsic" {
+ fn x86_mm_min_epi16(x: i16x8, y: i16x8) -> i16x8;
+ }
+ assert_eq!(x86_mm_min_epi16(i16x8(0, 1, 2, 3, 4, 5, 6, 7),
+ i16x8(7, 6, 5, 4, 3, 2, 1, 0)),
+ i16x8(0, 1, 2, 3, 3, 2, 1, 0));
+ };
+}
diff --git a/src/test/run-pass/sync-send-iterators-in-libcore.rs b/src/test/run-pass/sync-send-iterators-in-libcore.rs
index 9317899..d12bdf1 100644
--- a/src/test/run-pass/sync-send-iterators-in-libcore.rs
+++ b/src/test/run-pass/sync-send-iterators-in-libcore.rs
@@ -67,7 +67,7 @@
fn main() {
// for char.rs
- all_sync_send!("Я", escape_default, escape_unicode);
+ all_sync_send!("Я", escape_debug, escape_default, escape_unicode);
// for iter.rs
all_sync_send_mutable_ref!([1], iter);
diff --git a/src/test/run-pass/tcp-stress.rs b/src/test/run-pass/tcp-stress.rs
index dfc8649..0ba019c 100644
--- a/src/test/run-pass/tcp-stress.rs
+++ b/src/test/run-pass/tcp-stress.rs
@@ -21,6 +21,8 @@
use std::time::Duration;
use std::thread::{self, Builder};
+const TARGET_CNT: usize = 200;
+
fn main() {
// This test has a chance to time out, try to not let it time out
thread::spawn(move|| -> () {
@@ -42,8 +44,9 @@
});
let (tx, rx) = channel();
+
let mut spawned_cnt = 0;
- for _ in 0..1000 {
+ for _ in 0..TARGET_CNT {
let tx = tx.clone();
let res = Builder::new().stack_size(64 * 1024).spawn(move|| {
match TcpStream::connect(addr) {
@@ -66,6 +69,6 @@
for _ in 0..spawned_cnt {
rx.recv().unwrap();
}
- assert_eq!(spawned_cnt, 1000);
+ assert_eq!(spawned_cnt, TARGET_CNT);
process::exit(0);
}
diff --git a/src/test/run-pass/trait-bounds-in-arc.rs b/src/test/run-pass/trait-bounds-in-arc.rs
index 24dc73d..0de6fbc 100644
--- a/src/test/run-pass/trait-bounds-in-arc.rs
+++ b/src/test/run-pass/trait-bounds-in-arc.rs
@@ -16,7 +16,6 @@
#![allow(unknown_features)]
#![feature(box_syntax, std_misc)]
-#![feature(unboxed_closures)]
use std::sync::Arc;
use std::sync::mpsc::channel;
diff --git a/src/test/run-pass/type-id-higher-rank.rs b/src/test/run-pass/type-id-higher-rank.rs
index 3030833..c29fb5e 100644
--- a/src/test/run-pass/type-id-higher-rank.rs
+++ b/src/test/run-pass/type-id-higher-rank.rs
@@ -12,7 +12,7 @@
// Also acts as a regression test for an ICE (issue #19791)
-#![feature(unboxed_closures, core)]
+#![feature(core)]
use std::any::{Any, TypeId};
diff --git a/src/test/run-pass/unboxed-closures-all-traits.rs b/src/test/run-pass/unboxed-closures-all-traits.rs
index c28d4f4..201500d 100644
--- a/src/test/run-pass/unboxed-closures-all-traits.rs
+++ b/src/test/run-pass/unboxed-closures-all-traits.rs
@@ -8,8 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-#![feature(lang_items, unboxed_closures)]
+#![feature(lang_items)]
fn a<F:Fn(isize, isize) -> isize>(f: F) -> isize {
f(1, 2)
diff --git a/src/test/run-pass/unboxed-closures-blanket-fn-mut.rs b/src/test/run-pass/unboxed-closures-blanket-fn-mut.rs
index 54c9290..23ec0cb 100644
--- a/src/test/run-pass/unboxed-closures-blanket-fn-mut.rs
+++ b/src/test/run-pass/unboxed-closures-blanket-fn-mut.rs
@@ -10,8 +10,7 @@
// Test that you can supply `&F` where `F: FnMut()`.
-
-#![feature(lang_items, unboxed_closures)]
+#![feature(lang_items)]
fn a<F:FnMut() -> i32>(mut f: F) -> i32 {
f()
diff --git a/src/test/run-pass/unboxed-closures-blanket-fn.rs b/src/test/run-pass/unboxed-closures-blanket-fn.rs
index eb47447..2aa48e7 100644
--- a/src/test/run-pass/unboxed-closures-blanket-fn.rs
+++ b/src/test/run-pass/unboxed-closures-blanket-fn.rs
@@ -10,8 +10,7 @@
// Test that you can supply `&F` where `F: Fn()`.
-
-#![feature(lang_items, unboxed_closures)]
+#![feature(lang_items)]
fn a<F:Fn() -> i32>(f: F) -> i32 {
f()
diff --git a/src/test/run-pass/unboxed-closures-boxed.rs b/src/test/run-pass/unboxed-closures-boxed.rs
index 5dea6a7..069f268 100644
--- a/src/test/run-pass/unboxed-closures-boxed.rs
+++ b/src/test/run-pass/unboxed-closures-boxed.rs
@@ -10,7 +10,6 @@
#![allow(unknown_features)]
#![feature(box_syntax)]
-#![feature(unboxed_closures)]
use std::ops::FnMut;
diff --git a/src/test/run-pass/unboxed-closures-by-ref.rs b/src/test/run-pass/unboxed-closures-by-ref.rs
index e3ddfdb..b251215 100644
--- a/src/test/run-pass/unboxed-closures-by-ref.rs
+++ b/src/test/run-pass/unboxed-closures-by-ref.rs
@@ -8,9 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-#![feature(unboxed_closures)]
-
// Test by-ref capture of environment in unboxed closure types
fn call_fn<F: Fn()>(f: F) {
diff --git a/src/test/run-pass/unboxed-closures-call-fn-autoderef.rs b/src/test/run-pass/unboxed-closures-call-fn-autoderef.rs
index 64236ce..56c53bc 100644
--- a/src/test/run-pass/unboxed-closures-call-fn-autoderef.rs
+++ b/src/test/run-pass/unboxed-closures-call-fn-autoderef.rs
@@ -10,9 +10,6 @@
// Test that the call operator autoderefs when calling a bounded type parameter.
-
-#![feature(unboxed_closures)]
-
use std::ops::FnMut;
fn call_with_2(x: &fn(isize) -> isize) -> isize
diff --git a/src/test/run-pass/unboxed-closures-call-sugar-autoderef.rs b/src/test/run-pass/unboxed-closures-call-sugar-autoderef.rs
index 67ab84f..63667ec 100644
--- a/src/test/run-pass/unboxed-closures-call-sugar-autoderef.rs
+++ b/src/test/run-pass/unboxed-closures-call-sugar-autoderef.rs
@@ -10,9 +10,6 @@
// Test that the call operator autoderefs when calling a bounded type parameter.
-
-#![feature(unboxed_closures)]
-
use std::ops::FnMut;
fn call_with_2<F>(x: &mut F) -> isize
diff --git a/src/test/run-pass/unboxed-closures-call-sugar-object-autoderef.rs b/src/test/run-pass/unboxed-closures-call-sugar-object-autoderef.rs
index c820262..a92fb05 100644
--- a/src/test/run-pass/unboxed-closures-call-sugar-object-autoderef.rs
+++ b/src/test/run-pass/unboxed-closures-call-sugar-object-autoderef.rs
@@ -11,7 +11,6 @@
// Test that the call operator autoderefs when calling to an object type.
#![allow(unknown_features)]
-#![feature(unboxed_closures)]
use std::ops::FnMut;
diff --git a/src/test/run-pass/unboxed-closures-call-sugar-object.rs b/src/test/run-pass/unboxed-closures-call-sugar-object.rs
index 629da10..5dd2343 100644
--- a/src/test/run-pass/unboxed-closures-call-sugar-object.rs
+++ b/src/test/run-pass/unboxed-closures-call-sugar-object.rs
@@ -9,7 +9,6 @@
// except according to those terms.
#![allow(unknown_features)]
-#![feature(unboxed_closures)]
use std::ops::FnMut;
diff --git a/src/test/run-pass/unboxed-closures-counter-not-moved.rs b/src/test/run-pass/unboxed-closures-counter-not-moved.rs
index cb5f190..0b85916 100644
--- a/src/test/run-pass/unboxed-closures-counter-not-moved.rs
+++ b/src/test/run-pass/unboxed-closures-counter-not-moved.rs
@@ -10,7 +10,6 @@
// Test that we mutate a counter on the stack only when we expect to.
-
fn call<F>(f: F) where F : FnOnce() {
f();
}
diff --git a/src/test/run-pass/unboxed-closures-direct-sugary-call.rs b/src/test/run-pass/unboxed-closures-direct-sugary-call.rs
index c91aa6e..c8da4a6 100644
--- a/src/test/run-pass/unboxed-closures-direct-sugary-call.rs
+++ b/src/test/run-pass/unboxed-closures-direct-sugary-call.rs
@@ -10,8 +10,6 @@
// pretty-expanded FIXME #23616
-#![feature(unboxed_closures)]
-
fn main() {
let mut unboxed = || {};
unboxed();
diff --git a/src/test/run-pass/unboxed-closures-drop.rs b/src/test/run-pass/unboxed-closures-drop.rs
index 78f4905..57f2f87 100644
--- a/src/test/run-pass/unboxed-closures-drop.rs
+++ b/src/test/run-pass/unboxed-closures-drop.rs
@@ -11,9 +11,6 @@
// A battery of tests to ensure destructors of unboxed closure environments
// run at the right times.
-
-#![feature(unboxed_closures)]
-
static mut DROP_COUNT: usize = 0;
fn drop_count() -> usize {
diff --git a/src/test/run-pass/unboxed-closures-extern-fn.rs b/src/test/run-pass/unboxed-closures-extern-fn.rs
index 57acbae..eddb608 100644
--- a/src/test/run-pass/unboxed-closures-extern-fn.rs
+++ b/src/test/run-pass/unboxed-closures-extern-fn.rs
@@ -10,10 +10,6 @@
// Checks that extern fn pointers implement the full range of Fn traits.
-
-#![feature(unboxed_closures)]
-#![feature(unboxed_closures)]
-
use std::ops::{Fn,FnMut,FnOnce};
fn square(x: isize) -> isize { x * x }
diff --git a/src/test/run-pass/unboxed-closures-fn-as-fnmut-and-fnonce.rs b/src/test/run-pass/unboxed-closures-fn-as-fnmut-and-fnonce.rs
index 2e63c60..f90aced 100644
--- a/src/test/run-pass/unboxed-closures-fn-as-fnmut-and-fnonce.rs
+++ b/src/test/run-pass/unboxed-closures-fn-as-fnmut-and-fnonce.rs
@@ -11,7 +11,6 @@
// Checks that the Fn trait hierarchy rules permit
// any Fn trait to be used where Fn is implemented.
-
#![feature(unboxed_closures, fn_traits)]
use std::ops::{Fn,FnMut,FnOnce};
diff --git a/src/test/run-pass/unboxed-closures-fnmut-as-fnonce.rs b/src/test/run-pass/unboxed-closures-fnmut-as-fnonce.rs
index ce93fcaf..0a977ce 100644
--- a/src/test/run-pass/unboxed-closures-fnmut-as-fnonce.rs
+++ b/src/test/run-pass/unboxed-closures-fnmut-as-fnonce.rs
@@ -11,7 +11,6 @@
// Checks that the Fn trait hierarchy rules permit
// FnMut or FnOnce to be used where FnMut is implemented.
-
#![feature(unboxed_closures, fn_traits)]
struct S;
diff --git a/src/test/run-pass/unboxed-closures-generic.rs b/src/test/run-pass/unboxed-closures-generic.rs
index 47936ba..01c81ef 100644
--- a/src/test/run-pass/unboxed-closures-generic.rs
+++ b/src/test/run-pass/unboxed-closures-generic.rs
@@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(unboxed_closures)]
-
use std::ops::FnMut;
fn call_it<F:FnMut(i32,i32)->i32>(y: i32, mut f: F) -> i32 {
diff --git a/src/test/run-pass/unboxed-closures-infer-fnmut-calling-fnmut.rs b/src/test/run-pass/unboxed-closures-infer-fnmut-calling-fnmut.rs
index 2da899e..1783303 100644
--- a/src/test/run-pass/unboxed-closures-infer-fnmut-calling-fnmut.rs
+++ b/src/test/run-pass/unboxed-closures-infer-fnmut-calling-fnmut.rs
@@ -11,7 +11,6 @@
// Test that we are able to infer a suitable kind for this closure
// that is just called (`FnMut`).
-
fn main() {
let mut counter = 0;
diff --git a/src/test/run-pass/unboxed-closures-infer-fnmut-move.rs b/src/test/run-pass/unboxed-closures-infer-fnmut-move.rs
index 32fc343..7945272 100644
--- a/src/test/run-pass/unboxed-closures-infer-fnmut-move.rs
+++ b/src/test/run-pass/unboxed-closures-infer-fnmut-move.rs
@@ -11,7 +11,6 @@
// Test that we are able to infer a suitable kind for this `move`
// closure that is just called (`FnMut`).
-
fn main() {
let mut counter = 0;
diff --git a/src/test/run-pass/unboxed-closures-infer-fnmut.rs b/src/test/run-pass/unboxed-closures-infer-fnmut.rs
index a8469f4..67f36b9 100644
--- a/src/test/run-pass/unboxed-closures-infer-fnmut.rs
+++ b/src/test/run-pass/unboxed-closures-infer-fnmut.rs
@@ -11,7 +11,6 @@
// Test that we are able to infer a suitable kind for this closure
// that is just called (`FnMut`).
-
fn main() {
let mut counter = 0;
diff --git a/src/test/run-pass/unboxed-closures-infer-kind.rs b/src/test/run-pass/unboxed-closures-infer-kind.rs
index fa66847..c04df7e 100644
--- a/src/test/run-pass/unboxed-closures-infer-kind.rs
+++ b/src/test/run-pass/unboxed-closures-infer-kind.rs
@@ -11,9 +11,6 @@
// Test that we can infer the "kind" of an unboxed closure based on
// the expected type.
-
-#![feature(unboxed_closures)]
-
// Test by-ref capture of environment in unboxed closure types
fn call_fn<F: Fn()>(f: F) {
diff --git a/src/test/run-pass/unboxed-closures-infer-upvar.rs b/src/test/run-pass/unboxed-closures-infer-upvar.rs
index f242314..1401fe7 100644
--- a/src/test/run-pass/unboxed-closures-infer-upvar.rs
+++ b/src/test/run-pass/unboxed-closures-infer-upvar.rs
@@ -11,7 +11,6 @@
// Test that the type variable in the type(`Vec<_>`) of a closed over
// variable does not interfere with type inference.
-
fn f<F: FnMut()>(mut f: F) {
f();
}
diff --git a/src/test/run-pass/unboxed-closures-move-mutable.rs b/src/test/run-pass/unboxed-closures-move-mutable.rs
index 1aca317..a55b0a0 100644
--- a/src/test/run-pass/unboxed-closures-move-mutable.rs
+++ b/src/test/run-pass/unboxed-closures-move-mutable.rs
@@ -10,7 +10,6 @@
// pretty-expanded FIXME #23616
-#![feature(unboxed_closures)]
#![deny(unused_mut)]
// Test that mutating a mutable upvar in a capture-by-value unboxed
diff --git a/src/test/run-pass/unboxed-closures-move-some-upvars-in-by-ref-closure.rs b/src/test/run-pass/unboxed-closures-move-some-upvars-in-by-ref-closure.rs
index e2b2867..9966364 100644
--- a/src/test/run-pass/unboxed-closures-move-some-upvars-in-by-ref-closure.rs
+++ b/src/test/run-pass/unboxed-closures-move-some-upvars-in-by-ref-closure.rs
@@ -11,7 +11,6 @@
// Test that in a by-ref once closure we move some variables even as
// we capture others by mutable reference.
-
fn call<F>(f: F) where F : FnOnce() {
f();
}
diff --git a/src/test/run-pass/unboxed-closures-simple.rs b/src/test/run-pass/unboxed-closures-simple.rs
index ec34198..429afb9 100644
--- a/src/test/run-pass/unboxed-closures-simple.rs
+++ b/src/test/run-pass/unboxed-closures-simple.rs
@@ -8,9 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-#![feature(unboxed_closures)]
-
use std::ops::FnMut;
pub fn main() {
diff --git a/src/test/run-pass/unboxed-closures-single-word-env.rs b/src/test/run-pass/unboxed-closures-single-word-env.rs
index 166054e..3ed055a 100644
--- a/src/test/run-pass/unboxed-closures-single-word-env.rs
+++ b/src/test/run-pass/unboxed-closures-single-word-env.rs
@@ -11,9 +11,6 @@
// Ensures that single-word environments work right in unboxed closures.
// These take a different path in codegen.
-
-#![feature(unboxed_closures)]
-
fn a<F:Fn(isize, isize) -> isize>(f: F) -> isize {
f(1, 2)
}
diff --git a/src/test/run-pass/unboxed-closures-static-call-fn-once.rs b/src/test/run-pass/unboxed-closures-static-call-fn-once.rs
index e90a344..c13e951 100644
--- a/src/test/run-pass/unboxed-closures-static-call-fn-once.rs
+++ b/src/test/run-pass/unboxed-closures-static-call-fn-once.rs
@@ -10,8 +10,6 @@
// pretty-expanded FIXME #23616
-#![feature(unboxed_closures)]
-
fn main() {
let onetime = |x| x;
onetime(0);
diff --git a/src/test/run-pass/unboxed-closures-sugar-object.rs b/src/test/run-pass/unboxed-closures-sugar-object.rs
index 49b9b7f..b7d367f 100644
--- a/src/test/run-pass/unboxed-closures-sugar-object.rs
+++ b/src/test/run-pass/unboxed-closures-sugar-object.rs
@@ -10,9 +10,7 @@
// Test unboxed closure sugar used in object types.
-
#![allow(dead_code)]
-#![feature(unboxed_closures)]
struct Foo<T,U> {
t: T, u: U
diff --git a/src/test/run-pass/unboxed-closures-unique-type-id.rs b/src/test/run-pass/unboxed-closures-unique-type-id.rs
index 30c45fc..40071ec 100644
--- a/src/test/run-pass/unboxed-closures-unique-type-id.rs
+++ b/src/test/run-pass/unboxed-closures-unique-type-id.rs
@@ -19,9 +19,6 @@
//
// compile-flags: -g
-
-#![feature(unboxed_closures)]
-
use std::ptr;
pub fn replace_map<'a, T, F>(src: &mut T, prod: F) where F: FnOnce(T) -> T {
diff --git a/src/test/run-pass/unboxed-closures-zero-args.rs b/src/test/run-pass/unboxed-closures-zero-args.rs
index cb3a18a..9e6a7cc 100644
--- a/src/test/run-pass/unboxed-closures-zero-args.rs
+++ b/src/test/run-pass/unboxed-closures-zero-args.rs
@@ -10,8 +10,6 @@
// pretty-expanded FIXME #23616
-#![feature(unboxed_closures)]
-
fn main() {
let mut zero = || {};
let () = zero();
diff --git a/src/test/run-pass/where-clauses-unboxed-closures.rs b/src/test/run-pass/where-clauses-unboxed-closures.rs
index c509cbe..8a775ca 100644
--- a/src/test/run-pass/where-clauses-unboxed-closures.rs
+++ b/src/test/run-pass/where-clauses-unboxed-closures.rs
@@ -10,8 +10,6 @@
// pretty-expanded FIXME #23616
-#![feature(unboxed_closures)]
-
struct Bencher;
// ICE
diff --git a/src/test/compile-fail/feature-gate-abi-vectorcall.rs b/src/test/rustdoc/issue-34928.rs
similarity index 68%
copy from src/test/compile-fail/feature-gate-abi-vectorcall.rs
copy to src/test/rustdoc/issue-34928.rs
index 79f3c8d..b2104a0 100644
--- a/src/test/compile-fail/feature-gate-abi-vectorcall.rs
+++ b/src/test/rustdoc/issue-34928.rs
@@ -8,12 +8,9 @@
// 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();
-}
+#![crate_name = "foo"]
-extern "vectorcall" fn baz() { //~ ERROR vectorcall is experimental and subject to change
-}
+pub trait Bar {}
-fn main() {
-}
+// @has foo/struct.Foo.html '//pre' 'pub struct Foo<T>(pub T) where T: Bar;'
+pub struct Foo<T>(pub T) where T: Bar;
diff --git a/src/test/rustdoc/where.rs b/src/test/rustdoc/where.rs
index 91ec69d..d8dc115 100644
--- a/src/test/rustdoc/where.rs
+++ b/src/test/rustdoc/where.rs
@@ -12,7 +12,7 @@
pub trait MyTrait { fn dummy(&self) { } }
-// @has foo/struct.Alpha.html '//pre' "pub struct Alpha<A> where A: MyTrait"
+// @has foo/struct.Alpha.html '//pre' "pub struct Alpha<A>(_) where A: MyTrait"
pub struct Alpha<A>(A) where A: MyTrait;
// @has foo/trait.Bravo.html '//pre' "pub trait Bravo<B> where B: MyTrait"
pub trait Bravo<B> where B: MyTrait { fn get(&self, B: B); }
diff --git a/src/test/ui/codemap_tests/two_files.stderr b/src/test/ui/codemap_tests/two_files.stderr
index 6c388cd..cf3f187 100644
--- a/src/test/ui/codemap_tests/two_files.stderr
+++ b/src/test/ui/codemap_tests/two_files.stderr
@@ -2,12 +2,9 @@
--> $DIR/two_files.rs:16:6
|
16 | impl Bar for Baz { }
- | ^^^ `Bar` is not a trait
- |
- ::: $DIR/two_files_data.rs
+ | ^^^
|
-15 | type Bar = Foo;
- | --------------- type aliases cannot be used for traits
+ = note: type aliases cannot be used for traits
error: cannot continue compilation due to previous error
diff --git a/src/test/ui/mismatched_types/issue-26480.stderr b/src/test/ui/mismatched_types/issue-26480.stderr
index ff6920d..45638a6 100644
--- a/src/test/ui/mismatched_types/issue-26480.stderr
+++ b/src/test/ui/mismatched_types/issue-26480.stderr
@@ -5,7 +5,7 @@
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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 ())