sys.exit(ret)
def output(self, args, env=None, cwd=None):
+ default_encoding = sys.getdefaultencoding()
proc = subprocess.Popen(args, stdout=subprocess.PIPE, env=env, cwd=cwd)
(out, err) = proc.communicate()
ret = proc.wait()
if ret != 0:
print(out)
sys.exit(ret)
- return out
+ return out.decode(default_encoding)
def build_triple(self):
default_encoding = sys.getdefaultencoding()
for submod in submodules:
path, status = submod
- if path.endswith(b"llvm") and \
+ if path.endswith('llvm') and \
(self.get_toml('llvm-config') or self.get_mk('CFG_LLVM_ROOT')):
continue
- if path.endswith(b"jemalloc") and \
+ if path.endswith('jemalloc') and \
(self.get_toml('jemalloc') or self.get_mk('CFG_JEMALLOC_ROOT')):
continue
submod_path = os.path.join(self.rust_root, path)
pub backtrace: bool, // support for RUST_BACKTRACE
// misc
+ pub low_priority: bool,
pub channel: String,
pub quiet_tests: bool,
// Fallback musl-root for all targets
target: Vec<String>,
cargo: Option<String>,
rustc: Option<String>,
+ low_priority: Option<bool>,
compiler_docs: Option<bool>,
docs: Option<bool>,
submodules: Option<bool>,
config.nodejs = build.nodejs.map(PathBuf::from);
config.gdb = build.gdb.map(PathBuf::from);
config.python = build.python.map(PathBuf::from);
+ set(&mut config.low_priority, build.low_priority);
set(&mut config.compiler_docs, build.compiler_docs);
set(&mut config.docs, build.docs);
set(&mut config.submodules, build.submodules);
# known-good version of OpenSSL, compile it, and link it to Cargo.
#openssl-static = false
+# Run the build with low priority, by setting the process group's "nice" value
+# to +10 on Unix platforms, and by using a "low priority" job object on Windows.
+#low-priority = false
+
# =============================================================================
# General install configuration options
# =============================================================================
use Build;
use dist::{sanitize_sh, tmpdir};
-/// Installs everything.
-pub fn install(build: &Build, stage: u32, host: &str) {
- let prefix_default = PathBuf::from("/usr/local");
- let sysconfdir_default = PathBuf::from("/etc");
- let docdir_default = PathBuf::from("share/doc/rust");
- let bindir_default = PathBuf::from("bin");
- let libdir_default = PathBuf::from("lib");
- let mandir_default = PathBuf::from("share/man");
- let prefix = build.config.prefix.as_ref().unwrap_or(&prefix_default);
- let sysconfdir = build.config.sysconfdir.as_ref().unwrap_or(&sysconfdir_default);
- let docdir = build.config.docdir.as_ref().unwrap_or(&docdir_default);
- let bindir = build.config.bindir.as_ref().unwrap_or(&bindir_default);
- let libdir = build.config.libdir.as_ref().unwrap_or(&libdir_default);
- let mandir = build.config.mandir.as_ref().unwrap_or(&mandir_default);
-
- let sysconfdir = prefix.join(sysconfdir);
- let docdir = prefix.join(docdir);
- let bindir = prefix.join(bindir);
- let libdir = prefix.join(libdir);
- let mandir = prefix.join(mandir);
-
- let destdir = env::var_os("DESTDIR").map(PathBuf::from);
-
- let prefix = add_destdir(&prefix, &destdir);
- let sysconfdir = add_destdir(&sysconfdir, &destdir);
- let docdir = add_destdir(&docdir, &destdir);
- let bindir = add_destdir(&bindir, &destdir);
- let libdir = add_destdir(&libdir, &destdir);
- let mandir = add_destdir(&mandir, &destdir);
-
- let empty_dir = build.out.join("tmp/empty_dir");
- t!(fs::create_dir_all(&empty_dir));
- if build.config.docs {
- install_sh(&build, "docs", "rust-docs", &build.rust_package_vers(),
- stage, host, &prefix, &sysconfdir, &docdir, &bindir, &libdir,
- &mandir, &empty_dir);
- }
+pub struct Installer<'a> {
+ build: &'a Build,
+ prefix: PathBuf,
+ sysconfdir: PathBuf,
+ docdir: PathBuf,
+ bindir: PathBuf,
+ libdir: PathBuf,
+ mandir: PathBuf,
+}
- for target in build.config.target.iter() {
- install_sh(&build, "std", "rust-std", &build.rust_package_vers(),
- stage, target, &prefix, &sysconfdir, &docdir, &bindir, &libdir,
- &mandir, &empty_dir);
- }
+impl<'a> Installer<'a> {
+ pub fn new(build: &'a Build) -> Installer<'a> {
+ let prefix_default = PathBuf::from("/usr/local");
+ let sysconfdir_default = PathBuf::from("/etc");
+ let docdir_default = PathBuf::from("share/doc/rust");
+ let bindir_default = PathBuf::from("bin");
+ let libdir_default = PathBuf::from("lib");
+ let mandir_default = PathBuf::from("share/man");
+ let prefix = build.config.prefix.as_ref().unwrap_or(&prefix_default);
+ let sysconfdir = build.config.sysconfdir.as_ref().unwrap_or(&sysconfdir_default);
+ let docdir = build.config.docdir.as_ref().unwrap_or(&docdir_default);
+ let bindir = build.config.bindir.as_ref().unwrap_or(&bindir_default);
+ let libdir = build.config.libdir.as_ref().unwrap_or(&libdir_default);
+ let mandir = build.config.mandir.as_ref().unwrap_or(&mandir_default);
+
+ let sysconfdir = prefix.join(sysconfdir);
+ let docdir = prefix.join(docdir);
+ let bindir = prefix.join(bindir);
+ let libdir = prefix.join(libdir);
+ let mandir = prefix.join(mandir);
+
+ let destdir = env::var_os("DESTDIR").map(PathBuf::from);
- if build.config.extended {
- install_sh(&build, "cargo", "cargo", &build.cargo_package_vers(),
- stage, host, &prefix, &sysconfdir, &docdir, &bindir, &libdir,
- &mandir, &empty_dir);
- install_sh(&build, "rls", "rls", &build.rls_package_vers(),
- stage, host, &prefix, &sysconfdir, &docdir, &bindir, &libdir,
- &mandir, &empty_dir);
+ let prefix = add_destdir(&prefix, &destdir);
+ let sysconfdir = add_destdir(&sysconfdir, &destdir);
+ let docdir = add_destdir(&docdir, &destdir);
+ let bindir = add_destdir(&bindir, &destdir);
+ let libdir = add_destdir(&libdir, &destdir);
+ let mandir = add_destdir(&mandir, &destdir);
+
+ Installer {
+ build,
+ prefix,
+ sysconfdir,
+ docdir,
+ bindir,
+ libdir,
+ mandir,
+ }
}
- install_sh(&build, "rustc", "rustc", &build.rust_package_vers(),
- stage, host, &prefix, &sysconfdir, &docdir, &bindir, &libdir,
- &mandir, &empty_dir);
+ /// Installs everything.
+ pub fn install(&self, stage: u32, host: &str) {
+ let empty_dir = self.build.out.join("tmp/empty_dir");
+ t!(fs::create_dir_all(&empty_dir));
- t!(fs::remove_dir_all(&empty_dir));
-}
+ if self.build.config.docs {
+ self.install_sh("docs", "rust-docs", &self.build.rust_package_vers(),
+ stage, Some(host), &empty_dir);
+ }
-fn install_sh(build: &Build, package: &str, name: &str, version: &str, stage: u32, host: &str,
- prefix: &Path, sysconfdir: &Path, docdir: &Path, bindir: &Path, libdir: &Path,
- mandir: &Path, empty_dir: &Path) {
- println!("Install {} stage{} ({})", package, stage, host);
- let package_name = format!("{}-{}-{}", name, version, host);
-
- let mut cmd = Command::new("sh");
- cmd.current_dir(empty_dir)
- .arg(sanitize_sh(&tmpdir(build).join(&package_name).join("install.sh")))
- .arg(format!("--prefix={}", sanitize_sh(prefix)))
- .arg(format!("--sysconfdir={}", sanitize_sh(sysconfdir)))
- .arg(format!("--docdir={}", sanitize_sh(docdir)))
- .arg(format!("--bindir={}", sanitize_sh(bindir)))
- .arg(format!("--libdir={}", sanitize_sh(libdir)))
- .arg(format!("--mandir={}", sanitize_sh(mandir)))
- .arg("--disable-ldconfig");
- build.run(&mut cmd);
+ for target in self.build.config.target.iter() {
+ self.install_sh("std", "rust-std", &self.build.rust_package_vers(),
+ stage, Some(target), &empty_dir);
+ }
+
+ if self.build.config.extended {
+ self.install_sh("cargo", "cargo", &self.build.cargo_package_vers(),
+ stage, Some(host), &empty_dir);
+ self.install_sh("rls", "rls", &self.build.rls_package_vers(),
+ stage, Some(host), &empty_dir);
+ self.install_sh("analysis", "rust-analysis", &self.build.rust_package_vers(),
+ stage, Some(host), &empty_dir);
+ self.install_sh("src", "rust-src", &self.build.rust_package_vers(),
+ stage, None, &empty_dir);
+ }
+
+ self.install_sh("rustc", "rustc", &self.build.rust_package_vers(),
+ stage, Some(host), &empty_dir);
+
+ t!(fs::remove_dir_all(&empty_dir));
+ }
+
+ fn install_sh(&self, package: &str, name: &str, version: &str,
+ stage: u32, host: Option<&str>, empty_dir: &Path) {
+ println!("Install {} stage{} ({:?})", package, stage, host);
+ let package_name = if let Some(host) = host {
+ format!("{}-{}-{}", name, version, host)
+ } else {
+ format!("{}-{}", name, version)
+ };
+
+ let mut cmd = Command::new("sh");
+ cmd.current_dir(empty_dir)
+ .arg(sanitize_sh(&tmpdir(self.build).join(&package_name).join("install.sh")))
+ .arg(format!("--prefix={}", sanitize_sh(&self.prefix)))
+ .arg(format!("--sysconfdir={}", sanitize_sh(&self.sysconfdir)))
+ .arg(format!("--docdir={}", sanitize_sh(&self.docdir)))
+ .arg(format!("--bindir={}", sanitize_sh(&self.bindir)))
+ .arg(format!("--libdir={}", sanitize_sh(&self.libdir)))
+ .arg(format!("--mandir={}", sanitize_sh(&self.mandir)))
+ .arg("--disable-ldconfig");
+ self.build.run(&mut cmd);
+ }
}
fn add_destdir(path: &Path, destdir: &Option<PathBuf>) -> PathBuf {
use std::env;
use std::io;
use std::mem;
+use Build;
type HANDLE = *mut u8;
type BOOL = i32;
const PROCESS_DUP_HANDLE: DWORD = 0x40;
const JobObjectExtendedLimitInformation: JOBOBJECTINFOCLASS = 9;
const JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE: DWORD = 0x2000;
+const JOB_OBJECT_LIMIT_PRIORITY_CLASS: DWORD = 0x00000020;
const SEM_FAILCRITICALERRORS: UINT = 0x0001;
const SEM_NOGPFAULTERRORBOX: UINT = 0x0002;
+const BELOW_NORMAL_PRIORITY_CLASS: DWORD = 0x00004000;
extern "system" {
fn CreateJobObjectW(lpJobAttributes: *mut u8, lpName: *const u8) -> HANDLE;
SchedulingClass: DWORD,
}
-pub unsafe fn setup() {
+pub unsafe fn setup(build: &mut Build) {
// Tell Windows to not show any UI on errors (such as not finding a required dll
// during startup or terminating abnormally). This is important for running tests,
// since some of them use abnormal termination by design.
// children will reside in the job by default.
let mut info = mem::zeroed::<JOBOBJECT_EXTENDED_LIMIT_INFORMATION>();
info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
+ if build.config.low_priority {
+ info.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_PRIORITY_CLASS;
+ info.BasicLimitInformation.PriorityClass = BELOW_NORMAL_PRIORITY_CLASS;
+ }
let r = SetInformationJobObject(job,
JobObjectExtendedLimitInformation,
&mut info as *mut _ as LPVOID,
extern crate rustc_serialize;
extern crate toml;
+#[cfg(unix)]
+extern crate libc;
+
use std::cmp;
use std::collections::HashMap;
use std::env;
#[cfg(windows)]
mod job;
-#[cfg(not(windows))]
+#[cfg(unix)]
+mod job {
+ use libc;
+
+ pub unsafe fn setup(build: &mut ::Build) {
+ if build.config.low_priority {
+ libc::setpriority(libc::PRIO_PGRP as _, 0, 10);
+ }
+ }
+}
+
+#[cfg(not(any(unix, windows)))]
mod job {
- pub unsafe fn setup() {}
+ pub unsafe fn setup(_build: &mut ::Build) {
+ }
}
pub use config::Config;
/// Executes the entire build, as configured by the flags and configuration.
pub fn build(&mut self) {
unsafe {
- job::setup();
+ job::setup(self);
}
if let Subcommand::Clean = self.flags.cmd {
.run(move |s| dist::rls(build, s.stage, s.target));
rules.dist("install", "path/to/nowhere")
.dep(|s| s.name("default:dist"))
- .run(move |s| install::install(build, s.stage, s.target));
+ .run(move |s| install::Installer::new(build).install(s.stage, s.target));
rules.dist("dist-cargo", "cargo")
.host(true)
.only_host_build(true)
Images will output artifacts in an `obj` dir at the root of a repository.
+## Filesystem layout
+
+- Each directory, excluding `scripts` and `disabled`, corresponds to a docker image
+- `scripts` contains files shared by docker images
+- `disabled` contains images that are not build travis
+
## Cross toolchains
A number of these images take quite a long time to compile as they're building
+++ /dev/null
-#!/bin/sh
-# 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.
-
-set -ex
-
-URL=https://dl.google.com/android/repository
-
-download_ndk() {
- mkdir -p /android/ndk
- cd /android/ndk
- curl -O $URL/$1
- unzip -q $1
- rm $1
- mv android-ndk-* ndk
-}
-
-make_standalone_toolchain() {
- # See https://developer.android.com/ndk/guides/standalone_toolchain.htm
- python2.7 /android/ndk/ndk/build/tools/make_standalone_toolchain.py \
- --install-dir /android/ndk/$1-$2 \
- --arch $1 \
- --api $2
-}
-
-remove_ndk() {
- rm -rf /android/ndk/ndk
-}
RUN apt-get update && \
apt-get install -y --no-install-recommends \
+ ca-certificates \
+ cmake \
+ curl \
+ file \
g++ \
+ git \
+ libssl-dev \
make \
- file \
- curl \
- ca-certificates \
+ pkg-config \
python2.7 \
- git \
- cmake \
- unzip \
sudo \
- xz-utils \
- libssl-dev \
- pkg-config
-
-RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
- dpkg -i dumb-init_*.deb && \
- rm dumb-init_*.deb
+ unzip \
+ xz-utils
-RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
- chmod +x /usr/local/bin/sccache
+# dumb-init
+COPY scripts/dumb-init.sh /scripts/
+RUN sh /scripts/dumb-init.sh
-# Install NDK
-COPY install-ndk.sh /tmp
-RUN . /tmp/install-ndk.sh && \
- download_ndk android-ndk-r13b-linux-x86_64.zip && \
- make_standalone_toolchain arm 9 && \
- remove_ndk
+# ndk
+COPY scripts/android-ndk.sh /scripts/
+RUN . /scripts/android-ndk.sh && \
+ download_and_make_toolchain android-ndk-r13b-linux-x86_64.zip arm 9
-# Install SDK
+# sdk
RUN dpkg --add-architecture i386 && \
apt-get update && \
apt-get install -y --no-install-recommends \
- openjdk-9-jre-headless \
- tzdata \
- libstdc++6:i386 \
libgl1-mesa-glx \
- libpulse0
+ libpulse0 \
+ libstdc++6:i386 \
+ openjdk-9-jre-headless \
+ tzdata
-COPY install-sdk.sh /tmp
-RUN . /tmp/install-sdk.sh && \
- download_sdk tools_r25.2.5-linux.zip && \
- download_sysimage armeabi-v7a 18 && \
- create_avd armeabi-v7a 18
+COPY scripts/android-sdk.sh /scripts/
+RUN . /scripts/android-sdk.sh && \
+ download_and_create_avd tools_r25.2.5-linux.zip armeabi-v7a 18
-# Setup env
+# env
ENV PATH=$PATH:/android/sdk/tools
ENV PATH=$PATH:/android/sdk/platform-tools
--target=$TARGETS \
--arm-linux-androideabi-ndk=/android/ndk/arm-9
-ENV SCRIPT python2.7 ../x.py test --target $TARGETS --verbose
+ENV SCRIPT python2.7 ../x.py test --target $TARGETS
+
+# sccache
+COPY scripts/sccache.sh /scripts/
+RUN sh /scripts/sccache.sh
-# Entrypoint
-COPY start-emulator.sh /android/
-ENTRYPOINT ["/usr/bin/dumb-init", "--", "/android/start-emulator.sh"]
+# init
+COPY scripts/android-start-emulator.sh /scripts/
+ENTRYPOINT ["/usr/bin/dumb-init", "--", "/scripts/android-start-emulator.sh"]
+++ /dev/null
-#!/bin/sh
-# 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.
-
-set -ex
-
-URL=https://dl.google.com/android/repository
-
-download_ndk() {
- mkdir -p /android/ndk
- cd /android/ndk
- curl -O $URL/$1
- unzip -q $1
- rm $1
- mv android-ndk-* ndk
-}
-
-make_standalone_toolchain() {
- # See https://developer.android.com/ndk/guides/standalone_toolchain.html
- python2.7 /android/ndk/ndk/build/tools/make_standalone_toolchain.py \
- --install-dir /android/ndk/$1-$2 \
- --arch $1 \
- --api $2
-}
-
-remove_ndk() {
- rm -rf /android/ndk/ndk
-}
+++ /dev/null
-#!/bin/sh
-# 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.
-
-set -ex
-
-URL=https://dl.google.com/android/repository
-
-download_sdk() {
- mkdir -p /android/sdk
- cd /android/sdk
- curl -O $URL/$1
- unzip -q $1
- rm -rf $1
-}
-
-download_sysimage() {
- # See https://developer.android.com/studio/tools/help/android.html
- abi=$1
- api=$2
-
- filter="platform-tools,android-$api"
- filter="$filter,sys-img-$abi-android-$api"
-
- # Keep printing yes to accept the licenses
- while true; do echo yes; sleep 10; done | \
- /android/sdk/tools/android update sdk -a --no-ui \
- --filter "$filter"
-}
-
-create_avd() {
- # See https://developer.android.com/studio/tools/help/android.html
- abi=$1
- api=$2
-
- echo no | \
- /android/sdk/tools/android create avd \
- --name $abi-$api \
- --target android-$api \
- --abi $abi
-}
-
+++ /dev/null
-#!/bin/sh
-# 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.
-
-set -ex
-
-# Setting SHELL to a file instead on a symlink helps android
-# emulator identify the system
-export SHELL=/bin/bash
-
-# Using the default qemu2 engine makes time::tests::since_epoch fails because
-# the emulator date is set to unix epoch (in armeabi-v7a-18 image). Using
-# classic engine the emulator starts with the current date and the tests run
-# fine. If another image is used, this need to be evaluated again.
-nohup nohup emulator @armeabi-v7a-18 \
- -engine classic -no-window -partition-size 2047 0<&- &>/dev/null &
-
-exec "$@"
# The `vexpress_config` config file was a previously generated config file for
# the kernel. This file was generated by running `make vexpress_defconfig`
# followed by `make menuconfig` and then enabling the IPv6 protocol page.
-COPY vexpress_config /build/.config
+COPY armhf-gnu/vexpress_config /build/.config
RUN curl https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.4.42.tar.xz | \
tar xJf - && \
cd /build/linux-4.4.42 && \
# Copy over our init script, which starts up our test server and also a few
# other misc tasks.
-COPY rcS rootfs/etc/init.d/rcS
+COPY armhf-gnu/rcS rootfs/etc/init.d/rcS
RUN chmod +x rootfs/etc/init.d/rcS
# Helper to quickly fill the entropy pool in the kernel.
-COPY addentropy.c /tmp/
+COPY armhf-gnu/addentropy.c /tmp/
RUN arm-linux-gnueabihf-gcc addentropy.c -o rootfs/addentropy -static
# TODO: What is this?!
WORKDIR /tmp
-COPY build-rumprun.sh /tmp/
+COPY cross/build-rumprun.sh /tmp/
RUN ./build-rumprun.sh
-COPY build-arm-musl.sh /tmp/
+COPY cross/build-arm-musl.sh /tmp/
RUN ./build-arm-musl.sh
# originally from
RUN apt-get update && \
apt-get install -y --no-install-recommends \
+ ca-certificates \
+ cmake \
+ curl \
+ file \
g++ \
+ git \
+ libssl-dev \
make \
- file \
- curl \
- ca-certificates \
+ pkg-config \
python2.7 \
- git \
- cmake \
- unzip \
sudo \
- xz-utils \
- libssl-dev \
- pkg-config
-
-RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
- dpkg -i dumb-init_*.deb && \
- rm dumb-init_*.deb
-
-RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
- chmod +x /usr/local/bin/sccache
+ unzip \
+ xz-utils
-ENTRYPOINT ["/usr/bin/dumb-init", "--"]
+# dumb-init
+COPY scripts/dumb-init.sh /scripts/
+RUN sh /scripts/dumb-init.sh
-COPY android-ndk.sh /
-RUN . /android-ndk.sh && \
- download_ndk android-ndk-r13b-linux-x86_64.zip && \
- make_standalone_toolchain arm64 21 && \
- remove_ndk
+# ndk
+COPY scripts/android-ndk.sh /scripts/
+RUN . /scripts/android-ndk.sh && \
+ download_and_make_toolchain android-ndk-r13b-linux-x86_64.zip arm64 21
+# env
ENV PATH=$PATH:/android/ndk/arm64-21/bin
ENV DEP_Z_ROOT=/android/ndk/arm64-21/sysroot/usr/
--enable-cargo-openssl-static
ENV SCRIPT python2.7 ../x.py dist --target $HOSTS --host $HOSTS
+
+# sccache
+COPY scripts/sccache.sh /scripts/
+RUN sh /scripts/sccache.sh
+
+# init
+ENTRYPOINT ["/usr/bin/dumb-init", "--"]
RUN apt-get update && \
apt-get install -y --no-install-recommends \
+ ca-certificates \
+ cmake \
+ curl \
+ file \
g++ \
+ git \
+ libssl-dev \
make \
- file \
- curl \
- ca-certificates \
+ pkg-config \
python2.7 \
- git \
- cmake \
- unzip \
sudo \
- xz-utils \
- libssl-dev \
- pkg-config
-
-RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
- dpkg -i dumb-init_*.deb && \
- rm dumb-init_*.deb
-
-RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
- chmod +x /usr/local/bin/sccache
+ unzip \
+ xz-utils
-ENTRYPOINT ["/usr/bin/dumb-init", "--"]
+# dumb-init
+COPY scripts/dumb-init.sh /scripts/
+RUN sh /scripts/dumb-init.sh
-COPY android-ndk.sh /
-RUN . /android-ndk.sh && \
+# ndk
+COPY scripts/android-ndk.sh /scripts/
+RUN . /scripts/android-ndk.sh && \
download_ndk android-ndk-r13b-linux-x86_64.zip && \
make_standalone_toolchain arm 9 && \
make_standalone_toolchain arm 21 && \
remove_ndk
+RUN chmod 777 /android/ndk && \
+ ln -s /android/ndk/arm-21 /android/ndk/arm
+
+# env
ENV PATH=$PATH:/android/ndk/arm-9/bin
ENV DEP_Z_ROOT=/android/ndk/arm-9/sysroot/usr/
# level 9), the default linker behavior is to generate an error, to allow the
# build to finish we use --warn-unresolved-symbols. Note that the missing
# symbols does not affect std, only the compiler (llvm) and cargo (openssl).
-RUN chmod 777 /android/ndk && \
- ln -s /android/ndk/arm-21 /android/ndk/arm
-
ENV SCRIPT \
python2.7 ../x.py build src/llvm --host $HOSTS --target $HOSTS && \
(export RUSTFLAGS="\"-C link-arg=-Wl,--warn-unresolved-symbols\""; \
rm /android/ndk/arm && \
ln -s /android/ndk/arm-9 /android/ndk/arm && \
python2.7 ../x.py dist --host $HOSTS --target $HOSTS)
+
+# sccache
+COPY scripts/sccache.sh /scripts/
+RUN sh /scripts/sccache.sh
+
+# init
+ENTRYPOINT ["/usr/bin/dumb-init", "--"]
RUN apt-get update && \
apt-get install -y --no-install-recommends \
+ ca-certificates \
+ cmake \
+ curl \
+ file \
g++ \
+ git \
+ libssl-dev \
make \
- file \
- curl \
- ca-certificates \
+ pkg-config \
python2.7 \
- git \
- cmake \
- unzip \
sudo \
- xz-utils \
- libssl-dev \
- pkg-config
-
-RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
- dpkg -i dumb-init_*.deb && \
- rm dumb-init_*.deb
-
-RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
- chmod +x /usr/local/bin/sccache
+ unzip \
+ xz-utils
-ENTRYPOINT ["/usr/bin/dumb-init", "--"]
+# dumb-init
+COPY scripts/dumb-init.sh /scripts/
+RUN sh /scripts/dumb-init.sh
-COPY android-ndk.sh /
-RUN . /android-ndk.sh && \
+# ndk
+COPY scripts/android-ndk.sh /scripts/
+RUN . /scripts/android-ndk.sh && \
download_ndk android-ndk-r13b-linux-x86_64.zip && \
make_standalone_toolchain x86 9 && \
make_standalone_toolchain x86 21 && \
remove_ndk
+RUN chmod 777 /android/ndk && \
+ ln -s /android/ndk/x86-21 /android/ndk/x86
+
+# env
ENV PATH=$PATH:/android/ndk/x86-9/bin
ENV DEP_Z_ROOT=/android/ndk/x86-9/sysroot/usr/
# level 9), the default linker behavior is to generate an error, to allow the
# build to finish we use --warn-unresolved-symbols. Note that the missing
# symbols does not affect std, only the compiler (llvm) and cargo (openssl).
-RUN chmod 777 /android/ndk && \
- ln -s /android/ndk/x86-21 /android/ndk/x86
-
ENV SCRIPT \
python2.7 ../x.py build src/llvm --host $HOSTS --target $HOSTS && \
(export RUSTFLAGS="\"-C link-arg=-Wl,--warn-unresolved-symbols\""; \
rm /android/ndk/x86 && \
ln -s /android/ndk/x86-9 /android/ndk/x86 && \
python2.7 ../x.py dist --host $HOSTS --target $HOSTS)
+
+# sccache
+COPY scripts/sccache.sh /scripts/
+RUN sh /scripts/sccache.sh
+
+# init
+ENTRYPOINT ["/usr/bin/dumb-init", "--"]
RUN apt-get update && \
apt-get install -y --no-install-recommends \
+ ca-certificates \
+ cmake \
+ curl \
+ file \
g++ \
+ git \
+ libssl-dev \
make \
- file \
- curl \
- ca-certificates \
+ pkg-config \
python2.7 \
- git \
- cmake \
- unzip \
sudo \
- xz-utils \
- libssl-dev \
- pkg-config
-
-RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
- dpkg -i dumb-init_*.deb && \
- rm dumb-init_*.deb
-
-RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
- chmod +x /usr/local/bin/sccache
+ unzip \
+ xz-utils
-ENTRYPOINT ["/usr/bin/dumb-init", "--"]
+# dumb-init
+COPY scripts/dumb-init.sh /scripts/
+RUN sh /scripts/dumb-init.sh
-COPY android-ndk.sh /
-RUN . /android-ndk.sh && \
- download_ndk android-ndk-r13b-linux-x86_64.zip && \
- make_standalone_toolchain x86_64 21 && \
- remove_ndk
+# ndk
+COPY scripts/android-ndk.sh /scripts/
+RUN . /scripts/android-ndk.sh && \
+ download_and_make_toolchain android-ndk-r13b-linux-x86_64.zip x86_64 21
+# env
ENV PATH=$PATH:/android/ndk/x86_64-21/bin
ENV DEP_Z_ROOT=/android/ndk/x86_64-21/sysroot/usr/
--enable-cargo-openssl-static
ENV SCRIPT python2.7 ../x.py dist --target $HOSTS --host $HOSTS
+
+# sccache
+COPY scripts/sccache.sh /scripts/
+RUN sh /scripts/sccache.sh
+
+# init
+ENTRYPOINT ["/usr/bin/dumb-init", "--"]
USER rustbuild
WORKDIR /tmp
-COPY aarch64-linux-gnu.config build-toolchains.sh /tmp/
+COPY dist-aarch64-linux/aarch64-linux-gnu.config dist-aarch64-linux/build-toolchains.sh /tmp/
RUN ./build-toolchains.sh
USER root
RUN apt-get update && \
apt-get install -y --no-install-recommends \
+ ca-certificates \
+ cmake \
+ curl \
+ file \
g++ \
+ git \
+ libssl-dev \
make \
- file \
- curl \
- ca-certificates \
+ pkg-config \
python2.7 \
- git \
- cmake \
- unzip \
sudo \
- xz-utils \
- libssl-dev \
- pkg-config
-
-RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
- dpkg -i dumb-init_*.deb && \
- rm dumb-init_*.deb
-
-RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
- chmod +x /usr/local/bin/sccache
+ unzip \
+ xz-utils
-ENTRYPOINT ["/usr/bin/dumb-init", "--"]
+# dumb-init
+COPY scripts/dumb-init.sh /scripts/
+RUN sh /scripts/dumb-init.sh
-# Install NDK
-COPY install-ndk.sh /tmp
-RUN . /tmp/install-ndk.sh && \
+# ndk
+COPY scripts/android-ndk.sh /scripts/
+RUN . /scripts/android-ndk.sh && \
download_ndk android-ndk-r13b-linux-x86_64.zip && \
make_standalone_toolchain arm 9 && \
make_standalone_toolchain x86 9 && \
make_standalone_toolchain x86_64 21 && \
remove_ndk
+# env
ENV TARGETS=arm-linux-androideabi
ENV TARGETS=$TARGETS,armv7-linux-androideabi
ENV TARGETS=$TARGETS,i686-linux-android
--x86_64-linux-android-ndk=/android/ndk/x86_64-21
ENV SCRIPT python2.7 ../x.py dist --target $TARGETS
+
+# cache
+COPY scripts/sccache.sh /scripts/
+RUN sh /scripts/sccache.sh
+
+# init
+ENTRYPOINT ["/usr/bin/dumb-init", "--"]
+++ /dev/null
-#!/bin/sh
-# 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.
-
-set -ex
-
-URL=https://dl.google.com/android/repository
-
-download_ndk() {
- mkdir -p /android/ndk
- cd /android/ndk
- curl -O $URL/$1
- unzip -q $1
- rm $1
- mv android-ndk-* ndk
-}
-
-make_standalone_toolchain() {
- # See https://developer.android.com/ndk/guides/standalone_toolchain.html
- python2.7 /android/ndk/ndk/build/tools/make_standalone_toolchain.py \
- --install-dir /android/ndk/$1-$2 \
- --arch $1 \
- --api $2
-}
-
-remove_ndk() {
- rm -rf /android/ndk/ndk
-}
USER rustbuild
WORKDIR /tmp
-COPY arm-linux-gnueabi.config build-toolchains.sh /tmp/
+COPY dist-arm-linux/arm-linux-gnueabi.config dist-arm-linux/build-toolchains.sh /tmp/
RUN ./build-toolchains.sh
USER root
USER rustbuild
WORKDIR /tmp
-COPY arm-linux-gnueabihf.config build-toolchains.sh /tmp/
+COPY dist-armhf-linux/arm-linux-gnueabihf.config dist-armhf-linux/build-toolchains.sh /tmp/
RUN ./build-toolchains.sh
USER root
USER rustbuild
WORKDIR /tmp
-COPY build-toolchains.sh armv7-linux-gnueabihf.config /tmp/
+COPY dist-armv7-linux/build-toolchains.sh dist-armv7-linux/armv7-linux-gnueabihf.config /tmp/
RUN ./build-toolchains.sh
USER root
tar xzf - -C /usr/local --strip-components=1
WORKDIR /tmp
-COPY shared.sh build-toolchain.sh compiler-rt-dso-handle.patch /tmp/
+COPY dist-fuchsia/shared.sh dist-fuchsia/build-toolchain.sh dist-fuchsia/compiler-rt-dso-handle.patch /tmp/
RUN /tmp/build-toolchain.sh
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
pkg-config
WORKDIR /build/
-COPY musl-libunwind-patch.patch build-musl.sh /build/
+COPY dist-i586-gnu-i686-musl/musl-libunwind-patch.patch dist-i586-gnu-i686-musl/build-musl.sh /build/
RUN sh /build/build-musl.sh && rm -rf /build
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
libssl-dev \
pkg-config
-COPY build-toolchain.sh /tmp/
+COPY dist-i686-freebsd/build-toolchain.sh /tmp/
RUN /tmp/build-toolchain.sh i686
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
ENV LD_LIBRARY_PATH=/rustroot/lib64:/rustroot/lib
ENV PKG_CONFIG_PATH=/rustroot/lib/pkgconfig
WORKDIR /tmp
-COPY shared.sh build-binutils.sh /tmp/
+COPY dist-i686-linux/shared.sh dist-i686-linux/build-binutils.sh /tmp/
# We need a build of openssl which supports SNI to download artifacts from
# static.rust-lang.org. This'll be used to link into libcurl below (and used
# later as well), so build a copy of OpenSSL with dynamic libraries into our
# generic root.
-COPY build-openssl.sh /tmp/
+COPY dist-i686-linux/build-openssl.sh /tmp/
RUN ./build-openssl.sh
# The `curl` binary on CentOS doesn't support SNI which is needed for fetching
#
# Note that we also disable a bunch of optional features of curl that we don't
# really need.
-COPY build-curl.sh /tmp/
+COPY dist-i686-linux/build-curl.sh /tmp/
RUN ./build-curl.sh
# binutils < 2.22 has a bug where the 32-bit executables it generates
RUN ./build-binutils.sh
# Need a newer version of gcc than centos has to compile LLVM nowadays
-COPY build-gcc.sh /tmp/
+COPY dist-i686-linux/build-gcc.sh /tmp/
RUN ./build-gcc.sh
# CentOS 5.5 has Python 2.4 by default, but LLVM needs 2.7+
-COPY build-python.sh /tmp/
+COPY dist-i686-linux/build-python.sh /tmp/
RUN ./build-python.sh
# Apparently CentOS 5.5 desn't have `git` in yum, but we're gonna need it for
# cloning, so download and build it here.
-COPY build-git.sh /tmp/
+COPY dist-i686-linux/build-git.sh /tmp/
RUN ./build-git.sh
# libssh2 (a dependency of Cargo) requires cmake 2.8.11 or higher but CentOS
# only has 2.6.4, so build our own
-COPY build-cmake.sh /tmp/
+COPY dist-i686-linux/build-cmake.sh /tmp/
RUN ./build-cmake.sh
# for sanitizers, we need kernel headers files newer than the ones CentOS ships
# with so we install newer ones here
-COPY build-headers.sh /tmp/
+COPY dist-i686-linux/build-headers.sh /tmp/
RUN ./build-headers.sh
RUN curl -Lo /rustroot/dumb-init \
USER rustbuild
WORKDIR /tmp
-COPY patches/ /tmp/patches/
-COPY powerpc-linux-gnu.config build-powerpc-toolchain.sh /tmp/
+COPY dist-powerpc-linux/patches/ /tmp/patches/
+COPY dist-powerpc-linux/powerpc-linux-gnu.config dist-powerpc-linux/build-powerpc-toolchain.sh /tmp/
RUN ./build-powerpc-toolchain.sh
USER root
USER rustbuild
WORKDIR /tmp
-COPY patches/ /tmp/patches/
-COPY shared.sh powerpc64-linux-gnu.config build-powerpc64-toolchain.sh /tmp/
+COPY dist-powerpc64-linux/patches/ /tmp/patches/
+COPY dist-powerpc64-linux/shared.sh dist-powerpc64-linux/powerpc64-linux-gnu.config dist-powerpc64-linux/build-powerpc64-toolchain.sh /tmp/
RUN ./build-powerpc64-toolchain.sh
USER root
USER root
RUN apt-get install -y --no-install-recommends rpm2cpio cpio
-COPY shared.sh build-powerpc64le-toolchain.sh /tmp/
+COPY dist-powerpc64le-linux/shared.sh dist-powerpc64le-linux/build-powerpc64le-toolchain.sh /tmp/
RUN ./build-powerpc64le-toolchain.sh
RUN curl -o /usr/local/bin/sccache \
USER rustbuild
WORKDIR /tmp
-COPY patches/ /tmp/patches/
-COPY s390x-linux-gnu.config build-s390x-toolchain.sh /tmp/
+COPY dist-s390x-linux/patches/ /tmp/patches/
+COPY dist-s390x-linux/s390x-linux-gnu.config dist-s390x-linux/build-s390x-toolchain.sh /tmp/
RUN ./build-s390x-toolchain.sh
USER root
libssl-dev \
pkg-config
-COPY build-toolchain.sh /tmp/
+COPY dist-x86_64-freebsd/build-toolchain.sh /tmp/
RUN /tmp/build-toolchain.sh x86_64
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
ENV LD_LIBRARY_PATH=/rustroot/lib64:/rustroot/lib
ENV PKG_CONFIG_PATH=/rustroot/lib/pkgconfig
WORKDIR /tmp
-COPY shared.sh build-binutils.sh /tmp/
+COPY dist-x86_64-linux/shared.sh dist-x86_64-linux/build-binutils.sh /tmp/
# We need a build of openssl which supports SNI to download artifacts from
# static.rust-lang.org. This'll be used to link into libcurl below (and used
# later as well), so build a copy of OpenSSL with dynamic libraries into our
# generic root.
-COPY build-openssl.sh /tmp/
+COPY dist-x86_64-linux/build-openssl.sh /tmp/
RUN ./build-openssl.sh
# The `curl` binary on CentOS doesn't support SNI which is needed for fetching
#
# Note that we also disable a bunch of optional features of curl that we don't
# really need.
-COPY build-curl.sh /tmp/
+COPY dist-x86_64-linux/build-curl.sh /tmp/
RUN ./build-curl.sh
# binutils < 2.22 has a bug where the 32-bit executables it generates
RUN ./build-binutils.sh
# Need a newer version of gcc than centos has to compile LLVM nowadays
-COPY build-gcc.sh /tmp/
+COPY dist-x86_64-linux/build-gcc.sh /tmp/
RUN ./build-gcc.sh
# CentOS 5.5 has Python 2.4 by default, but LLVM needs 2.7+
-COPY build-python.sh /tmp/
+COPY dist-x86_64-linux/build-python.sh /tmp/
RUN ./build-python.sh
# Apparently CentOS 5.5 desn't have `git` in yum, but we're gonna need it for
# cloning, so download and build it here.
-COPY build-git.sh /tmp/
+COPY dist-x86_64-linux/build-git.sh /tmp/
RUN ./build-git.sh
# libssh2 (a dependency of Cargo) requires cmake 2.8.11 or higher but CentOS
# only has 2.6.4, so build our own
-COPY build-cmake.sh /tmp/
+COPY dist-x86_64-linux/build-cmake.sh /tmp/
RUN ./build-cmake.sh
# for sanitizers, we need kernel headers files newer than the ones CentOS ships
# with so we install newer ones here
-COPY build-headers.sh /tmp/
+COPY dist-x86_64-linux/build-headers.sh /tmp/
RUN ./build-headers.sh
RUN curl -Lo /rustroot/dumb-init \
pkg-config
WORKDIR /build/
-COPY build-musl.sh /build/
+COPY dist-x86_64-musl/build-musl.sh /build/
RUN sh /build/build-musl.sh && rm -rf /build
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
USER rustbuild
WORKDIR /tmp
-COPY build-netbsd-toolchain.sh /tmp/
+COPY dist-x86_64-netbsd/build-netbsd-toolchain.sh /tmp/
RUN ./build-netbsd-toolchain.sh
USER root
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
WORKDIR /tmp
-COPY build-emscripten.sh /tmp/
+COPY emscripten/build-emscripten.sh /tmp/
RUN ./build-emscripten.sh
ENV PATH=$PATH:/tmp/emsdk_portable
ENV PATH=$PATH:/tmp/emsdk_portable/clang/tag-e1.37.10/build_tag-e1.37.10_32/bin
build \
--rm \
-t rust-ci \
- "$docker_dir/$image"
+ -f "$docker_dir/$image/Dockerfile" \
+ "$docker_dir"
elif [ -f "$docker_dir/disabled/$image/Dockerfile" ]; then
if [ -n "$TRAVIS_OS_NAME" ]; then
echo Cannot run disabled images on travis!
--- /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.
+
+set -ex
+
+URL=https://dl.google.com/android/repository
+
+download_ndk() {
+ mkdir -p /android/ndk
+ cd /android/ndk
+ curl -O $URL/$1
+ unzip -q $1
+ rm $1
+ mv android-ndk-* ndk
+}
+
+make_standalone_toolchain() {
+ # See https://developer.android.com/ndk/guides/standalone_toolchain.htm
+ python2.7 /android/ndk/ndk/build/tools/make_standalone_toolchain.py \
+ --install-dir /android/ndk/$1-$2 \
+ --arch $1 \
+ --api $2
+}
+
+remove_ndk() {
+ rm -rf /android/ndk/ndk
+}
+
+download_and_make_toolchain() {
+ download_ndk $1 && \
+ make_standalone_toolchain $2 $3 && \
+ remove_ndk
+}
--- /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.
+
+set -ex
+
+URL=https://dl.google.com/android/repository
+
+download_sdk() {
+ mkdir -p /android/sdk
+ cd /android/sdk
+ curl -O $URL/$1
+ unzip -q $1
+ rm -rf $1
+}
+
+download_sysimage() {
+ # See https://developer.android.com/studio/tools/help/android.html
+ abi=$1
+ api=$2
+
+ filter="platform-tools,android-$api"
+ filter="$filter,sys-img-$abi-android-$api"
+
+ # Keep printing yes to accept the licenses
+ while true; do echo yes; sleep 10; done | \
+ /android/sdk/tools/android update sdk -a --no-ui \
+ --filter "$filter"
+}
+
+create_avd() {
+ # See https://developer.android.com/studio/tools/help/android.html
+ abi=$1
+ api=$2
+
+ echo no | \
+ /android/sdk/tools/android create avd \
+ --name $abi-$api \
+ --target android-$api \
+ --abi $abi
+}
+
+download_and_create_avd() {
+ download_sdk $1
+ download_sysimage $2 $3
+ create_avd $2 $3
+}
--- /dev/null
+#!/bin/sh
+# 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.
+
+set -ex
+
+# Setting SHELL to a file instead on a symlink helps android
+# emulator identify the system
+export SHELL=/bin/bash
+
+# Using the default qemu2 engine makes time::tests::since_epoch fails because
+# the emulator date is set to unix epoch (in armeabi-v7a-18 image). Using
+# classic engine the emulator starts with the current date and the tests run
+# fine. If another image is used, this need to be evaluated again.
+nohup nohup emulator @armeabi-v7a-18 \
+ -engine classic -no-window -partition-size 2047 0<&- &>/dev/null &
+
+exec "$@"
--- /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.
+
+set -ex
+
+curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb
+dpkg -i dumb-init_*.deb
+rm dumb-init_*.deb
--- /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.
+
+set -ex
+
+curl -o /usr/local/bin/sccache \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl
+
+chmod +x /usr/local/bin/sccache
--- /dev/null
+# `iterator_step_by`
+
+The tracking issue for this feature is: [#27741]
+
+[#27741]: https://github.com/rust-lang/rust/issues/27741
+
+------------------------
--- /dev/null
+# `needs_drop`
+
+The tracking issue for this feature is: [#41890]
+
+[#41890]: https://github.com/rust-lang/rust/issues/41890
+
+------------------------
}
}
-#[stable(feature = "boxed_str_conv", since = "1.18.0")]
+#[stable(feature = "boxed_str_conv", since = "1.19.0")]
impl From<Box<str>> for Box<[u8]> {
fn from(s: Box<str>) -> Self {
unsafe {
#![feature(core_intrinsics)]
#![feature(dropck_eyepatch)]
#![feature(generic_param_attrs)]
+#![feature(needs_drop)]
#![cfg_attr(stage0, feature(staged_api))]
#![cfg_attr(test, feature(test))]
unsafe fn destroy(&mut self, len: usize) {
// The branch on needs_drop() is an -O1 performance optimization.
// Without the branch, dropping TypedArena<u8> takes linear time.
- if intrinsics::needs_drop::<T>() {
+ if mem::needs_drop::<T>() {
let mut start = self.start();
// Destroy all allocated objects.
for _ in 0..len {
#[inline]
pub fn alloc<T>(&self, object: T) -> &mut T {
unsafe {
- assert!(!intrinsics::needs_drop::<T>());
+ assert!(!mem::needs_drop::<T>());
assert!(mem::size_of::<T>() != 0);
self.align_for::<T>();
#[inline]
pub fn alloc_slice<T>(&self, slice: &[T]) -> &mut [T]
where T: Copy {
- unsafe {
- assert!(!intrinsics::needs_drop::<T>());
- }
+ assert!(!mem::needs_drop::<T>());
assert!(mem::size_of::<T>() != 0);
assert!(slice.len() != 0);
self.align_for::<T>();
})
}
+
macro_rules! make_test_inner {
- ($s:ident, $code:expr, $name:ident, $str:expr) => {
+ ($s:ident, $code:expr, $name:ident, $str:expr, $iters:expr) => {
#[bench]
fn $name(bencher: &mut Bencher) {
let mut $s = $str;
black_box(&mut $s);
- bencher.iter(|| $code);
+ bencher.iter(|| for _ in 0..$iters { black_box($code); });
}
}
}
macro_rules! make_test {
($name:ident, $s:ident, $code:expr) => {
+ make_test!($name, $s, $code, 1);
+ };
+ ($name:ident, $s:ident, $code:expr, $iters:expr) => {
mod $name {
use test::Bencher;
use test::black_box;
// Short strings: 65 bytes each
make_test_inner!($s, $code, short_ascii,
- "Mary had a little lamb, Little lamb Mary had a littl lamb, lamb!");
+ "Mary had a little lamb, Little lamb Mary had a littl lamb, lamb!", $iters);
make_test_inner!($s, $code, short_mixed,
- "ศไทย中华Việt Nam; Mary had a little lamb, Little lam!");
+ "ศไทย中华Việt Nam; Mary had a little lamb, Little lam!", $iters);
make_test_inner!($s, $code, short_pile_of_poo,
- "💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩!");
+ "💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩!", $iters);
make_test_inner!($s, $code, long_lorem_ipsum,"\
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse quis lorem sit amet dolor \
ultricies condimentum. Praesent iaculis purus elit, ac malesuada quam malesuada in. Duis sed orci \
feugiat. Etiam quis mauris vel risus luctus mattis a a nunc. Nullam orci quam, imperdiet id \
vehicula in, porttitor ut nibh. Duis sagittis adipiscing nisl vitae congue. Donec mollis risus eu \
leo suscipit, varius porttitor nulla porta. Pellentesque ut sem nec nisi euismod vehicula. Nulla \
-malesuada sollicitudin quam eu fermentum!");
+malesuada sollicitudin quam eu fermentum!", $iters);
}
}
}
make_test!(rfind_zzz_char, s, s.rfind('\u{1F4A4}'));
make_test!(find_zzz_str, s, s.find("\u{1F4A4}"));
+make_test!(starts_with_ascii_char, s, s.starts_with('/'), 1024);
+make_test!(ends_with_ascii_char, s, s.ends_with('/'), 1024);
+make_test!(starts_with_unichar, s, s.starts_with('\u{1F4A4}'), 1024);
+make_test!(ends_with_unichar, s, s.ends_with('\u{1F4A4}'), 1024);
+make_test!(starts_with_str, s, s.starts_with("💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩"), 1024);
+make_test!(ends_with_str, s, s.ends_with("💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩"), 1024);
+
make_test!(split_space_char, s, s.split(' ').count());
make_test!(split_terminator_space_char, s, s.split_terminator(' ').count());
/// assert!(!bananas.contains("apples"));
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
+ #[inline]
pub fn contains<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool {
core_str::StrExt::contains(self, pat)
}
/// assert_eq!(s.find(x), None);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
+ #[inline]
pub fn find<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize> {
core_str::StrExt::find(self, pat)
}
/// assert_eq!(s.rfind(x), None);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
+ #[inline]
pub fn rfind<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize>
where P::Searcher: ReverseSearcher<'a>
{
///
/// [`split_whitespace`]: #method.split_whitespace
#[stable(feature = "rust1", since = "1.0.0")]
+ #[inline]
pub fn split<'a, P: Pattern<'a>>(&'a self, pat: P) -> Split<'a, P> {
core_str::StrExt::split(self, pat)
}
/// assert_eq!(v, ["ghi", "def", "abc"]);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
+ #[inline]
pub fn rsplit<'a, P: Pattern<'a>>(&'a self, pat: P) -> RSplit<'a, P>
where P::Searcher: ReverseSearcher<'a>
{
/// assert_eq!(v, ["A", "", "B", ""]);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
+ #[inline]
pub fn split_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitTerminator<'a, P> {
core_str::StrExt::split_terminator(self, pat)
}
/// assert_eq!(v, ["", "B", "", "A"]);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
+ #[inline]
pub fn rsplit_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> RSplitTerminator<'a, P>
where P::Searcher: ReverseSearcher<'a>
{
/// assert_eq!(v, ["abc", "defXghi"]);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
+ #[inline]
pub fn splitn<'a, P: Pattern<'a>>(&'a self, n: usize, pat: P) -> SplitN<'a, P> {
core_str::StrExt::splitn(self, n, pat)
}
/// assert_eq!(v, ["ghi", "abc1def"]);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
+ #[inline]
pub fn rsplitn<'a, P: Pattern<'a>>(&'a self, n: usize, pat: P) -> RSplitN<'a, P>
where P::Searcher: ReverseSearcher<'a>
{
/// assert_eq!(v, ["1", "2", "3"]);
/// ```
#[stable(feature = "str_matches", since = "1.2.0")]
+ #[inline]
pub fn matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> Matches<'a, P> {
core_str::StrExt::matches(self, pat)
}
/// assert_eq!(v, ["3", "2", "1"]);
/// ```
#[stable(feature = "str_matches", since = "1.2.0")]
+ #[inline]
pub fn rmatches<'a, P: Pattern<'a>>(&'a self, pat: P) -> RMatches<'a, P>
where P::Searcher: ReverseSearcher<'a>
{
/// assert_eq!(v, [(0, "aba")]); // only the first `aba`
/// ```
#[stable(feature = "str_match_indices", since = "1.5.0")]
+ #[inline]
pub fn match_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> MatchIndices<'a, P> {
core_str::StrExt::match_indices(self, pat)
}
/// assert_eq!(v, [(2, "aba")]); // only the last `aba`
/// ```
#[stable(feature = "str_match_indices", since = "1.5.0")]
+ #[inline]
pub fn rmatch_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> RMatchIndices<'a, P>
where P::Searcher: ReverseSearcher<'a>
{
/// assert_eq!(s, s.replace("cookie monster", "little lamb"));
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
+ #[inline]
pub fn replace<'a, P: Pattern<'a>>(&'a self, from: P, to: &str) -> String {
let mut result = String::new();
let mut last_end = 0;
}
}
-#[stable(feature = "derefmut_for_string", since = "1.2.0")]
+#[stable(feature = "derefmut_for_string", since = "1.3.0")]
impl ops::IndexMut<ops::Range<usize>> for String {
#[inline]
fn index_mut(&mut self, index: ops::Range<usize>) -> &mut str {
&mut self[..][index]
}
}
-#[stable(feature = "derefmut_for_string", since = "1.2.0")]
+#[stable(feature = "derefmut_for_string", since = "1.3.0")]
impl ops::IndexMut<ops::RangeTo<usize>> for String {
#[inline]
fn index_mut(&mut self, index: ops::RangeTo<usize>) -> &mut str {
&mut self[..][index]
}
}
-#[stable(feature = "derefmut_for_string", since = "1.2.0")]
+#[stable(feature = "derefmut_for_string", since = "1.3.0")]
impl ops::IndexMut<ops::RangeFrom<usize>> for String {
#[inline]
fn index_mut(&mut self, index: ops::RangeFrom<usize>) -> &mut str {
&mut self[..][index]
}
}
-#[stable(feature = "derefmut_for_string", since = "1.2.0")]
+#[stable(feature = "derefmut_for_string", since = "1.3.0")]
impl ops::IndexMut<ops::RangeFull> for String {
#[inline]
fn index_mut(&mut self, _index: ops::RangeFull) -> &mut str {
}
}
-#[stable(feature = "derefmut_for_string", since = "1.2.0")]
+#[stable(feature = "derefmut_for_string", since = "1.3.0")]
impl ops::DerefMut for String {
#[inline]
fn deref_mut(&mut self) -> &mut str {
// note: test pulls in libstd, which causes errors here
#[cfg(not(test))]
-#[stable(feature = "string_from_box", since = "1.17.0")]
+#[stable(feature = "string_from_box", since = "1.18.0")]
impl From<Box<str>> for String {
fn from(s: Box<str>) -> String {
s.into_string()
}
}
-#[stable(feature = "box_from_str", since = "1.17.0")]
+#[stable(feature = "box_from_str", since = "1.18.0")]
impl Into<Box<str>> for String {
fn into(self) -> Box<str> {
self.into_boxed_str()
}
}
-#[stable(feature = "vec_from_mut", since = "1.21.0")]
+#[stable(feature = "vec_from_mut", since = "1.19.0")]
impl<'a, T: Clone> From<&'a mut [T]> for Vec<T> {
#[cfg(not(test))]
fn from(s: &'a mut [T]) -> Vec<T> {
// note: test pulls in libstd, which causes errors here
#[cfg(not(test))]
-#[stable(feature = "vec_from_box", since = "1.17.0")]
+#[stable(feature = "vec_from_box", since = "1.18.0")]
impl<T> From<Box<[T]>> for Vec<T> {
fn from(s: Box<[T]>) -> Vec<T> {
s.into_vec()
}
}
-#[stable(feature = "box_from_vec", since = "1.17.0")]
+#[stable(feature = "box_from_vec", since = "1.18.0")]
impl<T> Into<Box<[T]>> for Vec<T> {
fn into(self) -> Box<[T]> {
self.into_boxed_slice()
// Clone-on-write
////////////////////////////////////////////////////////////////////////////////
-#[stable(feature = "cow_from_vec", since = "1.7.0")]
+#[stable(feature = "cow_from_vec", since = "1.8.0")]
impl<'a, T: Clone> From<&'a [T]> for Cow<'a, [T]> {
fn from(s: &'a [T]) -> Cow<'a, [T]> {
Cow::Borrowed(s)
}
}
-#[stable(feature = "cow_from_vec", since = "1.7.0")]
+#[stable(feature = "cow_from_vec", since = "1.8.0")]
impl<'a, T: Clone> From<Vec<T>> for Cow<'a, [T]> {
fn from(v: Vec<T>) -> Cow<'a, [T]> {
Cow::Owned(v)
}
}
-#[stable(feature = "unsafe_cell_default", since = "1.9.0")]
+#[stable(feature = "unsafe_cell_default", since = "1.10.0")]
impl<T: Default> Default for UnsafeCell<T> {
/// Creates an `UnsafeCell`, with the `Default` value for T.
fn default() -> UnsafeCell<T> {
use cmp::Ordering;
use super::{Chain, Cycle, Cloned, Enumerate, Filter, FilterMap, FlatMap, Fuse};
-use super::{Inspect, Map, Peekable, Scan, Skip, SkipWhile, Take, TakeWhile, Rev};
+use super::{Inspect, Map, Peekable, Scan, Skip, SkipWhile, StepBy, Take, TakeWhile, Rev};
use super::{Zip, Sum, Product};
use super::{ChainState, FromIterator, ZipImpl};
None
}
+ /// Creates an iterator starting at the same point, but stepping by
+ /// the given amount at each iteration.
+ ///
+ /// Note that it will always return the first element of the range,
+ /// regardless of the step given.
+ ///
+ /// # Panics
+ ///
+ /// The method will panic if the given step is `0`.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// #![feature(iterator_step_by)]
+ /// let a = [0, 1, 2, 3, 4, 5];
+ /// let mut iter = a.into_iter().step_by(2);
+ ///
+ /// assert_eq!(iter.next(), Some(&0));
+ /// assert_eq!(iter.next(), Some(&2));
+ /// assert_eq!(iter.next(), Some(&4));
+ /// assert_eq!(iter.next(), None);
+ /// ```
+ #[inline]
+ #[unstable(feature = "iterator_step_by",
+ reason = "unstable replacement of Range::step_by",
+ issue = "27741")]
+ fn step_by(self, step: usize) -> StepBy<Self> where Self: Sized {
+ assert!(step != 0);
+ StepBy{iter: self, step: step - 1, first_take: true}
+ }
+
/// Takes two iterators and creates a new iterator over both in sequence.
///
/// `chain()` will return a new iterator which will first iterate over
pub use self::range::Step;
#[unstable(feature = "step_by", reason = "recent addition",
issue = "27741")]
-pub use self::range::StepBy;
+pub use self::range::StepBy as DeprecatedStepBy;
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::sources::{Repeat, repeat};
#[unstable(feature = "fused", issue = "35602")]
impl<I> FusedIterator for Cycle<I> where I: Clone + Iterator {}
+/// An iterator that steps by n elements every iteration.
+///
+/// This `struct` is created by the [`step_by`] method on [`Iterator`]. See
+/// its documentation for more.
+///
+/// [`step_by`]: trait.Iterator.html#method.step_by
+/// [`Iterator`]: trait.Iterator.html
+#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
+#[unstable(feature = "iterator_step_by",
+ reason = "unstable replacement of Range::step_by",
+ issue = "27741")]
+#[derive(Clone, Debug)]
+pub struct StepBy<I> {
+ iter: I,
+ step: usize,
+ first_take: bool,
+}
+
+#[unstable(feature = "iterator_step_by",
+ reason = "unstable replacement of Range::step_by",
+ issue = "27741")]
+impl<I> Iterator for StepBy<I> where I: Iterator {
+ type Item = I::Item;
+
+ #[inline]
+ fn next(&mut self) -> Option<Self::Item> {
+ if self.first_take {
+ self.first_take = false;
+ self.iter.next()
+ } else {
+ self.iter.nth(self.step)
+ }
+ }
+}
+
/// An iterator that strings two iterators together.
///
/// This `struct` is created by the [`chain`] method on [`Iterator`]. See its
#[stable(feature = "rust1", since = "1.0.0")]
impl<I> ExactSizeIterator for Skip<I> where I: ExactSizeIterator {}
-#[stable(feature = "double_ended_skip_iterator", since = "1.8.0")]
+#[stable(feature = "double_ended_skip_iterator", since = "1.9.0")]
impl<I> DoubleEndedIterator for Skip<I> where I: DoubleEndedIterator + ExactSizeIterator {
fn next_back(&mut self) -> Option<Self::Item> {
if self.len() > 0 {
unsafe { intrinsics::min_align_of_val(val) }
}
+/// Returns whether dropping values of type `T` matters.
+///
+/// This is purely an optimization hint, and may be implemented conservatively.
+/// For instance, always returning `true` would be a valid implementation of
+/// this function.
+///
+/// Low level implementations of things like collections, which need to manually
+/// drop their data, should use this function to avoid unnecessarily
+/// trying to drop all their contents when they are destroyed. This might not
+/// make a difference in release builds (where a loop that has no side-effects
+/// is easily detected and eliminated), but is often a big win for debug builds.
+///
+/// Note that `ptr::drop_in_place` already performs this check, so if your workload
+/// can be reduced to some small number of drop_in_place calls, using this is
+/// unnecessary. In particular note that you can drop_in_place a slice, and that
+/// will do a single needs_drop check for all the values.
+///
+/// Types like Vec therefore just `drop_in_place(&mut self[..])` without using
+/// needs_drop explicitly. Types like HashMap, on the other hand, have to drop
+/// values one at a time and should use this API.
+///
+///
+/// # Examples
+///
+/// Here's an example of how a collection might make use of needs_drop:
+///
+/// ```ignore
+/// #![feature(needs_drop)]
+/// use std::{mem, ptr};
+///
+/// pub struct MyCollection<T> { /* ... */ }
+///
+/// impl<T> Drop for MyCollection<T> {
+/// fn drop(&mut self) {
+/// unsafe {
+/// // drop the data
+/// if mem::needs_drop::<T>() {
+/// for x in self.iter_mut() {
+/// ptr::drop_in_place(x);
+/// }
+/// }
+/// self.free_buffer();
+/// }
+/// }
+/// }
+/// ```
+#[inline]
+#[unstable(feature = "needs_drop", issue = "41890")]
+pub fn needs_drop<T>() -> bool {
+ unsafe { intrinsics::needs_drop::<T>() }
+}
+
/// Creates a value whose bytes are all zero.
///
/// This has the same effect as allocating space with
// Conversions T -> T are covered by a blanket impl and therefore excluded
// Some conversions from and to usize/isize are not implemented due to portability concerns
macro_rules! impl_from {
- ($Small: ty, $Large: ty) => {
- #[stable(feature = "lossless_prim_conv", since = "1.5.0")]
+ ($Small: ty, $Large: ty, #[$attr:meta]) => {
+ #[$attr]
impl From<$Small> for $Large {
#[inline]
fn from(small: $Small) -> $Large {
}
// Unsigned -> Unsigned
-impl_from! { u8, u16 }
-impl_from! { u8, u32 }
-impl_from! { u8, u64 }
-impl_from! { u8, u128 }
-impl_from! { u8, usize }
-impl_from! { u16, u32 }
-impl_from! { u16, u64 }
-impl_from! { u16, u128 }
-impl_from! { u32, u64 }
-impl_from! { u32, u128 }
-impl_from! { u64, u128 }
+impl_from! { u8, u16, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u8, u32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u8, u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u8, u128, #[unstable(feature = "i128", issue = "35118")] }
+impl_from! { u8, usize, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u16, u32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u16, u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u16, u128, #[unstable(feature = "i128", issue = "35118")] }
+impl_from! { u32, u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u32, u128, #[unstable(feature = "i128", issue = "35118")] }
+impl_from! { u64, u128, #[unstable(feature = "i128", issue = "35118")] }
// Signed -> Signed
-impl_from! { i8, i16 }
-impl_from! { i8, i32 }
-impl_from! { i8, i64 }
-impl_from! { i8, i128 }
-impl_from! { i8, isize }
-impl_from! { i16, i32 }
-impl_from! { i16, i64 }
-impl_from! { i16, i128 }
-impl_from! { i32, i64 }
-impl_from! { i32, i128 }
-impl_from! { i64, i128 }
+impl_from! { i8, i16, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { i8, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { i8, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { i8, i128, #[unstable(feature = "i128", issue = "35118")] }
+impl_from! { i8, isize, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { i16, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { i16, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { i16, i128, #[unstable(feature = "i128", issue = "35118")] }
+impl_from! { i32, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { i32, i128, #[unstable(feature = "i128", issue = "35118")] }
+impl_from! { i64, i128, #[unstable(feature = "i128", issue = "35118")] }
// Unsigned -> Signed
-impl_from! { u8, i16 }
-impl_from! { u8, i32 }
-impl_from! { u8, i64 }
-impl_from! { u8, i128 }
-impl_from! { u16, i32 }
-impl_from! { u16, i64 }
-impl_from! { u16, i128 }
-impl_from! { u32, i64 }
-impl_from! { u32, i128 }
-impl_from! { u64, i128 }
+impl_from! { u8, i16, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u8, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u8, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u8, i128, #[unstable(feature = "i128", issue = "35118")] }
+impl_from! { u16, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u16, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u16, i128, #[unstable(feature = "i128", issue = "35118")] }
+impl_from! { u32, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u32, i128, #[unstable(feature = "i128", issue = "35118")] }
+impl_from! { u64, i128, #[unstable(feature = "i128", issue = "35118")] }
// Note: integers can only be represented with full precision in a float if
// they fit in the significand, which is 24 bits in f32 and 53 bits in f64.
// Lossy float conversions are not implemented at this time.
// Signed -> Float
-impl_from! { i8, f32 }
-impl_from! { i8, f64 }
-impl_from! { i16, f32 }
-impl_from! { i16, f64 }
-impl_from! { i32, f64 }
+impl_from! { i8, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+impl_from! { i8, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+impl_from! { i16, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+impl_from! { i16, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+impl_from! { i32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
// Unsigned -> Float
-impl_from! { u8, f32 }
-impl_from! { u8, f64 }
-impl_from! { u16, f32 }
-impl_from! { u16, f64 }
-impl_from! { u32, f64 }
+impl_from! { u8, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+impl_from! { u8, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+impl_from! { u16, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+impl_from! { u16, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+impl_from! { u32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
// Float -> Float
-impl_from! { f32, f64 }
+impl_from! { f32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
fn clone(&self) -> Iter<'a, T> { Iter { ptr: self.ptr, end: self.end, _marker: self._marker } }
}
-#[stable(feature = "slice_iter_as_ref", since = "1.12.0")]
+#[stable(feature = "slice_iter_as_ref", since = "1.13.0")]
impl<'a, T> AsRef<[T]> for Iter<'a, T> {
fn as_ref(&self) -> &[T] {
self.as_slice()
/// byte offset of a character (as defined by `is_char_boundary`).
/// Requires that `begin <= end` and `end <= len` where `len` is the
/// length of the string.
- #[stable(feature = "derefmut_for_string", since = "1.2.0")]
+ #[stable(feature = "derefmut_for_string", since = "1.3.0")]
impl ops::IndexMut<ops::Range<usize>> for str {
#[inline]
fn index_mut(&mut self, index: ops::Range<usize>) -> &mut str {
/// `end`.
///
/// Equivalent to `&mut self[0 .. end]`.
- #[stable(feature = "derefmut_for_string", since = "1.2.0")]
+ #[stable(feature = "derefmut_for_string", since = "1.3.0")]
impl ops::IndexMut<ops::RangeTo<usize>> for str {
#[inline]
fn index_mut(&mut self, index: ops::RangeTo<usize>) -> &mut str {
/// to the end of the string.
///
/// Equivalent to `&mut self[begin .. len]`.
- #[stable(feature = "derefmut_for_string", since = "1.2.0")]
+ #[stable(feature = "derefmut_for_string", since = "1.3.0")]
impl ops::IndexMut<ops::RangeFrom<usize>> for str {
#[inline]
fn index_mut(&mut self, index: ops::RangeFrom<usize>) -> &mut str {
/// never panic.
///
/// Equivalent to `&mut self[0 .. len]`.
- #[stable(feature = "derefmut_for_string", since = "1.2.0")]
+ #[stable(feature = "derefmut_for_string", since = "1.3.0")]
impl ops::IndexMut<ops::RangeFull> for str {
#[inline]
fn index_mut(&mut self, _index: ops::RangeFull) -> &mut str {
/// Searches for chars that are equal to a given char
impl<'a> Pattern<'a> for char {
- pattern_methods!(CharSearcher<'a>, CharEqPattern, CharSearcher);
+ type Searcher = CharSearcher<'a>;
+
+ #[inline]
+ fn into_searcher(self, haystack: &'a str) -> Self::Searcher {
+ CharSearcher(CharEqPattern(self).into_searcher(haystack))
+ }
+
+ #[inline]
+ fn is_contained_in(self, haystack: &'a str) -> bool {
+ if (self as u32) < 128 {
+ haystack.as_bytes().contains(&(self as u8))
+ } else {
+ let mut buffer = [0u8; 4];
+ self.encode_utf8(&mut buffer).is_contained_in(haystack)
+ }
+ }
+
+ #[inline]
+ fn is_prefix_of(self, haystack: &'a str) -> bool {
+ CharEqPattern(self).is_prefix_of(haystack)
+ }
+
+ #[inline]
+ fn is_suffix_of(self, haystack: &'a str) -> bool where Self::Searcher: ReverseSearcher<'a>
+ {
+ CharEqPattern(self).is_suffix_of(haystack)
+ }
}
/////////////////////////////////////////////////////////////////////////////
assert_eq!(iter.next(), None);
}
+#[test]
+fn test_iterator_step_by() {
+ // Identity
+ // Replace with (0..).step_by(1) after Range::step_by gets removed
+ let mut it = Iterator::step_by((0..), 1).take(3);
+ assert_eq!(it.next(), Some(0));
+ assert_eq!(it.next(), Some(1));
+ assert_eq!(it.next(), Some(2));
+ assert_eq!(it.next(), None);
+
+ // Replace with (0..).step_by(3) after Range::step_by gets removed
+ let mut it = Iterator::step_by((0..), 3).take(4);
+ assert_eq!(it.next(), Some(0));
+ assert_eq!(it.next(), Some(3));
+ assert_eq!(it.next(), Some(6));
+ assert_eq!(it.next(), Some(9));
+ assert_eq!(it.next(), None);
+}
+
+#[test]
+#[should_panic]
+fn test_iterator_step_by_zero() {
+ // Replace with (0..).step_by(0) after Range::step_by gets removed
+ let mut it = Iterator::step_by((0..), 0);
+ it.next();
+}
+
#[test]
fn test_filter_map() {
let it = (0..).step_by(1).take(10)
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(iterator_step_by)]
#![feature(i128_type)]
#![feature(iter_rfind)]
#![feature(libc)]
use hir;
use hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE, DefIndexAddressSpace};
+use ich::Fingerprint;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::indexed_vec::IndexVec;
use rustc_data_structures::stable_hasher::StableHasher;
pub struct DefPathTable {
index_to_key: [Vec<DefKey>; 2],
key_to_index: FxHashMap<DefKey, DefIndex>,
- def_path_hashes: [Vec<u64>; 2],
+ def_path_hashes: [Vec<Fingerprint>; 2],
}
// Unfortunately we have to provide a manual impl of Clone because of the
fn allocate(&mut self,
key: DefKey,
- def_path_hash: u64,
+ def_path_hash: Fingerprint,
address_space: DefIndexAddressSpace)
-> DefIndex {
let index = {
}
#[inline(always)]
- pub fn def_path_hash(&self, index: DefIndex) -> u64 {
+ pub fn def_path_hash(&self, index: DefIndex) -> Fingerprint {
self.def_path_hashes[index.address_space().index()]
[index.as_array_index()]
}
let index_to_key_lo: Vec<DefKey> = Decodable::decode(d)?;
let index_to_key_hi: Vec<DefKey> = Decodable::decode(d)?;
- let def_path_hashes_lo: Vec<u64> = Decodable::decode(d)?;
- let def_path_hashes_hi: Vec<u64> = Decodable::decode(d)?;
+ let def_path_hashes_lo: Vec<Fingerprint> = Decodable::decode(d)?;
+ let def_path_hashes_hi: Vec<Fingerprint> = Decodable::decode(d)?;
let index_to_key = [index_to_key_lo, index_to_key_hi];
let def_path_hashes = [def_path_hashes_lo, def_path_hashes_hi];
}
impl DefKey {
- fn compute_stable_hash(&self, parent_hash: u64) -> u64 {
+ fn compute_stable_hash(&self, parent_hash: Fingerprint) -> Fingerprint {
let mut hasher = StableHasher::new();
// We hash a 0u8 here to disambiguate between regular DefPath hashes,
hasher.finish()
}
- fn root_parent_stable_hash(crate_name: &str, crate_disambiguator: &str) -> u64 {
+ fn root_parent_stable_hash(crate_name: &str, crate_disambiguator: &str) -> Fingerprint {
let mut hasher = StableHasher::new();
// Disambiguate this from a regular DefPath hash,
// see compute_stable_hash() above.
}
#[inline(always)]
- pub fn def_path_hash(&self, index: DefIndex) -> u64 {
+ pub fn def_path_hash(&self, index: DefIndex) -> Fingerprint {
self.table.def_path_hash(index)
}
use rustc_serialize::{Encodable, Decodable, Encoder, Decoder};
use rustc_data_structures::stable_hasher;
-use rustc_data_structures::ToHex;
-
-const FINGERPRINT_LENGTH: usize = 16;
+use std::mem;
+use std::slice;
#[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Clone, Copy)]
-pub struct Fingerprint(pub [u8; FINGERPRINT_LENGTH]);
+pub struct Fingerprint(u64, u64);
impl Fingerprint {
#[inline]
pub fn zero() -> Fingerprint {
- Fingerprint([0; FINGERPRINT_LENGTH])
+ Fingerprint(0, 0)
}
+ #[inline]
pub fn from_smaller_hash(hash: u64) -> Fingerprint {
- let mut result = Fingerprint::zero();
- result.0[0] = (hash >> 0) as u8;
- result.0[1] = (hash >> 8) as u8;
- result.0[2] = (hash >> 16) as u8;
- result.0[3] = (hash >> 24) as u8;
- result.0[4] = (hash >> 32) as u8;
- result.0[5] = (hash >> 40) as u8;
- result.0[6] = (hash >> 48) as u8;
- result.0[7] = (hash >> 56) as u8;
- result
+ Fingerprint(hash, hash)
}
+ #[inline]
pub fn to_smaller_hash(&self) -> u64 {
- ((self.0[0] as u64) << 0) |
- ((self.0[1] as u64) << 8) |
- ((self.0[2] as u64) << 16) |
- ((self.0[3] as u64) << 24) |
- ((self.0[4] as u64) << 32) |
- ((self.0[5] as u64) << 40) |
- ((self.0[6] as u64) << 48) |
- ((self.0[7] as u64) << 56)
+ self.0
}
pub fn to_hex(&self) -> String {
- self.0.to_hex()
+ format!("{:x}{:x}", self.0, self.1)
}
}
impl Encodable for Fingerprint {
#[inline]
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
- for &byte in &self.0 {
- s.emit_u8(byte)?;
- }
- Ok(())
+ s.emit_u64(self.0.to_le())?;
+ s.emit_u64(self.1.to_le())
}
}
impl Decodable for Fingerprint {
#[inline]
fn decode<D: Decoder>(d: &mut D) -> Result<Fingerprint, D::Error> {
- let mut result = Fingerprint([0u8; FINGERPRINT_LENGTH]);
- for byte in &mut result.0 {
- *byte = d.read_u8()?;
- }
- Ok(result)
+ let _0 = u64::from_le(d.read_u64()?);
+ let _1 = u64::from_le(d.read_u64()?);
+ Ok(Fingerprint(_0, _1))
}
}
impl ::std::fmt::Display for Fingerprint {
fn fmt(&self, formatter: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
- for i in 0 .. self.0.len() {
- if i > 0 {
- write!(formatter, "::")?;
- }
-
- write!(formatter, "{}", self.0[i])?;
- }
- Ok(())
+ write!(formatter, "{:x}-{:x}", self.0, self.1)
}
}
-
impl stable_hasher::StableHasherResult for Fingerprint {
fn finish(mut hasher: stable_hasher::StableHasher<Self>) -> Self {
- let mut fingerprint = Fingerprint::zero();
- fingerprint.0.copy_from_slice(hasher.finalize());
- fingerprint
+ let hash_bytes: &[u8] = hasher.finalize();
+
+ assert!(hash_bytes.len() >= mem::size_of::<u64>() * 2);
+ let hash_bytes: &[u64] = unsafe {
+ slice::from_raw_parts(hash_bytes.as_ptr() as *const u64, 2)
+ };
+
+ // The bytes returned bytes the Blake2B hasher are always little-endian.
+ Fingerprint(u64::from_le(hash_bytes[0]), u64::from_le(hash_bytes[1]))
}
}
impl<CTX> stable_hasher::HashStable<CTX> for Fingerprint {
+ #[inline]
fn hash_stable<W: stable_hasher::StableHasherResult>(&self,
_: &mut CTX,
hasher: &mut stable_hasher::StableHasher<W>) {
- ::std::hash::Hash::hash(&self.0, hasher);
+ ::std::hash::Hash::hash(self, hasher);
}
}
}
#[inline]
- pub fn def_path_hash(&mut self, def_id: DefId) -> u64 {
+ pub fn def_path_hash(&mut self, def_id: DefId) -> ich::Fingerprint {
self.tcx.def_path_hash(def_id)
}
heading: &str, span: Span)
-> (String, Option<Span>) {
let lo = tcx.sess.codemap().lookup_char_pos_adj(span.lo);
- (format!("the {} at {}:{}", heading, lo.line, lo.col.to_usize()),
+ (format!("the {} at {}:{}", heading, lo.line, lo.col.to_usize() + 1),
Some(span))
}
-> Option<DefId>;
fn def_key(&self, def: DefId) -> DefKey;
fn def_path(&self, def: DefId) -> hir_map::DefPath;
- fn def_path_hash(&self, def: DefId) -> u64;
+ fn def_path_hash(&self, def: DefId) -> ich::Fingerprint;
fn struct_field_names(&self, def: DefId) -> Vec<ast::Name>;
fn item_children(&self, did: DefId) -> Vec<def::Export>;
fn load_macro(&self, did: DefId, sess: &Session) -> LoadedMacro;
fn def_path(&self, def: DefId) -> hir_map::DefPath {
bug!("relative_def_path")
}
- fn def_path_hash(&self, def: DefId) -> u64 {
+ fn def_path_hash(&self, def: DefId) -> ich::Fingerprint {
bug!("wa")
}
fn struct_field_names(&self, def: DefId) -> Vec<ast::Name> { bug!("struct_field_names") }
linker: Option<String> = (None, parse_opt_string, [UNTRACKED],
"system linker to link outputs with"),
link_arg: Vec<String> = (vec![], parse_string_push, [UNTRACKED],
- "a single extra argument to pass to the linker (can be used several times)"),
+ "a single extra argument to append to the linker invocation (can be used several times)"),
link_args: Option<Vec<String>> = (None, parse_opt_list, [UNTRACKED],
- "extra arguments to pass to the linker (space separated)"),
+ "extra arguments to append to the linker invocation (space separated)"),
link_dead_code: bool = (false, parse_bool, [UNTRACKED],
"don't let linker strip dead code (turning it on can be used for code coverage)"),
lto: bool = (false, parse_bool, [TRACKED],
"add a mapping target to the file path remapping config"),
force_unstable_if_unmarked: bool = (false, parse_bool, [TRACKED],
"force all crates to be `rustc_private` unstable"),
+ pre_link_arg: Vec<String> = (vec![], parse_string_push, [UNTRACKED],
+ "a single extra argument to prepend the linker invocation (can be used several times)"),
+ pre_link_args: Option<Vec<String>> = (None, parse_opt_list, [UNTRACKED],
+ "extra arguments to prepend to the linker invocation (space separated)"),
}
pub fn default_lib_output() -> CrateType {
})
}
- match canonicalize(env::current_exe().ok()) {
- Some(mut p) => { p.pop(); p.pop(); p }
- None => bug!("can't determine value for sysroot")
+ match env::current_exe() {
+ Ok(exe) => {
+ match canonicalize(Some(exe)) {
+ Some(mut p) => { p.pop(); p.pop(); return p; },
+ None => bug!("can't determine value for sysroot")
+ }
+ }
+ Err(ref e) => panic!(format!("failed to get current_exe: {}", e))
}
}
use hir::{map as hir_map, FreevarMap, TraitMap};
use hir::def::{Def, CtorKind, ExportMap};
use hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
-use ich::StableHashingContext;
+use ich::{self, StableHashingContext};
use middle::const_val::ConstVal;
use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
use middle::privacy::AccessLevels;
}
#[inline]
- pub fn def_path_hash(self, def_id: DefId) -> u64 {
+ pub fn def_path_hash(self, def_id: DefId) -> ich::Fingerprint {
if def_id.is_local() {
self.hir.definitions().def_path_hash(def_id.index)
} else {
use serialize;
use hir;
+use ich;
use self::InferTy::*;
use self::TypeVariants::*;
self.item_name // safe to skip the binder to access a name
}
- pub fn sort_key(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> (u64, InternedString) {
+ pub fn sort_key(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> (ich::Fingerprint, InternedString) {
// We want something here that is stable across crate boundaries.
// The DefId isn't but the `deterministic_hash` of the corresponding
// DefPath is.
self.skip_binder().item_name()
}
- pub fn sort_key(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> (u64, InternedString) {
+ pub fn sort_key(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> (ich::Fingerprint, InternedString) {
self.skip_binder().sort_key(tcx)
}
// except according to those terms.
use hir::def_id::DefId;
+use ich::Fingerprint;
use traits::specialization_graph;
use ty::fast_reject;
use ty::fold::TypeFoldable;
/// The ICH of this trait's DefPath, cached here so it doesn't have to be
/// recomputed all the time.
- pub def_path_hash: u64,
+ pub def_path_hash: Fingerprint,
}
// We don't store the list of impls in a flat list because each cached list of
unsafety: hir::Unsafety,
paren_sugar: bool,
has_default_impl: bool,
- def_path_hash: u64)
+ def_path_hash: Fingerprint)
-> TraitDef {
TraitDef {
def_id,
use rustc::ty::{self, TyCtxt};
use rustc::ty::maps::Providers;
+use syntax_pos::DUMMY_SP;
+
use std::fmt;
use std::rc::Rc;
use std::hash::{Hash, Hasher};
MovedInCapture => ("capture", "captured"),
};
- let (_ol, _moved_lp_msg, mut err) = match the_move.kind {
+ let (_ol, _moved_lp_msg, mut err, need_note) = match the_move.kind {
move_data::Declared => {
// If this is an uninitialized variable, just emit a simple warning
// and return.
let msg = if !has_fork && partial { "partially " }
else if has_fork && !has_common { "collaterally "}
else { "" };
- let err = struct_span_err!(
+ let mut err = struct_span_err!(
self.tcx.sess, use_span, E0382,
"{} of {}moved value: `{}`",
verb, msg, nl);
- (ol, moved_lp_msg, err)}
+ let need_note = match lp.ty.sty {
+ ty::TypeVariants::TyClosure(id, _) => {
+ if let Ok(ty::ClosureKind::FnOnce) =
+ ty::queries::closure_kind::try_get(self.tcx, DUMMY_SP, id) {
+ err.help("closure was moved because it only implements `FnOnce`");
+ false
+ } else {
+ true
+ }
+ }
+ _ => true,
+ };
+ (ol, moved_lp_msg, err, need_note)
+ }
};
// Get type of value and span where it was previously
err
};
- err.note(&format!("move occurs because `{}` has type `{}`, \
- which does not implement the `Copy` trait",
- self.loan_path_to_string(moved_lp),
- moved_lp.ty));
+ if need_note {
+ err.note(&format!("move occurs because `{}` has type `{}`, \
+ which does not implement the `Copy` trait",
+ self.loan_path_to_string(moved_lp),
+ moved_lp.ty));
+ }
// Note: we used to suggest adding a `ref binding` or calling
// `clone` but those suggestions have been removed because
Registry::new(&all_errors)
}
+fn get_args() -> Vec<String> {
+ env::args_os().enumerate()
+ .map(|(i, arg)| arg.into_string().unwrap_or_else(|arg| {
+ early_error(ErrorOutputType::default(),
+ &format!("Argument {} is not valid Unicode: {:?}", i, arg))
+ }))
+ .collect()
+}
+
pub fn main() {
env_logger::init().unwrap();
- let result = run(|| run_compiler(&env::args().collect::<Vec<_>>(),
+ let result = run(|| run_compiler(&get_args(),
&mut RustcDefaultCalls,
None,
None));
}
}
-/// Destructor bomb - a DiagnosticBuilder must be either emitted or cancelled or
-/// we emit a bug.
+/// Destructor bomb - a `DiagnosticBuilder` must be either emitted or cancelled
+/// or we emit a bug.
impl<'a> Drop for DiagnosticBuilder<'a> {
fn drop(&mut self) {
if !panicking() && !self.cancelled() {
}
fn flush(&mut self) -> io::Result<()> {
let mut stderr = io::stderr();
- let result = (|| {
- stderr.write_all(&self.buffer)?;
- stderr.flush()
- })();
+ let result = stderr.write_all(&self.buffer)
+ .and_then(|_| stderr.flush());
self.buffer.clear();
result
}
pub fn span_fatal<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> FatalError {
self.emit(&sp.into(), msg, Fatal);
self.panic_if_treat_err_as_bug();
- return FatalError;
+ FatalError
}
pub fn span_fatal_with_code<S: Into<MultiSpan>>(&self,
sp: S,
-> FatalError {
self.emit_with_code(&sp.into(), msg, code, Fatal);
self.panic_if_treat_err_as_bug();
- return FatalError;
+ FatalError
}
pub fn span_err<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
self.emit(&sp.into(), msg, Error);
{
let tcx = self.hcx.tcx();
- let mut impls: Vec<(u64, Fingerprint)> = krate
+ let mut impls: Vec<(Fingerprint, Fingerprint)> = krate
.trait_impls
.iter()
.map(|(&trait_id, impls)| {
}
}
- // LLVM requires symbols from this library, but apparently they're not printeds
+ // LLVM requires symbols from this library, but apparently they're not printed
// during llvm-config?
- if target.contains("windows") {
- println!("cargo:rustc-link-lib=ole32");
- }
if target.contains("windows-gnu") {
println!("cargo:rustc-link-lib=static-nobundle=gcc_s");
println!("cargo:rustc-link-lib=static-nobundle=pthread");
ExternCrate, NativeLibrary, MetadataLoader, LinkMeta,
LinkagePreference, LoadedMacro, EncodedMetadata};
use rustc::hir::def;
+use rustc::ich;
use rustc::middle::lang_items;
use rustc::session::Session;
use rustc::ty::{self, TyCtxt};
self.get_crate_data(def.krate).def_path(def.index)
}
- fn def_path_hash(&self, def: DefId) -> u64 {
+ fn def_path_hash(&self, def: DefId) -> ich::Fingerprint {
self.get_crate_data(def.krate).def_path_hash(def.index)
}
use rustc::dep_graph::{DepGraph, DepNode, GlobalMetaDataKind};
use rustc::hir::map::{DefKey, DefPath, DefPathData};
use rustc::hir;
+use rustc::ich;
use rustc::middle::cstore::LinkagePreference;
use rustc::hir::def::{self, Def, CtorKind};
}
#[inline]
- pub fn def_path_hash(&self, index: DefIndex) -> u64 {
+ pub fn def_path_hash(&self, index: DefIndex) -> ich::Fingerprint {
self.def_path_table.def_path_hash(index)
}
if let Some(args) = sess.target.target.options.pre_link_args.get(&flavor) {
cmd.args(args);
}
+ if let Some(ref args) = sess.opts.debugging_opts.pre_link_args {
+ cmd.args(args);
+ }
+ cmd.args(&sess.opts.debugging_opts.pre_link_arg);
let pre_link_objects = if crate_type == config::CrateTypeExecutable {
&sess.target.target.options.pre_link_objects_exe
let dbg_cx = if shared.tcx.sess.opts.debuginfo != NoDebugInfo {
let dctx = debuginfo::CrateDebugContext::new(llmod);
- debuginfo::metadata::compile_unit_metadata(shared, &dctx, shared.tcx.sess);
+ debuginfo::metadata::compile_unit_metadata(shared,
+ codegen_unit.name(),
+ &dctx,
+ shared.tcx.sess);
Some(dctx)
} else {
None
}
pub fn compile_unit_metadata(scc: &SharedCrateContext,
+ codegen_unit_name: &str,
debug_context: &CrateDebugContext,
sess: &Session)
-> DIDescriptor {
- let compile_unit_name = match sess.local_crate_source_file {
- None => fallback_path(scc),
- Some(ref path) => {
- CString::new(&path[..]).unwrap()
- }
+ let mut name_in_debuginfo = match sess.local_crate_source_file {
+ Some(ref path) => path.clone(),
+ None => scc.tcx().crate_name(LOCAL_CRATE).to_string(),
};
- debug!("compile_unit_metadata: {:?}", compile_unit_name);
+ // The OSX linker has an idiosyncrasy where it will ignore some debuginfo
+ // if multiple object files with the same DW_AT_name are linked together.
+ // As a workaround we generate unique names for each object file. Those do
+ // not correspond to an actual source file but that should be harmless.
+ if scc.sess().target.target.options.is_like_osx {
+ name_in_debuginfo.push_str("@");
+ name_in_debuginfo.push_str(codegen_unit_name);
+ }
+
+ debug!("compile_unit_metadata: {:?}", name_in_debuginfo);
// FIXME(#41252) Remove "clang LLVM" if we can get GDB and LLVM to play nice.
let producer = format!("clang LLVM (rustc version {})",
(option_env!("CFG_VERSION")).expect("CFG_VERSION"));
- let compile_unit_name = compile_unit_name.as_ptr();
-
+ let name_in_debuginfo = CString::new(name_in_debuginfo).unwrap();
let work_dir = CString::new(&sess.working_dir.0[..]).unwrap();
let producer = CString::new(producer).unwrap();
let flags = "\0";
unsafe {
let file_metadata = llvm::LLVMRustDIBuilderCreateFile(
- debug_context.builder, compile_unit_name, work_dir.as_ptr());
+ debug_context.builder, name_in_debuginfo.as_ptr(), work_dir.as_ptr());
return llvm::LLVMRustDIBuilderCreateCompileUnit(
debug_context.builder,
0,
split_name.as_ptr() as *const _)
};
-
- fn fallback_path(scc: &SharedCrateContext) -> CString {
- CString::new(scc.tcx().crate_name(LOCAL_CRATE).to_string()).unwrap()
- }
}
struct MetadataCreationResult {
} else if (ev.target.tagName === 'SPAN' && hasClass(ev.target.parentNode, 'line-numbers')) {
var prev_id = 0;
- function set_fragment(name) {
+ var set_fragment = function (name) {
if (browserSupportsHistoryApi()) {
history.replaceState(null, null, '#' + name);
window.hashchange();
} else {
location.replace('#' + name);
}
- }
+ };
var cur_id = parseInt(ev.target.id, 10);
}
function escape(content) {
- let h1 = document.createElement('h1');
+ var h1 = document.createElement('h1');
h1.textContent = content;
return h1.innerHTML;
}
code.innerHTML = structs[j];
var x = code.getElementsByTagName('a');
- for (var i = 0; i < x.length; i++) {
- var href = x[i].href;
+ for (var k = 0; k < x.length; k++) {
+ var href = x[k].getAttribute('href');
if (href && href.indexOf('http') !== 0) {
- x[i].href = rootPath + href;
+ x[k].setAttribute('href', rootPath + href);
}
}
var li = document.createElement('li');
const STACK_SIZE: usize = 32_000_000; // 32MB
env_logger::init().unwrap();
let res = std::thread::Builder::new().stack_size(STACK_SIZE).spawn(move || {
- let s = env::args().collect::<Vec<_>>();
- main_args(&s)
+ get_args().map(|args| main_args(&args)).unwrap_or(1)
}).unwrap().join().unwrap_or(101);
process::exit(res as i32);
}
+fn get_args() -> Option<Vec<String>> {
+ env::args_os().enumerate()
+ .map(|(i, arg)| arg.into_string().map_err(|arg| {
+ print_error(format!("Argument {} is not valid Unicode: {:?}", i, arg));
+ }).ok())
+ .collect()
+}
+
fn stable(g: getopts::OptGroup) -> RustcOptGroup { RustcOptGroup::stable(g) }
fn unstable(g: getopts::OptGroup) -> RustcOptGroup { RustcOptGroup::unstable(g) }
use cmp;
use hash::{BuildHasher, Hash, Hasher};
-use intrinsics::needs_drop;
use marker;
-use mem::{align_of, size_of};
+use mem::{align_of, size_of, needs_drop};
use mem;
use ops::{Deref, DerefMut};
use ptr::{self, Unique, Shared};
//! This module contains functions to inspect various aspects such as
//! environment variables, process arguments, the current directory, and various
//! other important directories.
+//!
+//! There are several functions and structs in this module that have a
+//! counterpart ending in `os`. Those ending in `os` will return an [`OsString`]
+//! and those without will be returning a [`String`].
+//!
+//! [`OsString`]: ../../std/ffi/struct.OsString.html
+//! [`String`]: ../string/struct.String.html
#![stable(feature = "env", since = "1.0.0")]
/// use std::env;
///
/// // We assume that we are in a valid directory.
-/// let p = env::current_dir().unwrap();
-/// println!("The current directory is {}", p.display());
+/// let path = env::current_dir().unwrap();
+/// println!("The current directory is {}", path.display());
/// ```
#[stable(feature = "env", since = "1.0.0")]
pub fn current_dir() -> io::Result<PathBuf> {
os_imp::getcwd()
}
-/// Changes the current working directory to the specified path, returning
-/// whether the change was completed successfully or not.
+/// Changes the current working directory to the specified path.
+///
+/// Returns an [`Err`] if the operation fails.
+///
+/// [`Err`]: ../../std/result/enum.Result.html#method.err
///
/// # Examples
///
/// println!("Successfully changed working directory to {}!", root.display());
/// ```
#[stable(feature = "env", since = "1.0.0")]
-pub fn set_current_dir<P: AsRef<Path>>(p: P) -> io::Result<()> {
- os_imp::chdir(p.as_ref())
+pub fn set_current_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
+ os_imp::chdir(path.as_ref())
}
/// An iterator over a snapshot of the environment variables of this process.
///
-/// This structure is created through the [`std::env::vars`] function.
+/// This structure is created by the [`std::env::vars`] function. See its
+/// documentation for more.
///
/// [`std::env::vars`]: fn.vars.html
#[stable(feature = "env", since = "1.0.0")]
/// An iterator over a snapshot of the environment variables of this process.
///
-/// This structure is created through the [`std::env::vars_os`] function.
+/// This structure is created by the [`std::env::vars_os`] function. See
+/// its documentation for more.
///
/// [`std::env::vars_os`]: fn.vars_os.html
#[stable(feature = "env", since = "1.0.0")]
/// Fetches the environment variable `key` from the current process.
///
-/// The returned result is [`Ok(s)`] if the environment variable is present and is
-/// valid unicode. If the environment variable is not present, or it is not
-/// valid unicode, then [`Err`] will be returned.
+/// # Errors
///
-/// [`Ok(s)`]: ../result/enum.Result.html#variant.Ok
-/// [`Err`]: ../result/enum.Result.html#variant.Err
+/// * Environment variable is not present
+/// * Environment variable is not valid unicode
///
/// # Examples
///
fn _var(key: &OsStr) -> Result<String, VarError> {
match var_os(key) {
Some(s) => s.into_string().map_err(VarError::NotUnicode),
- None => Err(VarError::NotPresent)
+ None => Err(VarError::NotPresent),
}
}
})
}
-/// Possible errors from the [`env::var`] function.
+/// The error type for operations interacting with environment variables.
+/// Possibly returned from the [`env::var`] function.
///
/// [`env::var`]: fn.var.html
#[derive(Debug, PartialEq, Eq, Clone)]
})
}
-/// An iterator over `PathBuf` instances for parsing an environment variable
-/// according to platform-specific conventions.
+/// An iterator that splits an environment variable into paths according to
+/// platform-specific conventions.
+///
+/// This structure is created by the [`std::env::split_paths`] function See its
+/// documentation for more.
///
-/// This structure is returned from `std::env::split_paths`.
+/// [`std::env::split_paths`]: fn.split_paths.html
#[stable(feature = "env", since = "1.0.0")]
pub struct SplitPaths<'a> { inner: os_imp::SplitPaths<'a> }
}
}
-/// Error type returned from `std::env::join_paths` when paths fail to be
-/// joined.
+/// The error type for operations on the `PATH` variable. Possibly returned from
+/// the [`env::join_paths`] function.
+///
+/// [`env::join_paths`]: fn.join_paths.html
#[derive(Debug)]
#[stable(feature = "env", since = "1.0.0")]
pub struct JoinPathsError {
/// Joins a collection of [`Path`]s appropriately for the `PATH`
/// environment variable.
///
-/// Returns an [`OsString`] on success.
+/// # Errors
///
/// Returns an [`Err`][err] (containing an error message) if one of the input
/// [`Path`]s contains an invalid character for constructing the `PATH`
/// Returns the path of a temporary directory.
///
-/// On Unix, returns the value of the `TMPDIR` environment variable if it is
+/// # Unix
+///
+/// Returns the value of the `TMPDIR` environment variable if it is
/// set, otherwise for non-Android it returns `/tmp`. If Android, since there
/// is no global temporary folder (it is usually allocated per-app), it returns
/// `/data/local/tmp`.
///
-/// On Windows, returns the value of, in order, the `TMP`, `TEMP`,
+/// # Windows
+///
+/// Returns the value of, in order, the `TMP`, `TEMP`,
/// `USERPROFILE` environment variable if any are set and not the empty
/// string. Otherwise, `temp_dir` returns the path of the Windows directory.
/// This behavior is identical to that of [`GetTempPath`][msdn], which this
fn is_empty(&self) -> bool { self.inner.is_empty() }
}
-#[stable(feature = "env_iterators", since = "1.11.0")]
+#[stable(feature = "env_iterators", since = "1.12.0")]
impl DoubleEndedIterator for Args {
fn next_back(&mut self) -> Option<String> {
self.inner.next_back().map(|s| s.into_string().unwrap())
fn is_empty(&self) -> bool { self.inner.is_empty() }
}
-#[stable(feature = "env_iterators", since = "1.11.0")]
+#[stable(feature = "env_iterators", since = "1.12.0")]
impl DoubleEndedIterator for ArgsOs {
fn next_back(&mut self) -> Option<OsString> { self.inner.next_back() }
}
}
}
-#[stable(feature = "string_box_error", since = "1.7.0")]
+#[stable(feature = "string_box_error", since = "1.6.0")]
impl From<String> for Box<Error> {
fn from(str_err: String) -> Box<Error> {
let err1: Box<Error + Send + Sync> = From::from(str_err);
}
}
-#[stable(feature = "string_box_error", since = "1.7.0")]
+#[stable(feature = "string_box_error", since = "1.6.0")]
impl<'a> From<&'a str> for Box<Error> {
fn from(err: &'a str) -> Box<Error> {
From::from(String::from(err))
}
}
-#[stable(feature = "box_error", since = "1.7.0")]
+#[stable(feature = "box_error", since = "1.8.0")]
impl<T: Error> Error for Box<T> {
fn description(&self) -> &str {
Error::description(&**self)
}
}
-#[stable(feature = "c_string_from_box", since = "1.17.0")]
+#[stable(feature = "c_string_from_box", since = "1.18.0")]
impl From<Box<CStr>> for CString {
fn from(s: Box<CStr>) -> CString {
s.into_c_string()
}
}
-#[stable(feature = "box_from_c_string", since = "1.17.0")]
+#[stable(feature = "box_from_c_string", since = "1.18.0")]
impl Into<Box<CStr>> for CString {
fn into(self) -> Box<CStr> {
self.into_boxed_c_str()
}
}
-#[stable(feature = "os_string_from_box", since = "1.17.0")]
+#[stable(feature = "os_string_from_box", since = "1.18.0")]
impl<'a> From<Box<OsStr>> for OsString {
fn from(boxed: Box<OsStr>) -> OsString {
boxed.into_os_string()
}
}
-#[stable(feature = "box_from_c_string", since = "1.17.0")]
+#[stable(feature = "box_from_os_string", since = "1.18.0")]
impl Into<Box<OsStr>> for OsString {
fn into(self) -> Box<OsStr> {
self.into_boxed_os_str()
#![feature(linkage)]
#![feature(macro_reexport)]
#![feature(needs_panic_runtime)]
+#![feature(needs_drop)]
#![feature(never_type)]
#![feature(num_bits_bytes)]
#![feature(old_wrapping)]
///
/// Panics if writing to `io::stderr` fails.
#[macro_export]
-#[stable(feature = "eprint", since="1.18.0")]
+#[stable(feature = "eprint", since = "1.19.0")]
#[allow_internal_unstable]
macro_rules! eprint {
($($arg:tt)*) => ($crate::io::_eprint(format_args!($($arg)*)));
///
/// Panics if writing to `io::stderr` fails.
#[macro_export]
-#[stable(feature = "eprint", since="1.18.0")]
+#[stable(feature = "eprint", since = "1.19.0")]
macro_rules! eprintln {
() => (eprint!("\n"));
($fmt:expr) => (eprint!(concat!($fmt, "\n")));
}
}
-#[stable(feature = "ip_cmp", since = "1.15.0")]
+#[stable(feature = "ip_cmp", since = "1.16.0")]
impl PartialEq<Ipv4Addr> for IpAddr {
fn eq(&self, other: &Ipv4Addr) -> bool {
match *self {
}
}
-#[stable(feature = "ip_cmp", since = "1.15.0")]
+#[stable(feature = "ip_cmp", since = "1.16.0")]
impl PartialEq<IpAddr> for Ipv4Addr {
fn eq(&self, other: &IpAddr) -> bool {
match *other {
}
}
-#[stable(feature = "ip_cmp", since = "1.15.0")]
+#[stable(feature = "ip_cmp", since = "1.16.0")]
impl PartialOrd<Ipv4Addr> for IpAddr {
fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
match *self {
}
}
-#[stable(feature = "ip_cmp", since = "1.15.0")]
+#[stable(feature = "ip_cmp", since = "1.16.0")]
impl PartialOrd<IpAddr> for Ipv4Addr {
fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
match *other {
}
}
-#[stable(feature = "ip_cmp", since = "1.15.0")]
+#[stable(feature = "ip_cmp", since = "1.16.0")]
impl PartialEq<IpAddr> for Ipv6Addr {
fn eq(&self, other: &IpAddr) -> bool {
match *other {
}
}
-#[stable(feature = "ip_cmp", since = "1.15.0")]
+#[stable(feature = "ip_cmp", since = "1.16.0")]
impl PartialEq<Ipv6Addr> for IpAddr {
fn eq(&self, other: &Ipv6Addr) -> bool {
match *self {
}
}
-#[stable(feature = "ip_cmp", since = "1.15.0")]
+#[stable(feature = "ip_cmp", since = "1.16.0")]
impl PartialOrd<Ipv6Addr> for IpAddr {
fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {
match *self {
}
}
-#[stable(feature = "ip_cmp", since = "1.15.0")]
+#[stable(feature = "ip_cmp", since = "1.16.0")]
impl PartialOrd<IpAddr> for Ipv6Addr {
fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
match *other {
}
}
-#[stable(feature = "ipv6_from_segments", since = "1.15.0")]
+#[stable(feature = "ipv6_from_segments", since = "1.16.0")]
impl From<[u16; 8]> for Ipv6Addr {
fn from(segments: [u16; 8]) -> Ipv6Addr {
let [a, b, c, d, e, f, g, h] = segments;
}
}
-#[stable(feature = "path_buf_from_box", since = "1.17.0")]
+#[stable(feature = "path_buf_from_box", since = "1.18.0")]
impl<'a> From<Box<Path>> for PathBuf {
fn from(boxed: Box<Path>) -> PathBuf {
boxed.into_path_buf()
}
}
-#[stable(feature = "box_from_path_buf", since = "1.17.0")]
+#[stable(feature = "box_from_path_buf", since = "1.18.0")]
impl Into<Box<Path>> for PathBuf {
fn into(self) -> Box<Path> {
self.into_boxed_path()
}
}
-#[stable(feature = "default_for_pathbuf", since = "1.16.0")]
+#[stable(feature = "default_for_pathbuf", since = "1.17.0")]
impl Default for PathBuf {
fn default() -> Self {
PathBuf::new()
}
/// Describes the result of a process after it has terminated.
+///
+/// This `struct` is used to represent the exit status of a child process.
+/// Child processes are created via the [`Command`] struct and their exit
+/// status is exposed through the [`status`] method.
+///
+/// [`Command`]: struct.Command.html
+/// [`status`]: struct.Command.html#method.status
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
#[stable(feature = "process", since = "1.0.0")]
pub struct ExitStatus(imp::ExitStatus);
/// On Unix, this will return `None` if the process was terminated
/// by a signal; `std::os::unix` provides an extension trait for
/// extracting the signal and other details from the `ExitStatus`.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// use std::process::Command;
+ ///
+ /// let status = Command::new("mkdir")
+ /// .arg("projects")
+ /// .status()
+ /// .expect("failed to execute mkdir");
+ ///
+ /// match status.code() {
+ /// Some(code) => println!("Exited with status code: {}", code),
+ /// None => println!("Process terminated by signal")
+ /// }
+ /// ```
#[stable(feature = "process", since = "1.0.0")]
pub fn code(&self) -> Option<i32> {
self.0.code()
}
}
-#[stable(feature = "condvar_default", since = "1.9.0")]
+#[stable(feature = "condvar_default", since = "1.10.0")]
impl Default for Condvar {
/// Creates a `Condvar` which is ready to be waited on and notified.
fn default() -> Condvar {
}
}
-#[stable(feature = "mpsc_debug", since = "1.7.0")]
+#[stable(feature = "mpsc_debug", since = "1.8.0")]
impl<T> fmt::Debug for Sender<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Sender {{ .. }}")
}
}
-#[stable(feature = "mpsc_debug", since = "1.7.0")]
+#[stable(feature = "mpsc_debug", since = "1.8.0")]
impl<T> fmt::Debug for SyncSender<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "SyncSender {{ .. }}")
Receiver { inner: UnsafeCell::new(inner) }
}
- /// Attempts to return a pending value on this receiver without blocking
+ /// Attempts to return a pending value on this receiver without blocking.
///
/// This method will never block the caller in order to wait for data to
/// become available. Instead, this will always return immediately with a
}
}
-#[stable(feature = "mpsc_debug", since = "1.7.0")]
+#[stable(feature = "mpsc_debug", since = "1.8.0")]
impl<T> fmt::Debug for Receiver<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Receiver {{ .. }}")
}
}
-#[stable(feature = "mpsc_recv_timeout_error", since = "1.14.0")]
+#[stable(feature = "mpsc_recv_timeout_error", since = "1.15.0")]
impl fmt::Display for RecvTimeoutError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
}
}
-#[stable(feature = "mpsc_recv_timeout_error", since = "1.14.0")]
+#[stable(feature = "mpsc_recv_timeout_error", since = "1.15.0")]
impl error::Error for RecvTimeoutError {
fn description(&self) -> &str {
match *self {
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> !Send for MutexGuard<'a, T> { }
-#[stable(feature = "mutexguard", since = "1.18.0")]
+#[stable(feature = "mutexguard", since = "1.19.0")]
unsafe impl<'a, T: ?Sized + Sync> Sync for MutexGuard<'a, T> { }
impl<T> Mutex<T> {
}
}
-#[stable(feature = "mutex_default", since = "1.9.0")]
+#[stable(feature = "mutex_default", since = "1.10.0")]
impl<T: ?Sized + Default> Default for Mutex<T> {
/// Creates a `Mutex<T>`, with the `Default` value for T.
fn default() -> Mutex<T> {
}
}
-#[stable(feature = "rw_lock_default", since = "1.9.0")]
+#[stable(feature = "rw_lock_default", since = "1.10.0")]
impl<T: Default> Default for RwLock<T> {
/// Creates a new `RwLock<T>`, with the `Default` value for T.
fn default() -> RwLock<T> {
#![unstable(feature = "thread_local_internals", issue = "0")]
use cell::{Cell, UnsafeCell};
-use intrinsics;
+use mem;
use ptr;
+
pub struct Key<T> {
inner: UnsafeCell<Option<T>>,
pub fn get(&'static self) -> Option<&'static UnsafeCell<Option<T>>> {
unsafe {
- if intrinsics::needs_drop::<T>() && self.dtor_running.get() {
+ if mem::needs_drop::<T>() && self.dtor_running.get() {
return None
}
self.register_dtor();
}
unsafe fn register_dtor(&self) {
- if !intrinsics::needs_drop::<T>() || self.dtor_registered.get() {
+ if !mem::needs_drop::<T>() || self.dtor_registered.get() {
return
}
use cell::{Cell, UnsafeCell};
use fmt;
-use intrinsics;
+use mem;
use ptr;
pub struct Key<T> {
pub fn get(&'static self) -> Option<&'static UnsafeCell<Option<T>>> {
unsafe {
- if intrinsics::needs_drop::<T>() && self.dtor_running.get() {
+ if mem::needs_drop::<T>() && self.dtor_running.get() {
return None
}
self.register_dtor();
}
unsafe fn register_dtor(&self) {
- if !intrinsics::needs_drop::<T>() || self.dtor_registered.get() {
+ if !mem::needs_drop::<T>() || self.dtor_registered.get() {
return
}
#[cfg(any(target_os = "linux", target_os = "android", target_os = "emscripten"))]
pub fn current_exe() -> io::Result<PathBuf> {
- ::fs::read_link("/proc/self/exe")
+ let selfexe = PathBuf::from("/proc/self/exe");
+ if selfexe.exists() {
+ ::fs::read_link(selfexe)
+ } else {
+ Err(io::Error::new(io::ErrorKind::Other, "no /proc/self/exe available. Is /proc mounted?"))
+ }
}
#[cfg(any(target_os = "macos", target_os = "ios"))]
/// Creates an `OsString` from a potentially ill-formed UTF-16 slice of
/// 16-bit code units.
///
- /// This is lossless: calling `.encode_wide()` on the resulting string
+ /// This is lossless: calling [`encode_wide`] on the resulting string
/// will always return the original code units.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::ffi::OsString;
+ /// use std::os::windows::prelude::*;
+ ///
+ /// // UTF-16 encoding for "Unicode".
+ /// let source = [0x0055, 0x006E, 0x0069, 0x0063, 0x006F, 0x0064, 0x0065];
+ ///
+ /// let string = OsString::from_wide(&source[..]);
+ /// ```
+ ///
+ /// [`encode_wide`]: ./trait.OsStrExt.html#tymethod.encode_wide
#[stable(feature = "rust1", since = "1.0.0")]
fn from_wide(wide: &[u16]) -> Self;
}
/// Windows-specific extensions to `OsStr`.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait OsStrExt {
- /// Re-encodes an `OsStr` as a wide character sequence,
- /// i.e. potentially ill-formed UTF-16.
+ /// Re-encodes an `OsStr` as a wide character sequence, i.e. potentially
+ /// ill-formed UTF-16.
+ ///
+ /// This is lossless: calling [`OsString::from_wide`] and then
+ /// `encode_wide` on the result will yield the original code units.
+ /// Note that the encoding does not add a final null terminator.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::ffi::OsString;
+ /// use std::os::windows::prelude::*;
+ ///
+ /// // UTF-16 encoding for "Unicode".
+ /// let source = [0x0055, 0x006E, 0x0069, 0x0063, 0x006F, 0x0064, 0x0065];
+ ///
+ /// let string = OsString::from_wide(&source[..]);
+ ///
+ /// let result: Vec<u16> = string.encode_wide().collect();
+ /// assert_eq!(&source[..], &result[..]);
+ /// ```
///
- /// This is lossless. Note that the encoding does not include a final
- /// null.
+ /// [`OsString::from_wide`]: ./trait.OsStringExt.html#tymethod.from_wide
#[stable(feature = "rust1", since = "1.0.0")]
fn encode_wide(&self) -> EncodeWide;
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-//! Windows-specific extensions for the primitives in `std::fs`
+//! Windows-specific extensions for the primitives in the `std::fs` module.
#![stable(feature = "rust1", since = "1.0.0")]
use sys;
use sys_common::{AsInnerMut, AsInner};
-/// Windows-specific extensions to `File`
+/// Windows-specific extensions to [`File`].
+///
+/// [`File`]: ../../../fs/struct.File.html
#[stable(feature = "file_offset", since = "1.15.0")]
pub trait FileExt {
/// Seeks to a given position and reads a number of bytes.
/// Note that similar to `File::read`, it is not an error to return with a
/// short read. When returning from such a short read, the file pointer is
/// still updated.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// use std::io;
+ /// use std::fs::File;
+ /// use std::os::windows::prelude::*;
+ ///
+ /// # fn foo() -> io::Result<()> {
+ /// let mut file = File::open("foo.txt")?;
+ /// let mut buffer = [0; 10];
+ ///
+ /// // Read 10 bytes, starting 72 bytes from the
+ /// // start of the file.
+ /// file.seek_read(&mut buffer[..], 72)?;
+ /// # Ok(())
+ /// # }
+ /// ```
#[stable(feature = "file_offset", since = "1.15.0")]
fn seek_read(&self, buf: &mut [u8], offset: u64) -> io::Result<usize>;
/// Note that similar to `File::write`, it is not an error to return a
/// short write. When returning from such a short write, the file pointer
/// is still updated.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// use std::fs::File;
+ /// use std::os::windows::prelude::*;
+ ///
+ /// # fn foo() -> std::io::Result<()> {
+ /// let mut buffer = File::create("foo.txt")?;
+ ///
+ /// // Write a byte string starting 72 bytes from
+ /// // the start of the file.
+ /// buffer.seek_write(b"some bytes", 72)?;
+ /// # Ok(())
+ /// # }
+ /// ```
#[stable(feature = "file_offset", since = "1.15.0")]
fn seek_write(&self, buf: &[u8], offset: u64) -> io::Result<usize>;
}
}
}
-/// Windows-specific extensions to `OpenOptions`
+/// Windows-specific extensions to [`OpenOptions`].
+///
+/// [`OpenOptions`]: ../../../fs/struct.OpenOptions.html
#[stable(feature = "open_options_ext", since = "1.10.0")]
pub trait OpenOptionsExt {
- /// Overrides the `dwDesiredAccess` argument to the call to `CreateFile`
+ /// Overrides the `dwDesiredAccess` argument to the call to [`CreateFile`]
/// with the specified value.
///
/// This will override the `read`, `write`, and `append` flags on the
/// `OpenOptions` structure. This method provides fine-grained control over
/// the permissions to read, write and append data, attributes (like hidden
- /// and system) and extended attributes.
+ /// and system), and extended attributes.
///
/// # Examples
///
/// ```no_run
/// use std::fs::OpenOptions;
- /// use std::os::windows::fs::OpenOptionsExt;
+ /// use std::os::windows::prelude::*;
///
/// // Open without read and write permission, for example if you only need
- /// // to call `stat()` on the file
+ /// // to call `stat` on the file
/// let file = OpenOptions::new().access_mode(0).open("foo.txt");
/// ```
+ ///
+ /// [`CreateFile`]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858.aspx
#[stable(feature = "open_options_ext", since = "1.10.0")]
fn access_mode(&mut self, access: u32) -> &mut Self;
- /// Overrides the `dwShareMode` argument to the call to `CreateFile` with
+ /// Overrides the `dwShareMode` argument to the call to [`CreateFile`] with
/// the specified value.
///
/// By default `share_mode` is set to
- /// `FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE`. Specifying
- /// less permissions denies others to read from, write to and/or delete the
- /// file while it is open.
+ /// `FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE`. This allows
+ /// other processes to to read, write, and delete/rename the same file
+ /// while it is open. Removing any of the flags will prevent other
+ /// processes from performing the corresponding operation until the file
+ /// handle is closed.
///
/// # Examples
///
/// ```no_run
/// use std::fs::OpenOptions;
- /// use std::os::windows::fs::OpenOptionsExt;
+ /// use std::os::windows::prelude::*;
///
/// // Do not allow others to read or modify this file while we have it open
- /// // for writing
- /// let file = OpenOptions::new().write(true)
- /// .share_mode(0)
- /// .open("foo.txt");
+ /// // for writing.
+ /// let file = OpenOptions::new()
+ /// .write(true)
+ /// .share_mode(0)
+ /// .open("foo.txt");
/// ```
+ ///
+ /// [`CreateFile`]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858.aspx
#[stable(feature = "open_options_ext", since = "1.10.0")]
fn share_mode(&mut self, val: u32) -> &mut Self;
/// Sets extra flags for the `dwFileFlags` argument to the call to
- /// `CreateFile2` (or combines it with `attributes` and `security_qos_flags`
- /// to set the `dwFlagsAndAttributes` for `CreateFile`).
+ /// [`CreateFile2`] to the specified value (or combines it with
+ /// `attributes` and `security_qos_flags` to set the `dwFlagsAndAttributes`
+ /// for [`CreateFile`]).
///
- /// Custom flags can only set flags, not remove flags set by Rusts options.
- /// This options overwrites any previously set custom flags.
+ /// Custom flags can only set flags, not remove flags set by Rust's options.
+ /// This option overwrites any previously set custom flags.
///
/// # Examples
///
- /// ```rust,ignore
+ /// ```ignore
/// extern crate winapi;
+ ///
/// use std::fs::OpenOptions;
- /// use std::os::windows::fs::OpenOptionsExt;
- ///
- /// let mut options = OpenOptions::new();
- /// options.create(true).write(true);
- /// if cfg!(windows) {
- /// options.custom_flags(winapi::FILE_FLAG_DELETE_ON_CLOSE);
- /// }
- /// let file = options.open("foo.txt");
+ /// use std::os::windows::prelude::*;
+ ///
+ /// let file = OpenOptions::new()
+ /// .create(true)
+ /// .write(true)
+ /// .custom_flags(winapi::FILE_FLAG_DELETE_ON_CLOSE)
+ /// .open("foo.txt");
/// ```
+ ///
+ /// [`CreateFile`]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858.aspx
+ /// [`CreateFile2`]: https://msdn.microsoft.com/en-us/library/windows/desktop/hh449422.aspx
#[stable(feature = "open_options_ext", since = "1.10.0")]
fn custom_flags(&mut self, flags: u32) -> &mut Self;
- /// Sets the `dwFileAttributes` argument to the call to `CreateFile2` to
+ /// Sets the `dwFileAttributes` argument to the call to [`CreateFile2`] to
/// the specified value (or combines it with `custom_flags` and
/// `security_qos_flags` to set the `dwFlagsAndAttributes` for
- /// `CreateFile`).
+ /// [`CreateFile`]).
///
/// If a _new_ file is created because it does not yet exist and
/// `.create(true)` or `.create_new(true)` are specified, the new file is
///
/// # Examples
///
- /// ```rust,ignore
+ /// ```ignore
/// extern crate winapi;
+ ///
/// use std::fs::OpenOptions;
- /// use std::os::windows::fs::OpenOptionsExt;
+ /// use std::os::windows::prelude::*;
///
- /// let file = OpenOptions::new().write(true).create(true)
- /// .attributes(winapi::FILE_ATTRIBUTE_HIDDEN)
- /// .open("foo.txt");
+ /// let file = OpenOptions::new()
+ /// .write(true)
+ /// .create(true)
+ /// .attributes(winapi::FILE_ATTRIBUTE_HIDDEN)
+ /// .open("foo.txt");
/// ```
+ ///
+ /// [`CreateFile`]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858.aspx
+ /// [`CreateFile2`]: https://msdn.microsoft.com/en-us/library/windows/desktop/hh449422.aspx
#[stable(feature = "open_options_ext", since = "1.10.0")]
fn attributes(&mut self, val: u32) -> &mut Self;
- /// Sets the `dwSecurityQosFlags` argument to the call to `CreateFile2` to
+ /// Sets the `dwSecurityQosFlags` argument to the call to [`CreateFile2`] to
/// the specified value (or combines it with `custom_flags` and `attributes`
- /// to set the `dwFlagsAndAttributes` for `CreateFile`).
+ /// to set the `dwFlagsAndAttributes` for [`CreateFile`]).
+ ///
+ /// By default, `security_qos_flags` is set to `SECURITY_ANONYMOUS`. For
+ /// information about possible values, see [Impersonation Levels] on the
+ /// Windows Dev Center site.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// use std::fs::OpenOptions;
+ /// use std::os::windows::prelude::*;
+ ///
+ /// let file = OpenOptions::new()
+ /// .write(true)
+ /// .create(true)
+ ///
+ /// // Sets the flag value to `SecurityIdentification`.
+ /// .security_qos_flags(1)
+ ///
+ /// .open("foo.txt");
+ /// ```
+ ///
+ /// [`CreateFile`]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858.aspx
+ /// [`CreateFile2`]: https://msdn.microsoft.com/en-us/library/windows/desktop/hh449422.aspx
+ /// [Impersonation Levels]:
+ /// https://msdn.microsoft.com/en-us/library/windows/desktop/aa379572.aspx
#[stable(feature = "open_options_ext", since = "1.10.0")]
fn security_qos_flags(&mut self, flags: u32) -> &mut OpenOptions;
}
}
}
-/// Extension methods for `fs::Metadata` to access the raw fields contained
+/// Extension methods for [`fs::Metadata`] to access the raw fields contained
/// within.
+///
+/// The data members that this trait exposes correspond to the members
+/// of the [`BY_HANDLE_FILE_INFORMATION`] structure.
+///
+/// [`fs::Metadata`]: ../../../fs/struct.Metadata.html
+/// [`BY_HANDLE_FILE_INFORMATION`]:
+/// https://msdn.microsoft.com/en-us/library/windows/desktop/aa363788.aspx
#[stable(feature = "metadata_ext", since = "1.1.0")]
pub trait MetadataExt {
/// Returns the value of the `dwFileAttributes` field of this metadata.
///
/// This field contains the file system attribute information for a file
- /// or directory.
+ /// or directory. For possible values and their descriptions, see
+ /// [File Attribute Constants] in the Windows Dev Center.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// use std::io;
+ /// use std::fs;
+ /// use std::os::windows::prelude::*;
+ ///
+ /// # fn foo() -> io::Result<()> {
+ /// let metadata = fs::metadata("foo.txt")?;
+ /// let attributes = metadata.file_attributes();
+ /// # Ok(())
+ /// # }
+ /// ```
+ ///
+ /// [File Attribute Constants]:
+ /// https://msdn.microsoft.com/en-us/library/windows/desktop/gg258117.aspx
#[stable(feature = "metadata_ext", since = "1.1.0")]
fn file_attributes(&self) -> u32;
/// Returns the value of the `ftCreationTime` field of this metadata.
///
- /// The returned 64-bit value represents the number of 100-nanosecond
- /// intervals since January 1, 1601 (UTC).
+ /// The returned 64-bit value is equivalent to a [`FILETIME`] struct,
+ /// which represents the number of 100-nanosecond intervals since
+ /// January 1, 1601 (UTC). The struct is automatically
+ /// converted to a `u64` value, as that is the recommended way
+ /// to use it.
+ ///
+ /// If the underlying filesystem does not support creation time, the
+ /// returned value is 0.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// use std::io;
+ /// use std::fs;
+ /// use std::os::windows::prelude::*;
+ ///
+ /// # fn foo() -> io::Result<()> {
+ /// let metadata = fs::metadata("foo.txt")?;
+ /// let creation_time = metadata.creation_time();
+ /// # Ok(())
+ /// # }
+ /// ```
+ ///
+ /// [`FILETIME`]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724284.aspx
#[stable(feature = "metadata_ext", since = "1.1.0")]
fn creation_time(&self) -> u64;
/// Returns the value of the `ftLastAccessTime` field of this metadata.
///
- /// The returned 64-bit value represents the number of 100-nanosecond
- /// intervals since January 1, 1601 (UTC).
+ /// The returned 64-bit value is equivalent to a [`FILETIME`] struct,
+ /// which represents the number of 100-nanosecond intervals since
+ /// January 1, 1601 (UTC). The struct is automatically
+ /// converted to a `u64` value, as that is the recommended way
+ /// to use it.
+ ///
+ /// For a file, the value specifies the last time that a file was read
+ /// from or written to. For a directory, the value specifies when
+ /// the directory was created. For both files and directories, the
+ /// specified date is correct, but the time of day is always set to
+ /// midnight.
+ ///
+ /// If the underlying filesystem does not support last access time, the
+ /// returned value is 0.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// use std::io;
+ /// use std::fs;
+ /// use std::os::windows::prelude::*;
+ ///
+ /// # fn foo() -> io::Result<()> {
+ /// let metadata = fs::metadata("foo.txt")?;
+ /// let last_access_time = metadata.last_access_time();
+ /// # Ok(())
+ /// # }
+ /// ```
+ ///
+ /// [`FILETIME`]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724284.aspx
#[stable(feature = "metadata_ext", since = "1.1.0")]
fn last_access_time(&self) -> u64;
/// Returns the value of the `ftLastWriteTime` field of this metadata.
///
- /// The returned 64-bit value represents the number of 100-nanosecond
- /// intervals since January 1, 1601 (UTC).
+ /// The returned 64-bit value is equivalent to a [`FILETIME`] struct,
+ /// which represents the number of 100-nanosecond intervals since
+ /// January 1, 1601 (UTC). The struct is automatically
+ /// converted to a `u64` value, as that is the recommended way
+ /// to use it.
+ ///
+ /// For a file, the value specifies the last time that a file was written
+ /// to. For a directory, the structure specifies when the directory was
+ /// created.
+ ///
+ /// If the underlying filesystem does not support the last write time
+ /// time, the returned value is 0.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// use std::io;
+ /// use std::fs;
+ /// use std::os::windows::prelude::*;
+ ///
+ /// # fn foo() -> io::Result<()> {
+ /// let metadata = fs::metadata("foo.txt")?;
+ /// let last_write_time = metadata.last_write_time();
+ /// # Ok(())
+ /// # }
+ /// ```
+ ///
+ /// [`FILETIME`]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724284.aspx
#[stable(feature = "metadata_ext", since = "1.1.0")]
fn last_write_time(&self) -> u64;
/// metadata.
///
/// The returned value does not have meaning for directories.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// use std::io;
+ /// use std::fs;
+ /// use std::os::windows::prelude::*;
+ ///
+ /// # fn foo() -> io::Result<()> {
+ /// let metadata = fs::metadata("foo.txt")?;
+ /// let file_size = metadata.file_size();
+ /// # Ok(())
+ /// # }
+ /// ```
#[stable(feature = "metadata_ext", since = "1.1.0")]
fn file_size(&self) -> u64;
}
///
/// # Examples
///
-/// ```ignore
+/// ```no_run
/// use std::os::windows::fs;
///
/// # fn foo() -> std::io::Result<()> {
///
/// # Examples
///
-/// ```ignore
+/// ```no_run
/// use std::os::windows::fs;
///
/// # fn foo() -> std::io::Result<()> {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-//! Experimental extensions to `std` for Windows.
+//! Platform-specific extensions to `std` for Windows.
//!
-//! For now, this module is limited to extracting handles, file
-//! descriptors, and sockets, but its functionality will grow over
-//! time.
+//! Provides access to platform-level information for Windows, and exposes
+//! Windows-specific idioms that would otherwise be inappropriate as part
+//! the core `std` library. These extensions allow developers to use
+//! `std` types and idioms with Windows in a way that the normal
+//! platform-agnostic idioms would not normally support.
#![stable(feature = "rust1", since = "1.0.0")]
}
}
+/// Generates a wide character sequence for potentially ill-formed UTF-16.
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Clone)]
pub struct EncodeWide<'a> {
/// Returns span for the macro which originally caused the current expansion to happen.
///
/// Stops backtracing at include! boundary.
- pub fn expansion_cause(&self) -> Span {
+ pub fn expansion_cause(&self) -> Option<Span> {
let mut ctxt = self.backtrace();
let mut last_macro = None;
loop {
break
}
}
- last_macro.expect("missing expansion backtrace")
+ last_macro
}
pub fn struct_span_warn(&self,
-> Box<base::MacResult+'static> {
base::check_zero_tts(cx, sp, tts, "line!");
- let topmost = cx.expansion_cause();
+ let topmost = cx.expansion_cause().unwrap_or(sp);
let loc = cx.codemap().lookup_char_pos(topmost.lo);
base::MacEager::expr(cx.expr_u32(topmost, loc.line as u32))
-> Box<base::MacResult+'static> {
base::check_zero_tts(cx, sp, tts, "column!");
- let topmost = cx.expansion_cause();
+ let topmost = cx.expansion_cause().unwrap_or(sp);
let loc = cx.codemap().lookup_char_pos(topmost.lo);
base::MacEager::expr(cx.expr_u32(topmost, loc.col.to_usize() as u32))
-> Box<base::MacResult+'static> {
base::check_zero_tts(cx, sp, tts, "file!");
- let topmost = cx.expansion_cause();
+ let topmost = cx.expansion_cause().unwrap_or(sp);
let loc = cx.codemap().lookup_char_pos(topmost.lo);
base::MacEager::expr(cx.expr_str(topmost, Symbol::intern(&loc.file.name)))
}
(accepted, question_mark, "1.13.0", Some(31436)),
// Allows `..` in tuple (struct) patterns
(accepted, dotdot_in_tuple_patterns, "1.14.0", Some(33627)),
- (accepted, item_like_imports, "1.14.0", Some(35120)),
+ (accepted, item_like_imports, "1.15.0", Some(35120)),
// Allows using `Self` and associated types in struct expressions and patterns.
(accepted, more_struct_aliases, "1.16.0", Some(37544)),
// elide `'static` lifetimes in `static`s and `const`s
passed: usize,
failed: usize,
ignored: usize,
+ filtered_out: usize,
measured: usize,
metrics: MetricMap,
failures: Vec<(TestDesc, Vec<u8>)>,
passed: 0,
failed: 0,
ignored: 0,
+ filtered_out: 0,
measured: 0,
metrics: MetricMap::new(),
failures: Vec::new(),
} else {
self.write_pretty("FAILED", term::color::RED)?;
}
- let s = format!(". {} passed; {} failed; {} ignored; {} measured\n\n",
+ let s = format!(". {} passed; {} failed; {} ignored; {} measured; {} filtered out\n\n",
self.passed,
self.failed,
self.ignored,
- self.measured);
+ self.measured,
+ self.filtered_out);
self.write_plain(&s)?;
return Ok(success);
}
fn callback<T: Write>(event: &TestEvent, st: &mut ConsoleTestState<T>) -> io::Result<()> {
match (*event).clone() {
TeFiltered(ref filtered_tests) => st.write_run_start(filtered_tests.len()),
+ TeFilteredOut(filtered_out) => Ok(st.filtered_out = filtered_out),
TeWait(ref test, padding) => st.write_test_start(test, padding),
TeTimeout(ref test) => st.write_timeout(test),
TeResult(test, result, stdout) => {
passed: 0,
failed: 0,
ignored: 0,
+ filtered_out: 0,
measured: 0,
max_name_len: 10,
metrics: MetricMap::new(),
TeWait(TestDesc, NamePadding),
TeResult(TestDesc, TestResult, Vec<u8>),
TeTimeout(TestDesc),
+ TeFilteredOut(usize),
}
pub type MonitorMsg = (TestDesc, TestResult, Vec<u8>);
use std::collections::HashMap;
use std::sync::mpsc::RecvTimeoutError;
+ let tests_len = tests.len();
+
let mut filtered_tests = filter_tests(opts, tests);
if !opts.bench_benchmarks {
filtered_tests = convert_benchmarks_to_tests(filtered_tests);
}
+ let filtered_out = tests_len - filtered_tests.len();
+ callback(TeFilteredOut(filtered_out))?;
+
let filtered_descs = filtered_tests.iter()
.map(|t| t.desc.clone())
.collect();
pub trait Resources<'a> {}
pub trait Buffer<'a, R: Resources<'a>> {
- //~^ NOTE the lifetime 'a as defined on the trait at 13:0...
+ //~^ NOTE the lifetime 'a as defined on the trait at 13:1...
//~| NOTE ...does not necessarily outlive the lifetime 'a as defined on the trait
fn select(&self) -> BufferViewHandle<R>;
//~| ERROR mismatched types
//~| lifetime mismatch
//~| NOTE expected type `Resources<'_>`
- //~| NOTE the anonymous lifetime #1 defined on the method body at 17:4...
+ //~| NOTE the anonymous lifetime #1 defined on the method body at 17:5...
}
pub struct BufferViewHandle<'a, R: 'a+Resources<'a>>(&'a R);
--- /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.
+
+fn main() {
+ include!(line!()); //~ ERROR argument must be a string literal
+}
--- /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.
+
+
+// This test case makes sure that we get proper break points for binaries
+// compiled with multiple codegen units. (see #39160)
+
+
+// min-lldb-version: 310
+
+// compile-flags:-g -Ccodegen-units=2
+
+// === GDB TESTS ===============================================================
+
+// gdb-command:run
+
+// gdb-command:print xxx
+// gdb-check:$1 = 12345
+// gdb-command:continue
+
+// gdb-command:print yyy
+// gdb-check:$2 = 67890
+// gdb-command:continue
+
+
+// === LLDB TESTS ==============================================================
+
+// lldb-command:run
+
+// lldb-command:print xxx
+// lldb-check:[...]$0 = 12345
+// lldb-command:continue
+
+// lldb-command:print yyy
+// lldb-check:[...]$1 = 67890
+// lldb-command:continue
+
+
+#![feature(omit_gdb_pretty_printer_section)]
+#![omit_gdb_pretty_printer_section]
+
+mod a {
+ pub fn foo(xxx: u32) {
+ super::_zzz(); // #break
+ }
+}
+
+mod b {
+ pub fn bar(yyy: u64) {
+ super::_zzz(); // #break
+ }
+}
+
+fn main() {
+ a::foo(12345);
+ b::bar(67890);
+}
+
+#[inline(never)]
+fn _zzz() {}
--- /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.
+
+use std::collections::HashMap;
+
+fn main() {
+ let dict: HashMap<i32, i32> = HashMap::new();
+ let debug_dump_dict = || {
+ for (key, value) in dict {
+ println!("{:?} - {:?}", key, value);
+ }
+ };
+ debug_dump_dict();
+ debug_dump_dict();
+ //~^ ERROR use of moved value: `debug_dump_dict`
+ //~| NOTE closure was moved because it only implements `FnOnce`
+}
--- /dev/null
+error[E0382]: use of moved value: `debug_dump_dict`
+ --> $DIR/fn_once-moved.rs:21:5
+ |
+20 | debug_dump_dict();
+ | --------------- value moved here
+21 | debug_dump_dict();
+ | ^^^^^^^^^^^^^^^ value used here after move
+ |
+ = help: closure was moved because it only implements `FnOnce`
+
+error: aborting due to previous error
+
12 | if x > y { x } else { y }
| ^
|
-note: ...the reference is valid for the lifetime 'a as defined on the function body at 11:0...
+note: ...the reference is valid for the lifetime 'a as defined on the function body at 11:1...
--> $DIR/ex1-return-one-existing-name-if-else.rs:11:1
|
11 | / fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 {
12 | | if x > y { x } else { y }
13 | | }
| |_^
-note: ...but the borrowed content is only valid for the anonymous lifetime #1 defined on the function body at 11:0
+note: ...but the borrowed content is only valid for the anonymous lifetime #1 defined on the function body at 11:1
--> $DIR/ex1-return-one-existing-name-if-else.rs:11:1
|
11 | / fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 {
|
= note: expected type `Ref<'a, _>`
found type `Ref<'_, _>`
-note: the anonymous lifetime #2 defined on the function body at 15:0...
+note: the anonymous lifetime #2 defined on the function body at 15:1...
--> $DIR/ex2a-push-one-existing-name.rs:15:1
|
15 | / fn foo<'a>(x: &mut Vec<Ref<'a, i32>>, y: Ref<i32>) {
16 | | x.push(y);
17 | | }
| |_^
-note: ...does not necessarily outlive the lifetime 'a as defined on the function body at 15:0
+note: ...does not necessarily outlive the lifetime 'a as defined on the function body at 15:1
--> $DIR/ex2a-push-one-existing-name.rs:15:1
|
15 | / fn foo<'a>(x: &mut Vec<Ref<'a, i32>>, y: Ref<i32>) {
|
= note: expected type `Ref<'_, _>`
found type `Ref<'_, _>`
-note: the anonymous lifetime #3 defined on the function body at 15:0...
+note: the anonymous lifetime #3 defined on the function body at 15:1...
--> $DIR/ex2b-push-no-existing-names.rs:15:1
|
15 | / fn foo(x: &mut Vec<Ref<i32>>, y: Ref<i32>) {
16 | | x.push(y);
17 | | }
| |_^
-note: ...does not necessarily outlive the anonymous lifetime #2 defined on the function body at 15:0
+note: ...does not necessarily outlive the anonymous lifetime #2 defined on the function body at 15:1
--> $DIR/ex2b-push-no-existing-names.rs:15:1
|
15 | / fn foo(x: &mut Vec<Ref<i32>>, y: Ref<i32>) {
16 | let z = Ref { data: y.data };
| ^^^
|
-note: first, the lifetime cannot outlive the lifetime 'c as defined on the function body at 15:0...
+note: first, the lifetime cannot outlive the lifetime 'c as defined on the function body at 15:1...
--> $DIR/ex2c-push-inference-variable.rs:15:1
|
15 | / fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
|
16 | let z = Ref { data: y.data };
| ^^^^^^
-note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 15:0...
+note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 15:1...
--> $DIR/ex2c-push-inference-variable.rs:15:1
|
15 | / fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
17 | let b = Ref { data: y.data };
| ^^^
|
-note: first, the lifetime cannot outlive the lifetime 'c as defined on the function body at 15:0...
+note: first, the lifetime cannot outlive the lifetime 'c as defined on the function body at 15:1...
--> $DIR/ex2d-push-inference-variable-2.rs:15:1
|
15 | / fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
|
17 | let b = Ref { data: y.data };
| ^^^^^^
-note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 15:0...
+note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 15:1...
--> $DIR/ex2d-push-inference-variable-2.rs:15:1
|
15 | / fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
17 | let b = Ref { data: y.data };
| ^^^
|
-note: first, the lifetime cannot outlive the lifetime 'c as defined on the function body at 15:0...
+note: first, the lifetime cannot outlive the lifetime 'c as defined on the function body at 15:1...
--> $DIR/ex2e-push-inference-variable-3.rs:15:1
|
15 | / fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
|
17 | let b = Ref { data: y.data };
| ^^^^^^
-note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 15:0...
+note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 15:1...
--> $DIR/ex2e-push-inference-variable-3.rs:15:1
|
15 | / fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {