os: osx
osx_image: xcode8.2
install: &osx_install_sccache >
- travis_retry curl -o /usr/local/bin/sccache https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-apple-darwin &&
+ travis_retry curl -o /usr/local/bin/sccache https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-19-sccache-x86_64-apple-darwin &&
chmod +x /usr/local/bin/sccache &&
travis_retry curl -o /usr/local/bin/stamp https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-17-stamp-x86_64-apple-darwin &&
chmod +x /usr/local/bin/stamp
# came from the mingw-w64 SourceForge download site. Unfortunately
# SourceForge is notoriously flaky, so we mirror it on our own infrastructure.
- MSYS_BITS: 32
- RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-ninja
+ RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu
SCRIPT: python x.py test
MINGW_URL: https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror
MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z
MINGW_DIR: mingw32
- MSYS_BITS: 64
SCRIPT: python x.py test
- RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-ninja
+ RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu
MINGW_URL: https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror
MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z
MINGW_DIR: mingw64
SCRIPT: python x.py dist
DEPLOY: 1
- MSYS_BITS: 32
- RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-extended --enable-ninja
+ RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-extended
SCRIPT: python x.py dist
MINGW_URL: https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror
MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z
DEPLOY: 1
- MSYS_BITS: 64
SCRIPT: python x.py dist
- RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-extended --enable-ninja
+ RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-extended
MINGW_URL: https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror
MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z
MINGW_DIR: mingw64
- set PATH=C:\Python27;%PATH%
# Download and install sccache
- - appveyor-retry appveyor DownloadFile https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-pc-windows-msvc
- - mv 2017-04-04-sccache-x86_64-pc-windows-msvc sccache.exe
+ - appveyor-retry appveyor DownloadFile https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-19-sccache-x86_64-pc-windows-msvc
+ - mv 2017-04-19-sccache-x86_64-pc-windows-msvc sccache.exe
- set PATH=%PATH%;%CD%
# Download and install ninja
# Note that this is originally from the github releases patch of Ninja
- appveyor-retry appveyor DownloadFile https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-15-ninja-win.zip
- 7z x 2017-03-15-ninja-win.zip
+ - set RUST_CONFIGURE_ARGS=%RUST_CONFIGURE_ARGS% --enable-ninja
# - set PATH=%PATH%;%CD% -- this already happens above for sccache
# Install InnoSetup to get `iscc` used to produce installers
on_failure:
- cat %CD%\sccache.log || exit 0
-cache:
- - "build/i686-pc-windows-msvc/llvm -> src/rustllvm/llvm-rebuild-trigger"
- - "build/x86_64-pc-windows-msvc/llvm -> src/rustllvm/llvm-rebuild-trigger"
- - "i686-pc-windows-msvc/llvm -> src/rustllvm/llvm-rebuild-trigger"
- - "x86_64-pc-windows-msvc/llvm -> src/rustllvm/llvm-rebuild-trigger"
-
branches:
only:
- auto
"gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)",
"getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
- "num_cpus 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num_cpus 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)",
"toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "num_cpus"
-version = "0.2.13"
+version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
"checksum mdbook 0.0.21 (registry+https://github.com/rust-lang/crates.io-index)" = "f1e2e9d848514dcfad4195788d0d42ae5153a477c191d75d5b84fab10f222fbd"
"checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4"
"checksum num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "e1cbfa3781f3fe73dc05321bed52a06d2d491eaa764c52335cf4399f046ece99"
-"checksum num_cpus 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "cee7e88156f3f9e19bdd598f8d6c9db7bf4078f99f8381f43a55b09648d1a6e3"
+"checksum num_cpus 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca313f1862c7ec3e0dfe8ace9fa91b1d9cb5c84ace3d00f5ec4216238e93c167"
"checksum open 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3478ed1686bd1300c8a981a940abc92b06fac9cbef747f4c668d4e032ff7b842"
"checksum pest 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0a6dda33d67c26f0aac90d324ab2eb7239c819fc7b2552fe9faa4fe88441edc8"
"checksum pulldown-cmark 0.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9ab1e588ef8efd702c7ed9d2bd774db5e6f4d878bb5a1a9f371828fbdff6973"
path = "bin/rustdoc.rs"
test = false
+[[bin]]
+name = "sccache-plus-cl"
+path = "bin/sccache-plus-cl.rs"
+test = false
+
[dependencies]
build_helper = { path = "../build_helper" }
cmake = "0.1.17"
filetime = "0.1"
-num_cpus = "0.2"
+num_cpus = "1.0"
toml = "0.1"
getopts = "0.2"
rustc-serialize = "0.3"
--- /dev/null
+// Copyright 2017 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 crate gcc;
+
+use std::env;
+use std::process::{self, Command};
+
+fn main() {
+ let target = env::var("SCCACHE_TARGET").unwrap();
+ // Locate the actual compiler that we're invoking
+ env::remove_var("CC");
+ env::remove_var("CXX");
+ let mut cfg = gcc::Config::new();
+ cfg.cargo_metadata(false)
+ .out_dir("/")
+ .target(&target)
+ .host(&target)
+ .opt_level(0)
+ .debug(false);
+ let compiler = cfg.get_compiler();
+
+ // Invoke sccache with said compiler
+ let sccache_path = env::var_os("SCCACHE_PATH").unwrap();
+ let mut cmd = Command::new(&sccache_path);
+ cmd.arg(compiler.path());
+ for &(ref k, ref v) in compiler.env() {
+ cmd.env(k, v);
+ }
+ for arg in env::args().skip(1) {
+ cmd.arg(arg);
+ }
+
+ let status = cmd.status().expect("failed to spawn");
+ process::exit(status.code().unwrap_or(2))
+}
env["DYLD_LIBRARY_PATH"] = os.path.join(self.bin_root(), "lib") + \
(os.pathsep + env["DYLD_LIBRARY_PATH"]) \
if "DYLD_LIBRARY_PATH" in env else ""
+ env["LIBRARY_PATH"] = os.path.join(self.bin_root(), "lib") + \
+ (os.pathsep + env["LIBRARY_PATH"]) \
+ if "LIBRARY_PATH" in env else ""
env["PATH"] = os.path.join(self.bin_root(), "bin") + \
os.pathsep + env["PATH"]
if not os.path.isfile(self.cargo()):
# The goal here is to come up with the same triple as LLVM would,
# at least for the subset of platforms we're willing to target.
if ostype == 'Linux':
- ostype = 'unknown-linux-gnu'
+ os = subprocess.check_output(['uname', '-o']).strip().decode(default_encoding)
+ if os == 'Android':
+ ostype = 'linux-android'
+ else:
+ ostype = 'unknown-linux-gnu'
elif ostype == 'FreeBSD':
ostype = 'unknown-freebsd'
elif ostype == 'DragonFly':
cputype = 'i686'
elif cputype in {'xscale', 'arm'}:
cputype = 'arm'
+ if ostype == 'linux-android':
+ ostype = 'linux-androideabi'
elif cputype == 'armv6l':
cputype = 'arm'
- ostype += 'eabihf'
+ if ostype == 'linux-android':
+ ostype = 'linux-androideabi'
+ else:
+ ostype += 'eabihf'
elif cputype in {'armv7l', 'armv8l'}:
cputype = 'armv7'
- ostype += 'eabihf'
- elif cputype == 'aarch64':
- cputype = 'aarch64'
- elif cputype == 'arm64':
+ if ostype == 'linux-android':
+ ostype = 'linux-androideabi'
+ else:
+ ostype += 'eabihf'
+ elif cputype in {'aarch64', 'arm64'}:
cputype = 'aarch64'
elif cputype == 'mips':
if sys.byteorder == 'big':
# support. You'll need to write a target specification at least, and most
# likely, teach rustc about the C ABI of the target. Get in touch with the
# Rust team and file an issue if you need assistance in porting!
-#targets = "X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend;MSP430;Sparc;NVPTX"
+#targets = "X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend;MSP430;Sparc;NVPTX;Hexagon"
# Cap the number of parallel linker invocations when compiling LLVM.
# This can be useful when building LLVM with debug info, which significantly
println!("Dist src");
- let name = pkgname(build, "rust-src");
- let image = tmpdir(build).join(format!("{}-image", name));
- let _ = fs::remove_dir_all(&image);
-
- let dst = image.join("lib/rustlib/src");
- let dst_src = dst.join("rust");
- t!(fs::create_dir_all(&dst_src));
+ // Make sure that the root folder of tarball has the correct name
+ let plain_name = format!("rustc-{}-src", build.rust_package_vers());
+ let plain_dst_src = tmpdir(build).join(&plain_name);
+ let _ = fs::remove_dir_all(&plain_dst_src);
+ t!(fs::create_dir_all(&plain_dst_src));
// This is the set of root paths which will become part of the source package
let src_files = [
// Copy the directories using our filter
for item in &src_dirs {
- let dst = &dst_src.join(item);
+ let dst = &plain_dst_src.join(item);
t!(fs::create_dir(dst));
cp_filtered(&build.src.join(item), dst, &filter_fn);
}
// Copy the files normally
for item in &src_files {
- copy(&build.src.join(item), &dst_src.join(item));
+ copy(&build.src.join(item), &plain_dst_src.join(item));
}
// If we're building from git sources, we need to vendor a complete distribution.
// Vendor all Cargo dependencies
let mut cmd = Command::new(&build.cargo);
cmd.arg("vendor")
- .current_dir(&dst_src.join("src"));
+ .current_dir(&plain_dst_src.join("src"));
build.run(&mut cmd);
}
+ // Create the version file
+ write_file(&plain_dst_src.join("version"), build.rust_version().as_bytes());
+
+ // Create plain source tarball
+ let tarball = rust_src_location(build);
+ if let Some(dir) = tarball.parent() {
+ t!(fs::create_dir_all(dir));
+ }
+ let mut cmd = Command::new("tar");
+ cmd.arg("-czf").arg(sanitize_sh(&tarball))
+ .arg(&plain_name)
+ .current_dir(tmpdir(build));
+ build.run(&mut cmd);
+
+
+ let name = pkgname(build, "rust-src");
+ let image = tmpdir(build).join(format!("{}-image", name));
+ let _ = fs::remove_dir_all(&image);
+
+ let dst = image.join("lib/rustlib/src");
+ let dst_src = dst.join("rust");
+ t!(fs::create_dir_all(&dst_src));
+
+ // This is the reduced set of paths which will become the rust-src component
+ // (essentially libstd and all of its path dependencies)
+ let std_src_dirs = [
+ "src/build_helper",
+ "src/liballoc",
+ "src/liballoc_jemalloc",
+ "src/liballoc_system",
+ "src/libcollections",
+ "src/libcompiler_builtins",
+ "src/libcore",
+ "src/liblibc",
+ "src/libpanic_abort",
+ "src/libpanic_unwind",
+ "src/librand",
+ "src/librustc_asan",
+ "src/librustc_lsan",
+ "src/librustc_msan",
+ "src/librustc_tsan",
+ "src/libstd",
+ "src/libstd_unicode",
+ "src/libunwind",
+ "src/rustc/libc_shim",
+ ];
+
+ for item in &std_src_dirs {
+ let dst = &dst_src.join(item);
+ t!(fs::create_dir_all(dst));
+ cp_r(&plain_dst_src.join(item), dst);
+ }
+
// Create source tarball in rust-installer format
let mut cmd = Command::new(SH_CMD);
cmd.arg(sanitize_sh(&build.src.join("src/rust-installer/gen-installer.sh")))
.arg("--legacy-manifest-dirs=rustlib,cargo");
build.run(&mut cmd);
- // Rename directory, so that root folder of tarball has the correct name
- let plain_name = format!("rustc-{}-src", build.rust_package_vers());
- let plain_dst_src = tmpdir(build).join(&plain_name);
- let _ = fs::remove_dir_all(&plain_dst_src);
- t!(fs::create_dir_all(&plain_dst_src));
- cp_r(&dst_src, &plain_dst_src);
-
- // Create the version file
- write_file(&plain_dst_src.join("version"), build.rust_version().as_bytes());
-
- // Create plain source tarball
- let mut cmd = Command::new("tar");
- cmd.arg("-czf").arg(sanitize_sh(&rust_src_location(build)))
- .arg(&plain_name)
- .current_dir(tmpdir(build));
- build.run(&mut cmd);
-
t!(fs::remove_dir_all(&image));
t!(fs::remove_dir_all(&plain_dst_src));
}
//! ensure that they're always in place if needed.
use std::env;
+use std::ffi::OsString;
use std::fs::{self, File};
use std::io::{Read, Write};
use std::path::Path;
// NOTE: remember to also update `config.toml.example` when changing the defaults!
let llvm_targets = match build.config.llvm_targets {
Some(ref s) => s,
- None => "X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend;MSP430;Sparc;NVPTX",
+ None => "X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend;MSP430;Sparc;NVPTX;Hexagon",
};
let assertions = if build.config.llvm_assertions {"ON"} else {"OFF"};
.define("LLVM_TABLEGEN", &host);
}
- // MSVC handles compiler business itself
- if !target.contains("msvc") {
- if let Some(ref ccache) = build.config.ccache {
+ let sanitize_cc = |cc: &Path| {
+ if target.contains("msvc") {
+ OsString::from(cc.to_str().unwrap().replace("\\", "/"))
+ } else {
+ cc.as_os_str().to_owned()
+ }
+ };
+
+ let configure_compilers = |cfg: &mut cmake::Config| {
+ // MSVC with CMake uses msbuild by default which doesn't respect these
+ // vars that we'd otherwise configure. In that case we just skip this
+ // entirely.
+ if target.contains("msvc") && !build.config.ninja {
+ return
+ }
+
+ let cc = build.cc(target);
+ let cxx = build.cxx(target);
+
+ // Handle msvc + ninja + ccache specially (this is what the bots use)
+ if target.contains("msvc") &&
+ build.config.ninja &&
+ build.config.ccache.is_some() {
+ let mut cc = env::current_exe().expect("failed to get cwd");
+ cc.set_file_name("sccache-plus-cl.exe");
+
+ cfg.define("CMAKE_C_COMPILER", sanitize_cc(&cc))
+ .define("CMAKE_CXX_COMPILER", sanitize_cc(&cc));
+ cfg.env("SCCACHE_PATH",
+ build.config.ccache.as_ref().unwrap())
+ .env("SCCACHE_TARGET", target);
+
+ // If ccache is configured we inform the build a little differently hwo
+ // to invoke ccache while also invoking our compilers.
+ } else if let Some(ref ccache) = build.config.ccache {
cfg.define("CMAKE_C_COMPILER", ccache)
- .define("CMAKE_C_COMPILER_ARG1", build.cc(target))
+ .define("CMAKE_C_COMPILER_ARG1", sanitize_cc(cc))
.define("CMAKE_CXX_COMPILER", ccache)
- .define("CMAKE_CXX_COMPILER_ARG1", build.cxx(target));
+ .define("CMAKE_CXX_COMPILER_ARG1", sanitize_cc(cxx));
} else {
- cfg.define("CMAKE_C_COMPILER", build.cc(target))
- .define("CMAKE_CXX_COMPILER", build.cxx(target));
+ cfg.define("CMAKE_C_COMPILER", sanitize_cc(cc))
+ .define("CMAKE_CXX_COMPILER", sanitize_cc(cxx));
}
- cfg.build_arg("-j").build_arg(build.jobs().to_string());
+ cfg.build_arg("-j").build_arg(build.jobs().to_string());
cfg.define("CMAKE_C_FLAGS", build.cflags(target).join(" "));
cfg.define("CMAKE_CXX_FLAGS", build.cflags(target).join(" "));
- }
+ };
+
+ configure_compilers(&mut cfg);
if env::var_os("SCCACHE_ERROR_LOG").is_some() {
cfg.env("RUST_LOG", "sccache=info");
"PATH"
} else if cfg!(target_os = "macos") {
"DYLD_LIBRARY_PATH"
+ } else if cfg!(target_os = "haiku") {
+ "LIBRARY_PATH"
} else {
"LD_LIBRARY_PATH"
}
RUN curl -O http://ftp.nl.debian.org/debian/dists/jessie/main/installer-armhf/current/images/device-tree/vexpress-v2p-ca15-tc1.dtb
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-19-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
pkg-config
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-19-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
USER root
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-19-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV PATH=$PATH:/x-tools/aarch64-unknown-linux-gnueabi/bin
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-19-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV TARGETS=arm-linux-androideabi
USER root
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-19-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV PATH=$PATH:/x-tools/arm-unknown-linux-gnueabi/bin
USER root
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-19-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV PATH=$PATH:/x-tools/arm-unknown-linux-gnueabihf/bin
USER root
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-19-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV PATH=$PATH:/x-tools/armv7-unknown-linux-gnueabihf/bin
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-19-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV \
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-19-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV RUST_CONFIGURE_ARGS \
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-19-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV \
ENTRYPOINT ["/rustroot/dumb-init", "--"]
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-19-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV HOSTS=i686-unknown-linux-gnu
pkg-config
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-19-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
pkg-config
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-19-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
pkg-config
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-19-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
pkg-config
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-19-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
USER root
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-19-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV PATH=$PATH:/x-tools/powerpc-unknown-linux-gnu/bin
USER root
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-19-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV PATH=$PATH:/x-tools/powerpc64-unknown-linux-gnu/bin
RUN ./build-powerpc64le-toolchain.sh
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-19-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV \
USER root
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-19-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV PATH=$PATH:/x-tools/s390x-ibm-linux-gnu/bin
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-19-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV \
ENTRYPOINT ["/rustroot/dumb-init", "--"]
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-19-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV HOSTS=x86_64-unknown-linux-gnu
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-19-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV RUST_CONFIGURE_ARGS \
USER root
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-19-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV PATH=$PATH:/x-tools/x86_64-unknown-netbsd/bin
lib32stdc++6
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-19-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
xz-utils
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-19-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
xz-utils
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-19-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
pkg-config
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-19-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
xz-utils
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-19-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
pkg-config
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-19-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
xz-utils
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-19-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
xz-utils
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-19-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
xz-utils
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-19-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
xz-utils
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-19-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
xz-utils
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-19-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
%token TRAIT
%token TYPE
%token UNSAFE
+%token DEFAULT
%token USE
%token WHILE
%token CONTINUE
| %empty { $$ = mk_none(); }
;
+maybe_default_maybe_unsafe
+: DEFAULT UNSAFE { $$ = mk_atom("DefaultUnsafe"); }
+| DEFAULT { $$ = mk_atom("Default"); }
+| UNSAFE { $$ = mk_atom("Unsafe"); }
+| %empty { $$ = mk_none(); }
+
trait_method
: type_method { $$ = mk_node("Required", 1, $1); }
| method { $$ = mk_node("Provided", 1, $1); }
// they are ambiguous with traits. We do the same here, regrettably,
// by splitting ty into ty and ty_prim.
item_impl
-: maybe_unsafe IMPL generic_params ty_prim_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
+: maybe_default_maybe_unsafe IMPL generic_params ty_prim_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
{
$$ = mk_node("ItemImpl", 6, $1, $3, $4, $5, $7, $8);
}
-| maybe_unsafe IMPL generic_params '(' ty ')' maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
+| maybe_default_maybe_unsafe IMPL generic_params '(' ty ')' maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
{
$$ = mk_node("ItemImpl", 6, $1, $3, 5, $6, $9, $10);
}
-| maybe_unsafe IMPL generic_params trait_ref FOR ty_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
+| maybe_default_maybe_unsafe IMPL generic_params trait_ref FOR ty_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
{
$$ = mk_node("ItemImpl", 6, $3, $4, $6, $7, $9, $10);
}
-| maybe_unsafe IMPL generic_params '!' trait_ref FOR ty_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
+| maybe_default_maybe_unsafe IMPL generic_params '!' trait_ref FOR ty_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
{
$$ = mk_node("ItemImplNeg", 7, $1, $3, $5, $7, $8, $10, $11);
}
-| maybe_unsafe IMPL generic_params trait_ref FOR DOTDOT '{' '}'
+| maybe_default_maybe_unsafe IMPL generic_params trait_ref FOR DOTDOT '{' '}'
{
$$ = mk_node("ItemImplDefault", 3, $1, $3, $4);
}
-| maybe_unsafe IMPL generic_params '!' trait_ref FOR DOTDOT '{' '}'
+| maybe_default_maybe_unsafe IMPL generic_params '!' trait_ref FOR DOTDOT '{' '}'
{
$$ = mk_node("ItemImplDefaultNeg", 3, $1, $3, $4);
}
$2,
mk_node("TTTok", 1, mk_atom("]")));
}
-;
+;
\ No newline at end of file
#[inline]
fn replace_one(&mut self) -> Self {
- mem::replace(self, 0)
+ mem::replace(self, 1)
}
#[inline]
fn replace_zero(&mut self) -> Self {
- mem::replace(self, 1)
+ mem::replace(self, 0)
}
#[inline]
#[inline]
fn replace_one(&mut self) -> Self {
- mem::replace(self, 0)
+ mem::replace(self, 1)
}
#[inline]
fn replace_zero(&mut self) -> Self {
- mem::replace(self, 1)
+ mem::replace(self, 0)
}
#[inline]
#[inline]
fn replace_one(&mut self) -> Self {
- mem::replace(self, 0)
+ mem::replace(self, 1)
}
#[inline]
fn replace_zero(&mut self) -> Self {
- mem::replace(self, 1)
+ mem::replace(self, 0)
}
#[inline]
assert_eq!(&[2, 3, 1, 2, 0], &result[..]);
}
+#[test]
+fn test_step_replace_unsigned() {
+ let mut x = 4u32;
+ let y = x.replace_zero();
+ assert_eq!(x, 0);
+ assert_eq!(y, 4);
+
+ x = 5;
+ let y = x.replace_one();
+ assert_eq!(x, 1);
+ assert_eq!(y, 5);
+}
+
+#[test]
+fn test_step_replace_signed() {
+ let mut x = 4i32;
+ let y = x.replace_zero();
+ assert_eq!(x, 0);
+ assert_eq!(y, 4);
+
+ x = 5;
+ let y = x.replace_one();
+ assert_eq!(x, 1);
+ assert_eq!(y, 5);
+}
+
+#[test]
+fn test_step_replace_no_between() {
+ let mut x = 4u128;
+ let y = x.replace_zero();
+ assert_eq!(x, 0);
+ assert_eq!(y, 4);
+
+ x = 5;
+ let y = x.replace_one();
+ assert_eq!(x, 1);
+ assert_eq!(y, 5);
+}
\ No newline at end of file
#![feature(fixed_size_array)]
#![feature(flt2dec)]
#![feature(fmt_internals)]
+#![feature(i128_type)]
#![feature(iter_rfind)]
#![feature(libc)]
#![feature(nonzero)]
#![feature(sort_internals)]
#![feature(sort_unstable)]
#![feature(step_by)]
+#![feature(step_trait)]
#![feature(test)]
#![feature(try_from)]
#![feature(unicode)]
TypeckTables(D),
UsedTraitImports(D),
ConstEval(D),
+ SymbolName(D),
// The set of impls for a given trait. Ultimately, it would be
// nice to get more fine-grained here (e.g., to include a
TypeckTables(ref d) => op(d).map(TypeckTables),
UsedTraitImports(ref d) => op(d).map(UsedTraitImports),
ConstEval(ref d) => op(d).map(ConstEval),
+ SymbolName(ref d) => op(d).map(SymbolName),
TraitImpls(ref d) => op(d).map(TraitImpls),
TraitItems(ref d) => op(d).map(TraitItems),
ReprHints(ref d) => op(d).map(ReprHints),
hir::ItemDefaultImpl(self.lower_unsafety(unsafety),
trait_ref)
}
- ItemKind::Impl(unsafety, polarity, ref generics, ref ifce, ref ty, ref impl_items) => {
+ ItemKind::Impl(unsafety,
+ polarity,
+ defaultness,
+ ref generics,
+ ref ifce,
+ ref ty,
+ ref impl_items) => {
let new_impl_items = impl_items.iter()
.map(|item| self.lower_impl_item_ref(item))
.collect();
hir::ItemImpl(self.lower_unsafety(unsafety),
self.lower_impl_polarity(polarity),
+ self.lower_defaultness(defaultness, true /* [1] */),
self.lower_generics(generics),
ifce,
self.lower_ty(ty),
}
ItemKind::MacroDef(..) | ItemKind::Mac(..) => panic!("Shouldn't still be around"),
}
+
+ // [1] `defaultness.has_value()` is never called for an `impl`, always `true` in order to
+ // not cause an assertion failure inside the `lower_defaultness` function
}
fn lower_trait_item(&mut self, i: &TraitItem) -> hir::TraitItem {
/// An implementation, eg `impl<A> Trait for Foo { .. }`
ItemImpl(Unsafety,
ImplPolarity,
+ Defaultness,
Generics,
Option<TraitRef>, // (optional) trait this impl implements
P<Ty>, // self
}
hir::ItemImpl(unsafety,
polarity,
+ defaultness,
ref generics,
ref opt_trait,
ref ty,
ref impl_items) => {
self.head("")?;
self.print_visibility(&item.vis)?;
+ self.print_defaultness(defaultness)?;
self.print_unsafety(unsafety)?;
self.word_nbsp("impl")?;
}
}
+ pub fn print_defaultness(&mut self, defaultness: hir::Defaultness) -> io::Result<()> {
+ match defaultness {
+ hir::Defaultness::Default { .. } => self.word_nbsp("default")?,
+ hir::Defaultness::Final => (),
+ }
+ Ok(())
+ }
+
pub fn print_struct(&mut self,
struct_def: &hir::VariantData,
generics: &hir::Generics,
self.hardbreak_if_not_bol()?;
self.maybe_print_comment(ii.span.lo)?;
self.print_outer_attributes(&ii.attrs)?;
-
- match ii.defaultness {
- hir::Defaultness::Default { .. } => self.word_nbsp("default")?,
- hir::Defaultness::Final => (),
- }
+ self.print_defaultness(ii.defaultness)?;
match ii.node {
hir::ImplItemKind::Const(ref ty, expr) => {
ItemUnion(variant_data, generics),
ItemTrait(unsafety, generics, bounds, item_refs),
ItemDefaultImpl(unsafety, trait_ref),
- ItemImpl(unsafety, impl_polarity, generics, trait_ref, ty, impl_item_refs)
+ ItemImpl(unsafety, impl_polarity, impl_defaultness, generics, trait_ref, ty, impl_item_refs)
});
impl_stable_hash_for!(struct hir::TraitItemRef {
fn implementations_of_trait(&self, filter: Option<DefId>) -> Vec<DefId>;
// impl info
+ fn impl_defaultness(&self, def: DefId) -> hir::Defaultness;
fn impl_parent(&self, impl_def_id: DefId) -> Option<DefId>;
// trait/impl-item info
fn implementations_of_trait(&self, filter: Option<DefId>) -> Vec<DefId> { vec![] }
// impl info
+ fn impl_defaultness(&self, def: DefId) -> hir::Defaultness { bug!("impl_defaultness") }
fn impl_parent(&self, def: DefId) -> Option<DefId> { bug!("impl_parent") }
// trait/impl-item info
}
match item.node {
- hir::ItemImpl(_, _, ref generics, ..) |
+ hir::ItemImpl(_, _, _, ref generics, ..) |
hir::ItemFn(.., ref generics, _) => {
generics_require_inlining(generics)
}
// does too.
let impl_node_id = self.tcx.hir.as_local_node_id(impl_did).unwrap();
match self.tcx.hir.expect_item(impl_node_id).node {
- hir::ItemImpl(_, _, ref generics, ..) => {
+ hir::ItemImpl(_, _, _, ref generics, ..) => {
generics_require_inlining(generics)
}
_ => false
hir::ItemStruct(_, ref generics) |
hir::ItemUnion(_, ref generics) |
hir::ItemTrait(_, ref generics, ..) |
- hir::ItemImpl(_, _, ref generics, ..) => {
+ hir::ItemImpl(_, _, _, ref generics, ..) => {
// These kinds of items have only early bound lifetime parameters.
let mut index = if let hir::ItemTrait(..) = item.node {
1 // Self comes before lifetimes
}
match parent.node {
hir::ItemTrait(_, ref generics, ..) |
- hir::ItemImpl(_, _, ref generics, ..) => {
+ hir::ItemImpl(_, _, _, ref generics, ..) => {
index += (generics.lifetimes.len() + generics.ty_params.len()) as u32;
}
_ => {}
// being invoked).
node_item.item.defaultness.has_value()
} else {
- node_item.item.defaultness.is_default()
+ node_item.item.defaultness.is_default() ||
+ selcx.tcx().impl_is_default(node_item.node.def_id())
};
// Only reveal a specializable default if we're past type-checking
use ty::{self, Ty, TyCtxt, ToPredicate, ToPolyTraitRef};
use ty::outlives::Component;
use util::nodemap::FxHashSet;
+use hir::{self};
+use traits::specialize::specialization_graph::NodeItem;
use super::{Obligation, ObligationCause, PredicateObligation, SelectionContext, Normalized};
};
ty::Binder((trait_ref, sig.skip_binder().output()))
}
+
+ pub fn impl_is_default(self, node_item_def_id: DefId) -> bool {
+ match self.hir.as_local_node_id(node_item_def_id) {
+ Some(node_id) => {
+ let item = self.hir.expect_item(node_id);
+ if let hir::ItemImpl(_, _, defaultness, ..) = item.node {
+ defaultness.is_default()
+ } else {
+ false
+ }
+ }
+ None => {
+ self.global_tcx()
+ .sess
+ .cstore
+ .impl_defaultness(node_item_def_id)
+ .is_default()
+ }
+ }
+ }
+
+ pub fn impl_item_is_final(self, node_item: &NodeItem<hir::Defaultness>) -> bool {
+ node_item.item.is_final() && !self.impl_is_default(node_item.node.def_id())
+ }
}
pub enum TupleArgumentsFlag { Yes, No }
data @ DefPathData::LifetimeDef(..) |
data @ DefPathData::EnumVariant(..) |
data @ DefPathData::Field(..) |
- data @ DefPathData::StructCtor |
data @ DefPathData::Initializer |
data @ DefPathData::MacroDef(..) |
data @ DefPathData::ClosureExpr |
self.push_item_path(buffer, parent_def_id);
buffer.push(&data.as_interned_str());
}
+ DefPathData::StructCtor => { // present `X` instead of `X::{{constructor}}`
+ let parent_def_id = self.parent_def_id(def_id).unwrap();
+ self.push_item_path(buffer, parent_def_id);
+ }
}
}
use std::ops::Deref;
use std::rc::Rc;
use syntax_pos::{Span, DUMMY_SP};
+use syntax::symbol::Symbol;
trait Key {
fn map_crate(&self) -> CrateNum;
}
}
+impl<'tcx> Key for ty::Instance<'tcx> {
+ fn map_crate(&self) -> CrateNum {
+ LOCAL_CRATE
+ }
+
+ fn default_span(&self, tcx: TyCtxt) -> Span {
+ tcx.def_span(self.def_id())
+ }
+}
+
impl Key for CrateNum {
fn map_crate(&self) -> CrateNum {
*self
}
}
-
impl<'tcx> Value<'tcx> for ty::DtorckConstraint<'tcx> {
fn from_cycle_error<'a>(_: TyCtxt<'a, 'tcx, 'tcx>) -> Self {
Self::empty()
}
}
+impl<'tcx> Value<'tcx> for ty::SymbolName {
+ fn from_cycle_error<'a>(_: TyCtxt<'a, 'tcx, 'tcx>) -> Self {
+ ty::SymbolName { name: Symbol::intern("<error>").as_str() }
+ }
+}
+
pub struct CycleError<'a, 'tcx: 'a> {
span: Span,
cycle: RefMut<'a, [(Span, Query<'tcx>)]>,
}
}
+impl<'tcx> QueryDescription for queries::symbol_name<'tcx> {
+ fn describe(_tcx: TyCtxt, instance: ty::Instance<'tcx>) -> String {
+ format!("computing the symbol for `{}`", instance)
+ }
+}
+
macro_rules! define_maps {
(<$tcx:tt>
$($(#[$attr:meta])*
pub reachable_set: reachability_dep_node(CrateNum) -> Rc<NodeSet>,
- pub mir_shims: mir_shim_dep_node(ty::InstanceDef<'tcx>) -> &'tcx RefCell<mir::Mir<'tcx>>
+ pub mir_shims: mir_shim_dep_node(ty::InstanceDef<'tcx>) -> &'tcx RefCell<mir::Mir<'tcx>>,
+
+ pub def_symbol_name: SymbolName(DefId) -> ty::SymbolName,
+ pub symbol_name: symbol_name_dep_node(ty::Instance<'tcx>) -> ty::SymbolName
}
fn coherent_trait_dep_node((_, def_id): (CrateNum, DefId)) -> DepNode<DefId> {
instance.dep_node()
}
+fn symbol_name_dep_node(instance: ty::Instance) -> DepNode<DefId> {
+ // symbol_name uses the substs only to traverse them to find the
+ // hash, and that does not create any new dep-nodes.
+ DepNode::SymbolName(instance.def.def_id())
+}
+
fn typeck_item_bodies_dep_node(_: CrateNum) -> DepNode<DefId> {
DepNode::TypeckBodiesKrate
}
use std::cell::{Cell, RefCell, Ref};
use std::collections::BTreeMap;
use std::cmp;
+use std::fmt;
use std::hash::{Hash, Hasher};
use std::iter::FromIterator;
use std::ops::Deref;
self.dtorck_types.retain(|&val| dtorck_types.replace(val).is_none());
}
}
+
+#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
+pub struct SymbolName {
+ // FIXME: we don't rely on interning or equality here - better have
+ // this be a `&'tcx str`.
+ pub name: InternedString
+}
+
+impl Deref for SymbolName {
+ type Target = str;
+
+ fn deref(&self) -> &str { &self.name }
+}
+
+impl fmt::Display for SymbolName {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt::Display::fmt(&self.name, fmt)
+ }
+}
"PATH"
} else if cfg!(target_os = "macos") {
"DYLD_LIBRARY_PATH"
+ } else if cfg!(target_os = "haiku") {
+ "LIBRARY_PATH"
} else {
"LD_LIBRARY_PATH"
}
linker: "cc".to_string(),
dynamic_linking: true,
executables: true,
- has_rpath: true,
+ has_rpath: false,
target_family: Some("unix".to_string()),
linker_is_gnu: true,
+ no_integrated_as: true,
.. Default::default()
}
}
use borrowck::BorrowckCtxt;
use rustc::middle::mem_categorization as mc;
use rustc::middle::mem_categorization::Categorization;
+use rustc::middle::mem_categorization::NoteClosureEnv;
use rustc::middle::mem_categorization::InteriorOffsetKind as Kind;
use rustc::ty;
use syntax::ast;
let mut err = report_cannot_move_out_of(bccx, error.move_from.clone());
let mut is_first_note = true;
for move_to in &error.move_to_places {
- err = note_move_destination(err, move_to.span,
- move_to.name, is_first_note);
+ err = note_move_destination(err, move_to.span, move_to.name, is_first_note);
is_first_note = false;
}
+ if let NoteClosureEnv(upvar_id) = error.move_from.note {
+ err.span_label(bccx.tcx.hir.span(upvar_id.var_id), &"captured outer variable");
+ }
err.emit();
}
}
pub l_sysid: libc::c_int,
}
+ pub const F_RDLCK: libc::c_short = 0x0040;
pub const F_UNLCK: libc::c_short = 0x0200;
pub const F_WRLCK: libc::c_short = 0x0400;
pub const F_SETLK: libc::c_int = 0x0080;
sess.code_stats.borrow().print_type_sizes();
}
- if ::std::env::var("SKIP_LLVM").is_ok() { ::std::process::exit(0); }
-
let phase5_result = phase_5_run_llvm_passes(sess, &trans, &outputs);
controller_entry_point!(after_llvm,
mir::provide(&mut local_providers);
reachable::provide(&mut local_providers);
rustc_privacy::provide(&mut local_providers);
+ trans::provide(&mut local_providers);
typeck::provide(&mut local_providers);
ty::provide(&mut local_providers);
reachable::provide(&mut local_providers);
let mut extern_providers = ty::maps::Providers::default();
cstore::provide(&mut extern_providers);
+ trans::provide(&mut extern_providers);
ty::provide_extern(&mut extern_providers);
// FIXME(eddyb) get rid of this once we replace const_eval with miri.
rustc_const_eval::provide(&mut extern_providers);
use build_helper::output;
-fn detect_llvm_link(llvm_config: &Path) -> (&'static str, Option<&'static str>) {
- let mut version_cmd = Command::new(llvm_config);
- version_cmd.arg("--version");
- let version_output = output(&mut version_cmd);
- let mut parts = version_output.split('.').take(2)
- .filter_map(|s| s.parse::<u32>().ok());
- if let (Some(major), Some(minor)) = (parts.next(), parts.next()) {
- if major > 3 || (major == 3 && minor >= 9) {
- // Force the link mode we want, preferring static by default, but
- // possibly overridden by `configure --enable-llvm-link-shared`.
- if env::var_os("LLVM_LINK_SHARED").is_some() {
- return ("dylib", Some("--link-shared"));
- } else {
- return ("static", Some("--link-static"));
- }
- } else if major == 3 && minor == 8 {
- // Find out LLVM's default linking mode.
- let mut mode_cmd = Command::new(llvm_config);
- mode_cmd.arg("--shared-mode");
- if output(&mut mode_cmd).trim() == "shared" {
- return ("dylib", None);
- } else {
- return ("static", None);
- }
+fn detect_llvm_link(major: u32, minor: u32, llvm_config: &Path)
+ -> (&'static str, Option<&'static str>) {
+ if major > 3 || (major == 3 && minor >= 9) {
+ // Force the link mode we want, preferring static by default, but
+ // possibly overridden by `configure --enable-llvm-link-shared`.
+ if env::var_os("LLVM_LINK_SHARED").is_some() {
+ return ("dylib", Some("--link-shared"));
+ } else {
+ return ("static", Some("--link-static"));
+ }
+ } else if major == 3 && minor == 8 {
+ // Find out LLVM's default linking mode.
+ let mut mode_cmd = Command::new(llvm_config);
+ mode_cmd.arg("--shared-mode");
+ if output(&mut mode_cmd).trim() == "shared" {
+ return ("dylib", None);
+ } else {
+ return ("static", None);
}
}
("static", None)
let host = env::var("HOST").expect("HOST was not set");
let is_crossed = target != host;
- let optional_components =
- ["x86", "arm", "aarch64", "mips", "powerpc", "pnacl", "systemz", "jsbackend", "msp430",
- "sparc", "nvptx"];
+ let mut optional_components =
+ vec!["x86", "arm", "aarch64", "mips", "powerpc", "pnacl",
+ "systemz", "jsbackend", "msp430", "sparc", "nvptx"];
+
+ let mut version_cmd = Command::new(&llvm_config);
+ version_cmd.arg("--version");
+ let version_output = output(&mut version_cmd);
+ let mut parts = version_output.split('.').take(2)
+ .filter_map(|s| s.parse::<u32>().ok());
+ let (major, minor) =
+ if let (Some(major), Some(minor)) = (parts.next(), parts.next()) {
+ (major, minor)
+ } else {
+ (3, 7)
+ };
+
+ if major > 3 {
+ optional_components.push("hexagon");
+ }
// FIXME: surely we don't need all these components, right? Stuff like mcjit
// or interpreter the compiler itself never uses.
.cpp_link_stdlib(None) // we handle this below
.compile("librustllvm.a");
- let (llvm_kind, llvm_link_arg) = detect_llvm_link(&llvm_config);
+ let (llvm_kind, llvm_link_arg) = detect_llvm_link(major, minor, &llvm_config);
// Link in all LLVM libraries, if we're uwring the "wrong" llvm-config then
// we don't pick up system libs because unfortunately they're for the host
LLVMInitializeNVPTXTarget,
LLVMInitializeNVPTXTargetMC,
LLVMInitializeNVPTXAsmPrinter);
+ init_target!(llvm_component = "hexagon",
+ LLVMInitializeHexagonTargetInfo,
+ LLVMInitializeHexagonTarget,
+ LLVMInitializeHexagonTargetMC,
+ LLVMInitializeHexagonAsmPrinter,
+ LLVMInitializeHexagonAsmParser);
}
pub fn last_error() -> Option<String> {
result
}
+ fn impl_defaultness(&self, def: DefId) -> hir::Defaultness
+ {
+ self.dep_graph.read(DepNode::MetaData(def));
+ self.get_crate_data(def.krate).get_impl_defaultness(def.index)
+ }
+
fn impl_parent(&self, impl_def: DefId) -> Option<DefId> {
self.dep_graph.read(DepNode::MetaData(impl_def));
self.get_crate_data(impl_def.krate).get_parent_impl(impl_def.index)
self.get_impl_data(id).polarity
}
+ pub fn get_impl_defaultness(&self, id: DefIndex) -> hir::Defaultness {
+ self.get_impl_data(id).defaultness
+ }
+
pub fn get_coerce_unsized_info(&self,
id: DefIndex)
-> Option<ty::adjustment::CoerceUnsizedInfo> {
hir::ItemDefaultImpl(..) => {
let data = ImplData {
polarity: hir::ImplPolarity::Positive,
+ defaultness: hir::Defaultness::Final,
parent_impl: None,
coerce_unsized_info: None,
trait_ref: tcx.impl_trait_ref(def_id).map(|trait_ref| self.lazy(&trait_ref)),
EntryKind::DefaultImpl(self.lazy(&data))
}
- hir::ItemImpl(_, polarity, ..) => {
+ hir::ItemImpl(_, polarity, defaultness, ..) => {
let trait_ref = tcx.impl_trait_ref(def_id);
let parent = if let Some(trait_ref) = trait_ref {
let trait_def = tcx.trait_def(trait_ref.def_id);
let data = ImplData {
polarity: polarity,
+ defaultness: defaultness,
parent_impl: parent,
coerce_unsized_info: coerce_unsized_info,
trait_ref: trait_ref.map(|trait_ref| self.lazy(&trait_ref)),
#[derive(RustcEncodable, RustcDecodable)]
pub struct ImplData<'tcx> {
pub polarity: hir::ImplPolarity,
+ pub defaultness: hir::Defaultness,
pub parent_impl: Option<DefId>,
/// This is `Some` only for impls of `CoerceUnsized`.
impl_stable_hash_for!(struct ImplData<'tcx> {
polarity,
+ defaultness,
parent_impl,
coerce_unsized_info,
trait_ref
}
None => {
if let Some(NodeItem(item)) = self.tcx.hir.get_if_local(id) {
- if let hir::ItemImpl(_, _, _, _, ref ty, _) = item.node {
+ if let hir::ItemImpl(_, _, _, _, _, ref ty, _) = item.node {
trait_id = self.lookup_def_id(ty.id);
}
}
use cabi_sparc64;
use cabi_nvptx;
use cabi_nvptx64;
+use cabi_hexagon;
use machine::llalign_of_min;
use type_::Type;
use type_of;
"sparc64" => cabi_sparc64::compute_abi_info(ccx, self),
"nvptx" => cabi_nvptx::compute_abi_info(ccx, self),
"nvptx64" => cabi_nvptx64::compute_abi_info(ccx, self),
+ "hexagon" => cabi_hexagon::compute_abi_info(ccx, self),
a => ccx.sess().fatal(&format!("unrecognized arch \"{}\" in target specification", a))
}
use context::SharedCrateContext;
use monomorphize::Instance;
-use symbol_map::SymbolMap;
-use back::symbol_names::symbol_name;
use util::nodemap::FxHashMap;
use rustc::hir::def_id::{DefId, CrateNum, LOCAL_CRATE};
use rustc::session::config;
use rustc::ty::TyCtxt;
use syntax::attr;
-use trans_item::TransItem;
/// The SymbolExportLevel of a symbols specifies from which kinds of crates
/// the symbol will be exported. `C` symbols will be exported from any
}
impl ExportedSymbols {
-
pub fn empty() -> ExportedSymbols {
ExportedSymbols {
exports: FxHashMap(),
}
}
- pub fn compute_from<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
- symbol_map: &SymbolMap<'tcx>)
- -> ExportedSymbols {
+ pub fn compute<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>) -> ExportedSymbols {
let mut local_crate: Vec<_> = scx
.exported_symbols()
.iter()
scx.tcx().hir.local_def_id(node_id)
})
.map(|def_id| {
- let name = symbol_for_def_id(scx.tcx(), def_id, symbol_map);
+ let name = scx.tcx().symbol_name(Instance::mono(scx.tcx(), def_id));
let export_level = export_level(scx, def_id);
debug!("EXPORTED SYMBOL (local): {} ({:?})", name, export_level);
- (name, export_level)
+ (str::to_owned(&name), export_level)
})
.collect();
.exported_symbols(cnum)
.iter()
.map(|&def_id| {
- let name = symbol_name(Instance::mono(scx.tcx(), def_id), scx.tcx());
+ let name = scx.tcx().symbol_name(Instance::mono(scx.tcx(), def_id));
let export_level = if special_runtime_crate {
// We can probably do better here by just ensuring that
// it has hidden visibility rather than public
//
// In general though we won't link right if these
// symbols are stripped, and LTO currently strips them.
- if name == "rust_eh_personality" ||
- name == "rust_eh_register_frames" ||
- name == "rust_eh_unregister_frames" {
+ if &*name == "rust_eh_personality" ||
+ &*name == "rust_eh_register_frames" ||
+ &*name == "rust_eh_unregister_frames" {
SymbolExportLevel::C
} else {
SymbolExportLevel::Rust
export_level(scx, def_id)
};
debug!("EXPORTED SYMBOL (re-export): {} ({:?})", name, export_level);
- (name, export_level)
+ (str::to_owned(&name), export_level)
})
.collect();
level == SymbolExportLevel::C
}
}
-
-fn symbol_for_def_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- def_id: DefId,
- symbol_map: &SymbolMap<'tcx>)
- -> String {
- // Just try to look things up in the symbol map. If nothing's there, we
- // recompute.
- if let Some(node_id) = tcx.hir.as_local_node_id(def_id) {
- if let Some(sym) = symbol_map.get(TransItem::Static(node_id)) {
- return sym.to_owned();
- }
- }
-
- let instance = Instance::mono(tcx, def_id);
-
- symbol_map.get(TransItem::Fn(instance))
- .map(str::to_owned)
- .unwrap_or_else(|| symbol_name(instance, tcx))
-}
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
use rustc::ty::fold::TypeVisitor;
use rustc::ty::item_path::{self, ItemPathBuffer, RootMode};
+use rustc::ty::maps::Providers;
use rustc::ty::subst::Substs;
use rustc::hir::map::definitions::DefPathData;
use rustc::util::common::record_time;
use syntax::attr;
+use syntax_pos::symbol::Symbol;
use std::fmt::Write;
+pub fn provide(providers: &mut Providers) {
+ *providers = Providers {
+ def_symbol_name,
+ symbol_name,
+ ..*providers
+ };
+}
+
fn get_symbol_hash<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
// the DefId of the item this name is for
// values for generic type parameters,
// if any.
substs: Option<&'tcx Substs<'tcx>>)
- -> String {
+ -> u64 {
debug!("get_symbol_hash(def_id={:?}, parameters={:?})", def_id, substs);
let mut hasher = ty::util::TypeIdHasher::<u64>::new(tcx);
});
// 64 bits should be enough to avoid collisions.
- format!("h{:016x}", hasher.finish())
+ hasher.finish()
+}
+
+fn def_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
+ -> ty::SymbolName
+{
+ let mut buffer = SymbolPathBuffer::new();
+ item_path::with_forced_absolute_paths(|| {
+ tcx.push_item_path(&mut buffer, def_id);
+ });
+ buffer.into_interned()
}
-pub fn symbol_name<'a, 'tcx>(instance: Instance<'tcx>,
- tcx: TyCtxt<'a, 'tcx, 'tcx>) -> String {
+fn symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance<'tcx>)
+ -> ty::SymbolName
+{
+ ty::SymbolName { name: Symbol::intern(&compute_symbol_name(tcx, instance)).as_str() }
+}
+
+fn compute_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance<'tcx>)
+ -> String
+{
let def_id = instance.def_id();
let substs = instance.substs;
let hash = get_symbol_hash(tcx, Some(def_id), instance_ty, Some(substs));
- let mut buffer = SymbolPathBuffer::new();
- item_path::with_forced_absolute_paths(|| {
- tcx.push_item_path(&mut buffer, def_id);
- });
- buffer.finish(&hash)
+ SymbolPathBuffer::from_interned(tcx.def_symbol_name(def_id)).finish(hash)
}
// Follow C++ namespace-mangling style, see
result
}
- fn finish(mut self, hash: &str) -> String {
- // end name-sequence
- self.push(hash);
- self.result.push('E');
+ fn from_interned(symbol: ty::SymbolName) -> Self {
+ let mut result = SymbolPathBuffer {
+ result: String::with_capacity(64),
+ temp_buf: String::with_capacity(16)
+ };
+ result.result.push_str(&symbol.name);
+ result
+ }
+
+ fn into_interned(self) -> ty::SymbolName {
+ ty::SymbolName { name: Symbol::intern(&self.result).as_str() }
+ }
+
+ fn finish(mut self, hash: u64) -> String {
+ // E = end name-sequence
+ let _ = write!(self.result, "17h{:016x}E", hash);
self.result
}
}
let hash = get_symbol_hash(tcx, None, t, None);
let mut buffer = SymbolPathBuffer::new();
buffer.push(prefix);
- buffer.finish(&hash)
+ buffer.finish(hash)
}
// Name sanitation. LLVM will happily accept identifiers with weird names, but
use mir;
use monomorphize::{self, Instance};
use partitioning::{self, PartitioningStrategy, CodegenUnit};
-use symbol_cache::SymbolCache;
-use symbol_map::SymbolMap;
use symbol_names_test;
use trans_item::{TransItem, DefPathBasedNames};
use type_::Type;
scx: &SharedCrateContext<'a, 'tcx>,
translation_items: &FxHashSet<TransItem<'tcx>>,
llvm_modules: &[ModuleLlvm],
- symbol_map: &SymbolMap<'tcx>,
exported_symbols: &ExportedSymbols) {
let export_threshold =
symbol_export::crates_export_threshold(&sess.crate_types.borrow());
let mut linkage_fixed_explicitly = FxHashSet();
for trans_item in translation_items {
- let symbol_name = symbol_map.get_or_compute(scx, *trans_item);
+ let symbol_name = str::to_owned(&trans_item.symbol_name(tcx));
if trans_item.explicit_linkage(tcx).is_some() {
linkage_fixed_explicitly.insert(symbol_name.clone());
}
// Run the translation item collector and partition the collected items into
// codegen units.
- let (translation_items, codegen_units, symbol_map) =
+ let (translation_items, codegen_units) =
collect_and_partition_translation_items(&shared_ccx);
let mut all_stats = Stats::default();
let cgu_name = String::from(cgu.name());
let cgu_id = cgu.work_product_id();
- let symbol_cache = SymbolCache::new(scx.tcx());
- let symbol_name_hash = cgu.compute_symbol_name_hash(scx, &symbol_cache);
+ let symbol_name_hash = cgu.compute_symbol_name_hash(scx);
// Check whether there is a previous work-product we can
// re-use. Not only must the file exist, and the inputs not
}
// Instantiate translation items without filling out definitions yet...
- let lcx = LocalCrateContext::new(scx, cgu, &symbol_cache);
+ let lcx = LocalCrateContext::new(scx, cgu);
let module = {
let ccx = CrateContext::new(scx, &lcx);
let trans_items = ccx.codegen_unit()
- .items_in_deterministic_order(ccx.tcx(), &symbol_cache);
+ .items_in_deterministic_order(ccx.tcx());
for &(trans_item, linkage) in &trans_items {
trans_item.predefine(&ccx, linkage);
}
let sess = shared_ccx.sess();
- let exported_symbols = ExportedSymbols::compute_from(&shared_ccx,
- &symbol_map);
+ let exported_symbols = ExportedSymbols::compute(&shared_ccx);
// Get the list of llvm modules we created. We'll do a few wacky
// transforms on them now.
&shared_ccx,
&translation_items,
&llvm_modules,
- &symbol_map,
&exported_symbols);
});
}
}
+#[inline(never)] // give this a place in the profiler
+fn assert_symbols_are_distinct<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trans_items: I)
+ where I: Iterator<Item=&'a TransItem<'tcx>>
+{
+ let mut symbols: Vec<_> = trans_items.map(|trans_item| {
+ (trans_item, trans_item.symbol_name(tcx))
+ }).collect();
+
+ (&mut symbols[..]).sort_by(|&(_, ref sym1), &(_, ref sym2)|{
+ sym1.cmp(sym2)
+ });
+
+ for pair in (&symbols[..]).windows(2) {
+ let sym1 = &pair[0].1;
+ let sym2 = &pair[1].1;
+
+ if *sym1 == *sym2 {
+ let trans_item1 = pair[0].0;
+ let trans_item2 = pair[1].0;
+
+ let span1 = trans_item1.local_span(tcx);
+ let span2 = trans_item2.local_span(tcx);
+
+ // Deterministically select one of the spans for error reporting
+ let span = match (span1, span2) {
+ (Some(span1), Some(span2)) => {
+ Some(if span1.lo.0 > span2.lo.0 {
+ span1
+ } else {
+ span2
+ })
+ }
+ (Some(span), None) |
+ (None, Some(span)) => Some(span),
+ _ => None
+ };
+
+ let error_message = format!("symbol `{}` is already defined", sym1);
+
+ if let Some(span) = span {
+ tcx.sess.span_fatal(span, &error_message)
+ } else {
+ tcx.sess.fatal(&error_message)
+ }
+ }
+ }
+}
+
fn collect_and_partition_translation_items<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>)
-> (FxHashSet<TransItem<'tcx>>,
- Vec<CodegenUnit<'tcx>>,
- SymbolMap<'tcx>) {
+ Vec<CodegenUnit<'tcx>>) {
let time_passes = scx.sess().time_passes();
let collection_mode = match scx.sess().opts.debugging_opts.print_trans_items {
collector::collect_crate_translation_items(&scx, collection_mode)
});
- let symbol_map = SymbolMap::build(scx, items.iter().cloned());
+ assert_symbols_are_distinct(scx.tcx(), items.iter());
let strategy = if scx.sess().opts.debugging_opts.incremental.is_some() {
PartitioningStrategy::PerModule
}
}
- (translation_items, codegen_units, symbol_map)
+ (translation_items, codegen_units)
}
--- /dev/null
+// Copyright 2012-2013 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.
+
+#![allow(non_upper_case_globals)]
+
+use abi::{FnType, ArgType, LayoutExt};
+use context::CrateContext;
+
+fn classify_ret_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ret: &mut ArgType<'tcx>) {
+ if ret.layout.is_aggregate() && ret.layout.size(ccx).bits() > 64 {
+ ret.make_indirect(ccx);
+ } else {
+ ret.extend_integer_width_to(32);
+ }
+}
+
+fn classify_arg_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, arg: &mut ArgType<'tcx>) {
+ if arg.layout.is_aggregate() && arg.layout.size(ccx).bits() > 64 {
+ arg.make_indirect(ccx);
+ } else {
+ arg.extend_integer_width_to(32);
+ }
+}
+
+pub fn compute_abi_info<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fty: &mut FnType<'tcx>) {
+ if !fty.ret.is_ignore() {
+ classify_ret_ty(ccx, &mut fty.ret);
+ }
+
+ for arg in &mut fty.args {
+ if arg.is_ignore() {
+ continue;
+ }
+ classify_arg_ty(ccx, arg);
+ }
+}
use rustc::hir::def_id::DefId;
use rustc::ty::TypeFoldable;
use rustc::ty::subst::Substs;
-use trans_item::TransItem;
use type_of;
/// Translates a reference to a fn/method item, monomorphizing and
return llfn;
}
- let sym = ccx.symbol_cache().get(TransItem::Fn(instance));
+ let sym = tcx.symbol_name(instance);
debug!("get_fn({:?}: {:?}) => {}", instance, fn_ty, sym);
// This is subtle and surprising, but sometimes we have to bitcast
let parent_node_id = hir_map.get_parent_node(ii.id);
let is_impl_generic = match hir_map.expect_item(parent_node_id) {
&hir::Item {
- node: hir::ItemImpl(_, _, ref generics, ..),
+ node: hir::ItemImpl(_, _, _, ref generics, ..),
..
} => {
generics.is_type_parameterized()
let tcx = scx.tcx();
match item.node {
hir::ItemImpl(_,
+ _,
_,
ref generics,
..,
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-use back::symbol_names;
use llvm;
use llvm::{SetUnnamedAddr};
use llvm::{ValueRef, True};
hir_map::NodeItem(&hir::Item {
ref attrs, span, node: hir::ItemStatic(..), ..
}) => {
- let sym = ccx.symbol_cache()
- .get(TransItem::Static(id));
+ let sym = TransItem::Static(id).symbol_name(ccx.tcx());
let defined_in_current_codegen_unit = ccx.codegen_unit()
.items()
hir_map::NodeForeignItem(&hir::ForeignItem {
ref attrs, span, node: hir::ForeignItemStatic(..), ..
}) => {
- let sym = symbol_names::symbol_name(instance, ccx.tcx());
+ let sym = ccx.tcx().symbol_name(instance);
let g = if let Some(name) =
attr::first_attr_value_str_by_name(&attrs, "linkage") {
// If this is a static with a linkage specified, then we need to handle
g
} else {
- let sym = symbol_names::symbol_name(instance, ccx.tcx());
+ let sym = ccx.tcx().symbol_name(instance);
// FIXME(nagisa): perhaps the map of externs could be offloaded to llvm somehow?
// FIXME(nagisa): investigate whether it can be changed into define_global
use session::config::NoDebugInfo;
use session::Session;
use session::config;
-use symbol_cache::SymbolCache;
use util::nodemap::{NodeSet, DefIdMap, FxHashMap};
use std::ffi::{CStr, CString};
use std::ptr;
use std::iter;
use std::str;
+use std::marker::PhantomData;
use syntax::ast;
use syntax::symbol::InternedString;
use syntax_pos::DUMMY_SP;
llcx: ContextRef,
stats: Stats,
codegen_unit: CodegenUnit<'tcx>,
- needs_unwind_cleanup_cache: RefCell<FxHashMap<Ty<'tcx>, bool>>,
/// Cache instances of monomorphic and polymorphic items
instances: RefCell<FxHashMap<Instance<'tcx>, ValueRef>>,
/// Cache generated vtables
/// Mapping from static definitions to their DefId's.
statics: RefCell<FxHashMap<ValueRef, DefId>>,
- impl_method_cache: RefCell<FxHashMap<(DefId, ast::Name), DefId>>,
-
- /// Cache of closure wrappers for bare fn's.
- closure_bare_wrapper_cache: RefCell<FxHashMap<ValueRef, ValueRef>>,
-
/// List of globals for static variables which need to be passed to the
/// LLVM function ReplaceAllUsesWith (RAUW) when translation is complete.
/// (We have to make sure we don't invalidate any ValueRefs referring
used_statics: RefCell<Vec<ValueRef>>,
lltypes: RefCell<FxHashMap<Ty<'tcx>, Type>>,
- llsizingtypes: RefCell<FxHashMap<Ty<'tcx>, Type>>,
type_hashcodes: RefCell<FxHashMap<Ty<'tcx>, String>>,
int_type: Type,
opaque_vec_type: Type,
str_slice_type: Type,
- /// Holds the LLVM values for closure IDs.
- closure_vals: RefCell<FxHashMap<Instance<'tcx>, ValueRef>>,
-
dbg_cx: Option<debuginfo::CrateDebugContext<'tcx>>,
eh_personality: Cell<Option<ValueRef>>,
/// A counter that is used for generating local symbol names
local_gen_sym_counter: Cell<usize>,
- symbol_cache: &'a SymbolCache<'a, 'tcx>,
+ /// A placeholder so we can add lifetimes
+ placeholder: PhantomData<&'a ()>,
}
/// A CrateContext value binds together one LocalCrateContext with the
impl<'a, 'tcx> LocalCrateContext<'a, 'tcx> {
pub fn new(shared: &SharedCrateContext<'a, 'tcx>,
- codegen_unit: CodegenUnit<'tcx>,
- symbol_cache: &'a SymbolCache<'a, 'tcx>)
+ codegen_unit: CodegenUnit<'tcx>)
-> LocalCrateContext<'a, 'tcx> {
unsafe {
// Append ".rs" to LLVM module identifier.
llcx: llcx,
stats: Stats::default(),
codegen_unit: codegen_unit,
- needs_unwind_cleanup_cache: RefCell::new(FxHashMap()),
instances: RefCell::new(FxHashMap()),
vtables: RefCell::new(FxHashMap()),
const_cstr_cache: RefCell::new(FxHashMap()),
const_values: RefCell::new(FxHashMap()),
extern_const_values: RefCell::new(DefIdMap()),
statics: RefCell::new(FxHashMap()),
- impl_method_cache: RefCell::new(FxHashMap()),
- closure_bare_wrapper_cache: RefCell::new(FxHashMap()),
statics_to_rauw: RefCell::new(Vec::new()),
used_statics: RefCell::new(Vec::new()),
lltypes: RefCell::new(FxHashMap()),
- llsizingtypes: RefCell::new(FxHashMap()),
type_hashcodes: RefCell::new(FxHashMap()),
int_type: Type::from_ref(ptr::null_mut()),
opaque_vec_type: Type::from_ref(ptr::null_mut()),
str_slice_type: Type::from_ref(ptr::null_mut()),
- closure_vals: RefCell::new(FxHashMap()),
dbg_cx: dbg_cx,
eh_personality: Cell::new(None),
eh_unwind_resume: Cell::new(None),
intrinsics: RefCell::new(FxHashMap()),
type_of_depth: Cell::new(0),
local_gen_sym_counter: Cell::new(0),
- symbol_cache: symbol_cache,
+ placeholder: PhantomData,
};
let (int_type, opaque_vec_type, str_slice_ty, mut local_ccx) = {
unsafe { llvm::LLVMRustGetModuleDataLayout(self.llmod()) }
}
- pub fn needs_unwind_cleanup_cache(&self) -> &RefCell<FxHashMap<Ty<'tcx>, bool>> {
- &self.local().needs_unwind_cleanup_cache
- }
-
pub fn instances<'a>(&'a self) -> &'a RefCell<FxHashMap<Instance<'tcx>, ValueRef>> {
&self.local().instances
}
&self.local().statics
}
- pub fn impl_method_cache<'a>(&'a self)
- -> &'a RefCell<FxHashMap<(DefId, ast::Name), DefId>> {
- &self.local().impl_method_cache
- }
-
- pub fn closure_bare_wrapper_cache<'a>(&'a self) -> &'a RefCell<FxHashMap<ValueRef, ValueRef>> {
- &self.local().closure_bare_wrapper_cache
- }
-
pub fn statics_to_rauw<'a>(&'a self) -> &'a RefCell<Vec<(ValueRef, ValueRef)>> {
&self.local().statics_to_rauw
}
&self.local().lltypes
}
- pub fn llsizingtypes<'a>(&'a self) -> &'a RefCell<FxHashMap<Ty<'tcx>, Type>> {
- &self.local().llsizingtypes
- }
-
pub fn type_hashcodes<'a>(&'a self) -> &'a RefCell<FxHashMap<Ty<'tcx>, String>> {
&self.local().type_hashcodes
}
self.local().str_slice_type
}
- pub fn closure_vals<'a>(&'a self) -> &'a RefCell<FxHashMap<Instance<'tcx>, ValueRef>> {
- &self.local().closure_vals
- }
-
pub fn dbg_cx<'a>(&'a self) -> &'a Option<debuginfo::CrateDebugContext<'tcx>> {
&self.local().dbg_cx
}
self.shared.use_dll_storage_attrs()
}
- pub fn symbol_cache(&self) -> &'b SymbolCache<'b, 'tcx> {
- self.local().symbol_cache
- }
-
/// Given the def-id of some item that has no type parameters, make
/// a suitable "empty substs" for it.
pub fn empty_substs_for_def_id(&self, item_def_id: DefId) -> &'tcx Substs<'tcx> {
pub use rustc::util;
pub use base::trans_crate;
+pub use back::symbol_names::provide;
pub mod back {
pub use rustc::hir::svh;
mod cabi_aarch64;
mod cabi_arm;
mod cabi_asmjs;
+mod cabi_hexagon;
mod cabi_mips;
mod cabi_mips64;
mod cabi_msp430;
mod mir;
mod monomorphize;
mod partitioning;
-mod symbol_cache;
-mod symbol_map;
mod symbol_names_test;
mod trans_item;
mod tvec;
use rustc::ty::{self, TyCtxt};
use rustc::ty::item_path::characteristic_def_id_of_type;
use rustc_incremental::IchHasher;
-use std::cmp::Ordering;
use std::hash::Hash;
use std::sync::Arc;
-use symbol_cache::SymbolCache;
use syntax::ast::NodeId;
use syntax::symbol::{Symbol, InternedString};
use trans_item::{TransItem, InstantiationMode};
}
pub fn compute_symbol_name_hash<'a>(&self,
- scx: &SharedCrateContext<'a, 'tcx>,
- symbol_cache: &SymbolCache<'a, 'tcx>)
+ scx: &SharedCrateContext<'a, 'tcx>)
-> u64 {
let mut state = IchHasher::new();
let exported_symbols = scx.exported_symbols();
- let all_items = self.items_in_deterministic_order(scx.tcx(), symbol_cache);
+ let all_items = self.items_in_deterministic_order(scx.tcx());
for (item, _) in all_items {
- let symbol_name = symbol_cache.get(item);
+ let symbol_name = item.symbol_name(scx.tcx());
symbol_name.len().hash(&mut state);
symbol_name.hash(&mut state);
let exported = match item {
}
pub fn items_in_deterministic_order<'a>(&self,
- tcx: TyCtxt,
- symbol_cache: &SymbolCache<'a, 'tcx>)
+ tcx: TyCtxt<'a, 'tcx, 'tcx>)
-> Vec<(TransItem<'tcx>, llvm::Linkage)> {
- let mut items: Vec<(TransItem<'tcx>, llvm::Linkage)> =
- self.items.iter().map(|(item, linkage)| (*item, *linkage)).collect();
-
// The codegen tests rely on items being process in the same order as
// they appear in the file, so for local items, we sort by node_id first
- items.sort_by(|&(trans_item1, _), &(trans_item2, _)| {
- let node_id1 = local_node_id(tcx, trans_item1);
- let node_id2 = local_node_id(tcx, trans_item2);
-
- match (node_id1, node_id2) {
- (None, None) => {
- let symbol_name1 = symbol_cache.get(trans_item1);
- let symbol_name2 = symbol_cache.get(trans_item2);
- symbol_name1.cmp(&symbol_name2)
- }
- // In the following two cases we can avoid looking up the symbol
- (None, Some(_)) => Ordering::Less,
- (Some(_), None) => Ordering::Greater,
- (Some(node_id1), Some(node_id2)) => {
- let ordering = node_id1.cmp(&node_id2);
-
- if ordering != Ordering::Equal {
- return ordering;
- }
-
- let symbol_name1 = symbol_cache.get(trans_item1);
- let symbol_name2 = symbol_cache.get(trans_item2);
- symbol_name1.cmp(&symbol_name2)
- }
- }
- });
-
- return items;
+ #[derive(PartialEq, Eq, PartialOrd, Ord)]
+ pub struct ItemSortKey(Option<NodeId>, ty::SymbolName);
- fn local_node_id(tcx: TyCtxt, trans_item: TransItem) -> Option<NodeId> {
- match trans_item {
+ fn item_sort_key<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ item: TransItem<'tcx>) -> ItemSortKey {
+ ItemSortKey(match item {
TransItem::Fn(instance) => {
tcx.hir.as_local_node_id(instance.def_id())
}
TransItem::Static(node_id) | TransItem::GlobalAsm(node_id) => {
Some(node_id)
}
- }
+ }, item.symbol_name(tcx))
}
+
+ let items: Vec<_> = self.items.iter().map(|(&i, &l)| (i, l)).collect();
+ let mut items : Vec<_> = items.iter()
+ .map(|il| (il, item_sort_key(tcx, il.0))).collect();
+ items.sort_by(|&(_, ref key1), &(_, ref key2)| key1.cmp(key2));
+ items.into_iter().map(|(&item_linkage, _)| item_linkage).collect()
}
}
{
if cfg!(debug_assertions) {
debug!("{}", label);
- let symbol_cache = SymbolCache::new(tcx);
for cgu in cgus {
debug!("CodegenUnit {}:", cgu.name);
for (trans_item, linkage) in &cgu.items {
- let symbol_name = symbol_cache.get(*trans_item);
+ let symbol_name = trans_item.symbol_name(tcx);
let symbol_hash_start = symbol_name.rfind('h');
let symbol_hash = symbol_hash_start.map(|i| &symbol_name[i ..])
.unwrap_or("<no hash>");
+++ /dev/null
-// 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 rustc::ty::TyCtxt;
-use std::cell::RefCell;
-use syntax_pos::symbol::{InternedString, Symbol};
-use trans_item::TransItem;
-use util::nodemap::FxHashMap;
-
-// In the SymbolCache we collect the symbol names of translation items
-// and cache them for later reference. This is just a performance
-// optimization and the cache is populated lazilly; symbol names of
-// translation items are deterministic and fully defined by the item.
-// Thus they can always be recomputed if needed.
-
-pub struct SymbolCache<'a, 'tcx: 'a> {
- tcx: TyCtxt<'a, 'tcx, 'tcx>,
- index: RefCell<FxHashMap<TransItem<'tcx>, Symbol>>,
-}
-
-impl<'a, 'tcx> SymbolCache<'a, 'tcx> {
- pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Self {
- SymbolCache {
- tcx: tcx,
- index: RefCell::new(FxHashMap())
- }
- }
-
- pub fn get(&self, trans_item: TransItem<'tcx>) -> InternedString {
- let mut index = self.index.borrow_mut();
- index.entry(trans_item)
- .or_insert_with(|| Symbol::intern(&trans_item.compute_symbol_name(self.tcx)))
- .as_str()
- }
-}
+++ /dev/null
-// 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 context::SharedCrateContext;
-use monomorphize::Instance;
-use rustc::ty::TyCtxt;
-use std::borrow::Cow;
-use syntax::codemap::Span;
-use trans_item::TransItem;
-use util::nodemap::FxHashMap;
-
-// In the SymbolMap we collect the symbol names of all translation items of
-// the current crate. This map exists as a performance optimization. Symbol
-// names of translation items are deterministic and fully defined by the item.
-// Thus they could also always be recomputed if needed.
-
-pub struct SymbolMap<'tcx> {
- index: FxHashMap<TransItem<'tcx>, (usize, usize)>,
- arena: String,
-}
-
-impl<'tcx> SymbolMap<'tcx> {
-
- pub fn build<'a, I>(scx: &SharedCrateContext<'a, 'tcx>,
- trans_items: I)
- -> SymbolMap<'tcx>
- where I: Iterator<Item=TransItem<'tcx>>
- {
- // Check for duplicate symbol names
- let tcx = scx.tcx();
- let mut symbols: Vec<_> = trans_items.map(|trans_item| {
- (trans_item, trans_item.compute_symbol_name(tcx))
- }).collect();
-
- (&mut symbols[..]).sort_by(|&(_, ref sym1), &(_, ref sym2)|{
- sym1.cmp(sym2)
- });
-
- for pair in (&symbols[..]).windows(2) {
- let sym1 = &pair[0].1;
- let sym2 = &pair[1].1;
-
- if *sym1 == *sym2 {
- let trans_item1 = pair[0].0;
- let trans_item2 = pair[1].0;
-
- let span1 = get_span(scx.tcx(), trans_item1);
- let span2 = get_span(scx.tcx(), trans_item2);
-
- // Deterministically select one of the spans for error reporting
- let span = match (span1, span2) {
- (Some(span1), Some(span2)) => {
- Some(if span1.lo.0 > span2.lo.0 {
- span1
- } else {
- span2
- })
- }
- (Some(span), None) |
- (None, Some(span)) => Some(span),
- _ => None
- };
-
- let error_message = format!("symbol `{}` is already defined", sym1);
-
- if let Some(span) = span {
- scx.sess().span_fatal(span, &error_message)
- } else {
- scx.sess().fatal(&error_message)
- }
- }
- }
-
- let mut symbol_map = SymbolMap {
- index: FxHashMap(),
- arena: String::with_capacity(1024),
- };
-
- for (trans_item, symbol) in symbols {
- let start_index = symbol_map.arena.len();
- symbol_map.arena.push_str(&symbol[..]);
- let end_index = symbol_map.arena.len();
- let prev_entry = symbol_map.index.insert(trans_item,
- (start_index, end_index));
- if prev_entry.is_some() {
- bug!("TransItem encountered twice?")
- }
- }
-
- fn get_span<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- trans_item: TransItem<'tcx>) -> Option<Span> {
- match trans_item {
- TransItem::Fn(Instance { def, .. }) => {
- tcx.hir.as_local_node_id(def.def_id())
- }
- TransItem::Static(node_id) |
- TransItem::GlobalAsm(node_id) => {
- Some(node_id)
- }
- }.map(|node_id| {
- tcx.hir.span(node_id)
- })
- }
-
- symbol_map
- }
-
- pub fn get(&self, trans_item: TransItem<'tcx>) -> Option<&str> {
- self.index.get(&trans_item).map(|&(start_index, end_index)| {
- &self.arena[start_index .. end_index]
- })
- }
-
- pub fn get_or_compute<'map, 'scx>(&'map self,
- scx: &SharedCrateContext<'scx, 'tcx>,
- trans_item: TransItem<'tcx>)
- -> Cow<'map, str> {
- if let Some(sym) = self.get(trans_item) {
- Cow::from(sym)
- } else {
- Cow::from(trans_item.compute_symbol_name(scx.tcx()))
- }
- }
-}
//! item-path. This is used for unit testing the code that generates
//! paths etc in all kinds of annoying scenarios.
-use back::symbol_names;
use rustc::hir;
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
use rustc::ty::TyCtxt;
if attr.check_name(SYMBOL_NAME) {
// for now, can only use on monomorphic names
let instance = Instance::mono(tcx, def_id);
- let name = symbol_names::symbol_name(instance, self.tcx);
+ let name = self.tcx.symbol_name(instance);
tcx.sess.span_err(attr.span, &format!("symbol-name({})", name));
} else if attr.check_name(ITEM_PATH) {
let path = tcx.item_path_str(def_id);
use rustc::ty::subst::Substs;
use syntax::ast::{self, NodeId};
use syntax::attr;
+use syntax_pos::Span;
+use syntax_pos::symbol::Symbol;
use type_of;
-use back::symbol_names;
use std::fmt::Write;
use std::iter;
self.to_raw_string(),
ccx.codegen_unit().name());
- let symbol_name = ccx.symbol_cache().get(*self);
+ let symbol_name = self.symbol_name(ccx.tcx());
debug!("symbol {}", &symbol_name);
ccx.instances().borrow_mut().insert(instance, lldecl);
}
- pub fn compute_symbol_name(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> String {
+ pub fn symbol_name(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ty::SymbolName {
match *self {
- TransItem::Fn(instance) => symbol_names::symbol_name(instance, tcx),
+ TransItem::Fn(instance) => tcx.symbol_name(instance),
TransItem::Static(node_id) => {
let def_id = tcx.hir.local_def_id(node_id);
- symbol_names::symbol_name(Instance::mono(tcx, def_id), tcx)
+ tcx.symbol_name(Instance::mono(tcx, def_id))
}
TransItem::GlobalAsm(node_id) => {
let def_id = tcx.hir.local_def_id(node_id);
- format!("global_asm_{:?}", def_id)
+ ty::SymbolName {
+ name: Symbol::intern(&format!("global_asm_{:?}", def_id)).as_str()
+ }
}
}
}
+ pub fn local_span(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<Span> {
+ match *self {
+ TransItem::Fn(Instance { def, .. }) => {
+ tcx.hir.as_local_node_id(def.def_id())
+ }
+ TransItem::Static(node_id) |
+ TransItem::GlobalAsm(node_id) => {
+ Some(node_id)
+ }
+ }.map(|node_id| tcx.hir.span(node_id))
+ }
+
pub fn instantiation_mode(&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>)
-> InstantiationMode {
.map(|node_item| node_item.map(|parent| parent.defaultness));
if let Some(parent) = parent {
- if parent.item.is_final() {
+ if tcx.impl_item_is_final(&parent) {
report_forbidden_specialization(tcx, impl_item, parent.node.def_id());
}
}
///
/// won't be allowed unless there's an *explicit* implementation of `Send`
/// for `T`
- hir::ItemImpl(_, hir::ImplPolarity::Positive, _,
+ hir::ItemImpl(_, hir::ImplPolarity::Positive, _, _,
ref trait_ref, ref self_ty, _) => {
self.check_impl(item, self_ty, trait_ref);
}
- hir::ItemImpl(_, hir::ImplPolarity::Negative, _, Some(_), ..) => {
+ hir::ItemImpl(_, hir::ImplPolarity::Negative, _, _, Some(_), ..) => {
// FIXME(#27579) what amount of WF checking do we need for neg impls?
let trait_ref = tcx.impl_trait_ref(tcx.hir.local_def_id(item.id)).unwrap();
hir::ItemDefaultImpl(unsafety, _) => {
self.check_unsafety_coherence(item, None, unsafety, hir::ImplPolarity::Positive);
}
- hir::ItemImpl(unsafety, polarity, ref generics, Some(_), _, _) => {
+ hir::ItemImpl(unsafety, polarity, _, ref generics, ..) => {
self.check_unsafety_coherence(item, Some(generics), unsafety, polarity);
}
_ => {}
NodeItem(item) => {
match item.node {
ItemFn(.., ref generics, _) |
- ItemImpl(_, _, ref generics, ..) |
+ ItemImpl(_, _, _, ref generics, ..) |
ItemTy(_, ref generics) |
ItemEnum(_, ref generics) |
ItemStruct(_, ref generics) |
NodeItem(item) => {
match item.node {
ItemFn(.., ref generics, _) |
- ItemImpl(_, _, ref generics, ..) => generics,
+ ItemImpl(_, _, _, ref generics, ..) => generics,
ItemTy(_, ref generics) |
ItemEnum(_, ref generics) |
NodeItem(item) => {
match item.node {
ItemFn(.., ref generics, _) |
- ItemImpl(_, _, ref generics, ..) |
+ ItemImpl(_, _, _, ref generics, ..) |
ItemTy(_, ref generics) |
ItemEnum(_, ref generics) |
ItemStruct(_, ref generics) |
pub struct Impl {
pub unsafety: hir::Unsafety,
pub polarity: hir::ImplPolarity,
+ pub defaultness: hir::Defaultness,
pub generics: hir::Generics,
pub trait_: Option<hir::TraitRef>,
pub for_: P<hir::Ty>,
om.traits.push(t);
},
- hir::ItemImpl(unsafety, polarity, ref gen, ref tr, ref ty, ref item_ids) => {
+ hir::ItemImpl(unsafety,
+ polarity,
+ defaultness,
+ ref gen,
+ ref tr,
+ ref ty,
+ ref item_ids) => {
// Don't duplicate impls when inlining, we'll pick them up
// regardless of where they're located.
if !self.inlining {
let i = Impl {
unsafety: unsafety,
polarity: polarity,
+ defaultness: defaultness,
generics: gen.clone(),
trait_: tr.clone(),
for_: ty.clone(),
///
/// # Examples
///
-/// ```no_run
+/// ```
+/// # use std::io;
/// use std::net::{TcpListener, TcpStream};
///
-/// let listener = TcpListener::bind("127.0.0.1:80").unwrap();
-///
/// fn handle_client(stream: TcpStream) {
/// // ...
/// }
///
+/// # fn process() -> io::Result<()> {
+/// let listener = TcpListener::bind("127.0.0.1:80").unwrap();
+///
/// // accept connections and process them serially
/// for stream in listener.incoming() {
-/// match stream {
-/// Ok(stream) => {
-/// handle_client(stream);
-/// }
-/// Err(e) => { /* connection failed */ }
-/// }
+/// handle_client(stream?);
/// }
+/// # Ok(())
+/// # }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub struct TcpListener(net_imp::TcpListener);
///
/// [`Shutdown`]: ../../std/net/enum.Shutdown.html
///
+ /// # Platform-specific behavior
+ ///
+ /// Calling this function multiple times may result in different behavior,
+ /// depending on the operating system. On Linux, the second call will
+ /// return `Ok(())`, but on macOS, it will return `ErrorKind::NotConnected`.
+ /// This may change in the future.
+ ///
/// # Examples
///
/// ```no_run
mod mpsc_queue;
mod spsc_queue;
-/// The receiving-half of Rust's channel type. This half can only be owned by
-/// one thread.
+/// The receiving half of Rust's [`channel`][] (or [`sync_channel`]) type.
+/// This half can only be owned by one thread.
///
/// Messages sent to the channel can be retrieved using [`recv`].
///
-/// [`recv`]: ../../../std/sync/mpsc/struct.Receiver.html#method.recv
+/// [`channel`]: fn.channel.html
+/// [`sync_channel`]: fn.sync_channel.html
+/// [`recv`]: struct.Receiver.html#method.recv
///
/// # Examples
///
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> !Sync for Receiver<T> { }
-/// An iterator over messages on a receiver, this iterator will block whenever
-/// [`next`] is called, waiting for a new message, and [`None`] will be returned
+/// An iterator over messages on a [`Receiver`], created by [`iter`].
+///
+/// This iterator will block whenever [`next`] is called,
+/// waiting for a new message, and [`None`] will be returned
/// when the corresponding channel has hung up.
///
+/// [`iter`]: struct.Receiver.html#method.iter
+/// [`Receiver`]: struct.Receiver.html
/// [`next`]: ../../../std/iter/trait.Iterator.html#tymethod.next
/// [`None`]: ../../../std/option/enum.Option.html#variant.None
+///
+/// # Examples
+///
+/// ```rust
+/// use std::sync::mpsc::channel;
+/// use std::thread;
+///
+/// let (send, recv) = channel();
+///
+/// thread::spawn(move || {
+/// send.send(1u8).unwrap();
+/// send.send(2u8).unwrap();
+/// send.send(3u8).unwrap();
+/// });
+///
+/// for x in recv.iter() {
+/// println!("Got: {}", x);
+/// }
+/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Debug)]
pub struct Iter<'a, T: 'a> {
rx: &'a Receiver<T>
}
-/// An iterator that attempts to yield all pending values for a receiver.
-/// [`None`] will be returned when there are no pending values remaining or if
-/// the corresponding channel has hung up.
+/// An iterator that attempts to yield all pending values for a [`Receiver`],
+/// created by [`try_iter`].
+///
+/// [`None`] will be returned when there are no pending values remaining or
+/// if the corresponding channel has hung up.
///
-/// This Iterator will never block the caller in order to wait for data to
+/// This iterator will never block the caller in order to wait for data to
/// become available. Instead, it will return [`None`].
///
+/// [`Receiver`]: struct.Receiver.html
+/// [`try_iter`]: struct.Receiver.html#method.try_iter
/// [`None`]: ../../../std/option/enum.Option.html#variant.None
+///
+/// # Examples
+///
+/// ```rust
+/// use std::sync::mpsc::channel;
+/// use std::thread;
+/// use std::time::Duration;
+///
+/// let (sender, receiver) = channel();
+///
+/// // Nothing is in the buffer yet
+/// assert!(receiver.try_iter().next().is_none());
+/// println!("Nothing in the buffer...");
+///
+/// thread::spawn(move || {
+/// sender.send(1).unwrap();
+/// sender.send(2).unwrap();
+/// sender.send(3).unwrap();
+/// });
+///
+/// println!("Going to sleep...");
+/// thread::sleep(Duration::from_secs(2)); // block for two seconds
+///
+/// for x in receiver.try_iter() {
+/// println!("Got: {}", x);
+/// }
+/// ```
#[stable(feature = "receiver_try_iter", since = "1.15.0")]
#[derive(Debug)]
pub struct TryIter<'a, T: 'a> {
rx: &'a Receiver<T>
}
-/// An owning iterator over messages on a receiver, this iterator will block
-/// whenever [`next`] is called, waiting for a new message, and [`None`] will be
-/// returned when the corresponding channel has hung up.
+/// An owning iterator over messages on a [`Receiver`],
+/// created by **Receiver::into_iter**.
+///
+/// This iterator will block whenever [`next`]
+/// is called, waiting for a new message, and [`None`] will be
+/// returned if the corresponding channel has hung up.
///
+/// [`Receiver`]: struct.Receiver.html
/// [`next`]: ../../../std/iter/trait.Iterator.html#tymethod.next
/// [`None`]: ../../../std/option/enum.Option.html#variant.None
///
+/// # Examples
+///
+/// ```rust
+/// use std::sync::mpsc::channel;
+/// use std::thread;
+///
+/// let (send, recv) = channel();
+///
+/// thread::spawn(move || {
+/// send.send(1u8).unwrap();
+/// send.send(2u8).unwrap();
+/// send.send(3u8).unwrap();
+/// });
+///
+/// for x in recv.into_iter() {
+/// println!("Got: {}", x);
+/// }
+/// ```
#[stable(feature = "receiver_into_iter", since = "1.1.0")]
#[derive(Debug)]
pub struct IntoIter<T> {
rx: Receiver<T>
}
-/// The sending-half of Rust's asynchronous channel type. This half can only be
+/// The sending-half of Rust's asynchronous [`channel`] type. This half can only be
/// owned by one thread, but it can be cloned to send to other threads.
///
/// Messages can be sent through this channel with [`send`].
///
-/// [`send`]: ../../../std/sync/mpsc/struct.Sender.html#method.send
+/// [`channel`]: fn.channel.html
+/// [`send`]: struct.Sender.html#method.send
///
/// # Examples
///
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> !Sync for Sender<T> { }
-/// The sending-half of Rust's synchronous channel type. This half can only be
-/// owned by one thread, but it can be cloned to send to other threads.
+/// The sending-half of Rust's synchronous [`sync_channel`] type.
+/// This half can only be owned by one thread, but it can be cloned
+/// to send to other threads.
+///
+/// Messages can be sent through this channel with [`send`] or [`try_send`].
+///
+/// [`send`] will block if there is no space in the internal buffer.
+///
+/// [`sync_channel`]: fn.sync_channel.html
+/// [`send`]: struct.SyncSender.html#method.send
+/// [`try_send`]: struct.SyncSender.html#method.try_send
+///
+/// # Examples
+///
+/// ```rust
+/// use std::sync::mpsc::sync_channel;
+/// use std::thread;
///
-/// [`send`]: ../../../std/sync/mpsc/struct.Sender.html#method.send
-/// [`SyncSender::send`]: ../../../std/sync/mpsc/struct.SyncSender.html#method.send
+/// // Create a sync_channel with buffer size 2
+/// let (sync_sender, receiver) = sync_channel(2);
+/// let sync_sender2 = sync_sender.clone();
///
+/// // First thread owns sync_sender
+/// thread::spawn(move || {
+/// sync_sender.send(1).unwrap();
+/// sync_sender.send(2).unwrap();
+/// });
+///
+/// // Second thread owns sync_sender2
+/// thread::spawn(move || {
+/// sync_sender2.send(3).unwrap();
+/// // thread will now block since the buffer is full
+/// println!("Thread unblocked!");
+/// });
+///
+/// let mut msg;
+///
+/// msg = receiver.recv().unwrap();
+/// println!("message {} received", msg);
+///
+/// // "Thread unblocked!" will be printed now
+///
+/// msg = receiver.recv().unwrap();
+/// println!("message {} received", msg);
+///
+/// msg = receiver.recv().unwrap();
+///
+/// println!("message {} received", msg);
+/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub struct SyncSender<T> {
inner: Arc<sync::Packet<T>>,
/// Note that a successful send does *not* guarantee that the receiver will
/// ever see the data if there is a buffer on this channel. Items may be
/// enqueued in the internal buffer for the receiver to receive at a later
- /// time. If the buffer size is 0, however, it can be guaranteed that the
- /// receiver has indeed received the data if this function returns success.
+ /// time. If the buffer size is 0, however, the channel becomes a rendezvous
+ /// channel and it guarantees that the receiver has indeed received
+ /// the data if this function returns success.
///
/// This function will never panic, but it may return [`Err`] if the
/// [`Receiver`] has disconnected and is no longer able to receive
///
/// [`Err`]: ../../../std/result/enum.Result.html#variant.Err
/// [`Receiver`]: ../../../std/sync/mpsc/struct.Receiver.html
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use std::sync::mpsc::sync_channel;
+ /// use std::thread;
+ ///
+ /// // Create a rendezvous sync_channel with buffer size 0
+ /// let (sync_sender, receiver) = sync_channel(0);
+ ///
+ /// thread::spawn(move || {
+ /// println!("sending message...");
+ /// sync_sender.send(1).unwrap();
+ /// // Thread is now blocked until the message is received
+ ///
+ /// println!("...message received!");
+ /// });
+ ///
+ /// let msg = receiver.recv().unwrap();
+ /// assert_eq!(1, msg);
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn send(&self, t: T) -> Result<(), SendError<T>> {
self.inner.send(t).map_err(SendError)
/// data. Compared with [`send`], this function has two failure cases
/// instead of one (one for disconnection, one for a full buffer).
///
- /// See [`SyncSender::send`] for notes about guarantees of whether the
+ /// See [`send`] for notes about guarantees of whether the
/// receiver has received the data or not if this function is successful.
///
- /// [`send`]: ../../../std/sync/mpsc/struct.Sender.html#method.send
- /// [`SyncSender::send`]: ../../../std/sync/mpsc/struct.SyncSender.html#method.send
+ /// [`send`]: ../../../std/sync/mpsc/struct.SyncSender.html#method.send
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use std::sync::mpsc::sync_channel;
+ /// use std::thread;
+ ///
+ /// // Create a sync_channel with buffer size 1
+ /// let (sync_sender, receiver) = sync_channel(1);
+ /// let sync_sender2 = sync_sender.clone();
+ ///
+ /// // First thread owns sync_sender
+ /// thread::spawn(move || {
+ /// sync_sender.send(1).unwrap();
+ /// sync_sender.send(2).unwrap();
+ /// // Thread blocked
+ /// });
+ ///
+ /// // Second thread owns sync_sender2
+ /// thread::spawn(move || {
+ /// // This will return an error and send
+ /// // no message if the buffer is full
+ /// sync_sender2.try_send(3).is_err();
+ /// });
+ ///
+ /// let mut msg;
+ /// msg = receiver.recv().unwrap();
+ /// println!("message {} received", msg);
+ ///
+ /// msg = receiver.recv().unwrap();
+ /// println!("message {} received", msg);
+ ///
+ /// // Third message may have never been sent
+ /// match receiver.try_recv() {
+ /// Ok(msg) => println!("message {} received", msg),
+ /// Err(_) => println!("the third message was never sent"),
+ /// }
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn try_send(&self, t: T) -> Result<(), TrySendError<T>> {
self.inner.try_send(t)
///
/// This is useful for a flavor of "optimistic check" before deciding to
/// block on a receiver.
+ ///
+ /// Compared with [`recv`], this function has two failure cases instead of one
+ /// (one for disconnection, one for an empty buffer).
+ ///
+ /// [`recv`]: struct.Receiver.html#method.recv
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use std::sync::mpsc::{Receiver, channel};
+ ///
+ /// let (_, receiver): (_, Receiver<i32>) = channel();
+ ///
+ /// assert!(receiver.try_recv().is_err());
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn try_recv(&self) -> Result<T, TryRecvError> {
loop {
///
/// This function will always block the current thread if there is no data
/// available and it's possible for more data to be sent. Once a message is
- /// sent to the corresponding [`Sender`], then this receiver will wake up and
- /// return that message.
+ /// sent to the corresponding [`Sender`][] (or [`SyncSender`]), then this
+ /// receiver will wake up and return that message.
///
/// If the corresponding [`Sender`] has disconnected, or it disconnects while
/// this call is blocking, this call will wake up and return [`Err`] to
/// However, since channels are buffered, messages sent before the disconnect
/// will still be properly received.
///
- /// [`Sender`]: ../../../std/sync/mpsc/struct.Sender.html
+ /// [`Sender`]: struct.Sender.html
+ /// [`SyncSender`]: struct.SyncSender.html
/// [`Err`]: ../../../std/result/enum.Result.html#variant.Err
///
/// # Examples
///
/// This function will always block the current thread if there is no data
/// available and it's possible for more data to be sent. Once a message is
- /// sent to the corresponding [`Sender`], then this receiver will wake up and
- /// return that message.
+ /// sent to the corresponding [`Sender`][] (or [`SyncSender`]), then this
+ /// receiver will wake up and return that message.
///
/// If the corresponding [`Sender`] has disconnected, or it disconnects while
/// this call is blocking, this call will wake up and return [`Err`] to
/// However, since channels are buffered, messages sent before the disconnect
/// will still be properly received.
///
- /// [`Sender`]: ../../../std/sync/mpsc/struct.Sender.html
+ /// [`Sender`]: struct.Sender.html
+ /// [`SyncSender`]: struct.SyncSender.html
/// [`Err`]: ../../../std/result/enum.Result.html#variant.Err
///
/// # Examples
/// user by waiting for values.
///
/// [`panic!`]: ../../../std/macro.panic.html
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use std::sync::mpsc::channel;
+ /// use std::thread;
+ /// use std::time::Duration;
+ ///
+ /// let (sender, receiver) = channel();
+ ///
+ /// // Nothing is in the buffer yet
+ /// assert!(receiver.try_iter().next().is_none());
+ /// println!("Nothing in the buffer...");
+ ///
+ /// thread::spawn(move || {
+ /// sender.send(1).unwrap();
+ /// sender.send(2).unwrap();
+ /// sender.send(3).unwrap();
+ /// });
+ ///
+ /// println!("Going to sleep...");
+ /// thread::sleep(Duration::from_secs(2)); // block for two seconds
+ ///
+ /// for x in receiver.try_iter() {
+ /// println!("Got: {}", x);
+ /// }
+ /// ```
#[stable(feature = "receiver_try_iter", since = "1.15.0")]
pub fn try_iter(&self) -> TryIter<T> {
TryIter { rx: self }
/// E.g. `impl<A> Foo<A> { .. }` or `impl<A> Trait for Foo<A> { .. }`
Impl(Unsafety,
ImplPolarity,
+ Defaultness,
Generics,
Option<TraitRef>, // (optional) trait this impl implements
P<Ty>, // self
and possibly buggy");
}
- ast::ItemKind::Impl(_, polarity, _, _, _, _) => {
+ ast::ItemKind::Impl(_, polarity, defaultness, _, _, _, _) => {
match polarity {
ast::ImplPolarity::Negative => {
gate_feature_post!(&self, optin_builtin_traits,
},
_ => {}
}
+
+ if let ast::Defaultness::Default = defaultness {
+ gate_feature_post!(&self, specialization,
+ i.span,
+ "specialization is unstable");
+ }
}
_ => {}
ItemKind::DefaultImpl(unsafety, ref trait_ref) => {
ItemKind::DefaultImpl(unsafety, folder.fold_trait_ref((*trait_ref).clone()))
}
- ItemKind::Impl(unsafety, polarity, generics, ifce, ty, impl_items) => ItemKind::Impl(
+ ItemKind::Impl(unsafety,
+ polarity,
+ defaultness,
+ generics,
+ ifce,
+ ty,
+ impl_items) => ItemKind::Impl(
unsafety,
polarity,
+ defaultness,
folder.fold_generics(generics),
ifce.map(|trait_ref| folder.fold_trait_ref(trait_ref.clone())),
folder.fold_ty(ty),
use symbol::{Symbol, keywords};
use util::ThinVec;
+use std::cmp;
use std::collections::HashSet;
-use std::{cmp, mem, slice};
+use std::mem;
use std::path::{self, Path, PathBuf};
+use std::slice;
bitflags! {
flags Restrictions: u8 {
/// impl<T> Foo { ... }
/// impl<T> ToString for &'static T { ... }
/// impl Send for .. {}
- fn parse_item_impl(&mut self, unsafety: ast::Unsafety) -> PResult<'a, ItemInfo> {
+ fn parse_item_impl(&mut self,
+ unsafety: ast::Unsafety,
+ defaultness: Defaultness) -> PResult<'a, ItemInfo> {
let impl_span = self.span;
// First, parse type parameters if necessary.
allowed to have generics");
}
+ if let ast::Defaultness::Default = defaultness {
+ self.span_err(impl_span, "`default impl` is not allowed for \
+ default trait implementations");
+ }
+
self.expect(&token::OpenDelim(token::Brace))?;
self.expect(&token::CloseDelim(token::Brace))?;
Ok((keywords::Invalid.ident(),
}
Ok((keywords::Invalid.ident(),
- ItemKind::Impl(unsafety, polarity, generics, opt_trait, ty, impl_items),
+ ItemKind::Impl(unsafety, polarity, defaultness, generics, opt_trait, ty, impl_items),
Some(attrs)))
}
}
}
let mut err = self.diagnostic().struct_span_err(id_sp,
"cannot declare a new module at this location");
- let this_module = match self.directory.path.file_name() {
- Some(file_name) => file_name.to_str().unwrap().to_owned(),
- None => self.root_module_name.as_ref().unwrap().clone(),
- };
- err.span_note(id_sp,
- &format!("maybe move this module `{0}` to its own directory \
- via `{0}{1}mod.rs`",
- this_module,
- path::MAIN_SEPARATOR));
+ if id_sp != syntax_pos::DUMMY_SP {
+ let src_path = PathBuf::from(self.sess.codemap().span_to_filename(id_sp));
+ if let Some(stem) = src_path.file_stem() {
+ let mut dest_path = src_path.clone();
+ dest_path.set_file_name(stem);
+ dest_path.push("mod.rs");
+ err.span_note(id_sp,
+ &format!("maybe move this module `{}` to its own \
+ directory via `{}`", src_path.to_string_lossy(),
+ dest_path.to_string_lossy()));
+ }
+ }
if paths.path_exists {
err.span_note(id_sp,
&format!("... or maybe `use` the module `{}` instead \
of possibly redeclaring it",
paths.name));
- Err(err)
- } else {
- Err(err)
}
+ Err(err)
} else {
paths.result.map_err(|err| self.span_fatal_err(id_sp, err))
}
maybe_append(attrs, extra_attrs));
return Ok(Some(item));
}
- if self.check_keyword(keywords::Unsafe) &&
- self.look_ahead(1, |t| t.is_keyword(keywords::Impl))
+ if (self.check_keyword(keywords::Unsafe) &&
+ self.look_ahead(1, |t| t.is_keyword(keywords::Impl))) ||
+ (self.check_keyword(keywords::Default) &&
+ self.look_ahead(1, |t| t.is_keyword(keywords::Unsafe)) &&
+ self.look_ahead(2, |t| t.is_keyword(keywords::Impl)))
{
// IMPL ITEM
+ let defaultness = self.parse_defaultness()?;
self.expect_keyword(keywords::Unsafe)?;
self.expect_keyword(keywords::Impl)?;
- let (ident, item_, extra_attrs) = self.parse_item_impl(ast::Unsafety::Unsafe)?;
+ let (ident,
+ item_,
+ extra_attrs) = self.parse_item_impl(ast::Unsafety::Unsafe, defaultness)?;
let prev_span = self.prev_span;
let item = self.mk_item(lo.to(prev_span),
ident,
maybe_append(attrs, extra_attrs));
return Ok(Some(item));
}
- if self.eat_keyword(keywords::Impl) {
+ if (self.check_keyword(keywords::Impl)) ||
+ (self.check_keyword(keywords::Default) &&
+ self.look_ahead(1, |t| t.is_keyword(keywords::Impl)))
+ {
// IMPL ITEM
- let (ident, item_, extra_attrs) = self.parse_item_impl(ast::Unsafety::Normal)?;
+ let defaultness = self.parse_defaultness()?;
+ self.expect_keyword(keywords::Impl)?;
+ let (ident,
+ item_,
+ extra_attrs) = self.parse_item_impl(ast::Unsafety::Normal, defaultness)?;
let prev_span = self.prev_span;
let item = self.mk_item(lo.to(prev_span),
ident,
}
ast::ItemKind::Impl(unsafety,
polarity,
+ defaultness,
ref generics,
ref opt_trait,
ref ty,
ref impl_items) => {
self.head("")?;
self.print_visibility(&item.vis)?;
+ self.print_defaultness(defaultness)?;
self.print_unsafety(unsafety)?;
self.word_nbsp("impl")?;
}
}
+ pub fn print_defaultness(&mut self, defatulness: ast::Defaultness) -> io::Result<()> {
+ if let ast::Defaultness::Default = defatulness {
+ try!(self.word_nbsp("default"));
+ }
+ Ok(())
+ }
+
pub fn print_struct(&mut self,
struct_def: &ast::VariantData,
generics: &ast::Generics,
self.hardbreak_if_not_bol()?;
self.maybe_print_comment(ii.span.lo)?;
self.print_outer_attributes(&ii.attrs)?;
- if let ast::Defaultness::Default = ii.defaultness {
- self.word_nbsp("default")?;
- }
+ self.print_defaultness(ii.defaultness)?;
match ii.node {
ast::ImplItemKind::Const(ref ty, ref expr) => {
self.print_associated_const(ii.ident, &ty, Some(&expr), &ii.vis)?;
ItemKind::DefaultImpl(_, ref trait_ref) => {
visitor.visit_trait_ref(trait_ref)
}
- ItemKind::Impl(_, _,
+ ItemKind::Impl(_, _, _,
ref type_parameters,
ref opt_trait_reference,
ref typ,
a,
ast::ItemKind::Impl(unsafety,
ast::ImplPolarity::Positive,
+ ast::Defaultness::Final,
trait_generics,
opt_trait_ref,
self_type,
println!("cargo:rustc-link-lib=static-nobundle=pthread");
} else if target.contains("fuchsia") {
println!("cargo:rustc-link-lib=unwind");
+ } else if target.contains("haiku") {
+ println!("cargo:rustc-link-lib=gcc_s");
}
}
-Subproject commit a884d21cc5f0b23a1693d1e872fd8998a4fdd17f
+Subproject commit 15745af7683844e43bdec966072b8e7b44772450
#define SUBTARGET_SPARC
#endif
+#ifdef LLVM_COMPONENT_HEXAGON
+#define SUBTARGET_HEXAGON SUBTARGET(Hexagon)
+#else
+#define SUBTARGET_HEXAGON
+#endif
+
#define GEN_SUBTARGETS \
SUBTARGET_X86 \
SUBTARGET_ARM \
SUBTARGET_PPC \
SUBTARGET_SYSTEMZ \
SUBTARGET_MSP430 \
- SUBTARGET_SPARC
+ SUBTARGET_SPARC \
+ SUBTARGET_HEXAGON
#define SUBTARGET(x) \
namespace llvm { \
# If this file is modified, then llvm will be (optionally) 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.
-2017-03-23
+2017-04-26
+++ /dev/null
-// 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.
-
-// check that borrowck looks inside consts/statics
-
-static FN : &'static (Fn() -> (Box<Fn()->Box<i32>>) + Sync) = &|| {
- let x = Box::new(0);
- Box::new(|| x) //~ ERROR cannot move out of captured outer variable
-};
-
-fn main() {
- let f = (FN)();
- f();
- f();
-}
match s {
S{0: a, 0x1: b, ..} => {}
//~^ ERROR does not have a field named `0x1`
- //~| NOTE struct `S::{{constructor}}` does not have field `0x1`
+ //~| NOTE struct `S` does not have field `0x1`
}
}
--- /dev/null
+// 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(specialization)]
+
+// Make sure we can't project defaulted associated types
+
+trait Foo {
+ type Assoc;
+}
+
+default impl<T> Foo for T {
+ type Assoc = ();
+}
+
+impl Foo for u8 {
+ type Assoc = String;
+}
+
+fn generic<T>() -> <T as Foo>::Assoc {
+ // `T` could be some downstream crate type that specializes (or,
+ // for that matter, `u8`).
+
+ () //~ ERROR mismatched types
+}
+
+fn monomorphic() -> () {
+ // Even though we know that `()` is not specialized in a
+ // downstream crate, typeck refuses to project here.
+
+ generic::<()>() //~ ERROR mismatched types
+}
+
+fn main() {
+ // No error here, we CAN project from `u8`, as there is no `default`
+ // in that impl.
+ let s: String = generic::<u8>();
+ println!("{}", s); // bad news if this all compiles
+}
--- /dev/null
+// 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.
+
+// It should not be possible to use the concrete value of a defaulted
+// associated type in the impl defining it -- otherwise, what happens
+// if it's overridden?
+
+#![feature(specialization)]
+
+trait Example {
+ type Output;
+ fn generate(self) -> Self::Output;
+}
+
+default impl<T> Example for T {
+ type Output = Box<T>;
+ fn generate(self) -> Self::Output {
+ Box::new(self) //~ ERROR mismatched types
+ }
+}
+
+impl Example for bool {
+ type Output = bool;
+ fn generate(self) -> bool { self }
+}
+
+fn trouble<T>(t: T) -> Box<T> {
+ Example::generate(t) //~ ERROR mismatched types
+}
+
+fn weaponize() -> bool {
+ let b: Box<bool> = trouble(true);
+ *b
+}
+
+fn main() {
+ weaponize();
+}
--- /dev/null
+// 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.
+
+// Check that specialization must be ungated to use the `default` keyword
+
+trait Foo {
+ fn foo(&self);
+}
+
+default impl<T> Foo for T { //~ ERROR specialization is unstable
+ fn foo(&self) {}
+}
+
+fn main() {}
--- /dev/null
+// 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(specialization)]
+#![feature(optin_builtin_traits)]
+
+trait Foo {}
+
+default impl Foo for .. {}
+//~^ ERROR `default impl` is not allowed for default trait implementations
+
+fn main() {}
--- /dev/null
+// 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(specialization)]
+
+// Check a number of scenarios in which one impl tries to override another,
+// without correctly using `default`.
+
+////////////////////////////////////////////////////////////////////////////////
+// Test 1: one layer of specialization, multiple methods, missing `default`
+////////////////////////////////////////////////////////////////////////////////
+
+trait Foo {
+ fn foo(&self);
+ fn bar(&self);
+}
+
+impl<T> Foo for T {
+ fn foo(&self) {}
+ fn bar(&self) {}
+}
+
+impl Foo for u8 {}
+impl Foo for u16 {
+ fn foo(&self) {} //~ ERROR E0520
+}
+impl Foo for u32 {
+ fn bar(&self) {} //~ ERROR E0520
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Test 2: one layer of specialization, missing `default` on associated type
+////////////////////////////////////////////////////////////////////////////////
+
+trait Bar {
+ type T;
+}
+
+impl<T> Bar for T {
+ type T = u8;
+}
+
+impl Bar for u8 {
+ type T = (); //~ ERROR E0520
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Test 3a: multiple layers of specialization, missing interior `default`
+////////////////////////////////////////////////////////////////////////////////
+
+trait Baz {
+ fn baz(&self);
+}
+
+default impl<T> Baz for T {
+ fn baz(&self) {}
+}
+
+impl<T: Clone> Baz for T {
+ fn baz(&self) {}
+}
+
+impl Baz for i32 {
+ fn baz(&self) {} //~ ERROR E0520
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Test 3b: multiple layers of specialization, missing interior `default`,
+// redundant `default` in bottom layer.
+////////////////////////////////////////////////////////////////////////////////
+
+trait Redundant {
+ fn redundant(&self);
+}
+
+default impl<T> Redundant for T {
+ fn redundant(&self) {}
+}
+
+impl<T: Clone> Redundant for T {
+ fn redundant(&self) {}
+}
+
+default impl Redundant for i32 {
+ fn redundant(&self) {} //~ ERROR E0520
+}
+
+fn main() {}
+++ /dev/null
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Test that a by-ref `FnMut` closure gets an error when it tries to
-// consume a value.
-
-fn call<F>(f: F) where F : Fn() {
- f();
-}
-
-fn main() {
- let y = vec![format!("World")];
- call(|| {
- y.into_iter();
- //~^ ERROR cannot move out of captured outer variable in an `Fn` closure
- });
-}
--- /dev/null
+// Copyright 2017 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.
+
+const A: [u32; 1] = [0];
+
+fn test() {
+ let range = A[1]..;
+}
+
+fn main() { }
+
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(specialization)]
+
+// Common code used for tests that model the Fn/FnMut/FnOnce hierarchy.
+
+pub trait Go {
+ fn go(&self, arg: isize);
+}
+
+pub fn go<G:Go>(this: &G, arg: isize) {
+ this.go(arg)
+}
+
+pub trait GoMut {
+ fn go_mut(&mut self, arg: isize);
+}
+
+pub fn go_mut<G:GoMut>(this: &mut G, arg: isize) {
+ this.go_mut(arg)
+}
+
+pub trait GoOnce {
+ fn go_once(self, arg: isize);
+}
+
+pub fn go_once<G:GoOnce>(this: G, arg: isize) {
+ this.go_once(arg)
+}
+
+default impl<G> GoMut for G
+ where G : Go
+{
+ fn go_mut(&mut self, arg: isize) {
+ go(&*self, arg)
+ }
+}
+
+default impl<G> GoOnce for G
+ where G : GoMut
+{
+ fn go_once(mut self, arg: isize) {
+ go_mut(&mut self, arg)
+ }
+}
--- /dev/null
+// 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(specialization)]
+
+pub trait Foo {
+ fn foo(&self) -> &'static str;
+}
+
+default impl<T> Foo for T {
+ fn foo(&self) -> &'static str {
+ "generic"
+ }
+}
+
+default impl<T: Clone> Foo for T {
+ fn foo(&self) -> &'static str {
+ "generic Clone"
+ }
+}
+
+default impl<T, U> Foo for (T, U) where T: Clone, U: Clone {
+ fn foo(&self) -> &'static str {
+ "generic pair"
+ }
+}
+
+default impl<T: Clone> Foo for (T, T) {
+ fn foo(&self) -> &'static str {
+ "generic uniform pair"
+ }
+}
+
+default impl Foo for (u8, u32) {
+ fn foo(&self) -> &'static str {
+ "(u8, u32)"
+ }
+}
+
+default impl Foo for (u8, u8) {
+ fn foo(&self) -> &'static str {
+ "(u8, u8)"
+ }
+}
+
+default impl<T: Clone> Foo for Vec<T> {
+ fn foo(&self) -> &'static str {
+ "generic Vec"
+ }
+}
+
+impl Foo for Vec<i32> {
+ fn foo(&self) -> &'static str {
+ "Vec<i32>"
+ }
+}
+
+impl Foo for String {
+ fn foo(&self) -> &'static str {
+ "String"
+ }
+}
+
+impl Foo for i32 {
+ fn foo(&self) -> &'static str {
+ "i32"
+ }
+}
+
+pub trait MyMarker {}
+default impl<T: Clone + MyMarker> Foo for T {
+ fn foo(&self) -> &'static str {
+ "generic Clone + MyMarker"
+ }
+}
--- /dev/null
+// 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(specialization)]
+
+// First, test only use of explicit `default` items:
+
+pub trait Foo {
+ fn foo(&self) -> bool;
+}
+
+default impl<T> Foo for T {
+ fn foo(&self) -> bool { false }
+}
+
+impl Foo for i32 {}
+
+impl Foo for i64 {
+ fn foo(&self) -> bool { true }
+}
+
+// Next, test mixture of explicit `default` and provided methods:
+
+pub trait Bar {
+ fn bar(&self) -> i32 { 0 }
+}
+
+impl<T> Bar for T {} // use the provided method
+
+impl Bar for i32 {
+ fn bar(&self) -> i32 { 1 }
+}
+impl<'a> Bar for &'a str {}
+
+default impl<T> Bar for Vec<T> {
+ fn bar(&self) -> i32 { 2 }
+}
+impl Bar for Vec<i32> {}
+impl Bar for Vec<i64> {
+ fn bar(&self) -> i32 { 3 }
+}
--- /dev/null
+// 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.
+
+// aux-build:go_trait.rs
+
+#![feature(specialization)]
+
+extern crate go_trait;
+
+use go_trait::{Go,GoMut};
+use std::fmt::Debug;
+use std::default::Default;
+
+struct MyThingy;
+
+impl Go for MyThingy {
+ fn go(&self, arg: isize) { }
+}
+
+impl GoMut for MyThingy {
+ fn go_mut(&mut self, arg: isize) { }
+}
+
+fn main() { }
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that non-method associated functions can be specialized
+
+#![feature(specialization)]
+
+trait Foo {
+ fn mk() -> Self;
+}
+
+default impl<T: Default> Foo for T {
+ fn mk() -> T {
+ T::default()
+ }
+}
+
+impl Foo for Vec<u8> {
+ fn mk() -> Vec<u8> {
+ vec![0]
+ }
+}
+
+fn main() {
+ let v1: Vec<i32> = Foo::mk();
+ let v2: Vec<u8> = Foo::mk();
+
+ assert!(v1.len() == 0);
+ assert!(v2.len() == 1);
+}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(specialization)]
+
+// Tests a variety of basic specialization scenarios and method
+// dispatch for them.
+
+unsafe trait Foo {
+ fn foo(&self) -> &'static str;
+}
+
+default unsafe impl<T> Foo for T {
+ fn foo(&self) -> &'static str {
+ "generic"
+ }
+}
+
+default unsafe impl<T: Clone> Foo for T {
+ fn foo(&self) -> &'static str {
+ "generic Clone"
+ }
+}
+
+default unsafe impl<T, U> Foo for (T, U) where T: Clone, U: Clone {
+ fn foo(&self) -> &'static str {
+ "generic pair"
+ }
+}
+
+default unsafe impl<T: Clone> Foo for (T, T) {
+ fn foo(&self) -> &'static str {
+ "generic uniform pair"
+ }
+}
+
+default unsafe impl Foo for (u8, u32) {
+ fn foo(&self) -> &'static str {
+ "(u8, u32)"
+ }
+}
+
+default unsafe impl Foo for (u8, u8) {
+ fn foo(&self) -> &'static str {
+ "(u8, u8)"
+ }
+}
+
+default unsafe impl<T: Clone> Foo for Vec<T> {
+ fn foo(&self) -> &'static str {
+ "generic Vec"
+ }
+}
+
+default unsafe impl Foo for Vec<i32> {
+ fn foo(&self) -> &'static str {
+ "Vec<i32>"
+ }
+}
+
+default unsafe impl Foo for String {
+ fn foo(&self) -> &'static str {
+ "String"
+ }
+}
+
+default unsafe impl Foo for i32 {
+ fn foo(&self) -> &'static str {
+ "i32"
+ }
+}
+
+struct NotClone;
+
+unsafe trait MyMarker {}
+default unsafe impl<T: Clone + MyMarker> Foo for T {
+ fn foo(&self) -> &'static str {
+ "generic Clone + MyMarker"
+ }
+}
+
+#[derive(Clone)]
+struct MarkedAndClone;
+unsafe impl MyMarker for MarkedAndClone {}
+
+fn main() {
+ assert!(NotClone.foo() == "generic");
+ assert!(0u8.foo() == "generic Clone");
+ assert!(vec![NotClone].foo() == "generic");
+ assert!(vec![0u8].foo() == "generic Vec");
+ assert!(vec![0i32].foo() == "Vec<i32>");
+ assert!(0i32.foo() == "i32");
+ assert!(String::new().foo() == "String");
+ assert!(((), 0).foo() == "generic pair");
+ assert!(((), ()).foo() == "generic uniform pair");
+ assert!((0u8, 0u32).foo() == "(u8, u32)");
+ assert!((0u8, 0u8).foo() == "(u8, u8)");
+ assert!(MarkedAndClone.foo() == "generic Clone + MyMarker");
+}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(specialization)]
+
+// Tests a variety of basic specialization scenarios and method
+// dispatch for them.
+
+trait Foo {
+ fn foo(&self) -> &'static str;
+}
+
+default impl<T> Foo for T {
+ fn foo(&self) -> &'static str {
+ "generic"
+ }
+}
+
+default impl<T: Clone> Foo for T {
+ fn foo(&self) -> &'static str {
+ "generic Clone"
+ }
+}
+
+default impl<T, U> Foo for (T, U) where T: Clone, U: Clone {
+ fn foo(&self) -> &'static str {
+ "generic pair"
+ }
+}
+
+default impl<T: Clone> Foo for (T, T) {
+ fn foo(&self) -> &'static str {
+ "generic uniform pair"
+ }
+}
+
+default impl Foo for (u8, u32) {
+ fn foo(&self) -> &'static str {
+ "(u8, u32)"
+ }
+}
+
+default impl Foo for (u8, u8) {
+ fn foo(&self) -> &'static str {
+ "(u8, u8)"
+ }
+}
+
+default impl<T: Clone> Foo for Vec<T> {
+ fn foo(&self) -> &'static str {
+ "generic Vec"
+ }
+}
+
+impl Foo for Vec<i32> {
+ fn foo(&self) -> &'static str {
+ "Vec<i32>"
+ }
+}
+
+impl Foo for String {
+ fn foo(&self) -> &'static str {
+ "String"
+ }
+}
+
+impl Foo for i32 {
+ fn foo(&self) -> &'static str {
+ "i32"
+ }
+}
+
+struct NotClone;
+
+trait MyMarker {}
+default impl<T: Clone + MyMarker> Foo for T {
+ fn foo(&self) -> &'static str {
+ "generic Clone + MyMarker"
+ }
+}
+
+#[derive(Clone)]
+struct MarkedAndClone;
+impl MyMarker for MarkedAndClone {}
+
+fn main() {
+ assert!(NotClone.foo() == "generic");
+ assert!(0u8.foo() == "generic Clone");
+ assert!(vec![NotClone].foo() == "generic");
+ assert!(vec![0u8].foo() == "generic Vec");
+ assert!(vec![0i32].foo() == "Vec<i32>");
+ assert!(0i32.foo() == "i32");
+ assert!(String::new().foo() == "String");
+ assert!(((), 0).foo() == "generic pair");
+ assert!(((), ()).foo() == "generic uniform pair");
+ assert!((0u8, 0u32).foo() == "(u8, u32)");
+ assert!((0u8, 0u8).foo() == "(u8, u8)");
+ assert!(MarkedAndClone.foo() == "generic Clone + MyMarker");
+}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:specialization_cross_crate_defaults.rs
+
+#![feature(specialization)]
+
+extern crate specialization_cross_crate_defaults;
+
+use specialization_cross_crate_defaults::*;
+
+struct LocalDefault;
+struct LocalOverride;
+
+impl Foo for LocalDefault {}
+
+impl Foo for LocalOverride {
+ fn foo(&self) -> bool { true }
+}
+
+fn test_foo() {
+ assert!(!0i8.foo());
+ assert!(!0i32.foo());
+ assert!(0i64.foo());
+
+ assert!(!LocalDefault.foo());
+ assert!(LocalOverride.foo());
+}
+
+fn test_bar() {
+ assert!(0u8.bar() == 0);
+ assert!(0i32.bar() == 1);
+ assert!("hello".bar() == 0);
+ assert!(vec![()].bar() == 2);
+ assert!(vec![0i32].bar() == 2);
+ assert!(vec![0i64].bar() == 3);
+}
+
+fn main() {
+ test_foo();
+ test_bar();
+}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that specialization works even if only the upstream crate enables it
+
+// aux-build:specialization_cross_crate.rs
+
+extern crate specialization_cross_crate;
+
+use specialization_cross_crate::*;
+
+fn main() {
+ assert!(0u8.foo() == "generic Clone");
+ assert!(vec![0u8].foo() == "generic Vec");
+ assert!(vec![0i32].foo() == "Vec<i32>");
+ assert!(0i32.foo() == "i32");
+ assert!(String::new().foo() == "String");
+ assert!(((), 0).foo() == "generic pair");
+ assert!(((), ()).foo() == "generic uniform pair");
+ assert!((0u8, 0u32).foo() == "(u8, u32)");
+ assert!((0u8, 0u8).foo() == "(u8, u8)");
+}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:specialization_cross_crate.rs
+
+#![feature(specialization)]
+
+extern crate specialization_cross_crate;
+
+use specialization_cross_crate::*;
+
+struct NotClone;
+
+#[derive(Clone)]
+struct MarkedAndClone;
+impl MyMarker for MarkedAndClone {}
+
+struct MyType<T>(T);
+default impl<T> Foo for MyType<T> {
+ fn foo(&self) -> &'static str {
+ "generic MyType"
+ }
+}
+
+impl Foo for MyType<u8> {
+ fn foo(&self) -> &'static str {
+ "MyType<u8>"
+ }
+}
+
+struct MyOtherType;
+impl Foo for MyOtherType {}
+
+fn main() {
+ assert!(NotClone.foo() == "generic");
+ assert!(0u8.foo() == "generic Clone");
+ assert!(vec![NotClone].foo() == "generic");
+ assert!(vec![0u8].foo() == "generic Vec");
+ assert!(vec![0i32].foo() == "Vec<i32>");
+ assert!(0i32.foo() == "i32");
+ assert!(String::new().foo() == "String");
+ assert!(((), 0).foo() == "generic pair");
+ assert!(((), ()).foo() == "generic uniform pair");
+ assert!((0u8, 0u32).foo() == "(u8, u32)");
+ assert!((0u8, 0u8).foo() == "(u8, u8)");
+ assert!(MarkedAndClone.foo() == "generic Clone + MyMarker");
+
+ assert!(MyType(()).foo() == "generic MyType");
+ assert!(MyType(0u8).foo() == "MyType<u8>");
+ assert!(MyOtherType.foo() == "generic");
+}
--- /dev/null
+// 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(specialization)]
+
+// Test that default methods are cascaded correctly
+
+// First, test only use of explicit `default` items:
+
+trait Foo {
+ fn foo(&self) -> bool;
+}
+
+// Specialization tree for Foo:
+//
+// T
+// / \
+// i32 i64
+
+default impl<T> Foo for T {
+ fn foo(&self) -> bool { false }
+}
+
+impl Foo for i32 {}
+
+impl Foo for i64 {
+ fn foo(&self) -> bool { true }
+}
+
+fn test_foo() {
+ assert!(!0i8.foo());
+ assert!(!0i32.foo());
+ assert!(0i64.foo());
+}
+
+// Next, test mixture of explicit `default` and provided methods:
+
+trait Bar {
+ fn bar(&self) -> i32 { 0 }
+}
+
+// Specialization tree for Bar.
+// Uses of $ designate that method is provided
+//
+// $Bar (the trait)
+// |
+// T
+// /|\
+// / | \
+// / | \
+// / | \
+// / | \
+// / | \
+// $i32 &str $Vec<T>
+// /\
+// / \
+// Vec<i32> $Vec<i64>
+
+// use the provided method
+impl<T> Bar for T {}
+
+impl Bar for i32 {
+ fn bar(&self) -> i32 { 1 }
+}
+impl<'a> Bar for &'a str {}
+
+default impl<T> Bar for Vec<T> {
+ fn bar(&self) -> i32 { 2 }
+}
+impl Bar for Vec<i32> {}
+impl Bar for Vec<i64> {
+ fn bar(&self) -> i32 { 3 }
+}
+
+fn test_bar() {
+ assert!(0u8.bar() == 0);
+ assert!(0i32.bar() == 1);
+ assert!("hello".bar() == 0);
+ assert!(vec![()].bar() == 2);
+ assert!(vec![0i32].bar() == 2);
+ assert!(vec![0i64].bar() == 3);
+}
+
+fn main() {
+ test_foo();
+ test_bar();
+}
--- /dev/null
+// 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 you can list the more specific impl before the more general one.
+
+#![feature(specialization)]
+
+trait Foo {
+ type Out;
+}
+
+impl Foo for bool {
+ type Out = ();
+}
+
+default impl<T> Foo for T {
+ type Out = bool;
+}
+
+fn main() {}
--- /dev/null
+// 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 impls on projected self types can resolve overlap, even when the
+// projections involve specialization, so long as the associated type is
+// provided by the most specialized impl.
+
+#![feature(specialization)]
+
+trait Assoc {
+ type Output;
+}
+
+default impl<T> Assoc for T {
+ type Output = bool;
+}
+
+impl Assoc for u8 { type Output = u8; }
+impl Assoc for u16 { type Output = u16; }
+
+trait Foo {}
+impl Foo for u32 {}
+impl Foo for <u8 as Assoc>::Output {}
+impl Foo for <u16 as Assoc>::Output {}
+
+fn main() {}
--- /dev/null
+// 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(specialization)]
+
+// Regression test for ICE when combining specialized associated types and type
+// aliases
+
+trait Id_ {
+ type Out;
+}
+
+type Id<T> = <T as Id_>::Out;
+
+default impl<T> Id_ for T {
+ type Out = T;
+}
+
+fn test_proection() {
+ let x: Id<bool> = panic!();
+}
+
+fn main() {
+
+}
--- /dev/null
+// 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(specialization)]
+
+// Make sure we *can* project non-defaulted associated types
+// cf compile-fail/specialization-default-projection.rs
+
+// First, do so without any use of specialization
+
+trait Foo {
+ type Assoc;
+}
+
+impl<T> Foo for T {
+ type Assoc = ();
+}
+
+fn generic_foo<T>() -> <T as Foo>::Assoc {
+ ()
+}
+
+// Next, allow for one layer of specialization
+
+trait Bar {
+ type Assoc;
+}
+
+default impl<T> Bar for T {
+ type Assoc = ();
+}
+
+impl<T: Clone> Bar for T {
+ type Assoc = u8;
+}
+
+fn generic_bar_clone<T: Clone>() -> <T as Bar>::Assoc {
+ 0u8
+}
+
+fn main() {
+}
--- /dev/null
+// 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.
+
+// check that borrowck looks inside consts/statics
+
+static FN : &'static (Fn() -> (Box<Fn()->Box<i32>>) + Sync) = &|| {
+ let x = Box::new(0); //~ NOTE moved
+ Box::new(|| x) //~ ERROR cannot move out of captured outer variable
+};
+
+fn main() {
+ let f = (FN)();
+ f();
+ f();
+}
--- /dev/null
+error[E0507]: cannot move out of captured outer variable in an `Fn` closure
+ --> $DIR/borrowck-in-static.rs:15:17
+ |
+14 | let x = Box::new(0); //~ NOTE moved
+ | - captured outer variable
+15 | Box::new(|| x) //~ ERROR cannot move out of captured outer variable
+ | ^ cannot move out of captured outer variable in an `Fn` closure
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that a by-ref `FnMut` closure gets an error when it tries to
+// consume a value.
+
+fn call<F>(f: F) where F : Fn() {
+ f();
+}
+
+fn main() {
+ let y = vec![format!("World")]; //~ NOTE moved
+ call(|| {
+ y.into_iter();
+ //~^ ERROR cannot move out of captured outer variable in an `Fn` closure
+ });
+}
--- /dev/null
+error[E0507]: cannot move out of captured outer variable in an `Fn` closure
+ --> $DIR/unboxed-closures-move-upvar-from-non-once-ref-closure.rs:21:9
+ |
+19 | let y = vec![format!("World")]; //~ NOTE moved
+ | - captured outer variable
+20 | call(|| {
+21 | y.into_iter();
+ | ^ cannot move out of captured outer variable in an `Fn` closure
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2017 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.
+
+pub mod baz;
--- /dev/null
+// Copyright 2017 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.
+
+pub mod bar;
--- /dev/null
+// 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-tidy-linelength
+
+// error-pattern: cannot declare a new module at this location
+// error-pattern: maybe move this module
+
+mod auxiliary {
+ mod foo;
+}
+
+fn main() {}
--- /dev/null
+error: cannot declare a new module at this location
+ --> $DIR/auxiliary/foo/bar.rs:11:9
+ |
+11 | pub mod baz;
+ | ^^^
+ |
+note: maybe move this module `$DIR/auxiliary/foo/bar.rs` to its own directory via `$DIR/auxiliary/foo/bar/mod.rs`
+ --> $DIR/auxiliary/foo/bar.rs:11:9
+ |
+11 | pub mod baz;
+ | ^^^
+
+error: aborting due to previous error
+
fn call<F>(mut f: F) where F: FnMut(Fn) {
f(Box::new(|| {
//~^ ERROR: cannot borrow `f` as mutable more than once
+ //~| NOTE first mutable borrow occurs here
+ //~| NOTE second mutable borrow occurs here
f((Box::new(|| {})))
}));
+ //~^ NOTE first borrow ends here
}
fn test1() {
}
fn test2<F>(f: &F) where F: FnMut() {
- (*f)(); //~ ERROR: cannot borrow immutable borrowed content `*f` as mutable
+ //~^ NOTE use `&mut F` here to make mutable
+ (*f)();
+ //~^ ERROR cannot borrow immutable borrowed content `*f` as mutable
+ //~| NOTE cannot borrow as mutable
}
fn test3<F>(f: &mut F) where F: FnMut() {
}
fn test4(f: &Test) {
- f.f.call_mut(()) //~ ERROR: cannot borrow immutable `Box` content `*f.f` as mutable
+ //~^ NOTE use `&mut Test` here to make mutable
+ f.f.call_mut(())
+ //~^ ERROR: cannot borrow immutable `Box` content `*f.f` as mutable
+ //~| NOTE cannot borrow as mutable
}
fn test5(f: &mut Test) {
fn test7() {
fn foo<F>(_: F) where F: FnMut(Box<FnMut(isize)>, isize) {}
let mut f = |g: Box<FnMut(isize)>, b: isize| {};
+ //~^ NOTE moved
f(Box::new(|a| {
+ //~^ NOTE borrow of `f` occurs here
foo(f);
//~^ ERROR cannot move `f` into closure because it is borrowed
//~| ERROR cannot move out of captured outer variable in an `FnMut` closure
+ //~| NOTE move into closure occurs here
+ //~| NOTE cannot move out of captured outer variable in an `FnMut` closure
}), 3);
}
| - ^^ second mutable borrow occurs here
| |
| first mutable borrow occurs here
-23 | //~^ ERROR: cannot borrow `f` as mutable more than once
-24 | f((Box::new(|| {})))
+...
+26 | f((Box::new(|| {})))
| - borrow occurs due to use of `f` in closure
-25 | }));
+27 | }));
| - first borrow ends here
error: cannot borrow immutable borrowed content `*f` as mutable
- --> $DIR/borrowck-call-is-borrow-issue-12224.rs:35:5
+ --> $DIR/borrowck-call-is-borrow-issue-12224.rs:39:5
|
-34 | fn test2<F>(f: &F) where F: FnMut() {
+37 | fn test2<F>(f: &F) where F: FnMut() {
| -- use `&mut F` here to make mutable
-35 | (*f)(); //~ ERROR: cannot borrow immutable borrowed content `*f` as mutable
+38 | //~^ NOTE use `&mut F` here to make mutable
+39 | (*f)();
| ^^^^ cannot borrow as mutable
error: cannot borrow immutable `Box` content `*f.f` as mutable
- --> $DIR/borrowck-call-is-borrow-issue-12224.rs:43:5
+ --> $DIR/borrowck-call-is-borrow-issue-12224.rs:50:5
|
-42 | fn test4(f: &Test) {
+48 | fn test4(f: &Test) {
| ----- use `&mut Test` here to make mutable
-43 | f.f.call_mut(()) //~ ERROR: cannot borrow immutable `Box` content `*f.f` as mutable
+49 | //~^ NOTE use `&mut Test` here to make mutable
+50 | f.f.call_mut(())
| ^^^ cannot borrow as mutable
error[E0504]: cannot move `f` into closure because it is borrowed
- --> $DIR/borrowck-call-is-borrow-issue-12224.rs:61:13
+ --> $DIR/borrowck-call-is-borrow-issue-12224.rs:72:13
|
-60 | f(Box::new(|a| {
+70 | f(Box::new(|a| {
| - borrow of `f` occurs here
-61 | foo(f);
+71 | //~^ NOTE borrow of `f` occurs here
+72 | foo(f);
| ^ move into closure occurs here
error[E0507]: cannot move out of captured outer variable in an `FnMut` closure
- --> $DIR/borrowck-call-is-borrow-issue-12224.rs:61:13
+ --> $DIR/borrowck-call-is-borrow-issue-12224.rs:72:13
|
-61 | foo(f);
+68 | let mut f = |g: Box<FnMut(isize)>, b: isize| {};
+ | ----- captured outer variable
+...
+72 | foo(f);
| ^ cannot move out of captured outer variable in an `FnMut` closure
error: aborting due to 5 previous errors
"PATH"
} else if cfg!(target_os = "macos") {
"DYLD_LIBRARY_PATH"
+ } else if cfg!(target_os = "haiku") {
+ "LIBRARY_PATH"
} else {
"LD_LIBRARY_PATH"
}