Merge remote-tracking branch 'upstream/master' into format-with-capacity
This commit is contained in:
commit
0267529681
387 changed files with 7178 additions and 4905 deletions
7
.mailmap
7
.mailmap
|
|
@ -43,8 +43,8 @@ Brian Anderson <banderson@mozilla.com> <andersrb@gmail.com>
|
|||
Brian Dawn <brian.t.dawn@gmail.com>
|
||||
Brian Leibig <brian@brianleibig.com> Brian Leibig <brian.leibig@gmail.com>
|
||||
Carl-Anton Ingmarsson <mail@carlanton.se> <ca.ingmarsson@gmail.com>
|
||||
Carol (Nichols || Goulding) <carol.nichols@gmail.com> Carol Nichols <carol.nichols@gmail.com>
|
||||
Carol (Nichols || Goulding) <carol.nichols@gmail.com> Carol Nichols <cnichols@thinkthroughmath.com>
|
||||
Carol (Nichols || Goulding) <carol.nichols@gmail.com>
|
||||
Carol (Nichols || Goulding) <cnichols@thinkthroughmath.com>
|
||||
Carol Willing <carolcode@willingconsulting.com>
|
||||
Chris C Cerami <chrisccerami@users.noreply.github.com> Chris C Cerami <chrisccerami@gmail.com>
|
||||
Chris Pressey <cpressey@gmail.com>
|
||||
|
|
@ -53,6 +53,7 @@ Clark Gaebel <cg.wowus.cg@gmail.com> <cgaebel@mozilla.com>
|
|||
Clinton Ryan <clint.ryan3@gmail.com>
|
||||
Corey Farwell <coreyf+rust@rwell.org> Corey Farwell <coreyf@rwell.org>
|
||||
Corey Richardson <corey@octayn.net> Elaine "See More" Nemo <corey@octayn.net>
|
||||
Cyryl Płotnicki <cyplo@cyplo.net>
|
||||
Damien Schoof <damien.schoof@gmail.com>
|
||||
Daniel Ramos <dan@daramos.com>
|
||||
David Klein <david.klein@baesystemsdetica.com>
|
||||
|
|
@ -102,6 +103,7 @@ Jason Toffaletti <toffaletti@gmail.com> Jason Toffaletti <jason@topsy.com>
|
|||
Jauhien Piatlicki <jauhien@gentoo.org> Jauhien Piatlicki <jpiatlicki@zertisa.com>
|
||||
Jay True <glacjay@gmail.com>
|
||||
Jeremy Letang <letang.jeremy@gmail.com>
|
||||
Jethro Beekman <github@jbeekman.nl>
|
||||
Jihyun Yu <j.yu@navercorp.com> <yjh0502@gmail.com>
|
||||
Jihyun Yu <j.yu@navercorp.com> jihyun <jihyun@nablecomm.com>
|
||||
Jihyun Yu <j.yu@navercorp.com> Jihyun Yu <jihyun@nclab.kaist.ac.kr>
|
||||
|
|
@ -165,6 +167,7 @@ Ožbolt Menegatti <ozbolt.menegatti@gmail.com> gareins <ozbolt.menegatti@gmail.c
|
|||
Paul Faria <paul_faria@ultimatesoftware.com> Paul Faria <Nashenas88@gmail.com>
|
||||
Peer Aramillo Irizar <peer.aramillo.irizar@gmail.com> parir <peer.aramillo.irizar@gmail.com>
|
||||
Peter Elmers <peter.elmers@yahoo.com> <peter.elmers@rice.edu>
|
||||
Peter Liniker <peter.liniker+github@gmail.com>
|
||||
Peter Zotov <whitequark@whitequark.org>
|
||||
Phil Dawes <phil@phildawes.net> Phil Dawes <pdawes@drw.com>
|
||||
Philipp Brüschweiler <blei42@gmail.com> <blei42@gmail.com>
|
||||
|
|
|
|||
21
.travis.yml
21
.travis.yml
|
|
@ -35,6 +35,7 @@ matrix:
|
|||
- env: IMAGE=x86_64-gnu-make
|
||||
- env: IMAGE=x86_64-gnu-llvm-3.7 ALLOW_PR=1 RUST_BACKTRACE=1
|
||||
- env: IMAGE=x86_64-gnu-distcheck
|
||||
- env: IMAGE=x86_64-gnu-incremental
|
||||
|
||||
# OSX builders
|
||||
- env: >
|
||||
|
|
@ -43,17 +44,9 @@ matrix:
|
|||
SRC=.
|
||||
os: osx
|
||||
osx_image: xcode8.2
|
||||
before_script: &osx_before_script >
|
||||
ulimit -c unlimited
|
||||
install: &osx_install_sccache >
|
||||
curl -L https://api.pub.build.mozilla.org/tooltool/sha512/d0025b286468cc5ada83b23d3fafbc936b9f190eaa7d4a981715b18e8e3bf720a7bcee7bfe758cfdeb8268857f6098fd52dcdd8818232692a30ce91039936596 |
|
||||
tar xJf - -C /usr/local/bin --strip-components=1
|
||||
after_failure: &osx_after_failure >
|
||||
echo 'bt all' > cmds;
|
||||
for file in $(ls /cores); do
|
||||
echo core file $file;
|
||||
lldb -c /cores/$file `which ld` -b -s cmds;
|
||||
done
|
||||
|
||||
- env: >
|
||||
SCRIPT="./x.py test && ./x.py dist"
|
||||
|
|
@ -62,18 +55,14 @@ matrix:
|
|||
DEPLOY=1
|
||||
os: osx
|
||||
osx_image: xcode8.2
|
||||
before_script: *osx_before_script
|
||||
install: *osx_install_sccache
|
||||
after_failure: *osx_after_failure
|
||||
- env: >
|
||||
RUST_CHECK_TARGET=check
|
||||
RUST_CONFIGURE_ARGS=--build=x86_64-apple-darwin --disable-rustbuild
|
||||
SRC=.
|
||||
os: osx
|
||||
osx_image: xcode8.2
|
||||
before_script: *osx_before_script
|
||||
install: *osx_install_sccache
|
||||
after_failure: *osx_after_failure
|
||||
- env: >
|
||||
RUST_CHECK_TARGET=dist
|
||||
RUST_CONFIGURE_ARGS="--target=aarch64-apple-ios,armv7-apple-ios,armv7s-apple-ios,i386-apple-ios,x86_64-apple-ios --enable-extended"
|
||||
|
|
@ -81,9 +70,7 @@ matrix:
|
|||
DEPLOY=1
|
||||
os: osx
|
||||
osx_image: xcode8.2
|
||||
before_script: *osx_before_script
|
||||
install: *osx_install_sccache
|
||||
after_failure: *osx_after_failure
|
||||
|
||||
env:
|
||||
global:
|
||||
|
|
@ -124,9 +111,11 @@ before_deploy:
|
|||
- mkdir -p deploy/$TRAVIS_COMMIT
|
||||
- >
|
||||
if [ "$TRAVIS_OS_NAME" == "osx" ]; then
|
||||
cp build/dist/*.tar.gz deploy/$TRAVIS_COMMIT;
|
||||
rm -rf build/dist/doc &&
|
||||
cp -r build/dist/* deploy/$TRAVIS_COMMIT;
|
||||
else
|
||||
cp obj/build/dist/*.tar.gz deploy/$TRAVIS_COMMIT;
|
||||
rm -rf obj/build/dist/doc &&
|
||||
cp -r obj/build/dist/* deploy/$TRAVIS_COMMIT;
|
||||
fi
|
||||
|
||||
deploy:
|
||||
|
|
|
|||
|
|
@ -137,7 +137,8 @@ branches:
|
|||
before_deploy:
|
||||
- ps: |
|
||||
New-Item -Path deploy -ItemType directory
|
||||
Get-ChildItem -Path build\dist -Filter '*.tar.gz' | Move-Item -Destination deploy
|
||||
Remove-Item -Recurse -Force build\dist\doc
|
||||
Get-ChildItem -Path build\dist | Move-Item -Destination deploy
|
||||
Get-ChildItem -Path deploy | Foreach-Object {
|
||||
Push-AppveyorArtifact $_.FullName -FileName ${env:APPVEYOR_REPO_COMMIT}/$_
|
||||
}
|
||||
|
|
@ -151,7 +152,7 @@ deploy:
|
|||
bucket: rust-lang-ci
|
||||
set_public: true
|
||||
region: us-east-1
|
||||
artifact: /.*\.tar.gz/
|
||||
artifact: /.*/
|
||||
folder: rustc-builds
|
||||
on:
|
||||
branch: auto
|
||||
|
|
|
|||
15
src/Cargo.lock
generated
15
src/Cargo.lock
generated
|
|
@ -50,9 +50,20 @@ dependencies = [
|
|||
"toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "build-manifest"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "build_helper"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cargotest"
|
||||
|
|
@ -586,7 +597,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "std_shim"
|
||||
version = "0.1.0"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"core 0.0.0",
|
||||
"std 0.0.0",
|
||||
|
|
@ -645,7 +656,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "test_shim"
|
||||
version = "0.1.0"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"test 0.0.0",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ members = [
|
|||
"tools/linkchecker",
|
||||
"tools/rustbook",
|
||||
"tools/tidy",
|
||||
"tools/build-manifest",
|
||||
]
|
||||
|
||||
# Curiously, compiletest will segfault if compiled with opt-level=3 on 64-bit
|
||||
|
|
|
|||
|
|
@ -383,7 +383,7 @@ pub fn krate(build: &Build,
|
|||
// helper crate, not tested. If it leaks through then it ends up
|
||||
// messing with various mtime calculations and such.
|
||||
if !name.contains("jemalloc") && name != "build_helper" {
|
||||
cargo.arg("-p").arg(name);
|
||||
cargo.arg("-p").arg(&format!("{}:0.0.0", name));
|
||||
}
|
||||
for dep in build.crates[name].deps.iter() {
|
||||
if visited.insert(dep) {
|
||||
|
|
|
|||
|
|
@ -21,10 +21,10 @@ use std::fs::{self, File};
|
|||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
|
||||
use build_helper::output;
|
||||
use build_helper::{output, mtime};
|
||||
use filetime::FileTime;
|
||||
|
||||
use util::{exe, libdir, mtime, is_dylib, copy};
|
||||
use util::{exe, libdir, is_dylib, copy};
|
||||
use {Build, Compiler, Mode};
|
||||
|
||||
/// Build the standard library.
|
||||
|
|
|
|||
|
|
@ -78,6 +78,11 @@ pub struct Config {
|
|||
pub cargo: Option<PathBuf>,
|
||||
pub local_rebuild: bool,
|
||||
|
||||
// dist misc
|
||||
pub dist_sign_folder: Option<PathBuf>,
|
||||
pub dist_upload_addr: Option<String>,
|
||||
pub dist_gpg_password_file: Option<PathBuf>,
|
||||
|
||||
// libstd features
|
||||
pub debug_jemalloc: bool,
|
||||
pub use_jemalloc: bool,
|
||||
|
|
@ -123,6 +128,7 @@ struct TomlConfig {
|
|||
llvm: Option<Llvm>,
|
||||
rust: Option<Rust>,
|
||||
target: Option<HashMap<String, TomlTarget>>,
|
||||
dist: Option<Dist>,
|
||||
}
|
||||
|
||||
/// TOML representation of various global build decisions.
|
||||
|
|
@ -166,6 +172,13 @@ struct Llvm {
|
|||
targets: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(RustcDecodable, Default, Clone)]
|
||||
struct Dist {
|
||||
sign_folder: Option<String>,
|
||||
gpg_password_file: Option<String>,
|
||||
upload_addr: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(RustcDecodable)]
|
||||
enum StringOrBool {
|
||||
String(String),
|
||||
|
|
@ -352,6 +365,12 @@ impl Config {
|
|||
}
|
||||
}
|
||||
|
||||
if let Some(ref t) = toml.dist {
|
||||
config.dist_sign_folder = t.sign_folder.clone().map(PathBuf::from);
|
||||
config.dist_gpg_password_file = t.gpg_password_file.clone().map(PathBuf::from);
|
||||
config.dist_upload_addr = t.upload_addr.clone();
|
||||
}
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
|
|
@ -497,7 +516,7 @@ impl Config {
|
|||
"CFG_JEMALLOC_ROOT" if value.len() > 0 => {
|
||||
let target = self.target_config.entry(self.build.clone())
|
||||
.or_insert(Target::default());
|
||||
target.jemalloc = Some(parse_configure_path(value));
|
||||
target.jemalloc = Some(parse_configure_path(value).join("libjemalloc_pic.a"));
|
||||
}
|
||||
"CFG_ARM_LINUX_ANDROIDEABI_NDK" if value.len() > 0 => {
|
||||
let target = "arm-linux-androideabi".to_string();
|
||||
|
|
|
|||
|
|
@ -242,3 +242,33 @@
|
|||
# that this option only makes sense for MUSL targets that produce statically
|
||||
# linked binaries
|
||||
#musl-root = "..."
|
||||
|
||||
# =============================================================================
|
||||
# Distribution options
|
||||
#
|
||||
# These options are related to distribution, mostly for the Rust project itself.
|
||||
# You probably won't need to concern yourself with any of these options
|
||||
# =============================================================================
|
||||
[dist]
|
||||
|
||||
# This is the folder of artifacts that the build system will sign. All files in
|
||||
# this directory will be signed with the default gpg key using the system `gpg`
|
||||
# binary. The `asc` and `sha256` files will all be output into the standard dist
|
||||
# output folder (currently `build/dist`)
|
||||
#
|
||||
# This folder should be populated ahead of time before the build system is
|
||||
# invoked.
|
||||
#sign-folder = "path/to/folder/to/sign"
|
||||
|
||||
# This is a file which contains the password of the default gpg key. This will
|
||||
# be passed to `gpg` down the road when signing all files in `sign-folder`
|
||||
# above. This should be stored in plaintext.
|
||||
#gpg-password-file = "path/to/gpg/password"
|
||||
|
||||
# The remote address that all artifacts will eventually be uploaded to. The
|
||||
# build system generates manifests which will point to these urls, and for the
|
||||
# manifests to be correct they'll have to have the right URLs encoded.
|
||||
#
|
||||
# Note that this address should not contain a trailing slash as file names will
|
||||
# be appended to it.
|
||||
#upload-addr = "https://example.com/folder"
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ use std::env;
|
|||
use std::fs::{self, File};
|
||||
use std::io::{Read, Write};
|
||||
use std::path::{PathBuf, Path};
|
||||
use std::process::Command;
|
||||
use std::process::{Command, Stdio};
|
||||
|
||||
use build_helper::output;
|
||||
|
||||
|
|
@ -827,7 +827,7 @@ pub fn extended(build: &Build, stage: u32, target: &str) {
|
|||
cmd.arg("-nologo")
|
||||
.arg("-ext").arg("WixUIExtension")
|
||||
.arg("-ext").arg("WixUtilExtension")
|
||||
.arg("-out").arg(distdir(build).join(filename))
|
||||
.arg("-out").arg(exe.join(&filename))
|
||||
.arg("rust.wixobj")
|
||||
.arg("ui.wixobj")
|
||||
.arg("rustwelcomedlg.wixobj")
|
||||
|
|
@ -844,6 +844,8 @@ pub fn extended(build: &Build, stage: u32, target: &str) {
|
|||
cmd.arg("-sice:ICE57");
|
||||
|
||||
build.run(&mut cmd);
|
||||
|
||||
t!(fs::rename(exe.join(&filename), distdir(build).join(&filename)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -876,3 +878,34 @@ fn add_env(build: &Build, cmd: &mut Command, target: &str) {
|
|||
cmd.env("CFG_PLATFORM", "x86");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn hash_and_sign(build: &Build) {
|
||||
let compiler = Compiler::new(0, &build.config.build);
|
||||
let mut cmd = build.tool_cmd(&compiler, "build-manifest");
|
||||
let sign = build.config.dist_sign_folder.as_ref().unwrap_or_else(|| {
|
||||
panic!("\n\nfailed to specify `dist.sign-folder` in `config.toml`\n\n")
|
||||
});
|
||||
let addr = build.config.dist_upload_addr.as_ref().unwrap_or_else(|| {
|
||||
panic!("\n\nfailed to specify `dist.upload-addr` in `config.toml`\n\n")
|
||||
});
|
||||
let file = build.config.dist_gpg_password_file.as_ref().unwrap_or_else(|| {
|
||||
panic!("\n\nfailed to specify `dist.gpg-password-file` in `config.toml`\n\n")
|
||||
});
|
||||
let mut pass = String::new();
|
||||
t!(t!(File::open(&file)).read_to_string(&mut pass));
|
||||
|
||||
let today = output(Command::new("date").arg("+%Y-%m-%d"));
|
||||
|
||||
cmd.arg(sign);
|
||||
cmd.arg(distdir(build));
|
||||
cmd.arg(today.trim());
|
||||
cmd.arg(package_vers(build));
|
||||
cmd.arg(addr);
|
||||
|
||||
t!(fs::create_dir_all(distdir(build)));
|
||||
|
||||
let mut child = t!(cmd.stdin(Stdio::piped()).spawn());
|
||||
t!(child.stdin.take().unwrap().write_all(pass.as_bytes()));
|
||||
let status = t!(child.wait());
|
||||
assert!(status.success());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,8 @@ use std::io::prelude::*;
|
|||
use std::process::Command;
|
||||
|
||||
use {Build, Compiler, Mode};
|
||||
use util::{up_to_date, cp_r};
|
||||
use util::cp_r;
|
||||
use build_helper::up_to_date;
|
||||
|
||||
/// Invoke `rustbook` as compiled in `stage` for `target` for the doc book
|
||||
/// `name` into the `out` path.
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@
|
|||
|
||||
#![deny(warnings)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate build_helper;
|
||||
extern crate cmake;
|
||||
extern crate filetime;
|
||||
|
|
@ -83,24 +84,9 @@ use std::fs::{self, File};
|
|||
use std::path::{Component, PathBuf, Path};
|
||||
use std::process::Command;
|
||||
|
||||
use build_helper::{run_silent, output};
|
||||
use build_helper::{run_silent, output, mtime};
|
||||
|
||||
use util::{exe, mtime, libdir, add_lib_path};
|
||||
|
||||
/// A helper macro to `unwrap` a result except also print out details like:
|
||||
///
|
||||
/// * The file/line of the panic
|
||||
/// * The expression that failed
|
||||
/// * The error itself
|
||||
///
|
||||
/// This is currently used judiciously throughout the build system rather than
|
||||
/// using a `Result` with `try!`, but this may change one day...
|
||||
macro_rules! t {
|
||||
($e:expr) => (match $e {
|
||||
Ok(e) => e,
|
||||
Err(e) => panic!("{} failed with {}", stringify!($e), e),
|
||||
})
|
||||
}
|
||||
use util::{exe, libdir, add_lib_path};
|
||||
|
||||
mod cc;
|
||||
mod channel;
|
||||
|
|
@ -482,7 +468,8 @@ impl Build {
|
|||
//
|
||||
// These variables are primarily all read by
|
||||
// src/bootstrap/bin/{rustc.rs,rustdoc.rs}
|
||||
cargo.env("RUSTC", self.out.join("bootstrap/debug/rustc"))
|
||||
cargo.env("RUSTBUILD_NATIVE_DIR", self.native_dir(target))
|
||||
.env("RUSTC", self.out.join("bootstrap/debug/rustc"))
|
||||
.env("RUSTC_REAL", self.compiler_path(compiler))
|
||||
.env("RUSTC_STAGE", stage.to_string())
|
||||
.env("RUSTC_DEBUGINFO", self.config.rust_debuginfo.to_string())
|
||||
|
|
@ -746,10 +733,15 @@ impl Build {
|
|||
}
|
||||
}
|
||||
|
||||
/// Directory for libraries built from C/C++ code and shared between stages.
|
||||
fn native_dir(&self, target: &str) -> PathBuf {
|
||||
self.out.join(target).join("native")
|
||||
}
|
||||
|
||||
/// Root output directory for rust_test_helpers library compiled for
|
||||
/// `target`
|
||||
fn test_helpers_out(&self, target: &str) -> PathBuf {
|
||||
self.out.join(target).join("rust-test-helpers")
|
||||
self.native_dir(target).join("rust-test-helpers")
|
||||
}
|
||||
|
||||
/// Adds the compiler's directory of dynamic libraries to `cmd`'s dynamic
|
||||
|
|
|
|||
|
|
@ -28,7 +28,8 @@ use cmake;
|
|||
use gcc;
|
||||
|
||||
use Build;
|
||||
use util::{self, up_to_date};
|
||||
use util;
|
||||
use build_helper::up_to_date;
|
||||
|
||||
/// Compile LLVM for `target`.
|
||||
pub fn llvm(build: &Build, target: &str) {
|
||||
|
|
|
|||
|
|
@ -513,6 +513,9 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
|
|||
rules.build("tool-compiletest", "src/tools/compiletest")
|
||||
.dep(|s| s.name("libtest"))
|
||||
.run(move |s| compile::tool(build, s.stage, s.target, "compiletest"));
|
||||
rules.build("tool-build-manifest", "src/tools/build-manifest")
|
||||
.dep(|s| s.name("libstd"))
|
||||
.run(move |s| compile::tool(build, s.stage, s.target, "build-manifest"));
|
||||
|
||||
// ========================================================================
|
||||
// Documentation targets
|
||||
|
|
@ -633,6 +636,13 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
|
|||
.dep(|d| d.name("dist-cargo"))
|
||||
.run(move |s| dist::extended(build, s.stage, s.target));
|
||||
|
||||
rules.dist("dist-sign", "hash-and-sign")
|
||||
.host(true)
|
||||
.only_build(true)
|
||||
.only_host_build(true)
|
||||
.dep(move |s| s.name("tool-build-manifest").target(&build.config.build).stage(0))
|
||||
.run(move |_| dist::hash_and_sign(build));
|
||||
|
||||
rules.verify();
|
||||
return rules;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,8 +20,6 @@ use std::path::{Path, PathBuf};
|
|||
use std::process::Command;
|
||||
use std::time::Instant;
|
||||
|
||||
use filetime::FileTime;
|
||||
|
||||
/// Returns the `name` as the filename of a static library for `target`.
|
||||
pub fn staticlib(name: &str, target: &str) -> String {
|
||||
if target.contains("windows") {
|
||||
|
|
@ -31,13 +29,6 @@ pub fn staticlib(name: &str, target: &str) -> String {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns the last-modified time for `path`, or zero if it doesn't exist.
|
||||
pub fn mtime(path: &Path) -> FileTime {
|
||||
fs::metadata(path).map(|f| {
|
||||
FileTime::from_last_modification_time(&f)
|
||||
}).unwrap_or(FileTime::zero())
|
||||
}
|
||||
|
||||
/// Copies a file from `src` to `dst`, attempting to use hard links and then
|
||||
/// falling back to an actually filesystem copy if necessary.
|
||||
pub fn copy(src: &Path, dst: &Path) {
|
||||
|
|
@ -132,34 +123,6 @@ pub fn add_lib_path(path: Vec<PathBuf>, cmd: &mut Command) {
|
|||
cmd.env(dylib_path_var(), t!(env::join_paths(list)));
|
||||
}
|
||||
|
||||
/// Returns whether `dst` is up to date given that the file or files in `src`
|
||||
/// are used to generate it.
|
||||
///
|
||||
/// Uses last-modified time checks to verify this.
|
||||
pub fn up_to_date(src: &Path, dst: &Path) -> bool {
|
||||
let threshold = mtime(dst);
|
||||
let meta = match fs::metadata(src) {
|
||||
Ok(meta) => meta,
|
||||
Err(e) => panic!("source {:?} failed to get metadata: {}", src, e),
|
||||
};
|
||||
if meta.is_dir() {
|
||||
dir_up_to_date(src, &threshold)
|
||||
} else {
|
||||
FileTime::from_last_modification_time(&meta) <= threshold
|
||||
}
|
||||
}
|
||||
|
||||
fn dir_up_to_date(src: &Path, threshold: &FileTime) -> bool {
|
||||
t!(fs::read_dir(src)).map(|e| t!(e)).all(|e| {
|
||||
let meta = t!(e.metadata());
|
||||
if meta.is_dir() {
|
||||
dir_up_to_date(&e.path(), threshold)
|
||||
} else {
|
||||
FileTime::from_last_modification_time(&meta) < *threshold
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the environment variable which the dynamic library lookup path
|
||||
/// resides in for this platform.
|
||||
pub fn dylib_path_var() -> &'static str {
|
||||
|
|
|
|||
|
|
@ -6,3 +6,6 @@ authors = ["The Rust Project Developers"]
|
|||
[lib]
|
||||
name = "build_helper"
|
||||
path = "lib.rs"
|
||||
|
||||
[dependencies]
|
||||
filetime = "0.1"
|
||||
|
|
|
|||
|
|
@ -10,9 +10,30 @@
|
|||
|
||||
#![deny(warnings)]
|
||||
|
||||
extern crate filetime;
|
||||
|
||||
use std::fs;
|
||||
use std::process::{Command, Stdio};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use filetime::FileTime;
|
||||
|
||||
/// A helper macro to `unwrap` a result except also print out details like:
|
||||
///
|
||||
/// * The file/line of the panic
|
||||
/// * The expression that failed
|
||||
/// * The error itself
|
||||
///
|
||||
/// This is currently used judiciously throughout the build system rather than
|
||||
/// using a `Result` with `try!`, but this may change one day...
|
||||
#[macro_export]
|
||||
macro_rules! t {
|
||||
($e:expr) => (match $e {
|
||||
Ok(e) => e,
|
||||
Err(e) => panic!("{} failed with {}", stringify!($e), e),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn run(cmd: &mut Command) {
|
||||
println!("running: {:?}", cmd);
|
||||
run_silent(cmd);
|
||||
|
|
@ -88,6 +109,56 @@ pub fn output(cmd: &mut Command) -> String {
|
|||
String::from_utf8(output.stdout).unwrap()
|
||||
}
|
||||
|
||||
pub fn rerun_if_changed_anything_in_dir(dir: &Path) {
|
||||
let mut stack = dir.read_dir().unwrap()
|
||||
.map(|e| e.unwrap())
|
||||
.filter(|e| &*e.file_name() != ".git")
|
||||
.collect::<Vec<_>>();
|
||||
while let Some(entry) = stack.pop() {
|
||||
let path = entry.path();
|
||||
if entry.file_type().unwrap().is_dir() {
|
||||
stack.extend(path.read_dir().unwrap().map(|e| e.unwrap()));
|
||||
} else {
|
||||
println!("cargo:rerun-if-changed={}", path.display());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the last-modified time for `path`, or zero if it doesn't exist.
|
||||
pub fn mtime(path: &Path) -> FileTime {
|
||||
fs::metadata(path).map(|f| {
|
||||
FileTime::from_last_modification_time(&f)
|
||||
}).unwrap_or(FileTime::zero())
|
||||
}
|
||||
|
||||
/// Returns whether `dst` is up to date given that the file or files in `src`
|
||||
/// are used to generate it.
|
||||
///
|
||||
/// Uses last-modified time checks to verify this.
|
||||
pub fn up_to_date(src: &Path, dst: &Path) -> bool {
|
||||
let threshold = mtime(dst);
|
||||
let meta = match fs::metadata(src) {
|
||||
Ok(meta) => meta,
|
||||
Err(e) => panic!("source {:?} failed to get metadata: {}", src, e),
|
||||
};
|
||||
if meta.is_dir() {
|
||||
dir_up_to_date(src, &threshold)
|
||||
} else {
|
||||
FileTime::from_last_modification_time(&meta) <= threshold
|
||||
}
|
||||
}
|
||||
|
||||
fn dir_up_to_date(src: &Path, threshold: &FileTime) -> bool {
|
||||
t!(fs::read_dir(src)).map(|e| t!(e)).all(|e| {
|
||||
let meta = t!(e.metadata());
|
||||
if meta.is_dir() {
|
||||
dir_up_to_date(&e.path(), threshold)
|
||||
} else {
|
||||
FileTime::from_last_modification_time(&meta) < *threshold
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn fail(s: &str) -> ! {
|
||||
println!("\n\n{}\n\n", s);
|
||||
std::process::exit(1);
|
||||
|
|
|
|||
|
|
@ -143,3 +143,58 @@ For targets: `aarch64-unknown-linux-gnu`
|
|||
- C-library > glibc version = 2.17 -- aarch64 support was introduced in this version
|
||||
- C compiler > gcc version = 5.2.0
|
||||
- C compiler > C++ = ENABLE -- to cross compile LLVM
|
||||
|
||||
## `powerpc-linux-gnu.config`
|
||||
|
||||
For targets: `powerpc-unknown-linux-gnu`
|
||||
|
||||
- Path and misc options > Prefix directory = /x-tools/${CT\_TARGET}
|
||||
- Path and misc options > Patches origin = Bundled, then local
|
||||
- Path and misc options > Local patch directory = /tmp/patches
|
||||
- Target options > Target Architecture = powerpc
|
||||
- Target options > Emit assembly for CPU = power4 -- (+)
|
||||
- Target options > Tune for CPU = power6 -- (+)
|
||||
- Operating System > Target OS = linux
|
||||
- Operating System > Linux kernel version = 2.6.32.68 -- ~RHEL6 kernel
|
||||
- C-library > glibc version = 2.12.2 -- ~RHEL6 glibc
|
||||
- C compiler > gcc version = 4.9.3
|
||||
- C compiler > Core gcc extra config = --with-cpu-32=power4 --with-cpu=default32 -- (+)
|
||||
- C compiler > gcc extra config = --with-cpu-32=power4 --with-cpu=default32 -- (+)
|
||||
- C compiler > C++ = ENABLE -- to cross compile LLVM
|
||||
|
||||
(+) These CPU options match the configuration of the toolchains in RHEL6.
|
||||
|
||||
## `powerpc64-linux-gnu.config`
|
||||
|
||||
For targets: `powerpc64-unknown-linux-gnu`
|
||||
|
||||
- Path and misc options > Prefix directory = /x-tools/${CT\_TARGET}
|
||||
- Path and misc options > Patches origin = Bundled, then local
|
||||
- Path and misc options > Local patch directory = /tmp/patches
|
||||
- Target options > Target Architecture = powerpc
|
||||
- Target options > Bitness = 64-bit
|
||||
- Target options > Emit assembly for CPU = power4 -- (+)
|
||||
- Target options > Tune for CPU = power6 -- (+)
|
||||
- Operating System > Target OS = linux
|
||||
- Operating System > Linux kernel version = 2.6.32.68 -- ~RHEL6 kernel
|
||||
- C-library > glibc version = 2.12.2 -- ~RHEL6 glibc
|
||||
- C compiler > gcc version = 4.9.3
|
||||
- C compiler > C++ = ENABLE -- to cross compile LLVM
|
||||
|
||||
(+) These CPU options match the configuration of the toolchains in RHEL6.
|
||||
|
||||
## `s390x-linux-gnu.config`
|
||||
|
||||
For targets: `s390x-unknown-linux-gnu`
|
||||
|
||||
- Path and misc options > Prefix directory = /x-tools/${CT\_TARGET}
|
||||
- Path and misc options > Patches origin = Bundled, then local
|
||||
- Path and misc options > Local patch directory = /build/patches
|
||||
- Target options > Target Architecture = s390
|
||||
- Target options > Bitness = 64-bit
|
||||
- Operating System > Target OS = linux
|
||||
- Operating System > Linux kernel version = 2.6.32.68 -- ~RHEL6 kernel
|
||||
- C-library > glibc version = 2.12.2 -- ~RHEL6 glibc
|
||||
- C compiler > gcc version = 4.9.3
|
||||
- C compiler > gcc extra config = --with-arch=z10 -- LLVM's minimum support
|
||||
- C compiler > C++ = ENABLE -- to cross compile LLVM
|
||||
|
|
|
|||
|
|
@ -1,18 +1,29 @@
|
|||
FROM ubuntu:16.04
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
g++ \
|
||||
make \
|
||||
file \
|
||||
curl \
|
||||
automake \
|
||||
bison \
|
||||
bzip2 \
|
||||
ca-certificates \
|
||||
python2.7 \
|
||||
git \
|
||||
cmake \
|
||||
sudo \
|
||||
curl \
|
||||
file \
|
||||
flex \
|
||||
g++ \
|
||||
gawk \
|
||||
gdb \
|
||||
xz-utils \
|
||||
g++-powerpc-linux-gnu
|
||||
git \
|
||||
gperf \
|
||||
help2man \
|
||||
libncurses-dev \
|
||||
libtool-bin \
|
||||
make \
|
||||
patch \
|
||||
python2.7 \
|
||||
sudo \
|
||||
texinfo \
|
||||
wget \
|
||||
xz-utils
|
||||
|
||||
ENV SCCACHE_DIGEST=7237e38e029342fa27b7ac25412cb9d52554008b12389727320bd533fd7f05b6a96d55485f305caf95e5c8f5f97c3313e10012ccad3e752aba2518f3522ba783
|
||||
RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | \
|
||||
|
|
@ -23,6 +34,43 @@ RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-ini
|
|||
rm dumb-init_*.deb
|
||||
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
|
||||
|
||||
# Ubuntu 16.04 (this contianer) ships with make 4, but something in the
|
||||
# toolchains we build below chokes on that, so go back to make 3
|
||||
RUN curl https://ftp.gnu.org/gnu/make/make-3.81.tar.gz | tar xzf - && \
|
||||
cd make-3.81 && \
|
||||
./configure --prefix=/usr && \
|
||||
make && \
|
||||
make install && \
|
||||
cd .. && \
|
||||
rm -rf make-3.81
|
||||
|
||||
RUN curl http://crosstool-ng.org/download/crosstool-ng/crosstool-ng-1.22.0.tar.bz2 | \
|
||||
tar xjf - && \
|
||||
cd crosstool-ng && \
|
||||
./configure --prefix=/usr/local && \
|
||||
make -j$(nproc) && \
|
||||
make install && \
|
||||
cd .. && \
|
||||
rm -rf crosstool-ng
|
||||
|
||||
RUN groupadd -r rustbuild && useradd -m -r -g rustbuild rustbuild
|
||||
RUN mkdir /x-tools && chown rustbuild:rustbuild /x-tools
|
||||
USER rustbuild
|
||||
WORKDIR /tmp
|
||||
|
||||
COPY patches/ /tmp/patches/
|
||||
COPY powerpc-linux-gnu.config build-powerpc-toolchain.sh /tmp/
|
||||
RUN ./build-powerpc-toolchain.sh
|
||||
|
||||
USER root
|
||||
|
||||
ENV PATH=$PATH:/x-tools/powerpc-unknown-linux-gnu/bin
|
||||
|
||||
ENV \
|
||||
CC_powerpc_unknown_linux_gnu=powerpc-unknown-linux-gnu-gcc \
|
||||
AR_powerpc_unknown_linux_gnu=powerpc-unknown-linux-gnu-ar \
|
||||
CXX_powerpc_unknown_linux_gnu=powerpc-unknown-linux-gnu-g++
|
||||
|
||||
ENV HOSTS=powerpc-unknown-linux-gnu
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended
|
||||
|
|
|
|||
36
src/ci/docker/dist-powerpc-linux/build-powerpc-toolchain.sh
Executable file
36
src/ci/docker/dist-powerpc-linux/build-powerpc-toolchain.sh
Executable file
|
|
@ -0,0 +1,36 @@
|
|||
#!/bin/bash
|
||||
# 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
|
||||
|
||||
hide_output() {
|
||||
set +x
|
||||
on_err="
|
||||
echo ERROR: An error was encountered with the build.
|
||||
cat /tmp/build.log
|
||||
exit 1
|
||||
"
|
||||
trap "$on_err" ERR
|
||||
bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
|
||||
PING_LOOP_PID=$!
|
||||
$@ &> /tmp/build.log
|
||||
rm /tmp/build.log
|
||||
trap - ERR
|
||||
kill $PING_LOOP_PID
|
||||
set -x
|
||||
}
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
cp ../powerpc-linux-gnu.config .config
|
||||
hide_output ct-ng build
|
||||
cd ..
|
||||
rm -rf build
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
From b3563932f85d60bb0d38b0a5f3b8f4abc133f890 Mon Sep 17 00:00:00 2001
|
||||
From: Tulio Magno Quites Machado Filho <tuliom@linux.vnet.ibm.com>
|
||||
Date: Thu, 1 Nov 2012 18:00:06 -0500
|
||||
Subject: [PATCH] PowerPC: Remove unnecessary -mnew-mnemonics.
|
||||
|
||||
---
|
||||
sysdeps/powerpc/Makefile | 4 ----
|
||||
1 file changed, 4 deletions(-)
|
||||
|
||||
diff --git a/sysdeps/powerpc/Makefile b/sysdeps/powerpc/Makefile
|
||||
index 79dd6fa976d5..7442b6709ad1 100644
|
||||
--- a/sysdeps/powerpc/Makefile
|
||||
+++ b/sysdeps/powerpc/Makefile
|
||||
@@ -1,7 +1,3 @@
|
||||
-# We always want to use the new mnemonic syntax even if we are on a RS6000
|
||||
-# machine.
|
||||
-+cflags += -mnew-mnemonics
|
||||
-
|
||||
ifeq ($(subdir),gmon)
|
||||
sysdep_routines += ppc-mcount
|
||||
endif
|
||||
--
|
||||
2.9.3
|
||||
|
||||
528
src/ci/docker/dist-powerpc-linux/powerpc-linux-gnu.config
Normal file
528
src/ci/docker/dist-powerpc-linux/powerpc-linux-gnu.config
Normal file
|
|
@ -0,0 +1,528 @@
|
|||
#
|
||||
# Automatically generated file; DO NOT EDIT.
|
||||
# Crosstool-NG Configuration
|
||||
#
|
||||
CT_CONFIGURE_has_make381=y
|
||||
CT_CONFIGURE_has_xz=y
|
||||
CT_MODULES=y
|
||||
|
||||
#
|
||||
# Paths and misc options
|
||||
#
|
||||
|
||||
#
|
||||
# crosstool-NG behavior
|
||||
#
|
||||
# CT_OBSOLETE is not set
|
||||
# CT_EXPERIMENTAL is not set
|
||||
# CT_DEBUG_CT is not set
|
||||
|
||||
#
|
||||
# Paths
|
||||
#
|
||||
CT_LOCAL_TARBALLS_DIR=""
|
||||
CT_WORK_DIR="${CT_TOP_DIR}/.build"
|
||||
CT_PREFIX_DIR="/x-tools/${CT_TARGET}"
|
||||
CT_INSTALL_DIR="${CT_PREFIX_DIR}"
|
||||
CT_RM_RF_PREFIX_DIR=y
|
||||
CT_REMOVE_DOCS=y
|
||||
CT_INSTALL_DIR_RO=y
|
||||
CT_STRIP_HOST_TOOLCHAIN_EXECUTABLES=y
|
||||
# CT_STRIP_TARGET_TOOLCHAIN_EXECUTABLES is not set
|
||||
|
||||
#
|
||||
# Downloading
|
||||
#
|
||||
# CT_FORBID_DOWNLOAD is not set
|
||||
# CT_FORCE_DOWNLOAD is not set
|
||||
CT_CONNECT_TIMEOUT=10
|
||||
# CT_ONLY_DOWNLOAD is not set
|
||||
# CT_USE_MIRROR is not set
|
||||
|
||||
#
|
||||
# Extracting
|
||||
#
|
||||
# CT_FORCE_EXTRACT is not set
|
||||
CT_OVERIDE_CONFIG_GUESS_SUB=y
|
||||
# CT_ONLY_EXTRACT is not set
|
||||
# CT_PATCH_BUNDLED is not set
|
||||
# CT_PATCH_LOCAL is not set
|
||||
CT_PATCH_BUNDLED_LOCAL=y
|
||||
# CT_PATCH_LOCAL_BUNDLED is not set
|
||||
# CT_PATCH_BUNDLED_FALLBACK_LOCAL is not set
|
||||
# CT_PATCH_LOCAL_FALLBACK_BUNDLED is not set
|
||||
# CT_PATCH_NONE is not set
|
||||
CT_PATCH_ORDER="bundled,local"
|
||||
CT_PATCH_USE_LOCAL=y
|
||||
CT_LOCAL_PATCH_DIR="/tmp/patches"
|
||||
|
||||
#
|
||||
# Build behavior
|
||||
#
|
||||
CT_PARALLEL_JOBS=0
|
||||
CT_LOAD=""
|
||||
CT_USE_PIPES=y
|
||||
CT_EXTRA_CFLAGS_FOR_BUILD=""
|
||||
CT_EXTRA_LDFLAGS_FOR_BUILD=""
|
||||
CT_EXTRA_CFLAGS_FOR_HOST=""
|
||||
CT_EXTRA_LDFLAGS_FOR_HOST=""
|
||||
# CT_CONFIG_SHELL_SH is not set
|
||||
# CT_CONFIG_SHELL_ASH is not set
|
||||
CT_CONFIG_SHELL_BASH=y
|
||||
# CT_CONFIG_SHELL_CUSTOM is not set
|
||||
CT_CONFIG_SHELL="${bash}"
|
||||
|
||||
#
|
||||
# Logging
|
||||
#
|
||||
# CT_LOG_ERROR is not set
|
||||
# CT_LOG_WARN is not set
|
||||
CT_LOG_INFO=y
|
||||
# CT_LOG_EXTRA is not set
|
||||
# CT_LOG_ALL is not set
|
||||
# CT_LOG_DEBUG is not set
|
||||
CT_LOG_LEVEL_MAX="INFO"
|
||||
# CT_LOG_SEE_TOOLS_WARN is not set
|
||||
CT_LOG_PROGRESS_BAR=y
|
||||
CT_LOG_TO_FILE=y
|
||||
CT_LOG_FILE_COMPRESS=y
|
||||
|
||||
#
|
||||
# Target options
|
||||
#
|
||||
CT_ARCH="powerpc"
|
||||
CT_ARCH_SUPPORTS_BOTH_ENDIAN=y
|
||||
CT_ARCH_SUPPORTS_32=y
|
||||
CT_ARCH_SUPPORTS_64=y
|
||||
CT_ARCH_SUPPORTS_WITH_ABI=y
|
||||
CT_ARCH_SUPPORTS_WITH_CPU=y
|
||||
CT_ARCH_SUPPORTS_WITH_TUNE=y
|
||||
CT_ARCH_SUPPORTS_WITH_FLOAT=y
|
||||
CT_ARCH_DEFAULT_BE=y
|
||||
CT_ARCH_DEFAULT_32=y
|
||||
CT_ARCH_ABI=""
|
||||
CT_ARCH_CPU="power4"
|
||||
CT_ARCH_TUNE="power6"
|
||||
CT_ARCH_BE=y
|
||||
# CT_ARCH_LE is not set
|
||||
CT_ARCH_32=y
|
||||
# CT_ARCH_64 is not set
|
||||
CT_ARCH_BITNESS=32
|
||||
# CT_ARCH_FLOAT_HW is not set
|
||||
# CT_ARCH_FLOAT_SW is not set
|
||||
CT_TARGET_CFLAGS=""
|
||||
CT_TARGET_LDFLAGS=""
|
||||
# CT_ARCH_alpha is not set
|
||||
# CT_ARCH_arm is not set
|
||||
# CT_ARCH_avr is not set
|
||||
# CT_ARCH_m68k is not set
|
||||
# CT_ARCH_mips is not set
|
||||
# CT_ARCH_nios2 is not set
|
||||
CT_ARCH_powerpc=y
|
||||
# CT_ARCH_s390 is not set
|
||||
# CT_ARCH_sh is not set
|
||||
# CT_ARCH_sparc is not set
|
||||
# CT_ARCH_x86 is not set
|
||||
# CT_ARCH_xtensa is not set
|
||||
CT_ARCH_alpha_AVAILABLE=y
|
||||
CT_ARCH_arm_AVAILABLE=y
|
||||
CT_ARCH_avr_AVAILABLE=y
|
||||
CT_ARCH_m68k_AVAILABLE=y
|
||||
CT_ARCH_microblaze_AVAILABLE=y
|
||||
CT_ARCH_mips_AVAILABLE=y
|
||||
CT_ARCH_nios2_AVAILABLE=y
|
||||
CT_ARCH_powerpc_AVAILABLE=y
|
||||
CT_ARCH_s390_AVAILABLE=y
|
||||
CT_ARCH_sh_AVAILABLE=y
|
||||
CT_ARCH_sparc_AVAILABLE=y
|
||||
CT_ARCH_x86_AVAILABLE=y
|
||||
CT_ARCH_xtensa_AVAILABLE=y
|
||||
CT_ARCH_SUFFIX=""
|
||||
|
||||
#
|
||||
# Generic target options
|
||||
#
|
||||
# CT_MULTILIB is not set
|
||||
CT_ARCH_USE_MMU=y
|
||||
CT_ARCH_ENDIAN="big"
|
||||
|
||||
#
|
||||
# Target optimisations
|
||||
#
|
||||
CT_ARCH_FLOAT_AUTO=y
|
||||
CT_ARCH_FLOAT="auto"
|
||||
|
||||
#
|
||||
# powerpc other options
|
||||
#
|
||||
CT_ARCH_powerpc_ABI=""
|
||||
CT_ARCH_powerpc_ABI_DEFAULT=y
|
||||
# CT_ARCH_powerpc_ABI_SPE is not set
|
||||
|
||||
#
|
||||
# Toolchain options
|
||||
#
|
||||
|
||||
#
|
||||
# General toolchain options
|
||||
#
|
||||
CT_FORCE_SYSROOT=y
|
||||
CT_USE_SYSROOT=y
|
||||
CT_SYSROOT_NAME="sysroot"
|
||||
CT_SYSROOT_DIR_PREFIX=""
|
||||
CT_WANTS_STATIC_LINK=y
|
||||
# CT_STATIC_TOOLCHAIN is not set
|
||||
CT_TOOLCHAIN_PKGVERSION=""
|
||||
CT_TOOLCHAIN_BUGURL=""
|
||||
|
||||
#
|
||||
# Tuple completion and aliasing
|
||||
#
|
||||
CT_TARGET_VENDOR="unknown"
|
||||
CT_TARGET_ALIAS_SED_EXPR=""
|
||||
CT_TARGET_ALIAS=""
|
||||
|
||||
#
|
||||
# Toolchain type
|
||||
#
|
||||
CT_CROSS=y
|
||||
# CT_CANADIAN is not set
|
||||
CT_TOOLCHAIN_TYPE="cross"
|
||||
|
||||
#
|
||||
# Build system
|
||||
#
|
||||
CT_BUILD=""
|
||||
CT_BUILD_PREFIX=""
|
||||
CT_BUILD_SUFFIX=""
|
||||
|
||||
#
|
||||
# Misc options
|
||||
#
|
||||
# CT_TOOLCHAIN_ENABLE_NLS is not set
|
||||
|
||||
#
|
||||
# Operating System
|
||||
#
|
||||
CT_KERNEL_SUPPORTS_SHARED_LIBS=y
|
||||
CT_KERNEL="linux"
|
||||
CT_KERNEL_VERSION="2.6.32.68"
|
||||
# CT_KERNEL_bare_metal is not set
|
||||
CT_KERNEL_linux=y
|
||||
CT_KERNEL_bare_metal_AVAILABLE=y
|
||||
CT_KERNEL_linux_AVAILABLE=y
|
||||
# CT_KERNEL_V_4_3 is not set
|
||||
# CT_KERNEL_V_4_2 is not set
|
||||
# CT_KERNEL_V_4_1 is not set
|
||||
# CT_KERNEL_V_3_18 is not set
|
||||
# CT_KERNEL_V_3_14 is not set
|
||||
# CT_KERNEL_V_3_12 is not set
|
||||
# CT_KERNEL_V_3_10 is not set
|
||||
# CT_KERNEL_V_3_4 is not set
|
||||
# CT_KERNEL_V_3_2 is not set
|
||||
CT_KERNEL_V_2_6_32=y
|
||||
# CT_KERNEL_LINUX_CUSTOM is not set
|
||||
CT_KERNEL_windows_AVAILABLE=y
|
||||
|
||||
#
|
||||
# Common kernel options
|
||||
#
|
||||
CT_SHARED_LIBS=y
|
||||
|
||||
#
|
||||
# linux other options
|
||||
#
|
||||
CT_KERNEL_LINUX_VERBOSITY_0=y
|
||||
# CT_KERNEL_LINUX_VERBOSITY_1 is not set
|
||||
# CT_KERNEL_LINUX_VERBOSITY_2 is not set
|
||||
CT_KERNEL_LINUX_VERBOSE_LEVEL=0
|
||||
CT_KERNEL_LINUX_INSTALL_CHECK=y
|
||||
|
||||
#
|
||||
# Binary utilities
|
||||
#
|
||||
CT_ARCH_BINFMT_ELF=y
|
||||
CT_BINUTILS="binutils"
|
||||
CT_BINUTILS_binutils=y
|
||||
|
||||
#
|
||||
# GNU binutils
|
||||
#
|
||||
# CT_CC_BINUTILS_SHOW_LINARO is not set
|
||||
CT_BINUTILS_V_2_25_1=y
|
||||
# CT_BINUTILS_V_2_25 is not set
|
||||
# CT_BINUTILS_V_2_24 is not set
|
||||
# CT_BINUTILS_V_2_23_2 is not set
|
||||
# CT_BINUTILS_V_2_23_1 is not set
|
||||
# CT_BINUTILS_V_2_22 is not set
|
||||
# CT_BINUTILS_V_2_21_53 is not set
|
||||
# CT_BINUTILS_V_2_21_1a is not set
|
||||
# CT_BINUTILS_V_2_20_1a is not set
|
||||
# CT_BINUTILS_V_2_19_1a is not set
|
||||
# CT_BINUTILS_V_2_18a is not set
|
||||
CT_BINUTILS_VERSION="2.25.1"
|
||||
CT_BINUTILS_2_25_1_or_later=y
|
||||
CT_BINUTILS_2_25_or_later=y
|
||||
CT_BINUTILS_2_24_or_later=y
|
||||
CT_BINUTILS_2_23_or_later=y
|
||||
CT_BINUTILS_2_22_or_later=y
|
||||
CT_BINUTILS_2_21_or_later=y
|
||||
CT_BINUTILS_2_20_or_later=y
|
||||
CT_BINUTILS_2_19_or_later=y
|
||||
CT_BINUTILS_2_18_or_later=y
|
||||
CT_BINUTILS_HAS_HASH_STYLE=y
|
||||
CT_BINUTILS_HAS_GOLD=y
|
||||
CT_BINUTILS_HAS_PLUGINS=y
|
||||
CT_BINUTILS_HAS_PKGVERSION_BUGURL=y
|
||||
CT_BINUTILS_FORCE_LD_BFD=y
|
||||
CT_BINUTILS_LINKER_LD=y
|
||||
CT_BINUTILS_LINKERS_LIST="ld"
|
||||
CT_BINUTILS_LINKER_DEFAULT="bfd"
|
||||
# CT_BINUTILS_PLUGINS is not set
|
||||
CT_BINUTILS_EXTRA_CONFIG_ARRAY=""
|
||||
# CT_BINUTILS_FOR_TARGET is not set
|
||||
|
||||
#
|
||||
# binutils other options
|
||||
#
|
||||
|
||||
#
|
||||
# C-library
|
||||
#
|
||||
CT_LIBC="glibc"
|
||||
CT_LIBC_VERSION="2.12.2"
|
||||
CT_LIBC_glibc=y
|
||||
# CT_LIBC_musl is not set
|
||||
# CT_LIBC_uClibc is not set
|
||||
CT_LIBC_avr_libc_AVAILABLE=y
|
||||
CT_LIBC_glibc_AVAILABLE=y
|
||||
CT_THREADS="nptl"
|
||||
# CT_CC_GLIBC_SHOW_LINARO is not set
|
||||
# CT_LIBC_GLIBC_V_2_22 is not set
|
||||
# CT_LIBC_GLIBC_V_2_21 is not set
|
||||
# CT_LIBC_GLIBC_V_2_20 is not set
|
||||
# CT_LIBC_GLIBC_V_2_19 is not set
|
||||
# CT_LIBC_GLIBC_V_2_18 is not set
|
||||
# CT_LIBC_GLIBC_V_2_17 is not set
|
||||
# CT_LIBC_GLIBC_V_2_16_0 is not set
|
||||
# CT_LIBC_GLIBC_V_2_15 is not set
|
||||
# CT_LIBC_GLIBC_V_2_14_1 is not set
|
||||
# CT_LIBC_GLIBC_V_2_14 is not set
|
||||
# CT_LIBC_GLIBC_V_2_13 is not set
|
||||
CT_LIBC_GLIBC_V_2_12_2=y
|
||||
# CT_LIBC_GLIBC_V_2_12_1 is not set
|
||||
# CT_LIBC_GLIBC_V_2_11_1 is not set
|
||||
# CT_LIBC_GLIBC_V_2_11 is not set
|
||||
# CT_LIBC_GLIBC_V_2_10_1 is not set
|
||||
# CT_LIBC_GLIBC_V_2_9 is not set
|
||||
# CT_LIBC_GLIBC_V_2_8 is not set
|
||||
CT_LIBC_mingw_AVAILABLE=y
|
||||
CT_LIBC_musl_AVAILABLE=y
|
||||
CT_LIBC_newlib_AVAILABLE=y
|
||||
CT_LIBC_none_AVAILABLE=y
|
||||
CT_LIBC_uClibc_AVAILABLE=y
|
||||
CT_LIBC_SUPPORT_THREADS_ANY=y
|
||||
CT_LIBC_SUPPORT_THREADS_NATIVE=y
|
||||
|
||||
#
|
||||
# Common C library options
|
||||
#
|
||||
CT_THREADS_NATIVE=y
|
||||
CT_LIBC_XLDD=y
|
||||
|
||||
#
|
||||
# glibc other options
|
||||
#
|
||||
CT_LIBC_GLIBC_PORTS_EXTERNAL=y
|
||||
CT_LIBC_glibc_familly=y
|
||||
CT_LIBC_GLIBC_EXTRA_CONFIG_ARRAY=""
|
||||
CT_LIBC_GLIBC_CONFIGPARMS=""
|
||||
CT_LIBC_GLIBC_EXTRA_CFLAGS=""
|
||||
CT_LIBC_EXTRA_CC_ARGS=""
|
||||
# CT_LIBC_DISABLE_VERSIONING is not set
|
||||
CT_LIBC_OLDEST_ABI=""
|
||||
CT_LIBC_GLIBC_FORCE_UNWIND=y
|
||||
# CT_LIBC_GLIBC_USE_PORTS is not set
|
||||
CT_LIBC_ADDONS_LIST=""
|
||||
# CT_LIBC_LOCALES is not set
|
||||
# CT_LIBC_GLIBC_KERNEL_VERSION_NONE is not set
|
||||
CT_LIBC_GLIBC_KERNEL_VERSION_AS_HEADERS=y
|
||||
# CT_LIBC_GLIBC_KERNEL_VERSION_CHOSEN is not set
|
||||
CT_LIBC_GLIBC_MIN_KERNEL="2.6.32.68"
|
||||
|
||||
#
|
||||
# C compiler
|
||||
#
|
||||
CT_CC="gcc"
|
||||
CT_CC_CORE_PASSES_NEEDED=y
|
||||
CT_CC_CORE_PASS_1_NEEDED=y
|
||||
CT_CC_CORE_PASS_2_NEEDED=y
|
||||
CT_CC_gcc=y
|
||||
# CT_CC_GCC_SHOW_LINARO is not set
|
||||
# CT_CC_GCC_V_5_2_0 is not set
|
||||
CT_CC_GCC_V_4_9_3=y
|
||||
# CT_CC_GCC_V_4_8_5 is not set
|
||||
# CT_CC_GCC_V_4_7_4 is not set
|
||||
# CT_CC_GCC_V_4_6_4 is not set
|
||||
# CT_CC_GCC_V_4_5_4 is not set
|
||||
# CT_CC_GCC_V_4_4_7 is not set
|
||||
# CT_CC_GCC_V_4_3_6 is not set
|
||||
# CT_CC_GCC_V_4_2_4 is not set
|
||||
CT_CC_GCC_4_2_or_later=y
|
||||
CT_CC_GCC_4_3_or_later=y
|
||||
CT_CC_GCC_4_4_or_later=y
|
||||
CT_CC_GCC_4_5_or_later=y
|
||||
CT_CC_GCC_4_6_or_later=y
|
||||
CT_CC_GCC_4_7_or_later=y
|
||||
CT_CC_GCC_4_8_or_later=y
|
||||
CT_CC_GCC_4_9=y
|
||||
CT_CC_GCC_4_9_or_later=y
|
||||
CT_CC_GCC_HAS_GRAPHITE=y
|
||||
CT_CC_GCC_USE_GRAPHITE=y
|
||||
CT_CC_GCC_HAS_LTO=y
|
||||
CT_CC_GCC_USE_LTO=y
|
||||
CT_CC_GCC_HAS_PKGVERSION_BUGURL=y
|
||||
CT_CC_GCC_HAS_BUILD_ID=y
|
||||
CT_CC_GCC_HAS_LNK_HASH_STYLE=y
|
||||
CT_CC_GCC_USE_GMP_MPFR=y
|
||||
CT_CC_GCC_USE_MPC=y
|
||||
CT_CC_GCC_HAS_LIBQUADMATH=y
|
||||
CT_CC_GCC_HAS_LIBSANITIZER=y
|
||||
CT_CC_GCC_VERSION="4.9.3"
|
||||
# CT_CC_LANG_FORTRAN is not set
|
||||
CT_CC_GCC_ENABLE_CXX_FLAGS=""
|
||||
CT_CC_GCC_CORE_EXTRA_CONFIG_ARRAY="--with-cpu-32=power4 --with-cpu=default32"
|
||||
CT_CC_GCC_EXTRA_CONFIG_ARRAY="--with-cpu-32=power4 --with-cpu=default32"
|
||||
CT_CC_GCC_EXTRA_ENV_ARRAY=""
|
||||
CT_CC_GCC_STATIC_LIBSTDCXX=y
|
||||
# CT_CC_GCC_SYSTEM_ZLIB is not set
|
||||
|
||||
#
|
||||
# Optimisation features
|
||||
#
|
||||
|
||||
#
|
||||
# Settings for libraries running on target
|
||||
#
|
||||
CT_CC_GCC_ENABLE_TARGET_OPTSPACE=y
|
||||
# CT_CC_GCC_LIBMUDFLAP is not set
|
||||
# CT_CC_GCC_LIBGOMP is not set
|
||||
# CT_CC_GCC_LIBSSP is not set
|
||||
# CT_CC_GCC_LIBQUADMATH is not set
|
||||
# CT_CC_GCC_LIBSANITIZER is not set
|
||||
|
||||
#
|
||||
# Misc. obscure options.
|
||||
#
|
||||
CT_CC_CXA_ATEXIT=y
|
||||
# CT_CC_GCC_DISABLE_PCH is not set
|
||||
CT_CC_GCC_SJLJ_EXCEPTIONS=m
|
||||
CT_CC_GCC_LDBL_128=m
|
||||
# CT_CC_GCC_BUILD_ID is not set
|
||||
CT_CC_GCC_LNK_HASH_STYLE_DEFAULT=y
|
||||
# CT_CC_GCC_LNK_HASH_STYLE_SYSV is not set
|
||||
# CT_CC_GCC_LNK_HASH_STYLE_GNU is not set
|
||||
# CT_CC_GCC_LNK_HASH_STYLE_BOTH is not set
|
||||
CT_CC_GCC_LNK_HASH_STYLE=""
|
||||
CT_CC_GCC_DEC_FLOAT_AUTO=y
|
||||
# CT_CC_GCC_DEC_FLOAT_BID is not set
|
||||
# CT_CC_GCC_DEC_FLOAT_DPD is not set
|
||||
# CT_CC_GCC_DEC_FLOATS_NO is not set
|
||||
CT_CC_SUPPORT_CXX=y
|
||||
CT_CC_SUPPORT_FORTRAN=y
|
||||
CT_CC_SUPPORT_JAVA=y
|
||||
CT_CC_SUPPORT_ADA=y
|
||||
CT_CC_SUPPORT_OBJC=y
|
||||
CT_CC_SUPPORT_OBJCXX=y
|
||||
CT_CC_SUPPORT_GOLANG=y
|
||||
|
||||
#
|
||||
# Additional supported languages:
|
||||
#
|
||||
CT_CC_LANG_CXX=y
|
||||
# CT_CC_LANG_JAVA is not set
|
||||
|
||||
#
|
||||
# Debug facilities
|
||||
#
|
||||
# CT_DEBUG_dmalloc is not set
|
||||
# CT_DEBUG_duma is not set
|
||||
# CT_DEBUG_gdb is not set
|
||||
# CT_DEBUG_ltrace is not set
|
||||
# CT_DEBUG_strace is not set
|
||||
|
||||
#
|
||||
# Companion libraries
|
||||
#
|
||||
CT_COMPLIBS_NEEDED=y
|
||||
CT_LIBICONV_NEEDED=y
|
||||
CT_GETTEXT_NEEDED=y
|
||||
CT_GMP_NEEDED=y
|
||||
CT_MPFR_NEEDED=y
|
||||
CT_ISL_NEEDED=y
|
||||
CT_CLOOG_NEEDED=y
|
||||
CT_MPC_NEEDED=y
|
||||
CT_COMPLIBS=y
|
||||
CT_LIBICONV=y
|
||||
CT_GETTEXT=y
|
||||
CT_GMP=y
|
||||
CT_MPFR=y
|
||||
CT_ISL=y
|
||||
CT_CLOOG=y
|
||||
CT_MPC=y
|
||||
CT_LIBICONV_V_1_14=y
|
||||
CT_LIBICONV_VERSION="1.14"
|
||||
CT_GETTEXT_V_0_19_6=y
|
||||
CT_GETTEXT_VERSION="0.19.6"
|
||||
CT_GMP_V_6_0_0=y
|
||||
# CT_GMP_V_5_1_3 is not set
|
||||
# CT_GMP_V_5_1_1 is not set
|
||||
# CT_GMP_V_5_0_2 is not set
|
||||
# CT_GMP_V_5_0_1 is not set
|
||||
# CT_GMP_V_4_3_2 is not set
|
||||
# CT_GMP_V_4_3_1 is not set
|
||||
# CT_GMP_V_4_3_0 is not set
|
||||
CT_GMP_5_0_2_or_later=y
|
||||
CT_GMP_VERSION="6.0.0a"
|
||||
CT_MPFR_V_3_1_3=y
|
||||
# CT_MPFR_V_3_1_2 is not set
|
||||
# CT_MPFR_V_3_1_0 is not set
|
||||
# CT_MPFR_V_3_0_1 is not set
|
||||
# CT_MPFR_V_3_0_0 is not set
|
||||
# CT_MPFR_V_2_4_2 is not set
|
||||
# CT_MPFR_V_2_4_1 is not set
|
||||
# CT_MPFR_V_2_4_0 is not set
|
||||
CT_MPFR_VERSION="3.1.3"
|
||||
CT_ISL_V_0_14=y
|
||||
CT_ISL_V_0_14_or_later=y
|
||||
CT_ISL_V_0_12_or_later=y
|
||||
CT_ISL_VERSION="0.14"
|
||||
CT_CLOOG_V_0_18_4=y
|
||||
# CT_CLOOG_V_0_18_1 is not set
|
||||
# CT_CLOOG_V_0_18_0 is not set
|
||||
CT_CLOOG_VERSION="0.18.4"
|
||||
CT_CLOOG_0_18_4_or_later=y
|
||||
CT_CLOOG_0_18_or_later=y
|
||||
CT_MPC_V_1_0_3=y
|
||||
# CT_MPC_V_1_0_2 is not set
|
||||
# CT_MPC_V_1_0_1 is not set
|
||||
# CT_MPC_V_1_0 is not set
|
||||
# CT_MPC_V_0_9 is not set
|
||||
# CT_MPC_V_0_8_2 is not set
|
||||
# CT_MPC_V_0_8_1 is not set
|
||||
# CT_MPC_V_0_7 is not set
|
||||
CT_MPC_VERSION="1.0.3"
|
||||
|
||||
#
|
||||
# Companion libraries common options
|
||||
#
|
||||
# CT_COMPLIBS_CHECK is not set
|
||||
|
||||
#
|
||||
# Companion tools
|
||||
#
|
||||
|
||||
#
|
||||
# READ HELP before you say 'Y' below !!!
|
||||
#
|
||||
# CT_COMP_TOOLS is not set
|
||||
|
|
@ -1,19 +1,29 @@
|
|||
FROM ubuntu:16.04
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
g++ \
|
||||
make \
|
||||
file \
|
||||
curl \
|
||||
automake \
|
||||
bison \
|
||||
bzip2 \
|
||||
ca-certificates \
|
||||
python2.7 \
|
||||
git \
|
||||
cmake \
|
||||
sudo \
|
||||
curl \
|
||||
file \
|
||||
flex \
|
||||
g++ \
|
||||
gawk \
|
||||
gdb \
|
||||
xz-utils \
|
||||
g++-powerpc64-linux-gnu \
|
||||
g++-powerpc64le-linux-gnu
|
||||
git \
|
||||
gperf \
|
||||
help2man \
|
||||
libncurses-dev \
|
||||
libtool-bin \
|
||||
make \
|
||||
patch \
|
||||
python2.7 \
|
||||
sudo \
|
||||
texinfo \
|
||||
wget \
|
||||
xz-utils
|
||||
|
||||
ENV SCCACHE_DIGEST=7237e38e029342fa27b7ac25412cb9d52554008b12389727320bd533fd7f05b6a96d55485f305caf95e5c8f5f97c3313e10012ccad3e752aba2518f3522ba783
|
||||
RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | \
|
||||
|
|
@ -24,10 +34,49 @@ RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-ini
|
|||
rm dumb-init_*.deb
|
||||
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
|
||||
|
||||
# Ubuntu 16.04 (this contianer) ships with make 4, but something in the
|
||||
# toolchains we build below chokes on that, so go back to make 3
|
||||
RUN curl https://ftp.gnu.org/gnu/make/make-3.81.tar.gz | tar xzf - && \
|
||||
cd make-3.81 && \
|
||||
./configure --prefix=/usr && \
|
||||
make && \
|
||||
make install && \
|
||||
cd .. && \
|
||||
rm -rf make-3.81
|
||||
|
||||
RUN curl http://crosstool-ng.org/download/crosstool-ng/crosstool-ng-1.22.0.tar.bz2 | \
|
||||
tar xjf - && \
|
||||
cd crosstool-ng && \
|
||||
./configure --prefix=/usr/local && \
|
||||
make -j$(nproc) && \
|
||||
make install && \
|
||||
cd .. && \
|
||||
rm -rf crosstool-ng
|
||||
|
||||
RUN groupadd -r rustbuild && useradd -m -r -g rustbuild rustbuild
|
||||
RUN mkdir /x-tools && chown rustbuild:rustbuild /x-tools
|
||||
USER rustbuild
|
||||
WORKDIR /tmp
|
||||
|
||||
COPY patches/ /tmp/patches/
|
||||
COPY powerpc64-linux-gnu.config build-powerpc64-toolchain.sh /tmp/
|
||||
RUN ./build-powerpc64-toolchain.sh
|
||||
|
||||
USER root
|
||||
|
||||
RUN apt-get install -y --no-install-recommends rpm2cpio cpio
|
||||
COPY build-powerpc64le-toolchain.sh /tmp/
|
||||
RUN ./build-powerpc64le-toolchain.sh
|
||||
|
||||
ENV PATH=$PATH:/x-tools/powerpc64-unknown-linux-gnu/bin
|
||||
|
||||
ENV \
|
||||
AR_powerpc64_unknown_linux_gnu=powerpc64-linux-gnu-ar \
|
||||
CC_powerpc64_unknown_linux_gnu=powerpc64-linux-gnu-gcc \
|
||||
CXX_powerpc64_unknown_linux_gnu=powerpc64-linux-gnu-g++
|
||||
AR_powerpc64_unknown_linux_gnu=powerpc64-unknown-linux-gnu-ar \
|
||||
CC_powerpc64_unknown_linux_gnu=powerpc64-unknown-linux-gnu-gcc \
|
||||
CXX_powerpc64_unknown_linux_gnu=powerpc64-unknown-linux-gnu-g++ \
|
||||
AR_powerpc64le_unknown_linux_gnu=powerpc64le-linux-gnu-ar \
|
||||
CC_powerpc64le_unknown_linux_gnu=powerpc64le-linux-gnu-gcc \
|
||||
CXX_powerpc64le_unknown_linux_gnu=powerpc64le-linux-gnu-g++
|
||||
|
||||
ENV HOSTS=powerpc64-unknown-linux-gnu
|
||||
ENV HOSTS=$HOSTS,powerpc64le-unknown-linux-gnu
|
||||
|
|
|
|||
36
src/ci/docker/dist-powerpc64-linux/build-powerpc64-toolchain.sh
Executable file
36
src/ci/docker/dist-powerpc64-linux/build-powerpc64-toolchain.sh
Executable file
|
|
@ -0,0 +1,36 @@
|
|||
#!/bin/bash
|
||||
# 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
|
||||
|
||||
hide_output() {
|
||||
set +x
|
||||
on_err="
|
||||
echo ERROR: An error was encountered with the build.
|
||||
cat /tmp/build.log
|
||||
exit 1
|
||||
"
|
||||
trap "$on_err" ERR
|
||||
bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
|
||||
PING_LOOP_PID=$!
|
||||
$@ &> /tmp/build.log
|
||||
rm /tmp/build.log
|
||||
trap - ERR
|
||||
kill $PING_LOOP_PID
|
||||
set -x
|
||||
}
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
cp ../powerpc64-linux-gnu.config .config
|
||||
hide_output ct-ng build
|
||||
cd ..
|
||||
rm -rf build
|
||||
79
src/ci/docker/dist-powerpc64-linux/build-powerpc64le-toolchain.sh
Executable file
79
src/ci/docker/dist-powerpc64-linux/build-powerpc64le-toolchain.sh
Executable file
|
|
@ -0,0 +1,79 @@
|
|||
#!/bin/bash
|
||||
# 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
|
||||
|
||||
BINUTILS=2.25.1
|
||||
GCC=5.3.0
|
||||
TARGET=powerpc64le-linux-gnu
|
||||
SYSROOT=/usr/local/$TARGET/sysroot
|
||||
|
||||
# First, download the CentOS7 glibc.ppc64le and relevant header files.
|
||||
# (upstream ppc64le support wasn't added until 2.19, which el7 backported.)
|
||||
mkdir -p $SYSROOT
|
||||
pushd $SYSROOT
|
||||
|
||||
centos_base=http://mirror.centos.org/altarch/7.3.1611/os/ppc64le/Packages
|
||||
glibc_v=2.17-157.el7
|
||||
kernel_v=3.10.0-514.el7
|
||||
for package in glibc{,-devel,-headers}-$glibc_v kernel-headers-$kernel_v; do
|
||||
curl $centos_base/$package.ppc64le.rpm | \
|
||||
rpm2cpio - | cpio -idm
|
||||
done
|
||||
|
||||
ln -sT lib64 lib
|
||||
ln -sT lib64 usr/lib
|
||||
|
||||
popd
|
||||
|
||||
# Next, download and build binutils.
|
||||
mkdir binutils-$TARGET
|
||||
pushd binutils-$TARGET
|
||||
curl https://ftp.gnu.org/gnu/binutils/binutils-$BINUTILS.tar.bz2 | tar xjf -
|
||||
mkdir binutils-build
|
||||
cd binutils-build
|
||||
../binutils-$BINUTILS/configure --target=$TARGET --with-sysroot=$SYSROOT
|
||||
make -j10
|
||||
make install
|
||||
popd
|
||||
rm -rf binutils-$TARGET
|
||||
|
||||
# Finally, download and build gcc.
|
||||
mkdir gcc-$TARGET
|
||||
pushd gcc-$TARGET
|
||||
curl https://ftp.gnu.org/gnu/gcc/gcc-$GCC/gcc-$GCC.tar.bz2 | tar xjf -
|
||||
cd gcc-$GCC
|
||||
./contrib/download_prerequisites
|
||||
|
||||
mkdir ../gcc-build
|
||||
cd ../gcc-build
|
||||
../gcc-$GCC/configure \
|
||||
--enable-languages=c,c++ \
|
||||
--target=$TARGET \
|
||||
--with-cpu=power8 \
|
||||
--with-sysroot=$SYSROOT \
|
||||
--disable-libcilkrts \
|
||||
--disable-multilib \
|
||||
--disable-nls \
|
||||
--disable-libgomp \
|
||||
--disable-libquadmath \
|
||||
--disable-libssp \
|
||||
--disable-libvtv \
|
||||
--disable-libcilkrt \
|
||||
--disable-libada \
|
||||
--disable-libsanitizer \
|
||||
--disable-libquadmath-support \
|
||||
--disable-lto
|
||||
make -j10
|
||||
make install
|
||||
|
||||
popd
|
||||
rm -rf gcc-$TARGET
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
From b3563932f85d60bb0d38b0a5f3b8f4abc133f890 Mon Sep 17 00:00:00 2001
|
||||
From: Tulio Magno Quites Machado Filho <tuliom@linux.vnet.ibm.com>
|
||||
Date: Thu, 1 Nov 2012 18:00:06 -0500
|
||||
Subject: [PATCH] PowerPC: Remove unnecessary -mnew-mnemonics.
|
||||
|
||||
---
|
||||
sysdeps/powerpc/Makefile | 4 ----
|
||||
1 file changed, 4 deletions(-)
|
||||
|
||||
diff --git a/sysdeps/powerpc/Makefile b/sysdeps/powerpc/Makefile
|
||||
index 79dd6fa976d5..7442b6709ad1 100644
|
||||
--- a/sysdeps/powerpc/Makefile
|
||||
+++ b/sysdeps/powerpc/Makefile
|
||||
@@ -1,7 +1,3 @@
|
||||
-# We always want to use the new mnemonic syntax even if we are on a RS6000
|
||||
-# machine.
|
||||
-+cflags += -mnew-mnemonics
|
||||
-
|
||||
ifeq ($(subdir),gmon)
|
||||
sysdep_routines += ppc-mcount
|
||||
endif
|
||||
--
|
||||
2.9.3
|
||||
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
From a4f388e111ce05e2ab7912cff3c9070334bb74ae Mon Sep 17 00:00:00 2001
|
||||
From: Josh Stone <jistone@redhat.com>
|
||||
Date: Fri, 20 Jan 2017 15:41:56 -0800
|
||||
Subject: [PATCH] Prevent inlining in PPC64 initfini.s
|
||||
|
||||
Ref: https://sourceware.org/ml/libc-alpha/2012-01/msg00195.html
|
||||
---
|
||||
sysdeps/powerpc/powerpc64/Makefile | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/sysdeps/powerpc/powerpc64/Makefile b/sysdeps/powerpc/powerpc64/Makefile
|
||||
index 78d4f07e575f..fe96aae4d43e 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/Makefile
|
||||
+++ b/sysdeps/powerpc/powerpc64/Makefile
|
||||
@@ -28,7 +28,7 @@ elide-routines.os += hp-timing
|
||||
ifneq ($(elf),no)
|
||||
# The initfini generation code doesn't work in the presence of -fPIC, so
|
||||
# we use -fpic instead which is much better.
|
||||
-CFLAGS-initfini.s += -fpic -O1
|
||||
+CFLAGS-initfini.s += -fpic -O1 -fno-inline
|
||||
endif
|
||||
endif
|
||||
|
||||
--
|
||||
2.9.3
|
||||
|
||||
528
src/ci/docker/dist-powerpc64-linux/powerpc64-linux-gnu.config
Normal file
528
src/ci/docker/dist-powerpc64-linux/powerpc64-linux-gnu.config
Normal file
|
|
@ -0,0 +1,528 @@
|
|||
#
|
||||
# Automatically generated file; DO NOT EDIT.
|
||||
# Crosstool-NG Configuration
|
||||
#
|
||||
CT_CONFIGURE_has_make381=y
|
||||
CT_CONFIGURE_has_xz=y
|
||||
CT_MODULES=y
|
||||
|
||||
#
|
||||
# Paths and misc options
|
||||
#
|
||||
|
||||
#
|
||||
# crosstool-NG behavior
|
||||
#
|
||||
# CT_OBSOLETE is not set
|
||||
# CT_EXPERIMENTAL is not set
|
||||
# CT_DEBUG_CT is not set
|
||||
|
||||
#
|
||||
# Paths
|
||||
#
|
||||
CT_LOCAL_TARBALLS_DIR=""
|
||||
CT_WORK_DIR="${CT_TOP_DIR}/.build"
|
||||
CT_PREFIX_DIR="/x-tools/${CT_TARGET}"
|
||||
CT_INSTALL_DIR="${CT_PREFIX_DIR}"
|
||||
CT_RM_RF_PREFIX_DIR=y
|
||||
CT_REMOVE_DOCS=y
|
||||
CT_INSTALL_DIR_RO=y
|
||||
CT_STRIP_HOST_TOOLCHAIN_EXECUTABLES=y
|
||||
# CT_STRIP_TARGET_TOOLCHAIN_EXECUTABLES is not set
|
||||
|
||||
#
|
||||
# Downloading
|
||||
#
|
||||
# CT_FORBID_DOWNLOAD is not set
|
||||
# CT_FORCE_DOWNLOAD is not set
|
||||
CT_CONNECT_TIMEOUT=10
|
||||
# CT_ONLY_DOWNLOAD is not set
|
||||
# CT_USE_MIRROR is not set
|
||||
|
||||
#
|
||||
# Extracting
|
||||
#
|
||||
# CT_FORCE_EXTRACT is not set
|
||||
CT_OVERIDE_CONFIG_GUESS_SUB=y
|
||||
# CT_ONLY_EXTRACT is not set
|
||||
# CT_PATCH_BUNDLED is not set
|
||||
# CT_PATCH_LOCAL is not set
|
||||
CT_PATCH_BUNDLED_LOCAL=y
|
||||
# CT_PATCH_LOCAL_BUNDLED is not set
|
||||
# CT_PATCH_BUNDLED_FALLBACK_LOCAL is not set
|
||||
# CT_PATCH_LOCAL_FALLBACK_BUNDLED is not set
|
||||
# CT_PATCH_NONE is not set
|
||||
CT_PATCH_ORDER="bundled,local"
|
||||
CT_PATCH_USE_LOCAL=y
|
||||
CT_LOCAL_PATCH_DIR="/tmp/patches"
|
||||
|
||||
#
|
||||
# Build behavior
|
||||
#
|
||||
CT_PARALLEL_JOBS=0
|
||||
CT_LOAD=""
|
||||
CT_USE_PIPES=y
|
||||
CT_EXTRA_CFLAGS_FOR_BUILD=""
|
||||
CT_EXTRA_LDFLAGS_FOR_BUILD=""
|
||||
CT_EXTRA_CFLAGS_FOR_HOST=""
|
||||
CT_EXTRA_LDFLAGS_FOR_HOST=""
|
||||
# CT_CONFIG_SHELL_SH is not set
|
||||
# CT_CONFIG_SHELL_ASH is not set
|
||||
CT_CONFIG_SHELL_BASH=y
|
||||
# CT_CONFIG_SHELL_CUSTOM is not set
|
||||
CT_CONFIG_SHELL="${bash}"
|
||||
|
||||
#
|
||||
# Logging
|
||||
#
|
||||
# CT_LOG_ERROR is not set
|
||||
# CT_LOG_WARN is not set
|
||||
CT_LOG_INFO=y
|
||||
# CT_LOG_EXTRA is not set
|
||||
# CT_LOG_ALL is not set
|
||||
# CT_LOG_DEBUG is not set
|
||||
CT_LOG_LEVEL_MAX="INFO"
|
||||
# CT_LOG_SEE_TOOLS_WARN is not set
|
||||
CT_LOG_PROGRESS_BAR=y
|
||||
CT_LOG_TO_FILE=y
|
||||
CT_LOG_FILE_COMPRESS=y
|
||||
|
||||
#
|
||||
# Target options
|
||||
#
|
||||
CT_ARCH="powerpc"
|
||||
CT_ARCH_SUPPORTS_BOTH_ENDIAN=y
|
||||
CT_ARCH_SUPPORTS_32=y
|
||||
CT_ARCH_SUPPORTS_64=y
|
||||
CT_ARCH_SUPPORTS_WITH_ABI=y
|
||||
CT_ARCH_SUPPORTS_WITH_CPU=y
|
||||
CT_ARCH_SUPPORTS_WITH_TUNE=y
|
||||
CT_ARCH_SUPPORTS_WITH_FLOAT=y
|
||||
CT_ARCH_DEFAULT_BE=y
|
||||
CT_ARCH_DEFAULT_32=y
|
||||
CT_ARCH_ABI=""
|
||||
CT_ARCH_CPU="power4"
|
||||
CT_ARCH_TUNE="power6"
|
||||
CT_ARCH_BE=y
|
||||
# CT_ARCH_LE is not set
|
||||
# CT_ARCH_32 is not set
|
||||
CT_ARCH_64=y
|
||||
CT_ARCH_BITNESS=64
|
||||
# CT_ARCH_FLOAT_HW is not set
|
||||
# CT_ARCH_FLOAT_SW is not set
|
||||
CT_TARGET_CFLAGS=""
|
||||
CT_TARGET_LDFLAGS=""
|
||||
# CT_ARCH_alpha is not set
|
||||
# CT_ARCH_arm is not set
|
||||
# CT_ARCH_avr is not set
|
||||
# CT_ARCH_m68k is not set
|
||||
# CT_ARCH_mips is not set
|
||||
# CT_ARCH_nios2 is not set
|
||||
CT_ARCH_powerpc=y
|
||||
# CT_ARCH_s390 is not set
|
||||
# CT_ARCH_sh is not set
|
||||
# CT_ARCH_sparc is not set
|
||||
# CT_ARCH_x86 is not set
|
||||
# CT_ARCH_xtensa is not set
|
||||
CT_ARCH_alpha_AVAILABLE=y
|
||||
CT_ARCH_arm_AVAILABLE=y
|
||||
CT_ARCH_avr_AVAILABLE=y
|
||||
CT_ARCH_m68k_AVAILABLE=y
|
||||
CT_ARCH_microblaze_AVAILABLE=y
|
||||
CT_ARCH_mips_AVAILABLE=y
|
||||
CT_ARCH_nios2_AVAILABLE=y
|
||||
CT_ARCH_powerpc_AVAILABLE=y
|
||||
CT_ARCH_s390_AVAILABLE=y
|
||||
CT_ARCH_sh_AVAILABLE=y
|
||||
CT_ARCH_sparc_AVAILABLE=y
|
||||
CT_ARCH_x86_AVAILABLE=y
|
||||
CT_ARCH_xtensa_AVAILABLE=y
|
||||
CT_ARCH_SUFFIX=""
|
||||
|
||||
#
|
||||
# Generic target options
|
||||
#
|
||||
# CT_MULTILIB is not set
|
||||
CT_ARCH_USE_MMU=y
|
||||
CT_ARCH_ENDIAN="big"
|
||||
|
||||
#
|
||||
# Target optimisations
|
||||
#
|
||||
CT_ARCH_FLOAT_AUTO=y
|
||||
CT_ARCH_FLOAT="auto"
|
||||
|
||||
#
|
||||
# powerpc other options
|
||||
#
|
||||
CT_ARCH_powerpc_ABI=""
|
||||
CT_ARCH_powerpc_ABI_DEFAULT=y
|
||||
# CT_ARCH_powerpc_ABI_SPE is not set
|
||||
|
||||
#
|
||||
# Toolchain options
|
||||
#
|
||||
|
||||
#
|
||||
# General toolchain options
|
||||
#
|
||||
CT_FORCE_SYSROOT=y
|
||||
CT_USE_SYSROOT=y
|
||||
CT_SYSROOT_NAME="sysroot"
|
||||
CT_SYSROOT_DIR_PREFIX=""
|
||||
CT_WANTS_STATIC_LINK=y
|
||||
# CT_STATIC_TOOLCHAIN is not set
|
||||
CT_TOOLCHAIN_PKGVERSION=""
|
||||
CT_TOOLCHAIN_BUGURL=""
|
||||
|
||||
#
|
||||
# Tuple completion and aliasing
|
||||
#
|
||||
CT_TARGET_VENDOR="unknown"
|
||||
CT_TARGET_ALIAS_SED_EXPR=""
|
||||
CT_TARGET_ALIAS=""
|
||||
|
||||
#
|
||||
# Toolchain type
|
||||
#
|
||||
CT_CROSS=y
|
||||
# CT_CANADIAN is not set
|
||||
CT_TOOLCHAIN_TYPE="cross"
|
||||
|
||||
#
|
||||
# Build system
|
||||
#
|
||||
CT_BUILD=""
|
||||
CT_BUILD_PREFIX=""
|
||||
CT_BUILD_SUFFIX=""
|
||||
|
||||
#
|
||||
# Misc options
|
||||
#
|
||||
# CT_TOOLCHAIN_ENABLE_NLS is not set
|
||||
|
||||
#
|
||||
# Operating System
|
||||
#
|
||||
CT_KERNEL_SUPPORTS_SHARED_LIBS=y
|
||||
CT_KERNEL="linux"
|
||||
CT_KERNEL_VERSION="2.6.32.68"
|
||||
# CT_KERNEL_bare_metal is not set
|
||||
CT_KERNEL_linux=y
|
||||
CT_KERNEL_bare_metal_AVAILABLE=y
|
||||
CT_KERNEL_linux_AVAILABLE=y
|
||||
# CT_KERNEL_V_4_3 is not set
|
||||
# CT_KERNEL_V_4_2 is not set
|
||||
# CT_KERNEL_V_4_1 is not set
|
||||
# CT_KERNEL_V_3_18 is not set
|
||||
# CT_KERNEL_V_3_14 is not set
|
||||
# CT_KERNEL_V_3_12 is not set
|
||||
# CT_KERNEL_V_3_10 is not set
|
||||
# CT_KERNEL_V_3_4 is not set
|
||||
# CT_KERNEL_V_3_2 is not set
|
||||
CT_KERNEL_V_2_6_32=y
|
||||
# CT_KERNEL_LINUX_CUSTOM is not set
|
||||
CT_KERNEL_windows_AVAILABLE=y
|
||||
|
||||
#
|
||||
# Common kernel options
|
||||
#
|
||||
CT_SHARED_LIBS=y
|
||||
|
||||
#
|
||||
# linux other options
|
||||
#
|
||||
CT_KERNEL_LINUX_VERBOSITY_0=y
|
||||
# CT_KERNEL_LINUX_VERBOSITY_1 is not set
|
||||
# CT_KERNEL_LINUX_VERBOSITY_2 is not set
|
||||
CT_KERNEL_LINUX_VERBOSE_LEVEL=0
|
||||
CT_KERNEL_LINUX_INSTALL_CHECK=y
|
||||
|
||||
#
|
||||
# Binary utilities
|
||||
#
|
||||
CT_ARCH_BINFMT_ELF=y
|
||||
CT_BINUTILS="binutils"
|
||||
CT_BINUTILS_binutils=y
|
||||
|
||||
#
|
||||
# GNU binutils
|
||||
#
|
||||
# CT_CC_BINUTILS_SHOW_LINARO is not set
|
||||
CT_BINUTILS_V_2_25_1=y
|
||||
# CT_BINUTILS_V_2_25 is not set
|
||||
# CT_BINUTILS_V_2_24 is not set
|
||||
# CT_BINUTILS_V_2_23_2 is not set
|
||||
# CT_BINUTILS_V_2_23_1 is not set
|
||||
# CT_BINUTILS_V_2_22 is not set
|
||||
# CT_BINUTILS_V_2_21_53 is not set
|
||||
# CT_BINUTILS_V_2_21_1a is not set
|
||||
# CT_BINUTILS_V_2_20_1a is not set
|
||||
# CT_BINUTILS_V_2_19_1a is not set
|
||||
# CT_BINUTILS_V_2_18a is not set
|
||||
CT_BINUTILS_VERSION="2.25.1"
|
||||
CT_BINUTILS_2_25_1_or_later=y
|
||||
CT_BINUTILS_2_25_or_later=y
|
||||
CT_BINUTILS_2_24_or_later=y
|
||||
CT_BINUTILS_2_23_or_later=y
|
||||
CT_BINUTILS_2_22_or_later=y
|
||||
CT_BINUTILS_2_21_or_later=y
|
||||
CT_BINUTILS_2_20_or_later=y
|
||||
CT_BINUTILS_2_19_or_later=y
|
||||
CT_BINUTILS_2_18_or_later=y
|
||||
CT_BINUTILS_HAS_HASH_STYLE=y
|
||||
CT_BINUTILS_HAS_GOLD=y
|
||||
CT_BINUTILS_HAS_PLUGINS=y
|
||||
CT_BINUTILS_HAS_PKGVERSION_BUGURL=y
|
||||
CT_BINUTILS_FORCE_LD_BFD=y
|
||||
CT_BINUTILS_LINKER_LD=y
|
||||
CT_BINUTILS_LINKERS_LIST="ld"
|
||||
CT_BINUTILS_LINKER_DEFAULT="bfd"
|
||||
# CT_BINUTILS_PLUGINS is not set
|
||||
CT_BINUTILS_EXTRA_CONFIG_ARRAY=""
|
||||
# CT_BINUTILS_FOR_TARGET is not set
|
||||
|
||||
#
|
||||
# binutils other options
|
||||
#
|
||||
|
||||
#
|
||||
# C-library
|
||||
#
|
||||
CT_LIBC="glibc"
|
||||
CT_LIBC_VERSION="2.12.2"
|
||||
CT_LIBC_glibc=y
|
||||
# CT_LIBC_musl is not set
|
||||
# CT_LIBC_uClibc is not set
|
||||
CT_LIBC_avr_libc_AVAILABLE=y
|
||||
CT_LIBC_glibc_AVAILABLE=y
|
||||
CT_THREADS="nptl"
|
||||
# CT_CC_GLIBC_SHOW_LINARO is not set
|
||||
# CT_LIBC_GLIBC_V_2_22 is not set
|
||||
# CT_LIBC_GLIBC_V_2_21 is not set
|
||||
# CT_LIBC_GLIBC_V_2_20 is not set
|
||||
# CT_LIBC_GLIBC_V_2_19 is not set
|
||||
# CT_LIBC_GLIBC_V_2_18 is not set
|
||||
# CT_LIBC_GLIBC_V_2_17 is not set
|
||||
# CT_LIBC_GLIBC_V_2_16_0 is not set
|
||||
# CT_LIBC_GLIBC_V_2_15 is not set
|
||||
# CT_LIBC_GLIBC_V_2_14_1 is not set
|
||||
# CT_LIBC_GLIBC_V_2_14 is not set
|
||||
# CT_LIBC_GLIBC_V_2_13 is not set
|
||||
CT_LIBC_GLIBC_V_2_12_2=y
|
||||
# CT_LIBC_GLIBC_V_2_12_1 is not set
|
||||
# CT_LIBC_GLIBC_V_2_11_1 is not set
|
||||
# CT_LIBC_GLIBC_V_2_11 is not set
|
||||
# CT_LIBC_GLIBC_V_2_10_1 is not set
|
||||
# CT_LIBC_GLIBC_V_2_9 is not set
|
||||
# CT_LIBC_GLIBC_V_2_8 is not set
|
||||
CT_LIBC_mingw_AVAILABLE=y
|
||||
CT_LIBC_musl_AVAILABLE=y
|
||||
CT_LIBC_newlib_AVAILABLE=y
|
||||
CT_LIBC_none_AVAILABLE=y
|
||||
CT_LIBC_uClibc_AVAILABLE=y
|
||||
CT_LIBC_SUPPORT_THREADS_ANY=y
|
||||
CT_LIBC_SUPPORT_THREADS_NATIVE=y
|
||||
|
||||
#
|
||||
# Common C library options
|
||||
#
|
||||
CT_THREADS_NATIVE=y
|
||||
CT_LIBC_XLDD=y
|
||||
|
||||
#
|
||||
# glibc other options
|
||||
#
|
||||
CT_LIBC_GLIBC_PORTS_EXTERNAL=y
|
||||
CT_LIBC_glibc_familly=y
|
||||
CT_LIBC_GLIBC_EXTRA_CONFIG_ARRAY=""
|
||||
CT_LIBC_GLIBC_CONFIGPARMS=""
|
||||
CT_LIBC_GLIBC_EXTRA_CFLAGS=""
|
||||
CT_LIBC_EXTRA_CC_ARGS=""
|
||||
# CT_LIBC_DISABLE_VERSIONING is not set
|
||||
CT_LIBC_OLDEST_ABI=""
|
||||
CT_LIBC_GLIBC_FORCE_UNWIND=y
|
||||
# CT_LIBC_GLIBC_USE_PORTS is not set
|
||||
CT_LIBC_ADDONS_LIST=""
|
||||
# CT_LIBC_LOCALES is not set
|
||||
# CT_LIBC_GLIBC_KERNEL_VERSION_NONE is not set
|
||||
CT_LIBC_GLIBC_KERNEL_VERSION_AS_HEADERS=y
|
||||
# CT_LIBC_GLIBC_KERNEL_VERSION_CHOSEN is not set
|
||||
CT_LIBC_GLIBC_MIN_KERNEL="2.6.32.68"
|
||||
|
||||
#
|
||||
# C compiler
|
||||
#
|
||||
CT_CC="gcc"
|
||||
CT_CC_CORE_PASSES_NEEDED=y
|
||||
CT_CC_CORE_PASS_1_NEEDED=y
|
||||
CT_CC_CORE_PASS_2_NEEDED=y
|
||||
CT_CC_gcc=y
|
||||
# CT_CC_GCC_SHOW_LINARO is not set
|
||||
# CT_CC_GCC_V_5_2_0 is not set
|
||||
CT_CC_GCC_V_4_9_3=y
|
||||
# CT_CC_GCC_V_4_8_5 is not set
|
||||
# CT_CC_GCC_V_4_7_4 is not set
|
||||
# CT_CC_GCC_V_4_6_4 is not set
|
||||
# CT_CC_GCC_V_4_5_4 is not set
|
||||
# CT_CC_GCC_V_4_4_7 is not set
|
||||
# CT_CC_GCC_V_4_3_6 is not set
|
||||
# CT_CC_GCC_V_4_2_4 is not set
|
||||
CT_CC_GCC_4_2_or_later=y
|
||||
CT_CC_GCC_4_3_or_later=y
|
||||
CT_CC_GCC_4_4_or_later=y
|
||||
CT_CC_GCC_4_5_or_later=y
|
||||
CT_CC_GCC_4_6_or_later=y
|
||||
CT_CC_GCC_4_7_or_later=y
|
||||
CT_CC_GCC_4_8_or_later=y
|
||||
CT_CC_GCC_4_9=y
|
||||
CT_CC_GCC_4_9_or_later=y
|
||||
CT_CC_GCC_HAS_GRAPHITE=y
|
||||
CT_CC_GCC_USE_GRAPHITE=y
|
||||
CT_CC_GCC_HAS_LTO=y
|
||||
CT_CC_GCC_USE_LTO=y
|
||||
CT_CC_GCC_HAS_PKGVERSION_BUGURL=y
|
||||
CT_CC_GCC_HAS_BUILD_ID=y
|
||||
CT_CC_GCC_HAS_LNK_HASH_STYLE=y
|
||||
CT_CC_GCC_USE_GMP_MPFR=y
|
||||
CT_CC_GCC_USE_MPC=y
|
||||
CT_CC_GCC_HAS_LIBQUADMATH=y
|
||||
CT_CC_GCC_HAS_LIBSANITIZER=y
|
||||
CT_CC_GCC_VERSION="4.9.3"
|
||||
# CT_CC_LANG_FORTRAN is not set
|
||||
CT_CC_GCC_ENABLE_CXX_FLAGS=""
|
||||
CT_CC_GCC_CORE_EXTRA_CONFIG_ARRAY=""
|
||||
CT_CC_GCC_EXTRA_CONFIG_ARRAY=""
|
||||
CT_CC_GCC_EXTRA_ENV_ARRAY=""
|
||||
CT_CC_GCC_STATIC_LIBSTDCXX=y
|
||||
# CT_CC_GCC_SYSTEM_ZLIB is not set
|
||||
|
||||
#
|
||||
# Optimisation features
|
||||
#
|
||||
|
||||
#
|
||||
# Settings for libraries running on target
|
||||
#
|
||||
CT_CC_GCC_ENABLE_TARGET_OPTSPACE=y
|
||||
# CT_CC_GCC_LIBMUDFLAP is not set
|
||||
# CT_CC_GCC_LIBGOMP is not set
|
||||
# CT_CC_GCC_LIBSSP is not set
|
||||
# CT_CC_GCC_LIBQUADMATH is not set
|
||||
# CT_CC_GCC_LIBSANITIZER is not set
|
||||
|
||||
#
|
||||
# Misc. obscure options.
|
||||
#
|
||||
CT_CC_CXA_ATEXIT=y
|
||||
# CT_CC_GCC_DISABLE_PCH is not set
|
||||
CT_CC_GCC_SJLJ_EXCEPTIONS=m
|
||||
CT_CC_GCC_LDBL_128=m
|
||||
# CT_CC_GCC_BUILD_ID is not set
|
||||
CT_CC_GCC_LNK_HASH_STYLE_DEFAULT=y
|
||||
# CT_CC_GCC_LNK_HASH_STYLE_SYSV is not set
|
||||
# CT_CC_GCC_LNK_HASH_STYLE_GNU is not set
|
||||
# CT_CC_GCC_LNK_HASH_STYLE_BOTH is not set
|
||||
CT_CC_GCC_LNK_HASH_STYLE=""
|
||||
CT_CC_GCC_DEC_FLOAT_AUTO=y
|
||||
# CT_CC_GCC_DEC_FLOAT_BID is not set
|
||||
# CT_CC_GCC_DEC_FLOAT_DPD is not set
|
||||
# CT_CC_GCC_DEC_FLOATS_NO is not set
|
||||
CT_CC_SUPPORT_CXX=y
|
||||
CT_CC_SUPPORT_FORTRAN=y
|
||||
CT_CC_SUPPORT_JAVA=y
|
||||
CT_CC_SUPPORT_ADA=y
|
||||
CT_CC_SUPPORT_OBJC=y
|
||||
CT_CC_SUPPORT_OBJCXX=y
|
||||
CT_CC_SUPPORT_GOLANG=y
|
||||
|
||||
#
|
||||
# Additional supported languages:
|
||||
#
|
||||
CT_CC_LANG_CXX=y
|
||||
# CT_CC_LANG_JAVA is not set
|
||||
|
||||
#
|
||||
# Debug facilities
|
||||
#
|
||||
# CT_DEBUG_dmalloc is not set
|
||||
# CT_DEBUG_duma is not set
|
||||
# CT_DEBUG_gdb is not set
|
||||
# CT_DEBUG_ltrace is not set
|
||||
# CT_DEBUG_strace is not set
|
||||
|
||||
#
|
||||
# Companion libraries
|
||||
#
|
||||
CT_COMPLIBS_NEEDED=y
|
||||
CT_LIBICONV_NEEDED=y
|
||||
CT_GETTEXT_NEEDED=y
|
||||
CT_GMP_NEEDED=y
|
||||
CT_MPFR_NEEDED=y
|
||||
CT_ISL_NEEDED=y
|
||||
CT_CLOOG_NEEDED=y
|
||||
CT_MPC_NEEDED=y
|
||||
CT_COMPLIBS=y
|
||||
CT_LIBICONV=y
|
||||
CT_GETTEXT=y
|
||||
CT_GMP=y
|
||||
CT_MPFR=y
|
||||
CT_ISL=y
|
||||
CT_CLOOG=y
|
||||
CT_MPC=y
|
||||
CT_LIBICONV_V_1_14=y
|
||||
CT_LIBICONV_VERSION="1.14"
|
||||
CT_GETTEXT_V_0_19_6=y
|
||||
CT_GETTEXT_VERSION="0.19.6"
|
||||
CT_GMP_V_6_0_0=y
|
||||
# CT_GMP_V_5_1_3 is not set
|
||||
# CT_GMP_V_5_1_1 is not set
|
||||
# CT_GMP_V_5_0_2 is not set
|
||||
# CT_GMP_V_5_0_1 is not set
|
||||
# CT_GMP_V_4_3_2 is not set
|
||||
# CT_GMP_V_4_3_1 is not set
|
||||
# CT_GMP_V_4_3_0 is not set
|
||||
CT_GMP_5_0_2_or_later=y
|
||||
CT_GMP_VERSION="6.0.0a"
|
||||
CT_MPFR_V_3_1_3=y
|
||||
# CT_MPFR_V_3_1_2 is not set
|
||||
# CT_MPFR_V_3_1_0 is not set
|
||||
# CT_MPFR_V_3_0_1 is not set
|
||||
# CT_MPFR_V_3_0_0 is not set
|
||||
# CT_MPFR_V_2_4_2 is not set
|
||||
# CT_MPFR_V_2_4_1 is not set
|
||||
# CT_MPFR_V_2_4_0 is not set
|
||||
CT_MPFR_VERSION="3.1.3"
|
||||
CT_ISL_V_0_14=y
|
||||
CT_ISL_V_0_14_or_later=y
|
||||
CT_ISL_V_0_12_or_later=y
|
||||
CT_ISL_VERSION="0.14"
|
||||
CT_CLOOG_V_0_18_4=y
|
||||
# CT_CLOOG_V_0_18_1 is not set
|
||||
# CT_CLOOG_V_0_18_0 is not set
|
||||
CT_CLOOG_VERSION="0.18.4"
|
||||
CT_CLOOG_0_18_4_or_later=y
|
||||
CT_CLOOG_0_18_or_later=y
|
||||
CT_MPC_V_1_0_3=y
|
||||
# CT_MPC_V_1_0_2 is not set
|
||||
# CT_MPC_V_1_0_1 is not set
|
||||
# CT_MPC_V_1_0 is not set
|
||||
# CT_MPC_V_0_9 is not set
|
||||
# CT_MPC_V_0_8_2 is not set
|
||||
# CT_MPC_V_0_8_1 is not set
|
||||
# CT_MPC_V_0_7 is not set
|
||||
CT_MPC_VERSION="1.0.3"
|
||||
|
||||
#
|
||||
# Companion libraries common options
|
||||
#
|
||||
# CT_COMPLIBS_CHECK is not set
|
||||
|
||||
#
|
||||
# Companion tools
|
||||
#
|
||||
|
||||
#
|
||||
# READ HELP before you say 'Y' below !!!
|
||||
#
|
||||
# CT_COMP_TOOLS is not set
|
||||
|
|
@ -1,37 +1,81 @@
|
|||
FROM ubuntu:16.04
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
g++ \
|
||||
make \
|
||||
file \
|
||||
curl \
|
||||
ca-certificates \
|
||||
python2.7 \
|
||||
git \
|
||||
cmake \
|
||||
sudo \
|
||||
automake \
|
||||
bison \
|
||||
bzip2 \
|
||||
xz-utils \
|
||||
wget \
|
||||
ca-certificates \
|
||||
cmake \
|
||||
curl \
|
||||
file \
|
||||
flex \
|
||||
g++ \
|
||||
gawk \
|
||||
gdb \
|
||||
git \
|
||||
gperf \
|
||||
help2man \
|
||||
libncurses-dev \
|
||||
libtool-bin \
|
||||
make \
|
||||
patch \
|
||||
g++-s390x-linux-gnu
|
||||
python2.7 \
|
||||
sudo \
|
||||
texinfo \
|
||||
wget \
|
||||
xz-utils
|
||||
|
||||
COPY build-toolchain.sh /tmp/
|
||||
RUN sh /tmp/build-toolchain.sh
|
||||
ENV SCCACHE_DIGEST=7237e38e029342fa27b7ac25412cb9d52554008b12389727320bd533fd7f05b6a96d55485f305caf95e5c8f5f97c3313e10012ccad3e752aba2518f3522ba783
|
||||
RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | \
|
||||
tar xJf - -C /usr/local/bin --strip-components=1
|
||||
|
||||
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
|
||||
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
|
||||
|
||||
ENV SCCACHE_DIGEST=7237e38e029342fa27b7ac25412cb9d52554008b12389727320bd533fd7f05b6a96d55485f305caf95e5c8f5f97c3313e10012ccad3e752aba2518f3522ba783
|
||||
RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | \
|
||||
tar xJf - -C /usr/local/bin --strip-components=1
|
||||
# Ubuntu 16.04 (this contianer) ships with make 4, but something in the
|
||||
# toolchains we build below chokes on that, so go back to make 3
|
||||
RUN curl https://ftp.gnu.org/gnu/make/make-3.81.tar.gz | tar xzf - && \
|
||||
cd make-3.81 && \
|
||||
./configure --prefix=/usr && \
|
||||
make && \
|
||||
make install && \
|
||||
cd .. && \
|
||||
rm -rf make-3.81
|
||||
|
||||
RUN curl http://crosstool-ng.org/download/crosstool-ng/crosstool-ng-1.22.0.tar.bz2 | \
|
||||
tar xjf - && \
|
||||
cd crosstool-ng && \
|
||||
./configure --prefix=/usr/local && \
|
||||
make -j$(nproc) && \
|
||||
make install && \
|
||||
cd .. && \
|
||||
rm -rf crosstool-ng
|
||||
|
||||
RUN groupadd -r rustbuild && useradd -m -r -g rustbuild rustbuild
|
||||
RUN mkdir /x-tools && chown rustbuild:rustbuild /x-tools
|
||||
USER rustbuild
|
||||
WORKDIR /tmp
|
||||
|
||||
COPY patches/ /tmp/patches/
|
||||
COPY s390x-linux-gnu.config build-s390x-toolchain.sh /tmp/
|
||||
RUN ./build-s390x-toolchain.sh
|
||||
|
||||
USER root
|
||||
|
||||
COPY build-netbsd-toolchain.sh /tmp/
|
||||
RUN ./build-netbsd-toolchain.sh
|
||||
|
||||
ENV PATH=$PATH:/x-tools/s390x-ibm-linux-gnu/bin
|
||||
|
||||
ENV \
|
||||
AR_x86_64_unknown_netbsd=x86_64-unknown-netbsd-ar \
|
||||
CC_x86_64_unknown_netbsd=x86_64-unknown-netbsd-gcc \
|
||||
CXX_x86_64_unknown_netbsd=x86_64-unknown-netbsd-g++
|
||||
CXX_x86_64_unknown_netbsd=x86_64-unknown-netbsd-g++ \
|
||||
CC_s390x_unknown_linux_gnu=s390x-ibm-linux-gnu-gcc \
|
||||
AR_s390x_unknown_linux_gnu=s390x-ibm-linux-gnu-ar \
|
||||
CXX_s390x_unknown_linux_gnu=s390x-ibm-linux-gnu-g++
|
||||
|
||||
ENV HOSTS=x86_64-unknown-netbsd
|
||||
ENV HOSTS=$HOSTS,s390x-unknown-linux-gnu
|
||||
|
|
|
|||
0
src/ci/docker/dist-s390x-linux-netbsd/build-toolchain.sh → src/ci/docker/dist-s390x-linux-netbsd/build-netbsd-toolchain.sh
Normal file → Executable file
0
src/ci/docker/dist-s390x-linux-netbsd/build-toolchain.sh → src/ci/docker/dist-s390x-linux-netbsd/build-netbsd-toolchain.sh
Normal file → Executable file
36
src/ci/docker/dist-s390x-linux-netbsd/build-s390x-toolchain.sh
Executable file
36
src/ci/docker/dist-s390x-linux-netbsd/build-s390x-toolchain.sh
Executable file
|
|
@ -0,0 +1,36 @@
|
|||
#!/bin/bash
|
||||
# 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
|
||||
|
||||
hide_output() {
|
||||
set +x
|
||||
on_err="
|
||||
echo ERROR: An error was encountered with the build.
|
||||
cat /tmp/build.log
|
||||
exit 1
|
||||
"
|
||||
trap "$on_err" ERR
|
||||
bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
|
||||
PING_LOOP_PID=$!
|
||||
$@ &> /tmp/build.log
|
||||
rm /tmp/build.log
|
||||
trap - ERR
|
||||
kill $PING_LOOP_PID
|
||||
set -x
|
||||
}
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
cp ../s390x-linux-gnu.config .config
|
||||
hide_output ct-ng build
|
||||
cd ..
|
||||
rm -rf build
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
From 2739047682590b1df473401b4febf424f857fccf Mon Sep 17 00:00:00 2001
|
||||
From: Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
|
||||
Date: Sun, 17 Apr 2011 20:43:59 -0400
|
||||
Subject: [PATCH] Use .machine to prevent AS from complaining about z9-109
|
||||
instructions in iconv modules
|
||||
|
||||
---
|
||||
sysdeps/s390/s390-64/utf16-utf32-z9.c | 5 ++++-
|
||||
sysdeps/s390/s390-64/utf8-utf16-z9.c | 5 ++++-
|
||||
sysdeps/s390/s390-64/utf8-utf32-z9.c | 5 ++++-
|
||||
3 files changed, 12 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/sysdeps/s390/s390-64/utf16-utf32-z9.c b/sysdeps/s390/s390-64/utf16-utf32-z9.c
|
||||
index 14daf2118fe5..5bcaaaedec9c 100644
|
||||
--- a/sysdeps/s390/s390-64/utf16-utf32-z9.c
|
||||
+++ b/sysdeps/s390/s390-64/utf16-utf32-z9.c
|
||||
@@ -169,7 +169,10 @@ gconv_end (struct __gconv_step *data)
|
||||
register unsigned long long outlen asm("11") = outend - outptr; \
|
||||
uint64_t cc = 0; \
|
||||
\
|
||||
- asm volatile ("0: " INSTRUCTION " \n\t" \
|
||||
+ asm volatile (".machine push \n\t" \
|
||||
+ ".machine \"z9-109\" \n\t" \
|
||||
+ "0: " INSTRUCTION " \n\t" \
|
||||
+ ".machine pop \n\t" \
|
||||
" jo 0b \n\t" \
|
||||
" ipm %2 \n" \
|
||||
: "+a" (pOutput), "+a" (pInput), "+d" (cc), \
|
||||
diff --git a/sysdeps/s390/s390-64/utf8-utf16-z9.c b/sysdeps/s390/s390-64/utf8-utf16-z9.c
|
||||
index 5f73f3c59e21..812a42fae44c 100644
|
||||
--- a/sysdeps/s390/s390-64/utf8-utf16-z9.c
|
||||
+++ b/sysdeps/s390/s390-64/utf8-utf16-z9.c
|
||||
@@ -151,7 +151,10 @@ gconv_end (struct __gconv_step *data)
|
||||
register unsigned long long outlen asm("11") = outend - outptr; \
|
||||
uint64_t cc = 0; \
|
||||
\
|
||||
- asm volatile ("0: " INSTRUCTION " \n\t" \
|
||||
+ asm volatile (".machine push \n\t" \
|
||||
+ ".machine \"z9-109\" \n\t" \
|
||||
+ "0: " INSTRUCTION " \n\t" \
|
||||
+ ".machine pop \n\t" \
|
||||
" jo 0b \n\t" \
|
||||
" ipm %2 \n" \
|
||||
: "+a" (pOutput), "+a" (pInput), "+d" (cc), \
|
||||
diff --git a/sysdeps/s390/s390-64/utf8-utf32-z9.c b/sysdeps/s390/s390-64/utf8-utf32-z9.c
|
||||
index 17ef8bc890c3..0ffd848c8124 100644
|
||||
--- a/sysdeps/s390/s390-64/utf8-utf32-z9.c
|
||||
+++ b/sysdeps/s390/s390-64/utf8-utf32-z9.c
|
||||
@@ -155,7 +155,10 @@ gconv_end (struct __gconv_step *data)
|
||||
register unsigned long long outlen asm("11") = outend - outptr; \
|
||||
uint64_t cc = 0; \
|
||||
\
|
||||
- asm volatile ("0: " INSTRUCTION " \n\t" \
|
||||
+ asm volatile (".machine push \n\t" \
|
||||
+ ".machine \"z9-109\" \n\t" \
|
||||
+ "0: " INSTRUCTION " \n\t" \
|
||||
+ ".machine pop \n\t" \
|
||||
" jo 0b \n\t" \
|
||||
" ipm %2 \n" \
|
||||
: "+a" (pOutput), "+a" (pInput), "+d" (cc), \
|
||||
--
|
||||
2.9.3
|
||||
|
||||
508
src/ci/docker/dist-s390x-linux-netbsd/s390x-linux-gnu.config
Normal file
508
src/ci/docker/dist-s390x-linux-netbsd/s390x-linux-gnu.config
Normal file
|
|
@ -0,0 +1,508 @@
|
|||
#
|
||||
# Automatically generated file; DO NOT EDIT.
|
||||
# Crosstool-NG Configuration
|
||||
#
|
||||
CT_CONFIGURE_has_make381=y
|
||||
CT_CONFIGURE_has_xz=y
|
||||
CT_MODULES=y
|
||||
|
||||
#
|
||||
# Paths and misc options
|
||||
#
|
||||
|
||||
#
|
||||
# crosstool-NG behavior
|
||||
#
|
||||
# CT_OBSOLETE is not set
|
||||
# CT_EXPERIMENTAL is not set
|
||||
# CT_DEBUG_CT is not set
|
||||
|
||||
#
|
||||
# Paths
|
||||
#
|
||||
CT_LOCAL_TARBALLS_DIR=""
|
||||
CT_WORK_DIR="${CT_TOP_DIR}/.build"
|
||||
CT_PREFIX_DIR="/x-tools/${CT_TARGET}"
|
||||
CT_INSTALL_DIR="${CT_PREFIX_DIR}"
|
||||
CT_RM_RF_PREFIX_DIR=y
|
||||
CT_REMOVE_DOCS=y
|
||||
CT_INSTALL_DIR_RO=y
|
||||
CT_STRIP_HOST_TOOLCHAIN_EXECUTABLES=y
|
||||
# CT_STRIP_TARGET_TOOLCHAIN_EXECUTABLES is not set
|
||||
|
||||
#
|
||||
# Downloading
|
||||
#
|
||||
# CT_FORBID_DOWNLOAD is not set
|
||||
# CT_FORCE_DOWNLOAD is not set
|
||||
CT_CONNECT_TIMEOUT=10
|
||||
# CT_ONLY_DOWNLOAD is not set
|
||||
# CT_USE_MIRROR is not set
|
||||
|
||||
#
|
||||
# Extracting
|
||||
#
|
||||
# CT_FORCE_EXTRACT is not set
|
||||
CT_OVERIDE_CONFIG_GUESS_SUB=y
|
||||
# CT_ONLY_EXTRACT is not set
|
||||
# CT_PATCH_BUNDLED is not set
|
||||
# CT_PATCH_LOCAL is not set
|
||||
CT_PATCH_BUNDLED_LOCAL=y
|
||||
# CT_PATCH_LOCAL_BUNDLED is not set
|
||||
# CT_PATCH_BUNDLED_FALLBACK_LOCAL is not set
|
||||
# CT_PATCH_LOCAL_FALLBACK_BUNDLED is not set
|
||||
# CT_PATCH_NONE is not set
|
||||
CT_PATCH_ORDER="bundled,local"
|
||||
CT_PATCH_USE_LOCAL=y
|
||||
CT_LOCAL_PATCH_DIR="/tmp/patches"
|
||||
|
||||
#
|
||||
# Build behavior
|
||||
#
|
||||
CT_PARALLEL_JOBS=0
|
||||
CT_LOAD=""
|
||||
CT_USE_PIPES=y
|
||||
CT_EXTRA_CFLAGS_FOR_BUILD=""
|
||||
CT_EXTRA_LDFLAGS_FOR_BUILD=""
|
||||
CT_EXTRA_CFLAGS_FOR_HOST=""
|
||||
CT_EXTRA_LDFLAGS_FOR_HOST=""
|
||||
# CT_CONFIG_SHELL_SH is not set
|
||||
# CT_CONFIG_SHELL_ASH is not set
|
||||
CT_CONFIG_SHELL_BASH=y
|
||||
# CT_CONFIG_SHELL_CUSTOM is not set
|
||||
CT_CONFIG_SHELL="${bash}"
|
||||
|
||||
#
|
||||
# Logging
|
||||
#
|
||||
# CT_LOG_ERROR is not set
|
||||
# CT_LOG_WARN is not set
|
||||
CT_LOG_INFO=y
|
||||
# CT_LOG_EXTRA is not set
|
||||
# CT_LOG_ALL is not set
|
||||
# CT_LOG_DEBUG is not set
|
||||
CT_LOG_LEVEL_MAX="INFO"
|
||||
# CT_LOG_SEE_TOOLS_WARN is not set
|
||||
CT_LOG_PROGRESS_BAR=y
|
||||
CT_LOG_TO_FILE=y
|
||||
CT_LOG_FILE_COMPRESS=y
|
||||
|
||||
#
|
||||
# Target options
|
||||
#
|
||||
CT_ARCH="s390"
|
||||
CT_ARCH_SUPPORTS_32=y
|
||||
CT_ARCH_SUPPORTS_64=y
|
||||
CT_ARCH_SUPPORTS_WITH_FPU=y
|
||||
CT_ARCH_DEFAULT_32=y
|
||||
CT_ARCH_FPU=""
|
||||
# CT_ARCH_32 is not set
|
||||
CT_ARCH_64=y
|
||||
CT_ARCH_BITNESS=64
|
||||
CT_TARGET_CFLAGS=""
|
||||
CT_TARGET_LDFLAGS=""
|
||||
# CT_ARCH_alpha is not set
|
||||
# CT_ARCH_arm is not set
|
||||
# CT_ARCH_avr is not set
|
||||
# CT_ARCH_m68k is not set
|
||||
# CT_ARCH_mips is not set
|
||||
# CT_ARCH_nios2 is not set
|
||||
# CT_ARCH_powerpc is not set
|
||||
CT_ARCH_s390=y
|
||||
# CT_ARCH_sh is not set
|
||||
# CT_ARCH_sparc is not set
|
||||
# CT_ARCH_x86 is not set
|
||||
# CT_ARCH_xtensa is not set
|
||||
CT_ARCH_alpha_AVAILABLE=y
|
||||
CT_ARCH_arm_AVAILABLE=y
|
||||
CT_ARCH_avr_AVAILABLE=y
|
||||
CT_ARCH_m68k_AVAILABLE=y
|
||||
CT_ARCH_microblaze_AVAILABLE=y
|
||||
CT_ARCH_mips_AVAILABLE=y
|
||||
CT_ARCH_nios2_AVAILABLE=y
|
||||
CT_ARCH_powerpc_AVAILABLE=y
|
||||
CT_ARCH_s390_AVAILABLE=y
|
||||
CT_ARCH_sh_AVAILABLE=y
|
||||
CT_ARCH_sparc_AVAILABLE=y
|
||||
CT_ARCH_x86_AVAILABLE=y
|
||||
CT_ARCH_xtensa_AVAILABLE=y
|
||||
CT_ARCH_SUFFIX=""
|
||||
|
||||
#
|
||||
# Generic target options
|
||||
#
|
||||
# CT_MULTILIB is not set
|
||||
CT_ARCH_USE_MMU=y
|
||||
|
||||
#
|
||||
# Target optimisations
|
||||
#
|
||||
CT_ARCH_FLOAT=""
|
||||
|
||||
#
|
||||
# Toolchain options
|
||||
#
|
||||
|
||||
#
|
||||
# General toolchain options
|
||||
#
|
||||
CT_FORCE_SYSROOT=y
|
||||
CT_USE_SYSROOT=y
|
||||
CT_SYSROOT_NAME="sysroot"
|
||||
CT_SYSROOT_DIR_PREFIX=""
|
||||
CT_WANTS_STATIC_LINK=y
|
||||
# CT_STATIC_TOOLCHAIN is not set
|
||||
CT_TOOLCHAIN_PKGVERSION=""
|
||||
CT_TOOLCHAIN_BUGURL=""
|
||||
|
||||
#
|
||||
# Tuple completion and aliasing
|
||||
#
|
||||
CT_TARGET_VENDOR="unknown"
|
||||
CT_TARGET_ALIAS_SED_EXPR=""
|
||||
CT_TARGET_ALIAS=""
|
||||
|
||||
#
|
||||
# Toolchain type
|
||||
#
|
||||
CT_CROSS=y
|
||||
# CT_CANADIAN is not set
|
||||
CT_TOOLCHAIN_TYPE="cross"
|
||||
|
||||
#
|
||||
# Build system
|
||||
#
|
||||
CT_BUILD=""
|
||||
CT_BUILD_PREFIX=""
|
||||
CT_BUILD_SUFFIX=""
|
||||
|
||||
#
|
||||
# Misc options
|
||||
#
|
||||
# CT_TOOLCHAIN_ENABLE_NLS is not set
|
||||
|
||||
#
|
||||
# Operating System
|
||||
#
|
||||
CT_KERNEL_SUPPORTS_SHARED_LIBS=y
|
||||
CT_KERNEL="linux"
|
||||
CT_KERNEL_VERSION="2.6.32.68"
|
||||
# CT_KERNEL_bare_metal is not set
|
||||
CT_KERNEL_linux=y
|
||||
CT_KERNEL_bare_metal_AVAILABLE=y
|
||||
CT_KERNEL_linux_AVAILABLE=y
|
||||
# CT_KERNEL_V_4_3 is not set
|
||||
# CT_KERNEL_V_4_2 is not set
|
||||
# CT_KERNEL_V_4_1 is not set
|
||||
# CT_KERNEL_V_3_18 is not set
|
||||
# CT_KERNEL_V_3_14 is not set
|
||||
# CT_KERNEL_V_3_12 is not set
|
||||
# CT_KERNEL_V_3_10 is not set
|
||||
# CT_KERNEL_V_3_4 is not set
|
||||
# CT_KERNEL_V_3_2 is not set
|
||||
CT_KERNEL_V_2_6_32=y
|
||||
# CT_KERNEL_LINUX_CUSTOM is not set
|
||||
CT_KERNEL_windows_AVAILABLE=y
|
||||
|
||||
#
|
||||
# Common kernel options
|
||||
#
|
||||
CT_SHARED_LIBS=y
|
||||
|
||||
#
|
||||
# linux other options
|
||||
#
|
||||
CT_KERNEL_LINUX_VERBOSITY_0=y
|
||||
# CT_KERNEL_LINUX_VERBOSITY_1 is not set
|
||||
# CT_KERNEL_LINUX_VERBOSITY_2 is not set
|
||||
CT_KERNEL_LINUX_VERBOSE_LEVEL=0
|
||||
CT_KERNEL_LINUX_INSTALL_CHECK=y
|
||||
|
||||
#
|
||||
# Binary utilities
|
||||
#
|
||||
CT_ARCH_BINFMT_ELF=y
|
||||
CT_BINUTILS="binutils"
|
||||
CT_BINUTILS_binutils=y
|
||||
|
||||
#
|
||||
# GNU binutils
|
||||
#
|
||||
# CT_CC_BINUTILS_SHOW_LINARO is not set
|
||||
CT_BINUTILS_V_2_25_1=y
|
||||
# CT_BINUTILS_V_2_25 is not set
|
||||
# CT_BINUTILS_V_2_24 is not set
|
||||
# CT_BINUTILS_V_2_23_2 is not set
|
||||
# CT_BINUTILS_V_2_23_1 is not set
|
||||
# CT_BINUTILS_V_2_22 is not set
|
||||
# CT_BINUTILS_V_2_21_53 is not set
|
||||
# CT_BINUTILS_V_2_21_1a is not set
|
||||
# CT_BINUTILS_V_2_20_1a is not set
|
||||
# CT_BINUTILS_V_2_19_1a is not set
|
||||
# CT_BINUTILS_V_2_18a is not set
|
||||
CT_BINUTILS_VERSION="2.25.1"
|
||||
CT_BINUTILS_2_25_1_or_later=y
|
||||
CT_BINUTILS_2_25_or_later=y
|
||||
CT_BINUTILS_2_24_or_later=y
|
||||
CT_BINUTILS_2_23_or_later=y
|
||||
CT_BINUTILS_2_22_or_later=y
|
||||
CT_BINUTILS_2_21_or_later=y
|
||||
CT_BINUTILS_2_20_or_later=y
|
||||
CT_BINUTILS_2_19_or_later=y
|
||||
CT_BINUTILS_2_18_or_later=y
|
||||
CT_BINUTILS_HAS_HASH_STYLE=y
|
||||
CT_BINUTILS_HAS_GOLD=y
|
||||
CT_BINUTILS_HAS_PLUGINS=y
|
||||
CT_BINUTILS_HAS_PKGVERSION_BUGURL=y
|
||||
CT_BINUTILS_FORCE_LD_BFD=y
|
||||
CT_BINUTILS_LINKER_LD=y
|
||||
CT_BINUTILS_LINKERS_LIST="ld"
|
||||
CT_BINUTILS_LINKER_DEFAULT="bfd"
|
||||
# CT_BINUTILS_PLUGINS is not set
|
||||
CT_BINUTILS_EXTRA_CONFIG_ARRAY=""
|
||||
# CT_BINUTILS_FOR_TARGET is not set
|
||||
|
||||
#
|
||||
# binutils other options
|
||||
#
|
||||
|
||||
#
|
||||
# C-library
|
||||
#
|
||||
CT_LIBC="glibc"
|
||||
CT_LIBC_VERSION="2.12.2"
|
||||
CT_LIBC_glibc=y
|
||||
# CT_LIBC_musl is not set
|
||||
# CT_LIBC_uClibc is not set
|
||||
CT_LIBC_avr_libc_AVAILABLE=y
|
||||
CT_LIBC_glibc_AVAILABLE=y
|
||||
CT_THREADS="nptl"
|
||||
# CT_CC_GLIBC_SHOW_LINARO is not set
|
||||
# CT_LIBC_GLIBC_V_2_22 is not set
|
||||
# CT_LIBC_GLIBC_V_2_21 is not set
|
||||
# CT_LIBC_GLIBC_V_2_20 is not set
|
||||
# CT_LIBC_GLIBC_V_2_19 is not set
|
||||
# CT_LIBC_GLIBC_V_2_18 is not set
|
||||
# CT_LIBC_GLIBC_V_2_17 is not set
|
||||
# CT_LIBC_GLIBC_V_2_16_0 is not set
|
||||
# CT_LIBC_GLIBC_V_2_15 is not set
|
||||
# CT_LIBC_GLIBC_V_2_14_1 is not set
|
||||
# CT_LIBC_GLIBC_V_2_14 is not set
|
||||
# CT_LIBC_GLIBC_V_2_13 is not set
|
||||
CT_LIBC_GLIBC_V_2_12_2=y
|
||||
# CT_LIBC_GLIBC_V_2_12_1 is not set
|
||||
# CT_LIBC_GLIBC_V_2_11_1 is not set
|
||||
# CT_LIBC_GLIBC_V_2_11 is not set
|
||||
# CT_LIBC_GLIBC_V_2_10_1 is not set
|
||||
# CT_LIBC_GLIBC_V_2_9 is not set
|
||||
# CT_LIBC_GLIBC_V_2_8 is not set
|
||||
CT_LIBC_mingw_AVAILABLE=y
|
||||
CT_LIBC_musl_AVAILABLE=y
|
||||
CT_LIBC_newlib_AVAILABLE=y
|
||||
CT_LIBC_none_AVAILABLE=y
|
||||
CT_LIBC_uClibc_AVAILABLE=y
|
||||
CT_LIBC_SUPPORT_THREADS_ANY=y
|
||||
CT_LIBC_SUPPORT_THREADS_NATIVE=y
|
||||
|
||||
#
|
||||
# Common C library options
|
||||
#
|
||||
CT_THREADS_NATIVE=y
|
||||
CT_LIBC_XLDD=y
|
||||
|
||||
#
|
||||
# glibc other options
|
||||
#
|
||||
CT_LIBC_GLIBC_PORTS_EXTERNAL=y
|
||||
CT_LIBC_glibc_familly=y
|
||||
CT_LIBC_GLIBC_EXTRA_CONFIG_ARRAY=""
|
||||
CT_LIBC_GLIBC_CONFIGPARMS=""
|
||||
CT_LIBC_GLIBC_EXTRA_CFLAGS=""
|
||||
CT_LIBC_EXTRA_CC_ARGS=""
|
||||
# CT_LIBC_DISABLE_VERSIONING is not set
|
||||
CT_LIBC_OLDEST_ABI=""
|
||||
CT_LIBC_GLIBC_FORCE_UNWIND=y
|
||||
# CT_LIBC_GLIBC_USE_PORTS is not set
|
||||
CT_LIBC_ADDONS_LIST=""
|
||||
# CT_LIBC_LOCALES is not set
|
||||
# CT_LIBC_GLIBC_KERNEL_VERSION_NONE is not set
|
||||
CT_LIBC_GLIBC_KERNEL_VERSION_AS_HEADERS=y
|
||||
# CT_LIBC_GLIBC_KERNEL_VERSION_CHOSEN is not set
|
||||
CT_LIBC_GLIBC_MIN_KERNEL="2.6.32.68"
|
||||
|
||||
#
|
||||
# C compiler
|
||||
#
|
||||
CT_CC="gcc"
|
||||
CT_CC_CORE_PASSES_NEEDED=y
|
||||
CT_CC_CORE_PASS_1_NEEDED=y
|
||||
CT_CC_CORE_PASS_2_NEEDED=y
|
||||
CT_CC_gcc=y
|
||||
# CT_CC_GCC_SHOW_LINARO is not set
|
||||
# CT_CC_GCC_V_5_2_0 is not set
|
||||
CT_CC_GCC_V_4_9_3=y
|
||||
# CT_CC_GCC_V_4_8_5 is not set
|
||||
# CT_CC_GCC_V_4_7_4 is not set
|
||||
# CT_CC_GCC_V_4_6_4 is not set
|
||||
# CT_CC_GCC_V_4_5_4 is not set
|
||||
# CT_CC_GCC_V_4_4_7 is not set
|
||||
# CT_CC_GCC_V_4_3_6 is not set
|
||||
# CT_CC_GCC_V_4_2_4 is not set
|
||||
CT_CC_GCC_4_2_or_later=y
|
||||
CT_CC_GCC_4_3_or_later=y
|
||||
CT_CC_GCC_4_4_or_later=y
|
||||
CT_CC_GCC_4_5_or_later=y
|
||||
CT_CC_GCC_4_6_or_later=y
|
||||
CT_CC_GCC_4_7_or_later=y
|
||||
CT_CC_GCC_4_8_or_later=y
|
||||
CT_CC_GCC_4_9=y
|
||||
CT_CC_GCC_4_9_or_later=y
|
||||
CT_CC_GCC_HAS_GRAPHITE=y
|
||||
CT_CC_GCC_USE_GRAPHITE=y
|
||||
CT_CC_GCC_HAS_LTO=y
|
||||
CT_CC_GCC_USE_LTO=y
|
||||
CT_CC_GCC_HAS_PKGVERSION_BUGURL=y
|
||||
CT_CC_GCC_HAS_BUILD_ID=y
|
||||
CT_CC_GCC_HAS_LNK_HASH_STYLE=y
|
||||
CT_CC_GCC_USE_GMP_MPFR=y
|
||||
CT_CC_GCC_USE_MPC=y
|
||||
CT_CC_GCC_HAS_LIBQUADMATH=y
|
||||
CT_CC_GCC_HAS_LIBSANITIZER=y
|
||||
CT_CC_GCC_VERSION="4.9.3"
|
||||
# CT_CC_LANG_FORTRAN is not set
|
||||
CT_CC_GCC_ENABLE_CXX_FLAGS=""
|
||||
CT_CC_GCC_CORE_EXTRA_CONFIG_ARRAY=""
|
||||
CT_CC_GCC_EXTRA_CONFIG_ARRAY="--with-arch=z10"
|
||||
CT_CC_GCC_EXTRA_ENV_ARRAY=""
|
||||
CT_CC_GCC_STATIC_LIBSTDCXX=y
|
||||
# CT_CC_GCC_SYSTEM_ZLIB is not set
|
||||
|
||||
#
|
||||
# Optimisation features
|
||||
#
|
||||
|
||||
#
|
||||
# Settings for libraries running on target
|
||||
#
|
||||
CT_CC_GCC_ENABLE_TARGET_OPTSPACE=y
|
||||
# CT_CC_GCC_LIBMUDFLAP is not set
|
||||
# CT_CC_GCC_LIBGOMP is not set
|
||||
# CT_CC_GCC_LIBSSP is not set
|
||||
# CT_CC_GCC_LIBQUADMATH is not set
|
||||
# CT_CC_GCC_LIBSANITIZER is not set
|
||||
|
||||
#
|
||||
# Misc. obscure options.
|
||||
#
|
||||
CT_CC_CXA_ATEXIT=y
|
||||
# CT_CC_GCC_DISABLE_PCH is not set
|
||||
CT_CC_GCC_SJLJ_EXCEPTIONS=m
|
||||
CT_CC_GCC_LDBL_128=m
|
||||
# CT_CC_GCC_BUILD_ID is not set
|
||||
CT_CC_GCC_LNK_HASH_STYLE_DEFAULT=y
|
||||
# CT_CC_GCC_LNK_HASH_STYLE_SYSV is not set
|
||||
# CT_CC_GCC_LNK_HASH_STYLE_GNU is not set
|
||||
# CT_CC_GCC_LNK_HASH_STYLE_BOTH is not set
|
||||
CT_CC_GCC_LNK_HASH_STYLE=""
|
||||
CT_CC_GCC_DEC_FLOAT_AUTO=y
|
||||
# CT_CC_GCC_DEC_FLOAT_BID is not set
|
||||
# CT_CC_GCC_DEC_FLOAT_DPD is not set
|
||||
# CT_CC_GCC_DEC_FLOATS_NO is not set
|
||||
CT_CC_SUPPORT_CXX=y
|
||||
CT_CC_SUPPORT_FORTRAN=y
|
||||
CT_CC_SUPPORT_JAVA=y
|
||||
CT_CC_SUPPORT_ADA=y
|
||||
CT_CC_SUPPORT_OBJC=y
|
||||
CT_CC_SUPPORT_OBJCXX=y
|
||||
CT_CC_SUPPORT_GOLANG=y
|
||||
|
||||
#
|
||||
# Additional supported languages:
|
||||
#
|
||||
CT_CC_LANG_CXX=y
|
||||
# CT_CC_LANG_JAVA is not set
|
||||
|
||||
#
|
||||
# Debug facilities
|
||||
#
|
||||
# CT_DEBUG_dmalloc is not set
|
||||
# CT_DEBUG_duma is not set
|
||||
# CT_DEBUG_gdb is not set
|
||||
# CT_DEBUG_ltrace is not set
|
||||
# CT_DEBUG_strace is not set
|
||||
|
||||
#
|
||||
# Companion libraries
|
||||
#
|
||||
CT_COMPLIBS_NEEDED=y
|
||||
CT_LIBICONV_NEEDED=y
|
||||
CT_GETTEXT_NEEDED=y
|
||||
CT_GMP_NEEDED=y
|
||||
CT_MPFR_NEEDED=y
|
||||
CT_ISL_NEEDED=y
|
||||
CT_CLOOG_NEEDED=y
|
||||
CT_MPC_NEEDED=y
|
||||
CT_COMPLIBS=y
|
||||
CT_LIBICONV=y
|
||||
CT_GETTEXT=y
|
||||
CT_GMP=y
|
||||
CT_MPFR=y
|
||||
CT_ISL=y
|
||||
CT_CLOOG=y
|
||||
CT_MPC=y
|
||||
CT_LIBICONV_V_1_14=y
|
||||
CT_LIBICONV_VERSION="1.14"
|
||||
CT_GETTEXT_V_0_19_6=y
|
||||
CT_GETTEXT_VERSION="0.19.6"
|
||||
CT_GMP_V_6_0_0=y
|
||||
# CT_GMP_V_5_1_3 is not set
|
||||
# CT_GMP_V_5_1_1 is not set
|
||||
# CT_GMP_V_5_0_2 is not set
|
||||
# CT_GMP_V_5_0_1 is not set
|
||||
# CT_GMP_V_4_3_2 is not set
|
||||
# CT_GMP_V_4_3_1 is not set
|
||||
# CT_GMP_V_4_3_0 is not set
|
||||
CT_GMP_5_0_2_or_later=y
|
||||
CT_GMP_VERSION="6.0.0a"
|
||||
CT_MPFR_V_3_1_3=y
|
||||
# CT_MPFR_V_3_1_2 is not set
|
||||
# CT_MPFR_V_3_1_0 is not set
|
||||
# CT_MPFR_V_3_0_1 is not set
|
||||
# CT_MPFR_V_3_0_0 is not set
|
||||
# CT_MPFR_V_2_4_2 is not set
|
||||
# CT_MPFR_V_2_4_1 is not set
|
||||
# CT_MPFR_V_2_4_0 is not set
|
||||
CT_MPFR_VERSION="3.1.3"
|
||||
CT_ISL_V_0_14=y
|
||||
CT_ISL_V_0_14_or_later=y
|
||||
CT_ISL_V_0_12_or_later=y
|
||||
CT_ISL_VERSION="0.14"
|
||||
CT_CLOOG_V_0_18_4=y
|
||||
# CT_CLOOG_V_0_18_1 is not set
|
||||
# CT_CLOOG_V_0_18_0 is not set
|
||||
CT_CLOOG_VERSION="0.18.4"
|
||||
CT_CLOOG_0_18_4_or_later=y
|
||||
CT_CLOOG_0_18_or_later=y
|
||||
CT_MPC_V_1_0_3=y
|
||||
# CT_MPC_V_1_0_2 is not set
|
||||
# CT_MPC_V_1_0_1 is not set
|
||||
# CT_MPC_V_1_0 is not set
|
||||
# CT_MPC_V_0_9 is not set
|
||||
# CT_MPC_V_0_8_2 is not set
|
||||
# CT_MPC_V_0_8_1 is not set
|
||||
# CT_MPC_V_0_7 is not set
|
||||
CT_MPC_VERSION="1.0.3"
|
||||
|
||||
#
|
||||
# Companion libraries common options
|
||||
#
|
||||
# CT_COMPLIBS_CHECK is not set
|
||||
|
||||
#
|
||||
# Companion tools
|
||||
#
|
||||
|
||||
#
|
||||
# READ HELP before you say 'Y' below !!!
|
||||
#
|
||||
# CT_COMP_TOOLS is not set
|
||||
27
src/ci/docker/x86_64-gnu-incremental/Dockerfile
Normal file
27
src/ci/docker/x86_64-gnu-incremental/Dockerfile
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
FROM ubuntu:16.04
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
g++ \
|
||||
make \
|
||||
file \
|
||||
curl \
|
||||
ca-certificates \
|
||||
python2.7 \
|
||||
git \
|
||||
cmake \
|
||||
sudo \
|
||||
gdb \
|
||||
xz-utils
|
||||
|
||||
ENV SCCACHE_DIGEST=7237e38e029342fa27b7ac25412cb9d52554008b12389727320bd533fd7f05b6a96d55485f305caf95e5c8f5f97c3313e10012ccad3e752aba2518f3522ba783
|
||||
RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | \
|
||||
tar xJf - -C /usr/local/bin --strip-components=1
|
||||
|
||||
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
|
||||
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu
|
||||
ENV RUSTFLAGS -Zincremental=/tmp/rust-incr-cache
|
||||
ENV RUST_CHECK_TARGET check
|
||||
|
|
@ -118,7 +118,8 @@ These types are _generally_ found in struct fields, but they may be found elsewh
|
|||
|
||||
## `Cell<T>`
|
||||
|
||||
[`Cell<T>`][cell] is a type that provides zero-cost interior mutability, but only for `Copy` types.
|
||||
[`Cell<T>`][cell] is a type that provides zero-cost interior mutability by moving data in and
|
||||
out of the cell.
|
||||
Since the compiler knows that all the data owned by the contained value is on the stack, there's
|
||||
no worry of leaking any data behind references (or worse!) by simply replacing the data.
|
||||
|
||||
|
|
@ -160,7 +161,7 @@ This relaxes the “no aliasing with mutability” restriction in places
|
|||
unnecessary. However, this also relaxes the guarantees that the restriction provides; so if your
|
||||
invariants depend on data stored within `Cell`, you should be careful.
|
||||
|
||||
This is useful for mutating primitives and other `Copy` types when there is no easy way of
|
||||
This is useful for mutating primitives and other types when there is no easy way of
|
||||
doing it in line with the static rules of `&` and `&mut`.
|
||||
|
||||
`Cell` does not let you obtain interior references to the data, which makes it safe to freely
|
||||
|
|
@ -168,16 +169,17 @@ mutate.
|
|||
|
||||
#### Cost
|
||||
|
||||
There is no runtime cost to using `Cell<T>`, however if you are using it to wrap larger (`Copy`)
|
||||
There is no runtime cost to using `Cell<T>`, however if you are using it to wrap larger
|
||||
structs, it might be worthwhile to instead wrap individual fields in `Cell<T>` since each write is
|
||||
otherwise a full copy of the struct.
|
||||
|
||||
|
||||
## `RefCell<T>`
|
||||
|
||||
[`RefCell<T>`][refcell] also provides interior mutability, but isn't restricted to `Copy` types.
|
||||
[`RefCell<T>`][refcell] also provides interior mutability, but doesn't move data in and out of the
|
||||
cell.
|
||||
|
||||
Instead, it has a runtime cost. `RefCell<T>` enforces the read-write lock pattern at runtime (it's
|
||||
However, it has a runtime cost. `RefCell<T>` enforces the read-write lock pattern at runtime (it's
|
||||
like a single-threaded mutex), unlike `&T`/`&mut T` which do so at compile time. This is done by the
|
||||
`borrow()` and `borrow_mut()` functions, which modify an internal reference count and return smart
|
||||
pointers which can be dereferenced immutably and mutably respectively. The refcount is restored when
|
||||
|
|
|
|||
|
|
@ -56,9 +56,9 @@ almost any function that takes a pointer argument isn't valid for all possible
|
|||
inputs since the pointer could be dangling, and raw pointers fall outside of
|
||||
Rust's safe memory model.
|
||||
|
||||
When declaring the argument types to a foreign function, the Rust compiler can
|
||||
not check if the declaration is correct, so specifying it correctly is part of
|
||||
keeping the binding correct at runtime.
|
||||
When declaring the argument types to a foreign function, the Rust compiler
|
||||
cannot check if the declaration is correct, so specifying it correctly is part
|
||||
of keeping the binding correct at runtime.
|
||||
|
||||
The `extern` block can be extended to cover the entire snappy API:
|
||||
|
||||
|
|
@ -710,7 +710,7 @@ Please note that [`catch_unwind()`] will only catch unwinding panics, not
|
|||
those who abort the process. See the documentation of [`catch_unwind()`]
|
||||
for more information.
|
||||
|
||||
[`catch_unwind()`]: https://doc.rust-lang.org/std/panic/fn.catch_unwind.html
|
||||
[`catch_unwind()`]: ../std/panic/fn.catch_unwind.html
|
||||
|
||||
# Representing opaque structs
|
||||
|
||||
|
|
|
|||
|
|
@ -499,6 +499,10 @@ be imported in every test with `mod common;`
|
|||
That's all there is to the `tests` directory. The `tests` module isn't needed
|
||||
here, since the whole thing is focused on tests.
|
||||
|
||||
Note, when building integration tests, cargo will not pass the `test` attribute
|
||||
to the compiler. It means that all parts in `cfg(test)` won't be included in
|
||||
the build used in your integration tests.
|
||||
|
||||
Let's finally check out that third section: documentation tests.
|
||||
|
||||
# Documentation tests
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ this is totally fine.
|
|||
For instance, a custom implementation of `Box` might write `Drop` like this:
|
||||
|
||||
```rust
|
||||
#![feature(alloc, heap_api, drop_in_place, unique)]
|
||||
#![feature(alloc, heap_api, unique)]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
|
|
@ -57,7 +57,7 @@ use-after-free the `ptr` because when drop exits, it becomes inaccessible.
|
|||
However this wouldn't work:
|
||||
|
||||
```rust
|
||||
#![feature(alloc, heap_api, drop_in_place, unique)]
|
||||
#![feature(alloc, heap_api, unique)]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
|
|
@ -135,7 +135,7 @@ The classic safe solution to overriding recursive drop and allowing moving out
|
|||
of Self during `drop` is to use an Option:
|
||||
|
||||
```rust
|
||||
#![feature(alloc, heap_api, drop_in_place, unique)]
|
||||
#![feature(alloc, heap_api, unique)]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
|
|
|
|||
|
|
@ -199,24 +199,42 @@ assert (unsafely) that a generic type's destructor is *guaranteed* to
|
|||
not access any expired data, even if its type gives it the capability
|
||||
to do so.
|
||||
|
||||
That attribute is called `unsafe_destructor_blind_to_params`.
|
||||
That attribute is called `may_dangle` and was introduced in [RFC 1327]
|
||||
(https://github.com/rust-lang/rfcs/blob/master/text/1327-dropck-param-eyepatch.md).
|
||||
To deploy it on the Inspector example from above, we would write:
|
||||
|
||||
```rust,ignore
|
||||
struct Inspector<'a>(&'a u8, &'static str);
|
||||
|
||||
impl<'a> Drop for Inspector<'a> {
|
||||
#[unsafe_destructor_blind_to_params]
|
||||
unsafe impl<#[may_dangle] 'a> Drop for Inspector<'a> {
|
||||
fn drop(&mut self) {
|
||||
println!("Inspector(_, {}) knows when *not* to inspect.", self.1);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This attribute has the word `unsafe` in it because the compiler is not
|
||||
checking the implicit assertion that no potentially expired data
|
||||
Use of this attribute requires the `Drop` impl to be marked `unsafe` because the
|
||||
compiler is not checking the implicit assertion that no potentially expired data
|
||||
(e.g. `self.0` above) is accessed.
|
||||
|
||||
The attribute can be applied to any number of lifetime and type parameters. In
|
||||
the following example, we assert that we access no data behind a reference of
|
||||
lifetime `'b` and that the only uses of `T` will be moves or drops, but omit
|
||||
the attribute from `'a` and `U`, because we do access data with that lifetime
|
||||
and that type:
|
||||
|
||||
```rust,ignore
|
||||
use std::fmt::Display;
|
||||
|
||||
struct Inspector<'a, 'b, T, U: Display>(&'a u8, &'b u8, T, U);
|
||||
|
||||
unsafe impl<'a, #[may_dangle] 'b, #[may_dangle] T, U: Display> Drop for Inspector<'a, 'b, T, U> {
|
||||
fn drop(&mut self) {
|
||||
println!("Inspector({}, _, _, {})", self.0, self.3);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
It is sometimes obvious that no such access can occur, like the case above.
|
||||
However, when dealing with a generic type parameter, such access can
|
||||
occur indirectly. Examples of such indirect access are:
|
||||
|
|
@ -263,7 +281,7 @@ some other method invoked by the destructor, rather than being written
|
|||
directly within it.
|
||||
|
||||
In all of the above cases where the `&'a u8` is accessed in the
|
||||
destructor, adding the `#[unsafe_destructor_blind_to_params]`
|
||||
destructor, adding the `#[may_dangle]`
|
||||
attribute makes the type vulnerable to misuse that the borrower
|
||||
checker will not catch, inviting havoc. It is better to avoid adding
|
||||
the attribute.
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize;
|
|||
/// as long as `T` implements [`Send`] and [`Sync`][sync]. The disadvantage is
|
||||
/// that atomic operations are more expensive than ordinary memory accesses.
|
||||
/// If you are not sharing reference-counted values between threads, consider
|
||||
/// using [`rc::Rc`] for lower overhead. [`Rc`] is a safe default, because
|
||||
/// using [`rc::Rc`][`Rc`] for lower overhead. [`Rc`] is a safe default, because
|
||||
/// the compiler will catch any attempt to send an [`Rc`] between threads.
|
||||
/// However, a library might choose `Arc` in order to give library consumers
|
||||
/// more flexibility.
|
||||
|
|
|
|||
|
|
@ -103,6 +103,7 @@ pub struct ExchangeHeapSingleton {
|
|||
///
|
||||
/// See the [module-level documentation](../../std/boxed/index.html) for more.
|
||||
#[lang = "owned_box"]
|
||||
#[fundamental]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Box<T: ?Sized>(Unique<T>);
|
||||
|
||||
|
|
@ -292,6 +293,14 @@ impl<T: ?Sized> Box<T> {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(not(stage0))]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
unsafe impl<#[may_dangle] T: ?Sized> Drop for Box<T> {
|
||||
fn drop(&mut self) {
|
||||
// FIXME: Do nothing, drop is currently performed by compiler.
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: Default> Default for Box<T> {
|
||||
/// Creates a `Box<T>`, with the `Default` value for T.
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@
|
|||
//! that the contained type `T` is shareable. Additionally, `Arc<T>` is itself
|
||||
//! sendable while `Rc<T>` is not.
|
||||
//!
|
||||
//! This types allows for shared access to the contained data, and is often
|
||||
//! This type allows for shared access to the contained data, and is often
|
||||
//! paired with synchronization primitives such as mutexes to allow mutation of
|
||||
//! shared resources.
|
||||
//!
|
||||
|
|
|
|||
|
|
@ -17,9 +17,11 @@
|
|||
//! pointer to the same value in the heap. When the last [`Rc`] pointer to a
|
||||
//! given value is destroyed, the pointed-to value is also destroyed.
|
||||
//!
|
||||
//! Shared references in Rust disallow mutation by default, and `Rc` is no
|
||||
//! exception. If you need to mutate through an [`Rc`], use [`Cell`] or
|
||||
//! [`RefCell`].
|
||||
//! Shared references in Rust disallow mutation by default, and [`Rc`]
|
||||
//! is no exception: you cannot obtain a mutable reference to
|
||||
//! something inside an [`Rc`]. If you need mutability, put a [`Cell`]
|
||||
//! or [`RefCell`] inside the [`Rc`]; see [an example of mutability
|
||||
//! inside an Rc][mutability].
|
||||
//!
|
||||
//! [`Rc`] uses non-atomic reference counting. This means that overhead is very
|
||||
//! low, but an [`Rc`] cannot be sent between threads, and consequently [`Rc`]
|
||||
|
|
@ -214,6 +216,7 @@
|
|||
//! [upgrade]: struct.Weak.html#method.upgrade
|
||||
//! [`None`]: ../../std/option/enum.Option.html#variant.None
|
||||
//! [assoc]: ../../book/method-syntax.html#associated-functions
|
||||
//! [mutability]: ../../std/cell/index.html#introducing-mutability-inside-of-something-immutable
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
|
|
|
|||
|
|
@ -10,23 +10,20 @@
|
|||
|
||||
#![deny(warnings)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate build_helper;
|
||||
extern crate gcc;
|
||||
|
||||
use std::env;
|
||||
use std::path::PathBuf;
|
||||
use std::fs::{self, File};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
use build_helper::run;
|
||||
use build_helper::{run, rerun_if_changed_anything_in_dir, up_to_date};
|
||||
|
||||
fn main() {
|
||||
println!("cargo:rustc-cfg=cargobuild");
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
|
||||
let target = env::var("TARGET").expect("TARGET was not set");
|
||||
let host = env::var("HOST").expect("HOST was not set");
|
||||
let build_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
|
||||
let src_dir = env::current_dir().unwrap();
|
||||
|
||||
// FIXME: This is a hack to support building targets that don't
|
||||
// support jemalloc alongside hosts that do. The jemalloc build is
|
||||
// controlled by a feature of the std crate, and if that feature
|
||||
|
|
@ -35,6 +32,8 @@ fn main() {
|
|||
// that the feature set used by std is the same across all
|
||||
// targets, which means we have to build the alloc_jemalloc crate
|
||||
// for targets like emscripten, even if we don't use it.
|
||||
let target = env::var("TARGET").expect("TARGET was not set");
|
||||
let host = env::var("HOST").expect("HOST was not set");
|
||||
if target.contains("rumprun") || target.contains("bitrig") || target.contains("openbsd") ||
|
||||
target.contains("msvc") || target.contains("emscripten") || target.contains("fuchsia") ||
|
||||
target.contains("redox") {
|
||||
|
|
@ -57,6 +56,28 @@ fn main() {
|
|||
return;
|
||||
}
|
||||
|
||||
let build_dir = env::var_os("RUSTBUILD_NATIVE_DIR").unwrap_or(env::var_os("OUT_DIR").unwrap());
|
||||
let build_dir = PathBuf::from(build_dir).join("jemalloc");
|
||||
let _ = fs::create_dir_all(&build_dir);
|
||||
|
||||
if target.contains("windows") {
|
||||
println!("cargo:rustc-link-lib=static=jemalloc");
|
||||
} else {
|
||||
println!("cargo:rustc-link-lib=static=jemalloc_pic");
|
||||
}
|
||||
println!("cargo:rustc-link-search=native={}/lib", build_dir.display());
|
||||
if target.contains("android") {
|
||||
println!("cargo:rustc-link-lib=gcc");
|
||||
} else if !target.contains("windows") && !target.contains("musl") {
|
||||
println!("cargo:rustc-link-lib=pthread");
|
||||
}
|
||||
let src_dir = env::current_dir().unwrap().join("../jemalloc");
|
||||
rerun_if_changed_anything_in_dir(&src_dir);
|
||||
let timestamp = build_dir.join("rustbuild.timestamp");
|
||||
if up_to_date(&Path::new("build.rs"), ×tamp) && up_to_date(&src_dir, ×tamp) {
|
||||
return
|
||||
}
|
||||
|
||||
let compiler = gcc::Config::new().get_compiler();
|
||||
// only msvc returns None for ar so unwrap is okay
|
||||
let ar = build_helper::cc2ar(compiler.path(), &target).unwrap();
|
||||
|
|
@ -66,23 +87,8 @@ fn main() {
|
|||
.collect::<Vec<_>>()
|
||||
.join(" ");
|
||||
|
||||
let mut stack = src_dir.join("../jemalloc")
|
||||
.read_dir()
|
||||
.unwrap()
|
||||
.map(|e| e.unwrap())
|
||||
.filter(|e| &*e.file_name() != ".git")
|
||||
.collect::<Vec<_>>();
|
||||
while let Some(entry) = stack.pop() {
|
||||
let path = entry.path();
|
||||
if entry.file_type().unwrap().is_dir() {
|
||||
stack.extend(path.read_dir().unwrap().map(|e| e.unwrap()));
|
||||
} else {
|
||||
println!("cargo:rerun-if-changed={}", path.display());
|
||||
}
|
||||
}
|
||||
|
||||
let mut cmd = Command::new("sh");
|
||||
cmd.arg(src_dir.join("../jemalloc/configure")
|
||||
cmd.arg(src_dir.join("configure")
|
||||
.to_str()
|
||||
.unwrap()
|
||||
.replace("C:\\", "/c/")
|
||||
|
|
@ -158,6 +164,7 @@ fn main() {
|
|||
}
|
||||
|
||||
run(&mut cmd);
|
||||
|
||||
let mut make = Command::new(build_helper::make(&host));
|
||||
make.current_dir(&build_dir)
|
||||
.arg("build_lib_static");
|
||||
|
|
@ -170,15 +177,16 @@ fn main() {
|
|||
|
||||
run(&mut make);
|
||||
|
||||
if target.contains("windows") {
|
||||
println!("cargo:rustc-link-lib=static=jemalloc");
|
||||
} else {
|
||||
println!("cargo:rustc-link-lib=static=jemalloc_pic");
|
||||
}
|
||||
println!("cargo:rustc-link-search=native={}/lib", build_dir.display());
|
||||
if target.contains("android") {
|
||||
println!("cargo:rustc-link-lib=gcc");
|
||||
} else if !target.contains("windows") && !target.contains("musl") {
|
||||
println!("cargo:rustc-link-lib=pthread");
|
||||
// The pthread_atfork symbols is used by jemalloc on android but the really
|
||||
// old android we're building on doesn't have them defined, so just make
|
||||
// sure the symbols are available.
|
||||
if target.contains("androideabi") {
|
||||
println!("cargo:rerun-if-changed=pthread_atfork_dummy.c");
|
||||
gcc::Config::new()
|
||||
.flag("-fvisibility=hidden")
|
||||
.file("pthread_atfork_dummy.c")
|
||||
.compile("libpthread_atfork_dummy.a");
|
||||
}
|
||||
|
||||
t!(File::create(×tamp));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -143,7 +143,7 @@ mod imp {
|
|||
// we're building on doesn't have them defined, so just make sure the symbols
|
||||
// are available.
|
||||
#[no_mangle]
|
||||
#[cfg(target_os = "android")]
|
||||
#[cfg(all(target_os = "android", not(cargobuild)))]
|
||||
pub extern "C" fn pthread_atfork(_prefork: *mut u8,
|
||||
_postfork_parent: *mut u8,
|
||||
_postfork_child: *mut u8)
|
||||
|
|
|
|||
16
src/liballoc_jemalloc/pthread_atfork_dummy.c
Normal file
16
src/liballoc_jemalloc/pthread_atfork_dummy.c
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
// 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.
|
||||
|
||||
// See comments in build.rs for why this exists
|
||||
int pthread_atfork(void* prefork,
|
||||
void* postfork_parent,
|
||||
void* postfork_child) {
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -17,6 +17,8 @@
|
|||
reason = "matches collection reform specification, \
|
||||
waiting for dust to settle",
|
||||
issue = "37966")]
|
||||
#![rustc_deprecated(since = "1.16.0", reason = "long since replaced")]
|
||||
#![allow(deprecated)]
|
||||
|
||||
use core::marker;
|
||||
use core::fmt;
|
||||
|
|
|
|||
|
|
@ -79,6 +79,7 @@ pub use btree_set::BTreeSet;
|
|||
#[doc(no_inline)]
|
||||
pub use linked_list::LinkedList;
|
||||
#[doc(no_inline)]
|
||||
#[allow(deprecated)]
|
||||
pub use enum_set::EnumSet;
|
||||
#[doc(no_inline)]
|
||||
pub use vec_deque::VecDeque;
|
||||
|
|
|
|||
|
|
@ -509,7 +509,7 @@ impl<T> [T] {
|
|||
core_slice::SliceExt::swap(self, a, b)
|
||||
}
|
||||
|
||||
/// Reverse the order of elements in a slice, in place.
|
||||
/// Reverses the order of elements in a slice, in place.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
|
|
@ -1062,7 +1062,7 @@ impl<T> [T] {
|
|||
core_slice::SliceExt::binary_search_by_key(self, b, f)
|
||||
}
|
||||
|
||||
/// This is equivalent to `self.sort_by(|a, b| a.cmp(b))`.
|
||||
/// Sorts the slice.
|
||||
///
|
||||
/// This sort is stable (i.e. does not reorder equal elements) and `O(n log n)` worst-case.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -1607,7 +1607,6 @@ impl str {
|
|||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// # #![feature(str_replacen)]
|
||||
/// let s = "foo foo 123 foo";
|
||||
/// assert_eq!("new new 123 foo", s.replacen("foo", "new", 2));
|
||||
/// assert_eq!("faa fao 123 foo", s.replacen('o', "a", 3));
|
||||
|
|
@ -1617,13 +1616,10 @@ impl str {
|
|||
/// When the pattern doesn't match:
|
||||
///
|
||||
/// ```
|
||||
/// # #![feature(str_replacen)]
|
||||
/// let s = "this is old";
|
||||
/// assert_eq!(s, s.replacen("cookie monster", "little lamb", 10));
|
||||
/// ```
|
||||
#[unstable(feature = "str_replacen",
|
||||
issue = "36436",
|
||||
reason = "only need to replace first N matches")]
|
||||
#[stable(feature = "str_replacen", since = "1.16.0")]
|
||||
pub fn replacen<'a, P: Pattern<'a>>(&'a self, pat: P, to: &str, count: usize) -> String {
|
||||
// Hope to reduce the times of re-allocation
|
||||
let mut result = String::with_capacity(32);
|
||||
|
|
@ -1795,11 +1791,9 @@ impl str {
|
|||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(repeat_str)]
|
||||
///
|
||||
/// assert_eq!("abc".repeat(4), String::from("abcabcabcabc"));
|
||||
/// ```
|
||||
#[unstable(feature = "repeat_str", issue = "37079")]
|
||||
#[stable(feature = "repeat_str", since = "1.16.0")]
|
||||
pub fn repeat(&self, n: usize) -> String {
|
||||
let mut s = String::with_capacity(self.len() * n);
|
||||
s.extend((0..n).map(|_| self));
|
||||
|
|
|
|||
|
|
@ -1166,8 +1166,6 @@ impl String {
|
|||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(insert_str)]
|
||||
///
|
||||
/// let mut s = String::from("bar");
|
||||
///
|
||||
/// s.insert_str(0, "foo");
|
||||
|
|
@ -1175,9 +1173,7 @@ impl String {
|
|||
/// assert_eq!("foobar", s);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "insert_str",
|
||||
reason = "recent addition",
|
||||
issue = "35553")]
|
||||
#[stable(feature = "insert_str", since = "1.16.0")]
|
||||
pub fn insert_str(&mut self, idx: usize, string: &str) {
|
||||
assert!(self.is_char_boundary(idx));
|
||||
|
||||
|
|
@ -1270,7 +1266,6 @@ impl String {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # #![feature(string_split_off)]
|
||||
/// # fn main() {
|
||||
/// let mut hello = String::from("Hello, World!");
|
||||
/// let world = hello.split_off(7);
|
||||
|
|
@ -1279,7 +1274,7 @@ impl String {
|
|||
/// # }
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "string_split_off", issue = "38080")]
|
||||
#[stable(feature = "string_split_off", since = "1.16.0")]
|
||||
pub fn split_off(&mut self, mid: usize) -> String {
|
||||
assert!(self.is_char_boundary(mid));
|
||||
let other = self.vec.split_off(mid);
|
||||
|
|
|
|||
|
|
@ -820,15 +820,13 @@ impl<T> Vec<T> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(dedup_by)]
|
||||
///
|
||||
/// let mut vec = vec![10, 20, 21, 30, 20];
|
||||
///
|
||||
/// vec.dedup_by_key(|i| *i / 10);
|
||||
///
|
||||
/// assert_eq!(vec, [10, 20, 30, 20]);
|
||||
/// ```
|
||||
#[unstable(feature = "dedup_by", reason = "recently added", issue = "37087")]
|
||||
#[stable(feature = "dedup_by", since = "1.16.0")]
|
||||
#[inline]
|
||||
pub fn dedup_by_key<F, K>(&mut self, mut key: F) where F: FnMut(&mut T) -> K, K: PartialEq {
|
||||
self.dedup_by(|a, b| key(a) == key(b))
|
||||
|
|
@ -841,7 +839,6 @@ impl<T> Vec<T> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(dedup_by)]
|
||||
/// use std::ascii::AsciiExt;
|
||||
///
|
||||
/// let mut vec = vec!["foo", "bar", "Bar", "baz", "bar"];
|
||||
|
|
@ -850,7 +847,7 @@ impl<T> Vec<T> {
|
|||
///
|
||||
/// assert_eq!(vec, ["foo", "bar", "baz", "bar"]);
|
||||
/// ```
|
||||
#[unstable(feature = "dedup_by", reason = "recently added", issue = "37087")]
|
||||
#[stable(feature = "dedup_by", since = "1.16.0")]
|
||||
pub fn dedup_by<F>(&mut self, mut same_bucket: F) where F: FnMut(&mut T, &mut T) -> bool {
|
||||
unsafe {
|
||||
// Although we have a mutable reference to `self`, we cannot make
|
||||
|
|
@ -1961,7 +1958,7 @@ impl<T> IntoIter<T> {
|
|||
/// assert_eq!(into_iter.next().unwrap(), 'z');
|
||||
/// ```
|
||||
#[stable(feature = "vec_into_iter_as_slice", since = "1.15.0")]
|
||||
pub fn as_mut_slice(&self) -> &mut [T] {
|
||||
pub fn as_mut_slice(&mut self) -> &mut [T] {
|
||||
unsafe {
|
||||
slice::from_raw_parts_mut(self.ptr as *mut T, self.len())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -469,9 +469,9 @@ impl<T> VecDeque<T> {
|
|||
/// buf.push_back(3);
|
||||
/// buf.push_back(4);
|
||||
/// buf.push_back(5);
|
||||
/// assert_eq!(buf, [3, 4, 5]);
|
||||
/// buf.swap(0, 2);
|
||||
/// assert_eq!(buf[0], 5);
|
||||
/// assert_eq!(buf[2], 3);
|
||||
/// assert_eq!(buf, [5, 4, 3]);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn swap(&mut self, i: usize, j: usize) {
|
||||
|
|
@ -643,21 +643,17 @@ impl<T> VecDeque<T> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(deque_extras)]
|
||||
///
|
||||
/// use std::collections::VecDeque;
|
||||
///
|
||||
/// let mut buf = VecDeque::new();
|
||||
/// buf.push_back(5);
|
||||
/// buf.push_back(10);
|
||||
/// buf.push_back(15);
|
||||
/// assert_eq!(buf, [5, 10, 15]);
|
||||
/// buf.truncate(1);
|
||||
/// assert_eq!(buf.len(), 1);
|
||||
/// assert_eq!(Some(&5), buf.get(0));
|
||||
/// assert_eq!(buf, [5]);
|
||||
/// ```
|
||||
#[unstable(feature = "deque_extras",
|
||||
reason = "matches collection reform specification; waiting on panic semantics",
|
||||
issue = "27788")]
|
||||
#[stable(feature = "deque_extras", since = "1.16.0")]
|
||||
pub fn truncate(&mut self, len: usize) {
|
||||
for _ in len..self.len() {
|
||||
self.pop_back();
|
||||
|
|
@ -830,8 +826,9 @@ impl<T> VecDeque<T> {
|
|||
/// use std::collections::VecDeque;
|
||||
///
|
||||
/// let mut v: VecDeque<_> = vec![1, 2, 3].into_iter().collect();
|
||||
/// assert_eq!(vec![3].into_iter().collect::<VecDeque<_>>(), v.drain(2..).collect());
|
||||
/// assert_eq!(vec![1, 2].into_iter().collect::<VecDeque<_>>(), v);
|
||||
/// let drained = v.drain(2..).collect::<VecDeque<_>>();
|
||||
/// assert_eq!(drained, [3]);
|
||||
/// assert_eq!(v, [1, 2]);
|
||||
///
|
||||
/// // A full range clears all contents
|
||||
/// v.drain(..);
|
||||
|
|
@ -1183,11 +1180,10 @@ impl<T> VecDeque<T> {
|
|||
/// buf.push_back(1);
|
||||
/// buf.push_back(2);
|
||||
/// buf.push_back(3);
|
||||
/// assert_eq!(buf, [1, 2, 3]);
|
||||
///
|
||||
/// assert_eq!(buf.swap_remove_back(0), Some(1));
|
||||
/// assert_eq!(buf.len(), 2);
|
||||
/// assert_eq!(buf[0], 3);
|
||||
/// assert_eq!(buf[1], 2);
|
||||
/// assert_eq!(buf, [3, 2]);
|
||||
/// ```
|
||||
#[stable(feature = "deque_extras_15", since = "1.5.0")]
|
||||
pub fn swap_remove_back(&mut self, index: usize) -> Option<T> {
|
||||
|
|
@ -1219,11 +1215,10 @@ impl<T> VecDeque<T> {
|
|||
/// buf.push_back(1);
|
||||
/// buf.push_back(2);
|
||||
/// buf.push_back(3);
|
||||
/// assert_eq!(buf, [1, 2, 3]);
|
||||
///
|
||||
/// assert_eq!(buf.swap_remove_front(2), Some(3));
|
||||
/// assert_eq!(buf.len(), 2);
|
||||
/// assert_eq!(buf[0], 2);
|
||||
/// assert_eq!(buf[1], 1);
|
||||
/// assert_eq!(buf, [2, 1]);
|
||||
/// ```
|
||||
#[stable(feature = "deque_extras_15", since = "1.5.0")]
|
||||
pub fn swap_remove_front(&mut self, index: usize) -> Option<T> {
|
||||
|
|
@ -1254,11 +1249,10 @@ impl<T> VecDeque<T> {
|
|||
/// vec_deque.push_back('a');
|
||||
/// vec_deque.push_back('b');
|
||||
/// vec_deque.push_back('c');
|
||||
/// assert_eq!(vec_deque, &['a', 'b', 'c']);
|
||||
///
|
||||
/// vec_deque.insert(1, 'd');
|
||||
///
|
||||
/// let vec = vec_deque.into_iter().collect::<Vec<_>>();
|
||||
/// assert_eq!(vec, ['a', 'd', 'b', 'c']);
|
||||
/// assert_eq!(vec_deque, &['a', 'd', 'b', 'c']);
|
||||
/// ```
|
||||
#[stable(feature = "deque_extras_15", since = "1.5.0")]
|
||||
pub fn insert(&mut self, index: usize, value: T) {
|
||||
|
|
@ -1482,9 +1476,10 @@ impl<T> VecDeque<T> {
|
|||
/// buf.push_back(1);
|
||||
/// buf.push_back(2);
|
||||
/// buf.push_back(3);
|
||||
/// assert_eq!(buf, [1, 2, 3]);
|
||||
///
|
||||
/// assert_eq!(buf.remove(1), Some(2));
|
||||
/// assert_eq!(buf.get(1), Some(&3));
|
||||
/// assert_eq!(buf, [1, 3]);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn remove(&mut self, index: usize) -> Option<T> {
|
||||
|
|
@ -1663,9 +1658,8 @@ impl<T> VecDeque<T> {
|
|||
///
|
||||
/// let mut buf: VecDeque<_> = vec![1,2,3].into_iter().collect();
|
||||
/// let buf2 = buf.split_off(1);
|
||||
/// // buf = [1], buf2 = [2, 3]
|
||||
/// assert_eq!(buf.len(), 1);
|
||||
/// assert_eq!(buf2.len(), 2);
|
||||
/// assert_eq!(buf, [1]);
|
||||
/// assert_eq!(buf2, [2, 3]);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "split_off", since = "1.4.0")]
|
||||
|
|
@ -1722,11 +1716,11 @@ impl<T> VecDeque<T> {
|
|||
/// ```
|
||||
/// use std::collections::VecDeque;
|
||||
///
|
||||
/// let mut buf: VecDeque<_> = vec![1, 2, 3].into_iter().collect();
|
||||
/// let mut buf2: VecDeque<_> = vec![4, 5, 6].into_iter().collect();
|
||||
/// let mut buf: VecDeque<_> = vec![1, 2].into_iter().collect();
|
||||
/// let mut buf2: VecDeque<_> = vec![3, 4].into_iter().collect();
|
||||
/// buf.append(&mut buf2);
|
||||
/// assert_eq!(buf.len(), 6);
|
||||
/// assert_eq!(buf2.len(), 0);
|
||||
/// assert_eq!(buf, [1, 2, 3, 4]);
|
||||
/// assert_eq!(buf2, []);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "append", since = "1.4.0")]
|
||||
|
|
@ -1749,9 +1743,7 @@ impl<T> VecDeque<T> {
|
|||
/// let mut buf = VecDeque::new();
|
||||
/// buf.extend(1..5);
|
||||
/// buf.retain(|&x| x%2 == 0);
|
||||
///
|
||||
/// let v: Vec<_> = buf.into_iter().collect();
|
||||
/// assert_eq!(&v[..], &[2, 4]);
|
||||
/// assert_eq!(buf, [2, 4]);
|
||||
/// ```
|
||||
#[stable(feature = "vec_deque_retain", since = "1.4.0")]
|
||||
pub fn retain<F>(&mut self, mut f: F)
|
||||
|
|
@ -1779,23 +1771,21 @@ impl<T: Clone> VecDeque<T> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(deque_extras)]
|
||||
///
|
||||
/// use std::collections::VecDeque;
|
||||
///
|
||||
/// let mut buf = VecDeque::new();
|
||||
/// buf.push_back(5);
|
||||
/// buf.push_back(10);
|
||||
/// buf.push_back(15);
|
||||
/// assert_eq!(buf, [5, 10, 15]);
|
||||
///
|
||||
/// buf.resize(2, 0);
|
||||
/// buf.resize(6, 20);
|
||||
/// for (a, b) in [5, 10, 20, 20, 20, 20].iter().zip(&buf) {
|
||||
/// assert_eq!(a, b);
|
||||
/// }
|
||||
/// assert_eq!(buf, [5, 10]);
|
||||
///
|
||||
/// buf.resize(5, 20);
|
||||
/// assert_eq!(buf, [5, 10, 20, 20, 20]);
|
||||
/// ```
|
||||
#[unstable(feature = "deque_extras",
|
||||
reason = "matches collection reform specification; waiting on panic semantics",
|
||||
issue = "27788")]
|
||||
#[stable(feature = "deque_extras", since = "1.16.0")]
|
||||
pub fn resize(&mut self, new_len: usize, value: T) {
|
||||
let len = self.len();
|
||||
|
||||
|
|
@ -2170,6 +2160,46 @@ impl<A: PartialEq> PartialEq for VecDeque<A> {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A: Eq> Eq for VecDeque<A> {}
|
||||
|
||||
macro_rules! __impl_slice_eq1 {
|
||||
($Lhs: ty, $Rhs: ty) => {
|
||||
__impl_slice_eq1! { $Lhs, $Rhs, Sized }
|
||||
};
|
||||
($Lhs: ty, $Rhs: ty, $Bound: ident) => {
|
||||
#[stable(feature = "vec-deque-partial-eq-slice", since = "1.16.0")]
|
||||
impl<'a, 'b, A: $Bound, B> PartialEq<$Rhs> for $Lhs where A: PartialEq<B> {
|
||||
fn eq(&self, other: &$Rhs) -> bool {
|
||||
if self.len() != other.len() {
|
||||
return false;
|
||||
}
|
||||
let (sa, sb) = self.as_slices();
|
||||
let (oa, ob) = other[..].split_at(sa.len());
|
||||
sa == oa && sb == ob
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__impl_slice_eq1! { VecDeque<A>, Vec<B> }
|
||||
__impl_slice_eq1! { VecDeque<A>, &'b [B] }
|
||||
__impl_slice_eq1! { VecDeque<A>, &'b mut [B] }
|
||||
|
||||
macro_rules! array_impls {
|
||||
($($N: expr)+) => {
|
||||
$(
|
||||
__impl_slice_eq1! { VecDeque<A>, [B; $N] }
|
||||
__impl_slice_eq1! { VecDeque<A>, &'b [B; $N] }
|
||||
__impl_slice_eq1! { VecDeque<A>, &'b mut [B; $N] }
|
||||
)+
|
||||
}
|
||||
}
|
||||
|
||||
array_impls! {
|
||||
0 1 2 3 4 5 6 7 8 9
|
||||
10 11 12 13 14 15 16 17 18 19
|
||||
20 21 22 23 24 25 26 27 28 29
|
||||
30 31 32
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A: PartialOrd> PartialOrd for VecDeque<A> {
|
||||
fn partial_cmp(&self, other: &VecDeque<A>) -> Option<Ordering> {
|
||||
|
|
@ -2442,7 +2472,7 @@ mod tests {
|
|||
let final_len = usable_cap / 2;
|
||||
|
||||
for len in 0..final_len {
|
||||
let expected = if back {
|
||||
let expected: VecDeque<_> = if back {
|
||||
(0..len).collect()
|
||||
} else {
|
||||
(0..len).rev().collect()
|
||||
|
|
@ -2491,7 +2521,7 @@ mod tests {
|
|||
// len is the length *after* insertion
|
||||
for len in 1..cap {
|
||||
// 0, 1, 2, .., len - 1
|
||||
let expected = (0..).take(len).collect();
|
||||
let expected = (0..).take(len).collect::<VecDeque<_>>();
|
||||
for tail_pos in 0..cap {
|
||||
for to_insert in 0..len {
|
||||
tester.tail = tail_pos;
|
||||
|
|
@ -2524,7 +2554,7 @@ mod tests {
|
|||
// len is the length *after* removal
|
||||
for len in 0..cap - 1 {
|
||||
// 0, 1, 2, .., len - 1
|
||||
let expected = (0..).take(len).collect();
|
||||
let expected = (0..).take(len).collect::<VecDeque<_>>();
|
||||
for tail_pos in 0..cap {
|
||||
for to_remove in 0..len + 1 {
|
||||
tester.tail = tail_pos;
|
||||
|
|
@ -2599,7 +2629,7 @@ mod tests {
|
|||
|
||||
for len in 0..cap + 1 {
|
||||
// 0, 1, 2, .., len - 1
|
||||
let expected = (0..).take(len).collect();
|
||||
let expected = (0..).take(len).collect::<VecDeque<_>>();
|
||||
for tail_pos in 0..max_cap + 1 {
|
||||
tester.tail = tail_pos;
|
||||
tester.head = tail_pos;
|
||||
|
|
@ -2632,9 +2662,9 @@ mod tests {
|
|||
// index to split at
|
||||
for at in 0..len + 1 {
|
||||
// 0, 1, 2, .., at - 1 (may be empty)
|
||||
let expected_self = (0..).take(at).collect();
|
||||
let expected_self = (0..).take(at).collect::<VecDeque<_>>();
|
||||
// at, at + 1, .., len - 1 (may be empty)
|
||||
let expected_other = (at..).take(len - at).collect();
|
||||
let expected_other = (at..).take(len - at).collect::<VecDeque<_>>();
|
||||
|
||||
for tail_pos in 0..cap {
|
||||
tester.tail = tail_pos;
|
||||
|
|
|
|||
|
|
@ -1,268 +0,0 @@
|
|||
// Copyright 2012 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::mem;
|
||||
|
||||
use collections::enum_set::{CLike, EnumSet};
|
||||
|
||||
use self::Foo::*;
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||
#[repr(usize)]
|
||||
enum Foo {
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
}
|
||||
|
||||
impl CLike for Foo {
|
||||
fn to_usize(&self) -> usize {
|
||||
*self as usize
|
||||
}
|
||||
|
||||
fn from_usize(v: usize) -> Foo {
|
||||
unsafe { mem::transmute(v) }
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_new() {
|
||||
let e: EnumSet<Foo> = EnumSet::new();
|
||||
assert!(e.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_show() {
|
||||
let mut e = EnumSet::new();
|
||||
assert!(format!("{:?}", e) == "{}");
|
||||
e.insert(A);
|
||||
assert!(format!("{:?}", e) == "{A}");
|
||||
e.insert(C);
|
||||
assert!(format!("{:?}", e) == "{A, C}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_len() {
|
||||
let mut e = EnumSet::new();
|
||||
assert_eq!(e.len(), 0);
|
||||
e.insert(A);
|
||||
e.insert(B);
|
||||
e.insert(C);
|
||||
assert_eq!(e.len(), 3);
|
||||
e.remove(&A);
|
||||
assert_eq!(e.len(), 2);
|
||||
e.clear();
|
||||
assert_eq!(e.len(), 0);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// intersect
|
||||
|
||||
#[test]
|
||||
fn test_two_empties_do_not_intersect() {
|
||||
let e1: EnumSet<Foo> = EnumSet::new();
|
||||
let e2: EnumSet<Foo> = EnumSet::new();
|
||||
assert!(e1.is_disjoint(&e2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_empty_does_not_intersect_with_full() {
|
||||
let e1: EnumSet<Foo> = EnumSet::new();
|
||||
|
||||
let mut e2: EnumSet<Foo> = EnumSet::new();
|
||||
e2.insert(A);
|
||||
e2.insert(B);
|
||||
e2.insert(C);
|
||||
|
||||
assert!(e1.is_disjoint(&e2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_disjoint_intersects() {
|
||||
let mut e1: EnumSet<Foo> = EnumSet::new();
|
||||
e1.insert(A);
|
||||
|
||||
let mut e2: EnumSet<Foo> = EnumSet::new();
|
||||
e2.insert(B);
|
||||
|
||||
assert!(e1.is_disjoint(&e2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_overlapping_intersects() {
|
||||
let mut e1: EnumSet<Foo> = EnumSet::new();
|
||||
e1.insert(A);
|
||||
|
||||
let mut e2: EnumSet<Foo> = EnumSet::new();
|
||||
e2.insert(A);
|
||||
e2.insert(B);
|
||||
|
||||
assert!(!e1.is_disjoint(&e2));
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// contains and contains_elem
|
||||
|
||||
#[test]
|
||||
fn test_superset() {
|
||||
let mut e1: EnumSet<Foo> = EnumSet::new();
|
||||
e1.insert(A);
|
||||
|
||||
let mut e2: EnumSet<Foo> = EnumSet::new();
|
||||
e2.insert(A);
|
||||
e2.insert(B);
|
||||
|
||||
let mut e3: EnumSet<Foo> = EnumSet::new();
|
||||
e3.insert(C);
|
||||
|
||||
assert!(e1.is_subset(&e2));
|
||||
assert!(e2.is_superset(&e1));
|
||||
assert!(!e3.is_superset(&e2));
|
||||
assert!(!e2.is_superset(&e3))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_contains() {
|
||||
let mut e1: EnumSet<Foo> = EnumSet::new();
|
||||
e1.insert(A);
|
||||
assert!(e1.contains(&A));
|
||||
assert!(!e1.contains(&B));
|
||||
assert!(!e1.contains(&C));
|
||||
|
||||
e1.insert(A);
|
||||
e1.insert(B);
|
||||
assert!(e1.contains(&A));
|
||||
assert!(e1.contains(&B));
|
||||
assert!(!e1.contains(&C));
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// iter
|
||||
|
||||
#[test]
|
||||
fn test_iterator() {
|
||||
let mut e1: EnumSet<Foo> = EnumSet::new();
|
||||
|
||||
let elems: Vec<Foo> = e1.iter().collect();
|
||||
assert!(elems.is_empty());
|
||||
|
||||
e1.insert(A);
|
||||
let elems: Vec<_> = e1.iter().collect();
|
||||
assert_eq!(elems, [A]);
|
||||
|
||||
e1.insert(C);
|
||||
let elems: Vec<_> = e1.iter().collect();
|
||||
assert_eq!(elems, [A, C]);
|
||||
|
||||
e1.insert(C);
|
||||
let elems: Vec<_> = e1.iter().collect();
|
||||
assert_eq!(elems, [A, C]);
|
||||
|
||||
e1.insert(B);
|
||||
let elems: Vec<_> = e1.iter().collect();
|
||||
assert_eq!(elems, [A, B, C]);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// operators
|
||||
|
||||
#[test]
|
||||
fn test_operators() {
|
||||
let mut e1: EnumSet<Foo> = EnumSet::new();
|
||||
e1.insert(A);
|
||||
e1.insert(C);
|
||||
|
||||
let mut e2: EnumSet<Foo> = EnumSet::new();
|
||||
e2.insert(B);
|
||||
e2.insert(C);
|
||||
|
||||
let e_union = e1 | e2;
|
||||
let elems: Vec<_> = e_union.iter().collect();
|
||||
assert_eq!(elems, [A, B, C]);
|
||||
|
||||
let e_intersection = e1 & e2;
|
||||
let elems: Vec<_> = e_intersection.iter().collect();
|
||||
assert_eq!(elems, [C]);
|
||||
|
||||
// Another way to express intersection
|
||||
let e_intersection = e1 - (e1 - e2);
|
||||
let elems: Vec<_> = e_intersection.iter().collect();
|
||||
assert_eq!(elems, [C]);
|
||||
|
||||
let e_subtract = e1 - e2;
|
||||
let elems: Vec<_> = e_subtract.iter().collect();
|
||||
assert_eq!(elems, [A]);
|
||||
|
||||
// Bitwise XOR of two sets, aka symmetric difference
|
||||
let e_symmetric_diff = e1 ^ e2;
|
||||
let elems: Vec<_> = e_symmetric_diff.iter().collect();
|
||||
assert_eq!(elems, [A, B]);
|
||||
|
||||
// Another way to express symmetric difference
|
||||
let e_symmetric_diff = (e1 - e2) | (e2 - e1);
|
||||
let elems: Vec<_> = e_symmetric_diff.iter().collect();
|
||||
assert_eq!(elems, [A, B]);
|
||||
|
||||
// Yet another way to express symmetric difference
|
||||
let e_symmetric_diff = (e1 | e2) - (e1 & e2);
|
||||
let elems: Vec<_> = e_symmetric_diff.iter().collect();
|
||||
assert_eq!(elems, [A, B]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_overflow() {
|
||||
#[allow(dead_code)]
|
||||
#[derive(Copy, Clone)]
|
||||
#[repr(usize)]
|
||||
enum Bar {
|
||||
V00, V01, V02, V03, V04, V05, V06, V07, V08, V09,
|
||||
V10, V11, V12, V13, V14, V15, V16, V17, V18, V19,
|
||||
V20, V21, V22, V23, V24, V25, V26, V27, V28, V29,
|
||||
V30, V31, V32, V33, V34, V35, V36, V37, V38, V39,
|
||||
V40, V41, V42, V43, V44, V45, V46, V47, V48, V49,
|
||||
V50, V51, V52, V53, V54, V55, V56, V57, V58, V59,
|
||||
V60, V61, V62, V63, V64, V65, V66, V67, V68, V69,
|
||||
}
|
||||
|
||||
impl CLike for Bar {
|
||||
fn to_usize(&self) -> usize {
|
||||
*self as usize
|
||||
}
|
||||
|
||||
fn from_usize(v: usize) -> Bar {
|
||||
unsafe { mem::transmute(v) }
|
||||
}
|
||||
}
|
||||
let mut set = EnumSet::new();
|
||||
set.insert(Bar::V64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_extend_ref() {
|
||||
let mut a = EnumSet::new();
|
||||
a.insert(A);
|
||||
|
||||
a.extend(&[A, C]);
|
||||
|
||||
assert_eq!(a.len(), 2);
|
||||
assert!(a.contains(&A));
|
||||
assert!(a.contains(&C));
|
||||
|
||||
let mut b = EnumSet::new();
|
||||
b.insert(B);
|
||||
|
||||
a.extend(&b);
|
||||
|
||||
assert_eq!(a.len(), 3);
|
||||
assert!(a.contains(&A));
|
||||
assert!(a.contains(&B));
|
||||
assert!(a.contains(&C));
|
||||
}
|
||||
|
|
@ -18,17 +18,12 @@
|
|||
#![feature(collections)]
|
||||
#![feature(collections_bound)]
|
||||
#![feature(const_fn)]
|
||||
#![feature(dedup_by)]
|
||||
#![feature(enumset)]
|
||||
#![feature(exact_size_is_empty)]
|
||||
#![feature(pattern)]
|
||||
#![feature(placement_in_syntax)]
|
||||
#![feature(rand)]
|
||||
#![feature(repeat_str)]
|
||||
#![feature(step_by)]
|
||||
#![feature(str_escape)]
|
||||
#![feature(str_replacen)]
|
||||
#![feature(string_split_off)]
|
||||
#![feature(test)]
|
||||
#![feature(unboxed_closures)]
|
||||
#![feature(unicode)]
|
||||
|
|
@ -47,7 +42,6 @@ mod bench;
|
|||
mod binary_heap;
|
||||
mod btree;
|
||||
mod cow_str;
|
||||
mod enum_set;
|
||||
mod fmt;
|
||||
mod linked_list;
|
||||
mod slice;
|
||||
|
|
|
|||
|
|
@ -603,6 +603,25 @@ fn test_eq() {
|
|||
assert!(e == VecDeque::new());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_partial_eq_array() {
|
||||
let d = VecDeque::<char>::new();
|
||||
assert!(d == []);
|
||||
|
||||
let mut d = VecDeque::new();
|
||||
d.push_front('a');
|
||||
assert!(d == ['a']);
|
||||
|
||||
let mut d = VecDeque::new();
|
||||
d.push_back('a');
|
||||
assert!(d == ['a']);
|
||||
|
||||
let mut d = VecDeque::new();
|
||||
d.push_back('a');
|
||||
d.push_back('b');
|
||||
assert!(d == ['a', 'b']);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hash() {
|
||||
let mut x = VecDeque::new();
|
||||
|
|
|
|||
|
|
@ -15,10 +15,18 @@
|
|||
//! references. We say that `Cell<T>` and `RefCell<T>` provide 'interior mutability', in contrast
|
||||
//! with typical Rust types that exhibit 'inherited mutability'.
|
||||
//!
|
||||
//! Cell types come in two flavors: `Cell<T>` and `RefCell<T>`. `Cell<T>` provides `get` and `set`
|
||||
//! methods that change the interior value with a single method call. `Cell<T>` though is only
|
||||
//! compatible with types that implement `Copy`. For other types, one must use the `RefCell<T>`
|
||||
//! type, acquiring a write lock before mutating.
|
||||
//! Cell types come in two flavors: `Cell<T>` and `RefCell<T>`. `Cell<T>` implements interior
|
||||
//! mutability by moving values in and out of the `Cell<T>`. To use references instead of values,
|
||||
//! one must use the `RefCell<T>` type, acquiring a write lock before mutating. `Cell<T>` provides
|
||||
//! methods to retrieve and change the current interior value:
|
||||
//!
|
||||
//! - For types that implement `Copy`, the `get` method retrieves the current interior value.
|
||||
//! - For types that implement `Default`, the `take` method replaces the current interior value
|
||||
//! with `Default::default()` and returns the replaced value.
|
||||
//! - For all types, the `replace` method replaces the current interior value and returns the
|
||||
//! replaced value and the `into_inner` method consumes the `Cell<T>` and returns the interior
|
||||
//! value. Additionally, the `set` method replaces the interior value, dropping the replaced
|
||||
//! value.
|
||||
//!
|
||||
//! `RefCell<T>` uses Rust's lifetimes to implement 'dynamic borrowing', a process whereby one can
|
||||
//! claim temporary, exclusive, mutable access to the inner value. Borrows for `RefCell<T>`s are
|
||||
|
|
@ -176,9 +184,10 @@
|
|||
use cmp::Ordering;
|
||||
use fmt::{self, Debug, Display};
|
||||
use marker::Unsize;
|
||||
use mem;
|
||||
use ops::{Deref, DerefMut, CoerceUnsized};
|
||||
|
||||
/// A mutable memory location that admits only `Copy` data.
|
||||
/// A mutable memory location.
|
||||
///
|
||||
/// See the [module-level documentation](index.html) for more.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
|
@ -187,23 +196,6 @@ pub struct Cell<T> {
|
|||
}
|
||||
|
||||
impl<T:Copy> Cell<T> {
|
||||
/// Creates a new `Cell` containing the given value.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::cell::Cell;
|
||||
///
|
||||
/// let c = Cell::new(5);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub const fn new(value: T) -> Cell<T> {
|
||||
Cell {
|
||||
value: UnsafeCell::new(value),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a copy of the contained value.
|
||||
///
|
||||
/// # Examples
|
||||
|
|
@ -221,25 +213,6 @@ impl<T:Copy> Cell<T> {
|
|||
unsafe{ *self.value.get() }
|
||||
}
|
||||
|
||||
/// Sets the contained value.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::cell::Cell;
|
||||
///
|
||||
/// let c = Cell::new(5);
|
||||
///
|
||||
/// c.set(10);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn set(&self, value: T) {
|
||||
unsafe {
|
||||
*self.value.get() = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a reference to the underlying `UnsafeCell`.
|
||||
///
|
||||
/// # Examples
|
||||
|
|
@ -378,6 +351,100 @@ impl<T: Copy> From<T> for Cell<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> Cell<T> {
|
||||
/// Creates a new `Cell` containing the given value.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::cell::Cell;
|
||||
///
|
||||
/// let c = Cell::new(5);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub const fn new(value: T) -> Cell<T> {
|
||||
Cell {
|
||||
value: UnsafeCell::new(value),
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the contained value.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::cell::Cell;
|
||||
///
|
||||
/// let c = Cell::new(5);
|
||||
///
|
||||
/// c.set(10);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn set(&self, val: T) {
|
||||
let old = self.replace(val);
|
||||
drop(old);
|
||||
}
|
||||
|
||||
/// Replaces the contained value.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(move_cell)]
|
||||
/// use std::cell::Cell;
|
||||
///
|
||||
/// let c = Cell::new(5);
|
||||
/// let old = c.replace(10);
|
||||
///
|
||||
/// assert_eq!(5, old);
|
||||
/// ```
|
||||
#[unstable(feature = "move_cell", issue = "39264")]
|
||||
pub fn replace(&self, val: T) -> T {
|
||||
mem::replace(unsafe { &mut *self.value.get() }, val)
|
||||
}
|
||||
|
||||
/// Unwraps the value.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(move_cell)]
|
||||
/// use std::cell::Cell;
|
||||
///
|
||||
/// let c = Cell::new(5);
|
||||
/// let five = c.into_inner();
|
||||
///
|
||||
/// assert_eq!(five, 5);
|
||||
/// ```
|
||||
#[unstable(feature = "move_cell", issue = "39264")]
|
||||
pub fn into_inner(self) -> T {
|
||||
unsafe { self.value.into_inner() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Default> Cell<T> {
|
||||
/// Takes the value of the cell, leaving `Default::default()` in its place.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(move_cell)]
|
||||
/// use std::cell::Cell;
|
||||
///
|
||||
/// let c = Cell::new(5);
|
||||
/// let five = c.take();
|
||||
///
|
||||
/// assert_eq!(five, 5);
|
||||
/// assert_eq!(c.into_inner(), 0);
|
||||
/// ```
|
||||
#[unstable(feature = "move_cell", issue = "39264")]
|
||||
pub fn take(&self) -> T {
|
||||
self.replace(Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "coerce_unsized", issue = "27732")]
|
||||
impl<T: CoerceUnsized<U>, U> CoerceUnsized<Cell<U>> for Cell<T> {}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,25 +18,33 @@
|
|||
//! support arguments of multiple types.
|
||||
//!
|
||||
//! - Impl the `As*` traits for reference-to-reference conversions
|
||||
//! - Impl the `Into` trait when you want to consume the value in the conversion
|
||||
//! - The `From` trait is the most flexible, useful for value _and_ reference conversions
|
||||
//! - The `TryFrom` and `TryInto` traits behave like `From` and `Into`, but allow for the
|
||||
//! - Impl the [`Into`] trait when you want to consume the value in the conversion
|
||||
//! - The [`From`] trait is the most flexible, useful for value _and_ reference conversions
|
||||
//! - The [`TryFrom`] and [`TryInto`] traits behave like [`From`] and [`Into`], but allow for the
|
||||
//! conversion to fail
|
||||
//!
|
||||
//! As a library author, you should prefer implementing `From<T>` or `TryFrom<T>` rather than
|
||||
//! `Into<U>` or `TryInto<U>`, as `From` and `TryFrom` provide greater flexibility and offer
|
||||
//! equivalent `Into` or `TryInto` implementations for free, thanks to a blanket implementation
|
||||
//! As a library author, you should prefer implementing [`From<T>`][`From`] or
|
||||
//! [`TryFrom<T>`][`TryFrom`] rather than [`Into<U>`][`Into`] or [`TryInto<U>`][`TryInto`],
|
||||
//! as [`From`] and [`TryFrom`] provide greater flexibility and offer
|
||||
//! equivalent [`Into`] or [`TryInto`] implementations for free, thanks to a blanket implementation
|
||||
//! in the standard library.
|
||||
//!
|
||||
//! # Generic impl
|
||||
//!
|
||||
//! - `AsRef` and `AsMut` auto-dereference if the inner type is a reference
|
||||
//! - `From<U> for T` implies `Into<T> for U`
|
||||
//! - `TryFrom<U> for T` implies `TryInto<T> for U`
|
||||
//! - `From` and `Into` are reflexive, which means that all types can `into()`
|
||||
//! - [`AsRef`] and [`AsMut`] auto-dereference if the inner type is a reference
|
||||
//! - [`From`]`<U> for T` implies [`Into`]`<T> for U`
|
||||
//! - [`TryFrom`]`<U> for T` implies [`TryInto`]`<T> for U`
|
||||
//! - [`From`] and [`Into`] are reflexive, which means that all types can `into()`
|
||||
//! themselves and `from()` themselves
|
||||
//!
|
||||
//! See each trait for usage examples.
|
||||
//!
|
||||
//! [`Into`]: trait.Into.html
|
||||
//! [`From`]: trait.From.html
|
||||
//! [`TryFrom`]: trait.TryFrom.html
|
||||
//! [`TryInto`]: trait.TryInto.html
|
||||
//! [`AsRef`]: trait.AsRef.html
|
||||
//! [`AsMut`]: trait.AsMut.html
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
|
|
|
|||
|
|
@ -307,6 +307,7 @@ pub trait BuildHasher {
|
|||
/// [`BuildHasher`]: trait.BuildHasher.html
|
||||
/// [`Default`]: ../default/trait.Default.html
|
||||
/// [`Hasher`]: trait.Hasher.html
|
||||
/// [`HashMap`]: ../../std/collections/struct.HashMap.html
|
||||
#[stable(since = "1.7.0", feature = "build_hasher")]
|
||||
pub struct BuildHasherDefault<H>(marker::PhantomData<H>);
|
||||
|
||||
|
|
|
|||
|
|
@ -1108,9 +1108,9 @@ pub trait Iterator {
|
|||
///
|
||||
/// One of the keys to `collect()`'s power is that many things you might
|
||||
/// not think of as 'collections' actually are. For example, a [`String`]
|
||||
/// is a collection of [`char`]s. And a collection of [`Result<T, E>`] can
|
||||
/// be thought of as single [`Result`]`<Collection<T>, E>`. See the examples
|
||||
/// below for more.
|
||||
/// is a collection of [`char`]s. And a collection of
|
||||
/// [`Result<T, E>`][`Result`] can be thought of as single
|
||||
/// [`Result`]`<Collection<T>, E>`. See the examples below for more.
|
||||
///
|
||||
/// Because `collect()` is so general, it can cause problems with type
|
||||
/// inference. As such, `collect()` is one of the few times you'll see
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@
|
|||
//! the optional owned box, [`Option`]`<`[`Box<T>`]`>`.
|
||||
//!
|
||||
//! The following example uses [`Option`] to create an optional box of
|
||||
//! [`i32`]. Notice that in order to use the inner [`i32`] value first the
|
||||
//! [`i32`]. Notice that in order to use the inner [`i32`] value first, the
|
||||
//! `check_optional` function needs to use pattern matching to
|
||||
//! determine whether the box has a value (i.e. it is [`Some(...)`][`Some`]) or
|
||||
//! not ([`None`]).
|
||||
|
|
@ -74,8 +74,8 @@
|
|||
//!
|
||||
//! fn check_optional(optional: &Option<Box<i32>>) {
|
||||
//! match *optional {
|
||||
//! Some(ref p) => println!("have value {}", p),
|
||||
//! None => println!("have no value"),
|
||||
//! Some(ref p) => println!("has value {}", p),
|
||||
//! None => println!("has no value"),
|
||||
//! }
|
||||
//! }
|
||||
//! ```
|
||||
|
|
|
|||
|
|
@ -448,7 +448,6 @@ impl<T: ?Sized> *const T {
|
|||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(ptr_wrapping_offset)]
|
||||
/// // Iterate using a raw pointer in increments of two elements
|
||||
/// let data = [1u8, 2, 3, 4, 5];
|
||||
/// let mut ptr: *const u8 = data.as_ptr();
|
||||
|
|
@ -463,7 +462,7 @@ impl<T: ?Sized> *const T {
|
|||
/// ptr = ptr.wrapping_offset(step);
|
||||
/// }
|
||||
/// ```
|
||||
#[unstable(feature = "ptr_wrapping_offset", issue = "37570")]
|
||||
#[stable(feature = "ptr_wrapping_offset", since = "1.16.0")]
|
||||
#[inline]
|
||||
pub fn wrapping_offset(self, count: isize) -> *const T where T: Sized {
|
||||
unsafe {
|
||||
|
|
@ -572,7 +571,6 @@ impl<T: ?Sized> *mut T {
|
|||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(ptr_wrapping_offset)]
|
||||
/// // Iterate using a raw pointer in increments of two elements
|
||||
/// let mut data = [1u8, 2, 3, 4, 5];
|
||||
/// let mut ptr: *mut u8 = data.as_mut_ptr();
|
||||
|
|
@ -587,7 +585,7 @@ impl<T: ?Sized> *mut T {
|
|||
/// }
|
||||
/// assert_eq!(&data, &[0, 2, 0, 4, 0]);
|
||||
/// ```
|
||||
#[unstable(feature = "ptr_wrapping_offset", issue = "37570")]
|
||||
#[stable(feature = "ptr_wrapping_offset", since = "1.16.0")]
|
||||
#[inline]
|
||||
pub fn wrapping_offset(self, count: isize) -> *mut T where T: Sized {
|
||||
unsafe {
|
||||
|
|
|
|||
|
|
@ -840,8 +840,6 @@ impl<T: Default, E> Result<T, E> {
|
|||
/// `Err` on error.
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(result_unwrap_or_default)]
|
||||
///
|
||||
/// let good_year_from_input = "1909";
|
||||
/// let bad_year_from_input = "190blarg";
|
||||
/// let good_year = good_year_from_input.parse().unwrap_or_default();
|
||||
|
|
@ -854,7 +852,7 @@ impl<T: Default, E> Result<T, E> {
|
|||
/// [`FromStr`]: ../../std/str/trait.FromStr.html
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "result_unwrap_or_default", issue = "37516")]
|
||||
#[stable(feature = "result_unwrap_or_default", since = "1.16.0")]
|
||||
pub fn unwrap_or_default(self) -> T {
|
||||
match self {
|
||||
Ok(x) => x,
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
//! same as [LLVM atomic orderings][1]. For more information see the [nomicon][2].
|
||||
//!
|
||||
//! [1]: http://llvm.org/docs/LangRef.html#memory-model-for-concurrent-operations
|
||||
//! [2]: https://doc.rust-lang.org/nomicon/atomics.html
|
||||
//! [2]: ../../../nomicon/atomics.html
|
||||
//!
|
||||
//! Atomic variables are safe to share between threads (they implement `Sync`)
|
||||
//! but they do not themselves provide the mechanism for sharing and follow the
|
||||
|
|
@ -144,7 +144,7 @@ unsafe impl<T> Sync for AtomicPtr<T> {}
|
|||
/// LLVM's](http://llvm.org/docs/LangRef.html#memory-model-for-concurrent-operations).
|
||||
///
|
||||
/// For more information see the [nomicon][1].
|
||||
/// [1]: https://doc.rust-lang.org/nomicon/atomics.html
|
||||
/// [1]: ../../../nomicon/atomics.html
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum Ordering {
|
||||
|
|
|
|||
|
|
@ -209,6 +209,37 @@ fn cell_default() {
|
|||
assert_eq!(0, cell.get());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cell_set() {
|
||||
let cell = Cell::new(10);
|
||||
cell.set(20);
|
||||
assert_eq!(20, cell.get());
|
||||
|
||||
let cell = Cell::new("Hello".to_owned());
|
||||
cell.set("World".to_owned());
|
||||
assert_eq!("World".to_owned(), cell.into_inner());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cell_replace() {
|
||||
let cell = Cell::new(10);
|
||||
assert_eq!(10, cell.replace(20));
|
||||
assert_eq!(20, cell.get());
|
||||
|
||||
let cell = Cell::new("Hello".to_owned());
|
||||
assert_eq!("Hello".to_owned(), cell.replace("World".to_owned()));
|
||||
assert_eq!("World".to_owned(), cell.into_inner());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cell_into_inner() {
|
||||
let cell = Cell::new(10);
|
||||
assert_eq!(10, cell.into_inner());
|
||||
|
||||
let cell = Cell::new("Hello world".to_owned());
|
||||
assert_eq!("Hello world".to_owned(), cell.into_inner());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn refcell_default() {
|
||||
let cell: RefCell<u64> = Default::default();
|
||||
|
|
|
|||
|
|
@ -66,7 +66,6 @@ fn test_writer_hasher() {
|
|||
assert_eq!(hash(& s), 97 + 0xFF);
|
||||
let cs: &[u8] = &[1, 2, 3];
|
||||
assert_eq!(hash(& cs), 9);
|
||||
// FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
|
||||
let cs: Box<[u8]> = Box::new([1, 2, 3]);
|
||||
assert_eq!(hash(& cs), 9);
|
||||
|
||||
|
|
|
|||
|
|
@ -700,7 +700,6 @@ fn test_collect() {
|
|||
|
||||
#[test]
|
||||
fn test_all() {
|
||||
// FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
|
||||
let v: Box<[isize]> = Box::new([1, 2, 3, 4, 5]);
|
||||
assert!(v.iter().all(|&x| x < 10));
|
||||
assert!(!v.iter().all(|&x| x % 2 == 0));
|
||||
|
|
@ -710,7 +709,6 @@ fn test_all() {
|
|||
|
||||
#[test]
|
||||
fn test_any() {
|
||||
// FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
|
||||
let v: Box<[isize]> = Box::new([1, 2, 3, 4, 5]);
|
||||
assert!(v.iter().any(|&x| x < 10));
|
||||
assert!(v.iter().any(|&x| x % 2 == 0));
|
||||
|
|
|
|||
|
|
@ -32,8 +32,8 @@
|
|||
#![feature(unicode)]
|
||||
#![feature(unique)]
|
||||
#![feature(ordering_chaining)]
|
||||
#![feature(result_unwrap_or_default)]
|
||||
#![feature(ptr_unaligned)]
|
||||
#![feature(move_cell)]
|
||||
#![feature(fmt_internals)]
|
||||
|
||||
extern crate core;
|
||||
|
|
|
|||
|
|
@ -327,6 +327,69 @@ struct ListNode {
|
|||
This works because `Box` is a pointer, so its size is well-known.
|
||||
"##,
|
||||
|
||||
E0106: r##"
|
||||
This error indicates that a lifetime is missing from a type. If it is an error
|
||||
inside a function signature, the problem may be with failing to adhere to the
|
||||
lifetime elision rules (see below).
|
||||
|
||||
Here are some simple examples of where you'll run into this error:
|
||||
|
||||
```compile_fail,E0106
|
||||
struct Foo { x: &bool } // error
|
||||
struct Foo<'a> { x: &'a bool } // correct
|
||||
|
||||
enum Bar { A(u8), B(&bool), } // error
|
||||
enum Bar<'a> { A(u8), B(&'a bool), } // correct
|
||||
|
||||
type MyStr = &str; // error
|
||||
type MyStr<'a> = &'a str; // correct
|
||||
```
|
||||
|
||||
Lifetime elision is a special, limited kind of inference for lifetimes in
|
||||
function signatures which allows you to leave out lifetimes in certain cases.
|
||||
For more background on lifetime elision see [the book][book-le].
|
||||
|
||||
The lifetime elision rules require that any function signature with an elided
|
||||
output lifetime must either have
|
||||
|
||||
- exactly one input lifetime
|
||||
- or, multiple input lifetimes, but the function must also be a method with a
|
||||
`&self` or `&mut self` receiver
|
||||
|
||||
In the first case, the output lifetime is inferred to be the same as the unique
|
||||
input lifetime. In the second case, the lifetime is instead inferred to be the
|
||||
same as the lifetime on `&self` or `&mut self`.
|
||||
|
||||
Here are some examples of elision errors:
|
||||
|
||||
```compile_fail,E0106
|
||||
// error, no input lifetimes
|
||||
fn foo() -> &str { }
|
||||
|
||||
// error, `x` and `y` have distinct lifetimes inferred
|
||||
fn bar(x: &str, y: &str) -> &str { }
|
||||
|
||||
// error, `y`'s lifetime is inferred to be distinct from `x`'s
|
||||
fn baz<'a>(x: &'a str, y: &str) -> &str { }
|
||||
```
|
||||
|
||||
Here's an example that is currently an error, but may work in a future version
|
||||
of Rust:
|
||||
|
||||
```compile_fail,E0106
|
||||
struct Foo<'a>(&'a str);
|
||||
|
||||
trait Quux { }
|
||||
impl Quux for Foo { }
|
||||
```
|
||||
|
||||
Lifetime elision in implementation headers was part of the lifetime elision
|
||||
RFC. It is, however, [currently unimplemented][iss15872].
|
||||
|
||||
[book-le]: https://doc.rust-lang.org/nightly/book/lifetimes.html#lifetime-elision
|
||||
[iss15872]: https://github.com/rust-lang/rust/issues/15872
|
||||
"##,
|
||||
|
||||
E0109: r##"
|
||||
You tried to give a type parameter to a type which doesn't need it. Erroneous
|
||||
code example:
|
||||
|
|
|
|||
|
|
@ -301,7 +301,7 @@ pub trait Visitor<'v> : Sized {
|
|||
fn visit_ty_param_bound(&mut self, bounds: &'v TyParamBound) {
|
||||
walk_ty_param_bound(self, bounds)
|
||||
}
|
||||
fn visit_poly_trait_ref(&mut self, t: &'v PolyTraitRef, m: &'v TraitBoundModifier) {
|
||||
fn visit_poly_trait_ref(&mut self, t: &'v PolyTraitRef, m: TraitBoundModifier) {
|
||||
walk_poly_trait_ref(self, t, m)
|
||||
}
|
||||
fn visit_variant_data(&mut self,
|
||||
|
|
@ -421,7 +421,7 @@ pub fn walk_lifetime_def<'v, V: Visitor<'v>>(visitor: &mut V, lifetime_def: &'v
|
|||
|
||||
pub fn walk_poly_trait_ref<'v, V>(visitor: &mut V,
|
||||
trait_ref: &'v PolyTraitRef,
|
||||
_modifier: &'v TraitBoundModifier)
|
||||
_modifier: TraitBoundModifier)
|
||||
where V: Visitor<'v>
|
||||
{
|
||||
walk_list!(visitor, visit_lifetime_def, &trait_ref.bound_lifetimes);
|
||||
|
|
@ -547,8 +547,8 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
|
|||
TyPtr(ref mutable_type) => {
|
||||
visitor.visit_ty(&mutable_type.ty)
|
||||
}
|
||||
TyRptr(ref opt_lifetime, ref mutable_type) => {
|
||||
walk_list!(visitor, visit_lifetime, opt_lifetime);
|
||||
TyRptr(ref lifetime, ref mutable_type) => {
|
||||
visitor.visit_lifetime(lifetime);
|
||||
visitor.visit_ty(&mutable_type.ty)
|
||||
}
|
||||
TyNever => {},
|
||||
|
|
@ -566,8 +566,11 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
|
|||
visitor.visit_ty(ty);
|
||||
visitor.visit_nested_body(length)
|
||||
}
|
||||
TyTraitObject(ref bounds) => {
|
||||
walk_list!(visitor, visit_ty_param_bound, bounds);
|
||||
TyTraitObject(ref bounds, ref lifetime) => {
|
||||
for bound in bounds {
|
||||
visitor.visit_poly_trait_ref(bound, TraitBoundModifier::None);
|
||||
}
|
||||
visitor.visit_lifetime(lifetime);
|
||||
}
|
||||
TyImplTrait(ref bounds) => {
|
||||
walk_list!(visitor, visit_ty_param_bound, bounds);
|
||||
|
|
@ -695,7 +698,7 @@ pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V, foreign_item: &'v
|
|||
|
||||
pub fn walk_ty_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, bound: &'v TyParamBound) {
|
||||
match *bound {
|
||||
TraitTyParamBound(ref typ, ref modifier) => {
|
||||
TraitTyParamBound(ref typ, modifier) => {
|
||||
visitor.visit_poly_trait_ref(typ, modifier);
|
||||
}
|
||||
RegionTyParamBound(ref lifetime) => {
|
||||
|
|
|
|||
|
|
@ -41,12 +41,12 @@
|
|||
// in the HIR, especially for multiple identifiers.
|
||||
|
||||
use hir;
|
||||
use hir::map::Definitions;
|
||||
use hir::map::{Definitions, DefKey};
|
||||
use hir::map::definitions::DefPathData;
|
||||
use hir::def_id::{DefIndex, DefId};
|
||||
use hir::def::{Def, PathResolution};
|
||||
use session::Session;
|
||||
use util::nodemap::{NodeMap, FxHashMap};
|
||||
use util::nodemap::{DefIdMap, NodeMap, FxHashMap};
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use std::iter;
|
||||
|
|
@ -78,6 +78,8 @@ pub struct LoweringContext<'a> {
|
|||
trait_items: BTreeMap<hir::TraitItemId, hir::TraitItem>,
|
||||
impl_items: BTreeMap<hir::ImplItemId, hir::ImplItem>,
|
||||
bodies: FxHashMap<hir::BodyId, hir::Body>,
|
||||
|
||||
type_def_lifetime_params: DefIdMap<usize>,
|
||||
}
|
||||
|
||||
pub trait Resolver {
|
||||
|
|
@ -110,6 +112,7 @@ pub fn lower_crate(sess: &Session,
|
|||
trait_items: BTreeMap::new(),
|
||||
impl_items: BTreeMap::new(),
|
||||
bodies: FxHashMap(),
|
||||
type_def_lifetime_params: DefIdMap(),
|
||||
}.lower_crate(krate)
|
||||
}
|
||||
|
||||
|
|
@ -123,24 +126,33 @@ enum ParamMode {
|
|||
|
||||
impl<'a> LoweringContext<'a> {
|
||||
fn lower_crate(mut self, c: &Crate) -> hir::Crate {
|
||||
self.lower_items(c);
|
||||
let module = self.lower_mod(&c.module);
|
||||
let attrs = self.lower_attrs(&c.attrs);
|
||||
let exported_macros = c.exported_macros.iter().map(|m| self.lower_macro_def(m)).collect();
|
||||
|
||||
hir::Crate {
|
||||
module: module,
|
||||
attrs: attrs,
|
||||
span: c.span,
|
||||
exported_macros: exported_macros,
|
||||
items: self.items,
|
||||
trait_items: self.trait_items,
|
||||
impl_items: self.impl_items,
|
||||
bodies: self.bodies,
|
||||
/// Full-crate AST visitor that inserts into a fresh
|
||||
/// `LoweringContext` any information that may be
|
||||
/// needed from arbitrary locations in the crate.
|
||||
/// E.g. The number of lifetime generic parameters
|
||||
/// declared for every type and trait definition.
|
||||
struct MiscCollector<'lcx, 'interner: 'lcx> {
|
||||
lctx: &'lcx mut LoweringContext<'interner>,
|
||||
}
|
||||
|
||||
impl<'lcx, 'interner> Visitor<'lcx> for MiscCollector<'lcx, 'interner> {
|
||||
fn visit_item(&mut self, item: &'lcx Item) {
|
||||
match item.node {
|
||||
ItemKind::Struct(_, ref generics) |
|
||||
ItemKind::Union(_, ref generics) |
|
||||
ItemKind::Enum(_, ref generics) |
|
||||
ItemKind::Ty(_, ref generics) |
|
||||
ItemKind::Trait(_, ref generics, ..) => {
|
||||
let def_id = self.lctx.resolver.definitions().local_def_id(item.id);
|
||||
let count = generics.lifetimes.len();
|
||||
self.lctx.type_def_lifetime_params.insert(def_id, count);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
visit::walk_item(self, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn lower_items(&mut self, c: &Crate) {
|
||||
struct ItemLowerer<'lcx, 'interner: 'lcx> {
|
||||
lctx: &'lcx mut LoweringContext<'interner>,
|
||||
}
|
||||
|
|
@ -167,8 +179,23 @@ impl<'a> LoweringContext<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
let mut item_lowerer = ItemLowerer { lctx: self };
|
||||
visit::walk_crate(&mut item_lowerer, c);
|
||||
visit::walk_crate(&mut MiscCollector { lctx: &mut self }, c);
|
||||
visit::walk_crate(&mut ItemLowerer { lctx: &mut self }, c);
|
||||
|
||||
let module = self.lower_mod(&c.module);
|
||||
let attrs = self.lower_attrs(&c.attrs);
|
||||
let exported_macros = c.exported_macros.iter().map(|m| self.lower_macro_def(m)).collect();
|
||||
|
||||
hir::Crate {
|
||||
module: module,
|
||||
attrs: attrs,
|
||||
span: c.span,
|
||||
exported_macros: exported_macros,
|
||||
items: self.items,
|
||||
trait_items: self.trait_items,
|
||||
impl_items: self.impl_items,
|
||||
bodies: self.bodies,
|
||||
}
|
||||
}
|
||||
|
||||
fn record_body(&mut self, value: hir::Expr, decl: Option<&FnDecl>)
|
||||
|
|
@ -232,6 +259,14 @@ impl<'a> LoweringContext<'a> {
|
|||
result
|
||||
}
|
||||
|
||||
fn def_key(&mut self, id: DefId) -> DefKey {
|
||||
if id.is_local() {
|
||||
self.resolver.definitions().def_key(id.index)
|
||||
} else {
|
||||
self.sess.cstore.def_key(id)
|
||||
}
|
||||
}
|
||||
|
||||
fn lower_opt_sp_ident(&mut self, o_id: Option<Spanned<Ident>>) -> Option<Spanned<Name>> {
|
||||
o_id.map(|sp_ident| respan(sp_ident.span, sp_ident.node.name))
|
||||
}
|
||||
|
|
@ -279,7 +314,12 @@ impl<'a> LoweringContext<'a> {
|
|||
TyKind::Slice(ref ty) => hir::TySlice(self.lower_ty(ty)),
|
||||
TyKind::Ptr(ref mt) => hir::TyPtr(self.lower_mt(mt)),
|
||||
TyKind::Rptr(ref region, ref mt) => {
|
||||
hir::TyRptr(self.lower_opt_lifetime(region), self.lower_mt(mt))
|
||||
let span = Span { hi: t.span.lo, ..t.span };
|
||||
let lifetime = match *region {
|
||||
Some(ref lt) => self.lower_lifetime(lt),
|
||||
None => self.elided_lifetime(span)
|
||||
};
|
||||
hir::TyRptr(lifetime, self.lower_mt(mt))
|
||||
}
|
||||
TyKind::BareFn(ref f) => {
|
||||
hir::TyBareFn(P(hir::BareFnTy {
|
||||
|
|
@ -297,7 +337,8 @@ impl<'a> LoweringContext<'a> {
|
|||
return self.lower_ty(ty);
|
||||
}
|
||||
TyKind::Path(ref qself, ref path) => {
|
||||
hir::TyPath(self.lower_qpath(t.id, qself, path, ParamMode::Explicit))
|
||||
let qpath = self.lower_qpath(t.id, qself, path, ParamMode::Explicit);
|
||||
return self.ty_path(t.id, t.span, qpath);
|
||||
}
|
||||
TyKind::ImplicitSelf => {
|
||||
hir::TyPath(hir::QPath::Resolved(None, P(hir::Path {
|
||||
|
|
@ -319,7 +360,23 @@ impl<'a> LoweringContext<'a> {
|
|||
hir::TyTypeof(self.record_body(expr, None))
|
||||
}
|
||||
TyKind::TraitObject(ref bounds) => {
|
||||
hir::TyTraitObject(self.lower_bounds(bounds))
|
||||
let mut lifetime_bound = None;
|
||||
let bounds = bounds.iter().filter_map(|bound| {
|
||||
match *bound {
|
||||
TraitTyParamBound(ref ty, TraitBoundModifier::None) => {
|
||||
Some(self.lower_poly_trait_ref(ty))
|
||||
}
|
||||
TraitTyParamBound(_, TraitBoundModifier::Maybe) => None,
|
||||
RegionTyParamBound(ref lifetime) => {
|
||||
lifetime_bound = Some(self.lower_lifetime(lifetime));
|
||||
None
|
||||
}
|
||||
}
|
||||
}).collect();
|
||||
let lifetime_bound = lifetime_bound.unwrap_or_else(|| {
|
||||
self.elided_lifetime(t.span)
|
||||
});
|
||||
hir::TyTraitObject(bounds, lifetime_bound)
|
||||
}
|
||||
TyKind::ImplTrait(ref bounds) => {
|
||||
hir::TyImplTrait(self.lower_bounds(bounds))
|
||||
|
|
@ -377,7 +434,40 @@ impl<'a> LoweringContext<'a> {
|
|||
}
|
||||
_ => param_mode
|
||||
};
|
||||
self.lower_path_segment(segment, param_mode)
|
||||
|
||||
// Figure out if this is a type/trait segment,
|
||||
// which may need lifetime elision performed.
|
||||
let parent_def_id = |this: &mut Self, def_id: DefId| {
|
||||
DefId {
|
||||
krate: def_id.krate,
|
||||
index: this.def_key(def_id).parent.expect("missing parent")
|
||||
}
|
||||
};
|
||||
let type_def_id = match resolution.base_def {
|
||||
Def::AssociatedTy(def_id) if i + 2 == proj_start => {
|
||||
Some(parent_def_id(self, def_id))
|
||||
}
|
||||
Def::Variant(def_id) if i + 1 == proj_start => {
|
||||
Some(parent_def_id(self, def_id))
|
||||
}
|
||||
Def::Struct(def_id) |
|
||||
Def::Union(def_id) |
|
||||
Def::Enum(def_id) |
|
||||
Def::TyAlias(def_id) |
|
||||
Def::Trait(def_id) if i + 1 == proj_start => Some(def_id),
|
||||
_ => None
|
||||
};
|
||||
|
||||
let num_lifetimes = type_def_id.map_or(0, |def_id| {
|
||||
if let Some(&n) = self.type_def_lifetime_params.get(&def_id) {
|
||||
return n;
|
||||
}
|
||||
assert!(!def_id.is_local());
|
||||
let (n, _) = self.sess.cstore.item_generics_own_param_counts(def_id);
|
||||
self.type_def_lifetime_params.insert(def_id, n);
|
||||
n
|
||||
});
|
||||
self.lower_path_segment(p.span, segment, param_mode, num_lifetimes)
|
||||
}).collect(),
|
||||
span: p.span,
|
||||
});
|
||||
|
|
@ -397,7 +487,8 @@ impl<'a> LoweringContext<'a> {
|
|||
// Otherwise, the base path is an implicit `Self` type path,
|
||||
// e.g. `Vec` in `Vec::new` or `<I as Iterator>::Item` in
|
||||
// `<I as Iterator>::Item::default`.
|
||||
self.ty(p.span, hir::TyPath(hir::QPath::Resolved(qself, path)))
|
||||
let new_id = self.next_id();
|
||||
self.ty_path(new_id, p.span, hir::QPath::Resolved(qself, path))
|
||||
};
|
||||
|
||||
// Anything after the base path are associated "extensions",
|
||||
|
|
@ -411,7 +502,7 @@ impl<'a> LoweringContext<'a> {
|
|||
// 3. `<<std::vec::Vec<T>>::IntoIter>::Item`
|
||||
// * final path is `<<<std::vec::Vec<T>>::IntoIter>::Item>::clone`
|
||||
for (i, segment) in p.segments.iter().enumerate().skip(proj_start) {
|
||||
let segment = P(self.lower_path_segment(segment, param_mode));
|
||||
let segment = P(self.lower_path_segment(p.span, segment, param_mode, 0));
|
||||
let qpath = hir::QPath::TypeRelative(ty, segment);
|
||||
|
||||
// It's finished, return the extension of the right node type.
|
||||
|
|
@ -420,7 +511,8 @@ impl<'a> LoweringContext<'a> {
|
|||
}
|
||||
|
||||
// Wrap the associated extension in another type node.
|
||||
ty = self.ty(p.span, hir::TyPath(qpath));
|
||||
let new_id = self.next_id();
|
||||
ty = self.ty_path(new_id, p.span, qpath);
|
||||
}
|
||||
|
||||
// Should've returned in the for loop above.
|
||||
|
|
@ -443,7 +535,7 @@ impl<'a> LoweringContext<'a> {
|
|||
hir::Path {
|
||||
def: self.expect_full_def(id),
|
||||
segments: segments.map(|segment| {
|
||||
self.lower_path_segment(segment, param_mode)
|
||||
self.lower_path_segment(p.span, segment, param_mode, 0)
|
||||
}).chain(name.map(|name| {
|
||||
hir::PathSegment {
|
||||
name: name,
|
||||
|
|
@ -464,10 +556,12 @@ impl<'a> LoweringContext<'a> {
|
|||
}
|
||||
|
||||
fn lower_path_segment(&mut self,
|
||||
path_span: Span,
|
||||
segment: &PathSegment,
|
||||
param_mode: ParamMode)
|
||||
param_mode: ParamMode,
|
||||
expected_lifetimes: usize)
|
||||
-> hir::PathSegment {
|
||||
let parameters = if let Some(ref parameters) = segment.parameters {
|
||||
let mut parameters = if let Some(ref parameters) = segment.parameters {
|
||||
match **parameters {
|
||||
PathParameters::AngleBracketed(ref data) => {
|
||||
let data = self.lower_angle_bracketed_parameter_data(data, param_mode);
|
||||
|
|
@ -482,6 +576,14 @@ impl<'a> LoweringContext<'a> {
|
|||
hir::AngleBracketedParameters(data)
|
||||
};
|
||||
|
||||
if let hir::AngleBracketedParameters(ref mut data) = parameters {
|
||||
if data.lifetimes.is_empty() {
|
||||
data.lifetimes = (0..expected_lifetimes).map(|_| {
|
||||
self.elided_lifetime(path_span)
|
||||
}).collect();
|
||||
}
|
||||
}
|
||||
|
||||
hir::PathSegment {
|
||||
name: segment.identifier.name,
|
||||
parameters: parameters,
|
||||
|
|
@ -628,10 +730,6 @@ impl<'a> LoweringContext<'a> {
|
|||
lts.iter().map(|l| self.lower_lifetime_def(l)).collect()
|
||||
}
|
||||
|
||||
fn lower_opt_lifetime(&mut self, o_lt: &Option<Lifetime>) -> Option<hir::Lifetime> {
|
||||
o_lt.as_ref().map(|lt| self.lower_lifetime(lt))
|
||||
}
|
||||
|
||||
fn lower_generics(&mut self, g: &Generics) -> hir::Generics {
|
||||
// Collect `?Trait` bounds in where clause and move them to parameter definitions.
|
||||
let mut add_bounds = NodeMap();
|
||||
|
|
@ -751,8 +849,12 @@ impl<'a> LoweringContext<'a> {
|
|||
}
|
||||
|
||||
fn lower_trait_ref(&mut self, p: &TraitRef) -> hir::TraitRef {
|
||||
let path = match self.lower_qpath(p.ref_id, &None, &p.path, ParamMode::Explicit) {
|
||||
hir::QPath::Resolved(None, path) => path.and_then(|path| path),
|
||||
qpath => bug!("lower_trait_ref: unexpected QPath `{:?}`", qpath)
|
||||
};
|
||||
hir::TraitRef {
|
||||
path: self.lower_path(p.ref_id, &p.path, ParamMode::Explicit, false),
|
||||
path: path,
|
||||
ref_id: p.ref_id,
|
||||
}
|
||||
}
|
||||
|
|
@ -2269,11 +2371,40 @@ impl<'a> LoweringContext<'a> {
|
|||
self.expr_block(block, attrs)
|
||||
}
|
||||
|
||||
fn ty(&mut self, span: Span, node: hir::Ty_) -> P<hir::Ty> {
|
||||
P(hir::Ty {
|
||||
fn ty_path(&mut self, id: NodeId, span: Span, qpath: hir::QPath) -> P<hir::Ty> {
|
||||
let mut id = id;
|
||||
let node = match qpath {
|
||||
hir::QPath::Resolved(None, path) => {
|
||||
// Turn trait object paths into `TyTraitObject` instead.
|
||||
if let Def::Trait(_) = path.def {
|
||||
let principal = hir::PolyTraitRef {
|
||||
bound_lifetimes: hir_vec![],
|
||||
trait_ref: hir::TraitRef {
|
||||
path: path.and_then(|path| path),
|
||||
ref_id: id,
|
||||
},
|
||||
span,
|
||||
};
|
||||
|
||||
// The original ID is taken by the `PolyTraitRef`,
|
||||
// so the `Ty` itself needs a different one.
|
||||
id = self.next_id();
|
||||
|
||||
hir::TyTraitObject(hir_vec![principal], self.elided_lifetime(span))
|
||||
} else {
|
||||
hir::TyPath(hir::QPath::Resolved(None, path))
|
||||
}
|
||||
}
|
||||
_ => hir::TyPath(qpath)
|
||||
};
|
||||
P(hir::Ty { id, node, span })
|
||||
}
|
||||
|
||||
fn elided_lifetime(&mut self, span: Span) -> hir::Lifetime {
|
||||
hir::Lifetime {
|
||||
id: self.next_id(),
|
||||
node: node,
|
||||
span: span,
|
||||
})
|
||||
name: keywords::Invalid.name()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ use syntax_pos::Span;
|
|||
/// - The default implementation for a trait method.
|
||||
///
|
||||
/// To construct one, use the `Code::from_node` function.
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct FnLikeNode<'a> { node: map::Node<'a> }
|
||||
|
||||
/// MaybeFnLike wraps a method that indicates if an object
|
||||
|
|
|
|||
|
|
@ -77,6 +77,13 @@ pub mod svh;
|
|||
pub struct Lifetime {
|
||||
pub id: NodeId,
|
||||
pub span: Span,
|
||||
|
||||
/// Either "'a", referring to a named lifetime definition,
|
||||
/// or "" (aka keywords::Invalid), for elision placeholders.
|
||||
///
|
||||
/// HIR lowering inserts these placeholders in type paths that
|
||||
/// refer to type definitions needing lifetime parameters,
|
||||
/// `&T` and `&mut T`, and trait objects without `... + 'a`.
|
||||
pub name: Name,
|
||||
}
|
||||
|
||||
|
|
@ -89,6 +96,12 @@ impl fmt::Debug for Lifetime {
|
|||
}
|
||||
}
|
||||
|
||||
impl Lifetime {
|
||||
pub fn is_elided(&self) -> bool {
|
||||
self.name == keywords::Invalid.name()
|
||||
}
|
||||
}
|
||||
|
||||
/// A lifetime definition, eg `'a: 'b+'c+'d`
|
||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||
pub struct LifetimeDef {
|
||||
|
|
@ -165,30 +178,6 @@ impl PathParameters {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
match *self {
|
||||
AngleBracketedParameters(ref data) => data.is_empty(),
|
||||
|
||||
// Even if the user supplied no types, something like
|
||||
// `X()` is equivalent to `X<(),()>`.
|
||||
ParenthesizedParameters(..) => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn has_lifetimes(&self) -> bool {
|
||||
match *self {
|
||||
AngleBracketedParameters(ref data) => !data.lifetimes.is_empty(),
|
||||
ParenthesizedParameters(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn has_types(&self) -> bool {
|
||||
match *self {
|
||||
AngleBracketedParameters(ref data) => !data.types.is_empty(),
|
||||
ParenthesizedParameters(..) => true,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the types that the user wrote. Note that these do not necessarily map to the type
|
||||
/// parameters in the parenthesized case.
|
||||
pub fn types(&self) -> HirVec<&P<Ty>> {
|
||||
|
|
@ -245,12 +234,6 @@ pub struct AngleBracketedParameterData {
|
|||
pub bindings: HirVec<TypeBinding>,
|
||||
}
|
||||
|
||||
impl AngleBracketedParameterData {
|
||||
fn is_empty(&self) -> bool {
|
||||
self.lifetimes.is_empty() && self.types.is_empty() && self.bindings.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
/// A path like `Foo(A,B) -> C`
|
||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||
pub struct ParenthesizedParameterData {
|
||||
|
|
@ -1208,7 +1191,7 @@ pub enum Ty_ {
|
|||
/// A raw pointer (`*const T` or `*mut T`)
|
||||
TyPtr(MutTy),
|
||||
/// A reference (`&'a T` or `&'a mut T`)
|
||||
TyRptr(Option<Lifetime>, MutTy),
|
||||
TyRptr(Lifetime, MutTy),
|
||||
/// A bare function (e.g. `fn(usize) -> bool`)
|
||||
TyBareFn(P<BareFnTy>),
|
||||
/// The never type (`!`)
|
||||
|
|
@ -1222,7 +1205,7 @@ pub enum Ty_ {
|
|||
TyPath(QPath),
|
||||
/// A trait object type `Bound1 + Bound2 + Bound3`
|
||||
/// where `Bound` is a trait or a lifetime.
|
||||
TyTraitObject(TyParamBounds),
|
||||
TyTraitObject(HirVec<PolyTraitRef>, Lifetime),
|
||||
/// An `impl Bound1 + Bound2 + Bound3` type
|
||||
/// where `Bound` is a trait or a lifetime.
|
||||
TyImplTrait(TyParamBounds),
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ use syntax_pos::{self, BytePos};
|
|||
use hir;
|
||||
use hir::{PatKind, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier, RangeEnd};
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::io::{self, Write, Read};
|
||||
|
||||
pub enum AnnNode<'a> {
|
||||
|
|
@ -359,9 +360,9 @@ impl<'a> State<'a> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn print_opt_lifetime(&mut self, lifetime: &Option<hir::Lifetime>) -> io::Result<()> {
|
||||
if let Some(l) = *lifetime {
|
||||
self.print_lifetime(&l)?;
|
||||
pub fn print_opt_lifetime(&mut self, lifetime: &hir::Lifetime) -> io::Result<()> {
|
||||
if !lifetime.is_elided() {
|
||||
self.print_lifetime(lifetime)?;
|
||||
self.nbsp()?;
|
||||
}
|
||||
Ok(())
|
||||
|
|
@ -415,8 +416,21 @@ impl<'a> State<'a> {
|
|||
hir::TyPath(ref qpath) => {
|
||||
self.print_qpath(qpath, false)?
|
||||
}
|
||||
hir::TyTraitObject(ref bounds) => {
|
||||
self.print_bounds("", &bounds[..])?;
|
||||
hir::TyTraitObject(ref bounds, ref lifetime) => {
|
||||
let mut first = true;
|
||||
for bound in bounds {
|
||||
self.nbsp()?;
|
||||
if first {
|
||||
first = false;
|
||||
} else {
|
||||
self.word_space("+")?;
|
||||
}
|
||||
self.print_poly_trait_ref(bound)?;
|
||||
}
|
||||
if !lifetime.is_elided() {
|
||||
self.word_space("+")?;
|
||||
self.print_lifetime(lifetime)?;
|
||||
}
|
||||
}
|
||||
hir::TyImplTrait(ref bounds) => {
|
||||
self.print_bounds("impl ", &bounds[..])?;
|
||||
|
|
@ -1553,65 +1567,49 @@ impl<'a> State<'a> {
|
|||
parameters: &hir::PathParameters,
|
||||
colons_before_params: bool)
|
||||
-> io::Result<()> {
|
||||
if parameters.is_empty() {
|
||||
let infer_types = match *parameters {
|
||||
hir::AngleBracketedParameters(ref data) => data.infer_types,
|
||||
hir::ParenthesizedParameters(_) => false
|
||||
};
|
||||
|
||||
// FIXME(eddyb) See the comment below about infer_types.
|
||||
if !(infer_types && false) {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
if colons_before_params {
|
||||
word(&mut self.s, "::")?
|
||||
}
|
||||
|
||||
match *parameters {
|
||||
hir::AngleBracketedParameters(ref data) => {
|
||||
word(&mut self.s, "<")?;
|
||||
|
||||
let mut comma = false;
|
||||
for lifetime in &data.lifetimes {
|
||||
if comma {
|
||||
self.word_space(",")?
|
||||
let start = if colons_before_params { "::<" } else { "<" };
|
||||
let empty = Cell::new(true);
|
||||
let start_or_comma = |this: &mut Self| {
|
||||
if empty.get() {
|
||||
empty.set(false);
|
||||
word(&mut this.s, start)
|
||||
} else {
|
||||
this.word_space(",")
|
||||
}
|
||||
};
|
||||
|
||||
if !data.lifetimes.iter().all(|lt| lt.is_elided()) {
|
||||
for lifetime in &data.lifetimes {
|
||||
start_or_comma(self)?;
|
||||
self.print_lifetime(lifetime)?;
|
||||
}
|
||||
self.print_lifetime(lifetime)?;
|
||||
comma = true;
|
||||
}
|
||||
|
||||
if !data.types.is_empty() {
|
||||
if comma {
|
||||
self.word_space(",")?
|
||||
}
|
||||
start_or_comma(self)?;
|
||||
self.commasep(Inconsistent, &data.types, |s, ty| s.print_type(&ty))?;
|
||||
comma = true;
|
||||
}
|
||||
|
||||
// FIXME(eddyb) This would leak into error messages, e.g.:
|
||||
// "non-exhaustive patterns: `Some::<..>(_)` not covered".
|
||||
if data.infer_types && false {
|
||||
if comma {
|
||||
self.word_space(",")?
|
||||
}
|
||||
start_or_comma(self)?;
|
||||
word(&mut self.s, "..")?;
|
||||
comma = true;
|
||||
}
|
||||
|
||||
for binding in data.bindings.iter() {
|
||||
if comma {
|
||||
self.word_space(",")?
|
||||
}
|
||||
start_or_comma(self)?;
|
||||
self.print_name(binding.name)?;
|
||||
space(&mut self.s)?;
|
||||
self.word_space("=")?;
|
||||
self.print_type(&binding.ty)?;
|
||||
comma = true;
|
||||
}
|
||||
|
||||
word(&mut self.s, ">")?
|
||||
if !empty.get() {
|
||||
word(&mut self.s, ">")?
|
||||
}
|
||||
}
|
||||
|
||||
hir::ParenthesizedParameters(ref data) => {
|
||||
|
|
|
|||
|
|
@ -55,8 +55,6 @@
|
|||
//! ported to this system, and which relies on string concatenation at the
|
||||
//! time of error detection.
|
||||
|
||||
use self::FreshOrKept::*;
|
||||
|
||||
use super::InferCtxt;
|
||||
use super::TypeTrace;
|
||||
use super::SubregionOrigin;
|
||||
|
|
@ -71,13 +69,10 @@ use super::region_inference::ProcessedErrors;
|
|||
use super::region_inference::ProcessedErrorOrigin;
|
||||
use super::region_inference::SameRegions;
|
||||
|
||||
use std::collections::HashSet;
|
||||
|
||||
use hir::map as hir_map;
|
||||
use hir;
|
||||
|
||||
use lint;
|
||||
use hir::def::Def;
|
||||
use hir::def_id::DefId;
|
||||
use infer;
|
||||
use middle::region;
|
||||
|
|
@ -86,13 +81,9 @@ use ty::{self, TyCtxt, TypeFoldable};
|
|||
use ty::{Region, ReFree};
|
||||
use ty::error::TypeError;
|
||||
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::char::from_u32;
|
||||
use std::fmt;
|
||||
use syntax::ast;
|
||||
use syntax::ptr::P;
|
||||
use syntax::symbol::Symbol;
|
||||
use syntax_pos::{self, Pos, Span};
|
||||
use syntax_pos::{Pos, Span};
|
||||
use errors::DiagnosticBuilder;
|
||||
|
||||
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
|
|
@ -292,7 +283,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||
ProcessedErrors(ref origins,
|
||||
ref same_regions) => {
|
||||
if !same_regions.is_empty() {
|
||||
self.report_processed_errors(origins, same_regions);
|
||||
self.report_processed_errors(origins);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1050,9 +1041,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
|
||||
fn report_processed_errors(&self,
|
||||
origins: &[ProcessedErrorOrigin<'tcx>],
|
||||
same_regions: &[SameRegions]) {
|
||||
for (i, origin) in origins.iter().enumerate() {
|
||||
origins: &[ProcessedErrorOrigin<'tcx>]) {
|
||||
for origin in origins.iter() {
|
||||
let mut err = match *origin {
|
||||
ProcessedErrorOrigin::VariableFailure(ref var_origin) =>
|
||||
self.report_inference_failure(var_origin.clone()),
|
||||
|
|
@ -1060,78 +1050,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||
self.report_concrete_failure(sr_origin.clone(), sub, sup),
|
||||
};
|
||||
|
||||
// attach the suggestion to the last such error
|
||||
if i == origins.len() - 1 {
|
||||
self.give_suggestion(&mut err, same_regions);
|
||||
}
|
||||
|
||||
err.emit();
|
||||
}
|
||||
}
|
||||
|
||||
fn give_suggestion(&self, err: &mut DiagnosticBuilder, same_regions: &[SameRegions]) {
|
||||
let scope_id = same_regions[0].scope_id;
|
||||
let parent = self.tcx.hir.get_parent(scope_id);
|
||||
let parent_node = self.tcx.hir.find(parent);
|
||||
let taken = lifetimes_in_scope(self.tcx, scope_id);
|
||||
let life_giver = LifeGiver::with_taken(&taken[..]);
|
||||
let node_inner = match parent_node {
|
||||
Some(ref node) => match *node {
|
||||
hir_map::NodeItem(ref item) => {
|
||||
match item.node {
|
||||
hir::ItemFn(ref fn_decl, unsafety, constness, _, ref gen, body) => {
|
||||
Some((fn_decl, gen, unsafety, constness, item.name, item.span, body))
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
hir_map::NodeImplItem(item) => {
|
||||
let id = self.tcx.hir.get_parent(item.id);
|
||||
if let Some(hir_map::NodeItem(parent_scope)) = self.tcx.hir.find(id) {
|
||||
if let hir::ItemImpl(_, _, _, None, _, _) = parent_scope.node {
|
||||
// this impl scope implements a trait, do not recomend
|
||||
// using explicit lifetimes (#37363)
|
||||
return;
|
||||
}
|
||||
}
|
||||
if let hir::ImplItemKind::Method(ref sig, body) = item.node {
|
||||
Some((&sig.decl,
|
||||
&sig.generics,
|
||||
sig.unsafety,
|
||||
sig.constness,
|
||||
item.name,
|
||||
item.span,
|
||||
body))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
hir_map::NodeTraitItem(item) => {
|
||||
match item.node {
|
||||
hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) => {
|
||||
Some((&sig.decl,
|
||||
&sig.generics,
|
||||
sig.unsafety,
|
||||
sig.constness,
|
||||
item.name,
|
||||
item.span,
|
||||
body))
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
let (fn_decl, generics, unsafety, constness, name, span, body)
|
||||
= node_inner.expect("expect item fn");
|
||||
let rebuilder = Rebuilder::new(self.tcx, fn_decl, generics, same_regions, &life_giver);
|
||||
let (fn_decl, generics) = rebuilder.rebuild();
|
||||
self.give_expl_lifetime_param(
|
||||
err, &fn_decl, unsafety, constness, name, &generics, span, body);
|
||||
}
|
||||
|
||||
pub fn issue_32330_warnings(&self, span: Span, issue32330s: &[ty::Issue32330]) {
|
||||
for issue32330 in issue32330s {
|
||||
match *issue32330 {
|
||||
|
|
@ -1154,530 +1076,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
struct RebuildPathInfo<'a> {
|
||||
path: &'a hir::Path,
|
||||
// indexes to insert lifetime on path.lifetimes
|
||||
indexes: Vec<u32>,
|
||||
// number of lifetimes we expect to see on the type referred by `path`
|
||||
// (e.g., expected=1 for struct Foo<'a>)
|
||||
expected: u32,
|
||||
anon_nums: &'a HashSet<u32>,
|
||||
region_names: &'a HashSet<ast::Name>
|
||||
}
|
||||
|
||||
struct Rebuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
fn_decl: &'a hir::FnDecl,
|
||||
generics: &'a hir::Generics,
|
||||
same_regions: &'a [SameRegions],
|
||||
life_giver: &'a LifeGiver,
|
||||
cur_anon: Cell<u32>,
|
||||
inserted_anons: RefCell<HashSet<u32>>,
|
||||
}
|
||||
|
||||
enum FreshOrKept {
|
||||
Fresh,
|
||||
Kept
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> Rebuilder<'a, 'gcx, 'tcx> {
|
||||
fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
fn_decl: &'a hir::FnDecl,
|
||||
generics: &'a hir::Generics,
|
||||
same_regions: &'a [SameRegions],
|
||||
life_giver: &'a LifeGiver)
|
||||
-> Rebuilder<'a, 'gcx, 'tcx> {
|
||||
Rebuilder {
|
||||
tcx: tcx,
|
||||
fn_decl: fn_decl,
|
||||
generics: generics,
|
||||
same_regions: same_regions,
|
||||
life_giver: life_giver,
|
||||
cur_anon: Cell::new(0),
|
||||
inserted_anons: RefCell::new(HashSet::new()),
|
||||
}
|
||||
}
|
||||
|
||||
fn rebuild(&self) -> (hir::FnDecl, hir::Generics) {
|
||||
let mut inputs = self.fn_decl.inputs.clone();
|
||||
let mut output = self.fn_decl.output.clone();
|
||||
let mut ty_params = self.generics.ty_params.clone();
|
||||
let where_clause = self.generics.where_clause.clone();
|
||||
let mut kept_lifetimes = HashSet::new();
|
||||
for sr in self.same_regions {
|
||||
self.cur_anon.set(0);
|
||||
self.offset_cur_anon();
|
||||
let (anon_nums, region_names) =
|
||||
self.extract_anon_nums_and_names(sr);
|
||||
let (lifetime, fresh_or_kept) = self.pick_lifetime(®ion_names);
|
||||
match fresh_or_kept {
|
||||
Kept => { kept_lifetimes.insert(lifetime.name); }
|
||||
_ => ()
|
||||
}
|
||||
inputs = self.rebuild_args_ty(&inputs[..], lifetime,
|
||||
&anon_nums, ®ion_names);
|
||||
output = self.rebuild_output(&output, lifetime, &anon_nums, ®ion_names);
|
||||
ty_params = self.rebuild_ty_params(ty_params, lifetime,
|
||||
®ion_names);
|
||||
}
|
||||
let fresh_lifetimes = self.life_giver.get_generated_lifetimes();
|
||||
let all_region_names = self.extract_all_region_names();
|
||||
let generics = self.rebuild_generics(self.generics,
|
||||
&fresh_lifetimes,
|
||||
&kept_lifetimes,
|
||||
&all_region_names,
|
||||
ty_params,
|
||||
where_clause);
|
||||
let new_fn_decl = hir::FnDecl {
|
||||
inputs: inputs,
|
||||
output: output,
|
||||
variadic: self.fn_decl.variadic
|
||||
};
|
||||
(new_fn_decl, generics)
|
||||
}
|
||||
|
||||
fn pick_lifetime(&self,
|
||||
region_names: &HashSet<ast::Name>)
|
||||
-> (hir::Lifetime, FreshOrKept) {
|
||||
if !region_names.is_empty() {
|
||||
// It's not necessary to convert the set of region names to a
|
||||
// vector of string and then sort them. However, it makes the
|
||||
// choice of lifetime name deterministic and thus easier to test.
|
||||
let mut names = Vec::new();
|
||||
for rn in region_names {
|
||||
let lt_name = rn.to_string();
|
||||
names.push(lt_name);
|
||||
}
|
||||
names.sort();
|
||||
let name = Symbol::intern(&names[0]);
|
||||
return (name_to_dummy_lifetime(name), Kept);
|
||||
}
|
||||
return (self.life_giver.give_lifetime(), Fresh);
|
||||
}
|
||||
|
||||
fn extract_anon_nums_and_names(&self, same_regions: &SameRegions)
|
||||
-> (HashSet<u32>, HashSet<ast::Name>) {
|
||||
let mut anon_nums = HashSet::new();
|
||||
let mut region_names = HashSet::new();
|
||||
for br in &same_regions.regions {
|
||||
match *br {
|
||||
ty::BrAnon(i) => {
|
||||
anon_nums.insert(i);
|
||||
}
|
||||
ty::BrNamed(_, name, _) => {
|
||||
region_names.insert(name);
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
(anon_nums, region_names)
|
||||
}
|
||||
|
||||
fn extract_all_region_names(&self) -> HashSet<ast::Name> {
|
||||
let mut all_region_names = HashSet::new();
|
||||
for sr in self.same_regions {
|
||||
for br in &sr.regions {
|
||||
match *br {
|
||||
ty::BrNamed(_, name, _) => {
|
||||
all_region_names.insert(name);
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
}
|
||||
all_region_names
|
||||
}
|
||||
|
||||
fn inc_cur_anon(&self, n: u32) {
|
||||
let anon = self.cur_anon.get();
|
||||
self.cur_anon.set(anon+n);
|
||||
}
|
||||
|
||||
fn offset_cur_anon(&self) {
|
||||
let mut anon = self.cur_anon.get();
|
||||
while self.inserted_anons.borrow().contains(&anon) {
|
||||
anon += 1;
|
||||
}
|
||||
self.cur_anon.set(anon);
|
||||
}
|
||||
|
||||
fn inc_and_offset_cur_anon(&self, n: u32) {
|
||||
self.inc_cur_anon(n);
|
||||
self.offset_cur_anon();
|
||||
}
|
||||
|
||||
fn track_anon(&self, anon: u32) {
|
||||
self.inserted_anons.borrow_mut().insert(anon);
|
||||
}
|
||||
|
||||
fn rebuild_ty_params(&self,
|
||||
ty_params: hir::HirVec<hir::TyParam>,
|
||||
lifetime: hir::Lifetime,
|
||||
region_names: &HashSet<ast::Name>)
|
||||
-> hir::HirVec<hir::TyParam> {
|
||||
ty_params.into_iter().map(|ty_param| {
|
||||
let bounds = self.rebuild_ty_param_bounds(ty_param.bounds,
|
||||
lifetime,
|
||||
region_names);
|
||||
hir::TyParam {
|
||||
name: ty_param.name,
|
||||
id: ty_param.id,
|
||||
bounds: bounds,
|
||||
default: ty_param.default,
|
||||
span: ty_param.span,
|
||||
pure_wrt_drop: ty_param.pure_wrt_drop,
|
||||
}
|
||||
}).collect()
|
||||
}
|
||||
|
||||
fn rebuild_ty_param_bounds(&self,
|
||||
ty_param_bounds: hir::TyParamBounds,
|
||||
lifetime: hir::Lifetime,
|
||||
region_names: &HashSet<ast::Name>)
|
||||
-> hir::TyParamBounds {
|
||||
ty_param_bounds.iter().map(|tpb| {
|
||||
match tpb {
|
||||
&hir::RegionTyParamBound(lt) => {
|
||||
// FIXME -- it's unclear whether I'm supposed to
|
||||
// substitute lifetime here. I suspect we need to
|
||||
// be passing down a map.
|
||||
hir::RegionTyParamBound(lt)
|
||||
}
|
||||
&hir::TraitTyParamBound(ref poly_tr, modifier) => {
|
||||
let tr = &poly_tr.trait_ref;
|
||||
let last_seg = tr.path.segments.last().unwrap();
|
||||
let mut insert = Vec::new();
|
||||
let lifetimes = last_seg.parameters.lifetimes();
|
||||
for (i, lt) in lifetimes.iter().enumerate() {
|
||||
if region_names.contains(<.name) {
|
||||
insert.push(i as u32);
|
||||
}
|
||||
}
|
||||
let rebuild_info = RebuildPathInfo {
|
||||
path: &tr.path,
|
||||
indexes: insert,
|
||||
expected: lifetimes.len() as u32,
|
||||
anon_nums: &HashSet::new(),
|
||||
region_names: region_names
|
||||
};
|
||||
let new_path = self.rebuild_path(rebuild_info, lifetime);
|
||||
hir::TraitTyParamBound(hir::PolyTraitRef {
|
||||
bound_lifetimes: poly_tr.bound_lifetimes.clone(),
|
||||
trait_ref: hir::TraitRef {
|
||||
path: new_path,
|
||||
ref_id: tr.ref_id,
|
||||
},
|
||||
span: poly_tr.span,
|
||||
}, modifier)
|
||||
}
|
||||
}
|
||||
}).collect()
|
||||
}
|
||||
|
||||
fn rebuild_generics(&self,
|
||||
generics: &hir::Generics,
|
||||
add: &Vec<hir::Lifetime>,
|
||||
keep: &HashSet<ast::Name>,
|
||||
remove: &HashSet<ast::Name>,
|
||||
ty_params: hir::HirVec<hir::TyParam>,
|
||||
where_clause: hir::WhereClause)
|
||||
-> hir::Generics {
|
||||
let mut lifetimes = Vec::new();
|
||||
for lt in add {
|
||||
lifetimes.push(hir::LifetimeDef {
|
||||
lifetime: *lt,
|
||||
bounds: hir::HirVec::new(),
|
||||
pure_wrt_drop: false,
|
||||
});
|
||||
}
|
||||
for lt in &generics.lifetimes {
|
||||
if keep.contains(<.lifetime.name) ||
|
||||
!remove.contains(<.lifetime.name) {
|
||||
lifetimes.push((*lt).clone());
|
||||
}
|
||||
}
|
||||
hir::Generics {
|
||||
lifetimes: lifetimes.into(),
|
||||
ty_params: ty_params,
|
||||
where_clause: where_clause,
|
||||
span: generics.span,
|
||||
}
|
||||
}
|
||||
|
||||
fn rebuild_args_ty(&self,
|
||||
inputs: &[P<hir::Ty>],
|
||||
lifetime: hir::Lifetime,
|
||||
anon_nums: &HashSet<u32>,
|
||||
region_names: &HashSet<ast::Name>)
|
||||
-> hir::HirVec<P<hir::Ty>> {
|
||||
inputs.iter().map(|arg_ty| {
|
||||
self.rebuild_arg_ty_or_output(arg_ty, lifetime, anon_nums, region_names)
|
||||
}).collect()
|
||||
}
|
||||
|
||||
fn rebuild_output(&self, ty: &hir::FunctionRetTy,
|
||||
lifetime: hir::Lifetime,
|
||||
anon_nums: &HashSet<u32>,
|
||||
region_names: &HashSet<ast::Name>) -> hir::FunctionRetTy {
|
||||
match *ty {
|
||||
hir::Return(ref ret_ty) => hir::Return(
|
||||
self.rebuild_arg_ty_or_output(&ret_ty, lifetime, anon_nums, region_names)
|
||||
),
|
||||
hir::DefaultReturn(span) => hir::DefaultReturn(span),
|
||||
}
|
||||
}
|
||||
|
||||
fn rebuild_arg_ty_or_output(&self,
|
||||
ty: &hir::Ty,
|
||||
lifetime: hir::Lifetime,
|
||||
anon_nums: &HashSet<u32>,
|
||||
region_names: &HashSet<ast::Name>)
|
||||
-> P<hir::Ty> {
|
||||
let mut new_ty = P(ty.clone());
|
||||
let mut ty_queue = vec![ty];
|
||||
while !ty_queue.is_empty() {
|
||||
let cur_ty = ty_queue.remove(0);
|
||||
match cur_ty.node {
|
||||
hir::TyRptr(lt_opt, ref mut_ty) => {
|
||||
let rebuild = match lt_opt {
|
||||
Some(lt) => region_names.contains(<.name),
|
||||
None => {
|
||||
let anon = self.cur_anon.get();
|
||||
let rebuild = anon_nums.contains(&anon);
|
||||
if rebuild {
|
||||
self.track_anon(anon);
|
||||
}
|
||||
self.inc_and_offset_cur_anon(1);
|
||||
rebuild
|
||||
}
|
||||
};
|
||||
if rebuild {
|
||||
let to = hir::Ty {
|
||||
id: cur_ty.id,
|
||||
node: hir::TyRptr(Some(lifetime), mut_ty.clone()),
|
||||
span: cur_ty.span
|
||||
};
|
||||
new_ty = self.rebuild_ty(new_ty, P(to));
|
||||
}
|
||||
ty_queue.push(&mut_ty.ty);
|
||||
}
|
||||
hir::TyPath(hir::QPath::Resolved(ref maybe_qself, ref path)) => {
|
||||
match path.def {
|
||||
Def::Enum(did) | Def::TyAlias(did) |
|
||||
Def::Struct(did) | Def::Union(did) => {
|
||||
let generics = self.tcx.item_generics(did);
|
||||
|
||||
let expected =
|
||||
generics.regions.len() as u32;
|
||||
let lifetimes =
|
||||
path.segments.last().unwrap().parameters.lifetimes();
|
||||
let mut insert = Vec::new();
|
||||
if lifetimes.is_empty() {
|
||||
let anon = self.cur_anon.get();
|
||||
for (i, a) in (anon..anon+expected).enumerate() {
|
||||
if anon_nums.contains(&a) {
|
||||
insert.push(i as u32);
|
||||
}
|
||||
self.track_anon(a);
|
||||
}
|
||||
self.inc_and_offset_cur_anon(expected);
|
||||
} else {
|
||||
for (i, lt) in lifetimes.iter().enumerate() {
|
||||
if region_names.contains(<.name) {
|
||||
insert.push(i as u32);
|
||||
}
|
||||
}
|
||||
}
|
||||
let rebuild_info = RebuildPathInfo {
|
||||
path: path,
|
||||
indexes: insert,
|
||||
expected: expected,
|
||||
anon_nums: anon_nums,
|
||||
region_names: region_names
|
||||
};
|
||||
let new_path = self.rebuild_path(rebuild_info, lifetime);
|
||||
let qself = maybe_qself.as_ref().map(|qself| {
|
||||
self.rebuild_arg_ty_or_output(qself, lifetime,
|
||||
anon_nums, region_names)
|
||||
});
|
||||
let to = hir::Ty {
|
||||
id: cur_ty.id,
|
||||
node: hir::TyPath(hir::QPath::Resolved(qself, P(new_path))),
|
||||
span: cur_ty.span
|
||||
};
|
||||
new_ty = self.rebuild_ty(new_ty, P(to));
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
|
||||
hir::TyPtr(ref mut_ty) => {
|
||||
ty_queue.push(&mut_ty.ty);
|
||||
}
|
||||
hir::TySlice(ref ty) |
|
||||
hir::TyArray(ref ty, _) => {
|
||||
ty_queue.push(&ty);
|
||||
}
|
||||
hir::TyTup(ref tys) => ty_queue.extend(tys.iter().map(|ty| &**ty)),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
new_ty
|
||||
}
|
||||
|
||||
fn rebuild_ty(&self,
|
||||
from: P<hir::Ty>,
|
||||
to: P<hir::Ty>)
|
||||
-> P<hir::Ty> {
|
||||
|
||||
fn build_to(from: P<hir::Ty>,
|
||||
to: &mut Option<P<hir::Ty>>)
|
||||
-> P<hir::Ty> {
|
||||
if Some(from.id) == to.as_ref().map(|ty| ty.id) {
|
||||
return to.take().expect("`to` type found more than once during rebuild");
|
||||
}
|
||||
from.map(|hir::Ty {id, node, span}| {
|
||||
let new_node = match node {
|
||||
hir::TyRptr(lifetime, mut_ty) => {
|
||||
hir::TyRptr(lifetime, hir::MutTy {
|
||||
mutbl: mut_ty.mutbl,
|
||||
ty: build_to(mut_ty.ty, to),
|
||||
})
|
||||
}
|
||||
hir::TyPtr(mut_ty) => {
|
||||
hir::TyPtr(hir::MutTy {
|
||||
mutbl: mut_ty.mutbl,
|
||||
ty: build_to(mut_ty.ty, to),
|
||||
})
|
||||
}
|
||||
hir::TySlice(ty) => hir::TySlice(build_to(ty, to)),
|
||||
hir::TyArray(ty, e) => {
|
||||
hir::TyArray(build_to(ty, to), e)
|
||||
}
|
||||
hir::TyTup(tys) => {
|
||||
hir::TyTup(tys.into_iter().map(|ty| build_to(ty, to)).collect())
|
||||
}
|
||||
other => other
|
||||
};
|
||||
hir::Ty { id: id, node: new_node, span: span }
|
||||
})
|
||||
}
|
||||
|
||||
build_to(from, &mut Some(to))
|
||||
}
|
||||
|
||||
fn rebuild_path(&self,
|
||||
rebuild_info: RebuildPathInfo,
|
||||
lifetime: hir::Lifetime)
|
||||
-> hir::Path
|
||||
{
|
||||
let RebuildPathInfo {
|
||||
path,
|
||||
indexes,
|
||||
expected,
|
||||
anon_nums,
|
||||
region_names,
|
||||
} = rebuild_info;
|
||||
|
||||
let last_seg = path.segments.last().unwrap();
|
||||
let new_parameters = match last_seg.parameters {
|
||||
hir::ParenthesizedParameters(..) => {
|
||||
last_seg.parameters.clone()
|
||||
}
|
||||
|
||||
hir::AngleBracketedParameters(ref data) => {
|
||||
let mut new_lts = Vec::new();
|
||||
if data.lifetimes.is_empty() {
|
||||
// traverse once to see if there's a need to insert lifetime
|
||||
let need_insert = (0..expected).any(|i| {
|
||||
indexes.contains(&i)
|
||||
});
|
||||
if need_insert {
|
||||
for i in 0..expected {
|
||||
if indexes.contains(&i) {
|
||||
new_lts.push(lifetime);
|
||||
} else {
|
||||
new_lts.push(self.life_giver.give_lifetime());
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (i, lt) in data.lifetimes.iter().enumerate() {
|
||||
if indexes.contains(&(i as u32)) {
|
||||
new_lts.push(lifetime);
|
||||
} else {
|
||||
new_lts.push(*lt);
|
||||
}
|
||||
}
|
||||
}
|
||||
let new_types = data.types.iter().map(|t| {
|
||||
self.rebuild_arg_ty_or_output(&t, lifetime, anon_nums, region_names)
|
||||
}).collect();
|
||||
let new_bindings = data.bindings.iter().map(|b| {
|
||||
hir::TypeBinding {
|
||||
id: b.id,
|
||||
name: b.name,
|
||||
ty: self.rebuild_arg_ty_or_output(&b.ty,
|
||||
lifetime,
|
||||
anon_nums,
|
||||
region_names),
|
||||
span: b.span
|
||||
}
|
||||
}).collect();
|
||||
hir::AngleBracketedParameters(hir::AngleBracketedParameterData {
|
||||
lifetimes: new_lts.into(),
|
||||
types: new_types,
|
||||
infer_types: data.infer_types,
|
||||
bindings: new_bindings,
|
||||
})
|
||||
}
|
||||
};
|
||||
let new_seg = hir::PathSegment {
|
||||
name: last_seg.name,
|
||||
parameters: new_parameters
|
||||
};
|
||||
let mut new_segs = Vec::new();
|
||||
new_segs.extend_from_slice(path.segments.split_last().unwrap().1);
|
||||
new_segs.push(new_seg);
|
||||
hir::Path {
|
||||
span: path.span,
|
||||
def: path.def,
|
||||
segments: new_segs.into()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
fn give_expl_lifetime_param(&self,
|
||||
err: &mut DiagnosticBuilder,
|
||||
decl: &hir::FnDecl,
|
||||
unsafety: hir::Unsafety,
|
||||
constness: hir::Constness,
|
||||
name: ast::Name,
|
||||
generics: &hir::Generics,
|
||||
span: Span,
|
||||
body: hir::BodyId) {
|
||||
let s = hir::print::to_string(&self.tcx.hir, |s| {
|
||||
use syntax::abi::Abi;
|
||||
use syntax::print::pprust::PrintState;
|
||||
|
||||
s.head("")?;
|
||||
s.print_fn(decl,
|
||||
unsafety,
|
||||
constness,
|
||||
Abi::Rust,
|
||||
Some(name),
|
||||
generics,
|
||||
&hir::Inherited,
|
||||
&[],
|
||||
Some(body))?;
|
||||
s.end()?; // Close the head box
|
||||
s.end() // Close the outer box
|
||||
});
|
||||
let msg = format!("consider using an explicit lifetime parameter as shown: {}", s);
|
||||
err.span_help(span, &msg[..]);
|
||||
}
|
||||
|
||||
fn report_inference_failure(&self,
|
||||
var_origin: RegionVariableOrigin)
|
||||
-> DiagnosticBuilder<'tcx> {
|
||||
|
|
@ -1890,114 +1289,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn lifetimes_in_scope<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
scope_id: ast::NodeId)
|
||||
-> Vec<hir::LifetimeDef> {
|
||||
let mut taken = Vec::new();
|
||||
let parent = tcx.hir.get_parent(scope_id);
|
||||
let method_id_opt = match tcx.hir.find(parent) {
|
||||
Some(node) => match node {
|
||||
hir_map::NodeItem(item) => match item.node {
|
||||
hir::ItemFn(.., ref gen, _) => {
|
||||
taken.extend_from_slice(&gen.lifetimes);
|
||||
None
|
||||
},
|
||||
_ => None
|
||||
},
|
||||
hir_map::NodeImplItem(ii) => {
|
||||
match ii.node {
|
||||
hir::ImplItemKind::Method(ref sig, _) => {
|
||||
taken.extend_from_slice(&sig.generics.lifetimes);
|
||||
Some(ii.id)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
_ => None
|
||||
},
|
||||
None => None
|
||||
};
|
||||
if let Some(method_id) = method_id_opt {
|
||||
let parent = tcx.hir.get_parent(method_id);
|
||||
if let Some(node) = tcx.hir.find(parent) {
|
||||
match node {
|
||||
hir_map::NodeItem(item) => match item.node {
|
||||
hir::ItemImpl(_, _, ref gen, ..) => {
|
||||
taken.extend_from_slice(&gen.lifetimes);
|
||||
}
|
||||
_ => ()
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
}
|
||||
return taken;
|
||||
}
|
||||
|
||||
// LifeGiver is responsible for generating fresh lifetime names
|
||||
struct LifeGiver {
|
||||
taken: HashSet<String>,
|
||||
counter: Cell<usize>,
|
||||
generated: RefCell<Vec<hir::Lifetime>>,
|
||||
}
|
||||
|
||||
impl LifeGiver {
|
||||
fn with_taken(taken: &[hir::LifetimeDef]) -> LifeGiver {
|
||||
let mut taken_ = HashSet::new();
|
||||
for lt in taken {
|
||||
let lt_name = lt.lifetime.name.to_string();
|
||||
taken_.insert(lt_name);
|
||||
}
|
||||
LifeGiver {
|
||||
taken: taken_,
|
||||
counter: Cell::new(0),
|
||||
generated: RefCell::new(Vec::new()),
|
||||
}
|
||||
}
|
||||
|
||||
fn inc_counter(&self) {
|
||||
let c = self.counter.get();
|
||||
self.counter.set(c+1);
|
||||
}
|
||||
|
||||
fn give_lifetime(&self) -> hir::Lifetime {
|
||||
let lifetime;
|
||||
loop {
|
||||
let mut s = String::from("'");
|
||||
s.push_str(&num_to_string(self.counter.get()));
|
||||
if !self.taken.contains(&s) {
|
||||
lifetime = name_to_dummy_lifetime(Symbol::intern(&s));
|
||||
self.generated.borrow_mut().push(lifetime);
|
||||
break;
|
||||
}
|
||||
self.inc_counter();
|
||||
}
|
||||
self.inc_counter();
|
||||
return lifetime;
|
||||
|
||||
// 0 .. 25 generates a .. z, 26 .. 51 generates aa .. zz, and so on
|
||||
fn num_to_string(counter: usize) -> String {
|
||||
let mut s = String::new();
|
||||
let (n, r) = (counter/26 + 1, counter % 26);
|
||||
let letter: char = from_u32((r+97) as u32).unwrap();
|
||||
for _ in 0..n {
|
||||
s.push(letter);
|
||||
}
|
||||
s
|
||||
}
|
||||
}
|
||||
|
||||
fn get_generated_lifetimes(&self) -> Vec<hir::Lifetime> {
|
||||
self.generated.borrow().clone()
|
||||
}
|
||||
}
|
||||
|
||||
fn name_to_dummy_lifetime(name: ast::Name) -> hir::Lifetime {
|
||||
hir::Lifetime { id: ast::DUMMY_NODE_ID,
|
||||
span: syntax_pos::DUMMY_SP,
|
||||
name: name }
|
||||
}
|
||||
|
||||
impl<'tcx> ObligationCause<'tcx> {
|
||||
fn as_failure_str(&self) -> &'static str {
|
||||
use traits::ObligationCauseCode::*;
|
||||
|
|
@ -2038,4 +1329,3 @@ impl<'tcx> ObligationCause<'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -156,7 +156,6 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> {
|
|||
ty::TyUint(..) |
|
||||
ty::TyFloat(..) |
|
||||
ty::TyAdt(..) |
|
||||
ty::TyBox(..) |
|
||||
ty::TyStr |
|
||||
ty::TyError |
|
||||
ty::TyArray(..) |
|
||||
|
|
|
|||
|
|
@ -29,7 +29,9 @@
|
|||
#![feature(conservative_impl_trait)]
|
||||
#![feature(const_fn)]
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(field_init_shorthand)]
|
||||
#![feature(libc)]
|
||||
#![feature(loop_break_value)]
|
||||
#![feature(nonzero)]
|
||||
#![feature(pub_restricted)]
|
||||
#![feature(quote)]
|
||||
|
|
@ -107,7 +109,6 @@ pub mod util {
|
|||
pub mod common;
|
||||
pub mod ppaux;
|
||||
pub mod nodemap;
|
||||
pub mod num;
|
||||
pub mod fs;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -223,6 +223,12 @@ declare_lint! {
|
|||
"detects names that resolve to ambiguous glob imports with RFC 1560"
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub LEGACY_CONSTRUCTOR_VISIBILITY,
|
||||
Deny,
|
||||
"detects use of struct constructors that would be invisible with new visibility rules"
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub DEPRECATED,
|
||||
Warn,
|
||||
|
|
@ -271,6 +277,7 @@ impl LintPass for HardwiredLints {
|
|||
EXTRA_REQUIREMENT_IN_IMPL,
|
||||
LEGACY_DIRECTORY_OWNERSHIP,
|
||||
LEGACY_IMPORTS,
|
||||
LEGACY_CONSTRUCTOR_VISIBILITY,
|
||||
DEPRECATED
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ use hir::map as hir_map;
|
|||
use hir::map::definitions::{Definitions, DefKey, DisambiguatedDefPathData};
|
||||
use hir::svh::Svh;
|
||||
use middle::lang_items;
|
||||
use middle::resolve_lifetime::ObjectLifetimeDefault;
|
||||
use ty::{self, Ty, TyCtxt};
|
||||
use mir::Mir;
|
||||
use session::Session;
|
||||
|
|
@ -182,6 +183,9 @@ pub trait CrateStore<'tcx> {
|
|||
-> ty::GenericPredicates<'tcx>;
|
||||
fn item_generics<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
|
||||
-> ty::Generics<'tcx>;
|
||||
fn item_generics_own_param_counts(&self, def: DefId) -> (usize, usize);
|
||||
fn item_generics_object_lifetime_defaults(&self, def: DefId)
|
||||
-> Vec<ObjectLifetimeDefault>;
|
||||
fn item_attrs(&self, def_id: DefId) -> Vec<ast::Attribute>;
|
||||
fn trait_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)-> ty::TraitDef;
|
||||
fn adt_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> &'tcx ty::AdtDef;
|
||||
|
|
@ -331,6 +335,11 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
|
|||
-> ty::GenericPredicates<'tcx> { bug!("item_super_predicates") }
|
||||
fn item_generics<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
|
||||
-> ty::Generics<'tcx> { bug!("item_generics") }
|
||||
fn item_generics_own_param_counts(&self, def: DefId) -> (usize, usize)
|
||||
{ bug!("item_generics_own_param_counts") }
|
||||
fn item_generics_object_lifetime_defaults(&self, def: DefId)
|
||||
-> Vec<ObjectLifetimeDefault>
|
||||
{ bug!("item_generics_object_lifetime_defaults") }
|
||||
fn item_attrs(&self, def_id: DefId) -> Vec<ast::Attribute> { bug!("item_attrs") }
|
||||
fn trait_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)-> ty::TraitDef
|
||||
{ bug!("trait_def") }
|
||||
|
|
|
|||
|
|
@ -194,6 +194,63 @@ pub struct cmt_<'tcx> {
|
|||
|
||||
pub type cmt<'tcx> = Rc<cmt_<'tcx>>;
|
||||
|
||||
impl<'tcx> cmt_<'tcx> {
|
||||
pub fn get_field(&self, name: ast::Name) -> Option<DefId> {
|
||||
match self.cat {
|
||||
Categorization::Deref(ref cmt, ..) |
|
||||
Categorization::Interior(ref cmt, _) |
|
||||
Categorization::Downcast(ref cmt, _) => {
|
||||
if let Categorization::Local(_) = cmt.cat {
|
||||
if let ty::TyAdt(def, _) = self.ty.sty {
|
||||
return def.struct_variant().find_field_named(name).map(|x| x.did);
|
||||
}
|
||||
None
|
||||
} else {
|
||||
cmt.get_field(name)
|
||||
}
|
||||
}
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_field_name(&self) -> Option<ast::Name> {
|
||||
match self.cat {
|
||||
Categorization::Interior(_, ref ik) => {
|
||||
if let InteriorKind::InteriorField(FieldName::NamedField(name)) = *ik {
|
||||
Some(name)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
Categorization::Deref(ref cmt, ..) |
|
||||
Categorization::Downcast(ref cmt, _) => {
|
||||
cmt.get_field_name()
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_arg_if_immutable(&self, map: &hir_map::Map) -> Option<ast::NodeId> {
|
||||
match self.cat {
|
||||
Categorization::Deref(ref cmt, ..) |
|
||||
Categorization::Interior(ref cmt, _) |
|
||||
Categorization::Downcast(ref cmt, _) => {
|
||||
if let Categorization::Local(nid) = cmt.cat {
|
||||
if let ty::TyAdt(_, _) = self.ty.sty {
|
||||
if let ty::TyRef(_, ty::TypeAndMut{mutbl: MutImmutable, ..}) = cmt.ty.sty {
|
||||
return Some(nid);
|
||||
}
|
||||
}
|
||||
None
|
||||
} else {
|
||||
cmt.get_arg_if_immutable(map)
|
||||
}
|
||||
}
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ast_node {
|
||||
fn id(&self) -> ast::NodeId;
|
||||
fn span(&self) -> Span;
|
||||
|
|
@ -904,7 +961,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
|||
-> cmt<'tcx>
|
||||
{
|
||||
let ptr = match base_cmt.ty.sty {
|
||||
ty::TyBox(..) => Unique,
|
||||
ty::TyAdt(def, ..) if def.is_box() => Unique,
|
||||
ty::TyRawPtr(ref mt) => UnsafePtr(mt.mutbl),
|
||||
ty::TyRef(r, mt) => {
|
||||
let bk = ty::BorrowKind::from_mutbl(mt.mutbl);
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -899,6 +899,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
|
|||
"attempt to recover from parse errors (experimental)"),
|
||||
incremental: Option<String> = (None, parse_opt_string, [UNTRACKED],
|
||||
"enable incremental compilation (experimental)"),
|
||||
incremental_cc: bool = (false, parse_bool, [UNTRACKED],
|
||||
"enable cross-crate incremental compilation (even more experimental)"),
|
||||
incremental_info: bool = (false, parse_bool, [UNTRACKED],
|
||||
"print high-level information about incremental reuse (or the lack thereof)"),
|
||||
incremental_dump_hash: bool = (false, parse_bool, [UNTRACKED],
|
||||
|
|
|
|||
|
|
@ -199,7 +199,7 @@ fn orphan_check_trait_ref<'tcx>(tcx: TyCtxt,
|
|||
|
||||
fn uncovered_tys<'tcx>(tcx: TyCtxt, ty: Ty<'tcx>, infer_is_local: InferIsLocal)
|
||||
-> Vec<Ty<'tcx>> {
|
||||
if ty_is_local_constructor(tcx, ty, infer_is_local) {
|
||||
if ty_is_local_constructor(ty, infer_is_local) {
|
||||
vec![]
|
||||
} else if fundamental_ty(tcx, ty) {
|
||||
ty.walk_shallow()
|
||||
|
|
@ -219,13 +219,13 @@ fn is_type_parameter(ty: Ty) -> bool {
|
|||
}
|
||||
|
||||
fn ty_is_local(tcx: TyCtxt, ty: Ty, infer_is_local: InferIsLocal) -> bool {
|
||||
ty_is_local_constructor(tcx, ty, infer_is_local) ||
|
||||
ty_is_local_constructor(ty, infer_is_local) ||
|
||||
fundamental_ty(tcx, ty) && ty.walk_shallow().any(|t| ty_is_local(tcx, t, infer_is_local))
|
||||
}
|
||||
|
||||
fn fundamental_ty(tcx: TyCtxt, ty: Ty) -> bool {
|
||||
match ty.sty {
|
||||
ty::TyBox(..) | ty::TyRef(..) => true,
|
||||
ty::TyRef(..) => true,
|
||||
ty::TyAdt(def, _) => def.is_fundamental(),
|
||||
ty::TyDynamic(ref data, ..) => {
|
||||
data.principal().map_or(false, |p| tcx.has_attr(p.def_id(), "fundamental"))
|
||||
|
|
@ -234,7 +234,7 @@ fn fundamental_ty(tcx: TyCtxt, ty: Ty) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
fn ty_is_local_constructor(tcx: TyCtxt, ty: Ty, infer_is_local: InferIsLocal)-> bool {
|
||||
fn ty_is_local_constructor(ty: Ty, infer_is_local: InferIsLocal)-> bool {
|
||||
debug!("ty_is_local_constructor({:?})", ty);
|
||||
|
||||
match ty.sty {
|
||||
|
|
@ -265,11 +265,6 @@ fn ty_is_local_constructor(tcx: TyCtxt, ty: Ty, infer_is_local: InferIsLocal)->
|
|||
def.did.is_local()
|
||||
}
|
||||
|
||||
ty::TyBox(_) => { // Box<T>
|
||||
let krate = tcx.lang_items.owned_box().map(|d| d.krate);
|
||||
krate == Some(LOCAL_CRATE)
|
||||
}
|
||||
|
||||
ty::TyDynamic(ref tt, ..) => {
|
||||
tt.principal().map_or(false, |p| p.def_id().is_local())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||
ty::TyStr => Some(2),
|
||||
ty::TyInt(..) | ty::TyUint(..) | ty::TyInfer(ty::IntVar(..)) => Some(3),
|
||||
ty::TyFloat(..) | ty::TyInfer(ty::FloatVar(..)) => Some(4),
|
||||
ty::TyBox(..) | ty::TyRef(..) | ty::TyRawPtr(..) => Some(5),
|
||||
ty::TyRef(..) | ty::TyRawPtr(..) => Some(5),
|
||||
ty::TyArray(..) | ty::TySlice(..) => Some(6),
|
||||
ty::TyFnDef(..) | ty::TyFnPtr(..) => Some(7),
|
||||
ty::TyDynamic(..) => Some(8),
|
||||
|
|
|
|||
|
|
@ -1735,7 +1735,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
ty::TyInfer(ty::IntVar(_)) | ty::TyInfer(ty::FloatVar(_)) |
|
||||
ty::TyUint(_) | ty::TyInt(_) | ty::TyBool | ty::TyFloat(_) |
|
||||
ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyRawPtr(..) |
|
||||
ty::TyChar | ty::TyBox(_) | ty::TyRef(..) |
|
||||
ty::TyChar | ty::TyRef(..) |
|
||||
ty::TyArray(..) | ty::TyClosure(..) | ty::TyNever |
|
||||
ty::TyError => {
|
||||
// safe for everything
|
||||
|
|
@ -1788,7 +1788,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
Where(ty::Binder(Vec::new()))
|
||||
}
|
||||
|
||||
ty::TyBox(_) | ty::TyDynamic(..) | ty::TyStr | ty::TySlice(..) |
|
||||
ty::TyDynamic(..) | ty::TyStr | ty::TySlice(..) |
|
||||
ty::TyClosure(..) |
|
||||
ty::TyRef(_, ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => {
|
||||
Never
|
||||
|
|
@ -1865,10 +1865,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
t);
|
||||
}
|
||||
|
||||
ty::TyBox(referent_ty) => { // Box<T>
|
||||
vec![referent_ty]
|
||||
}
|
||||
|
||||
ty::TyRawPtr(ty::TypeAndMut { ty: element_ty, ..}) |
|
||||
ty::TyRef(_, ty::TypeAndMut { ty: element_ty, ..}) => {
|
||||
vec![element_ty]
|
||||
|
|
|
|||
|
|
@ -56,12 +56,8 @@ def_type_content_sets! {
|
|||
// InteriorAll = 0b00000000__00000000__1111,
|
||||
|
||||
// Things that are owned by the value (second and third nibbles):
|
||||
OwnsOwned = 0b0000_0000__0000_0001__0000,
|
||||
OwnsDtor = 0b0000_0000__0000_0010__0000,
|
||||
OwnsAll = 0b0000_0000__1111_1111__0000,
|
||||
|
||||
// Things that mean drop glue is necessary
|
||||
NeedsDrop = 0b0000_0000__0000_0111__0000,
|
||||
// OwnsAll = 0b0000_0000__1111_1111__0000,
|
||||
|
||||
// All bits
|
||||
All = 0b1111_1111__1111_1111__1111
|
||||
|
|
@ -77,10 +73,6 @@ impl TypeContents {
|
|||
(self.bits & tc.bits) != 0
|
||||
}
|
||||
|
||||
pub fn owns_owned(&self) -> bool {
|
||||
self.intersects(TC::OwnsOwned)
|
||||
}
|
||||
|
||||
pub fn interior_param(&self) -> bool {
|
||||
self.intersects(TC::InteriorParam)
|
||||
}
|
||||
|
|
@ -90,12 +82,7 @@ impl TypeContents {
|
|||
}
|
||||
|
||||
pub fn needs_drop(&self, _: TyCtxt) -> bool {
|
||||
self.intersects(TC::NeedsDrop)
|
||||
}
|
||||
|
||||
/// Includes only those bits that still apply when indirected through a `Box` pointer
|
||||
pub fn owned_pointer(&self) -> TypeContents {
|
||||
TC::OwnsOwned | (*self & TC::OwnsAll)
|
||||
self.intersects(TC::OwnsDtor)
|
||||
}
|
||||
|
||||
pub fn union<I, T, F>(v: I, mut f: F) -> TypeContents where
|
||||
|
|
@ -104,10 +91,6 @@ impl TypeContents {
|
|||
{
|
||||
v.into_iter().fold(TC::None, |tc, ty| tc | f(ty))
|
||||
}
|
||||
|
||||
pub fn has_dtor(&self) -> bool {
|
||||
self.intersects(TC::OwnsDtor)
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::BitOr for TypeContents {
|
||||
|
|
@ -191,10 +174,6 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
|
|||
TC::None
|
||||
}
|
||||
|
||||
ty::TyBox(typ) => {
|
||||
tc_ty(tcx, typ, cache).owned_pointer()
|
||||
}
|
||||
|
||||
ty::TyDynamic(..) => {
|
||||
TC::All - TC::InteriorParam
|
||||
}
|
||||
|
|
@ -237,7 +216,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
|
|||
|
||||
if def.is_union() {
|
||||
// unions don't have destructors regardless of the child types
|
||||
res = res - TC::NeedsDrop;
|
||||
res = res - TC::OwnsDtor;
|
||||
}
|
||||
|
||||
if def.has_dtor() {
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ use hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
|
|||
use hir::map as hir_map;
|
||||
use hir::map::DisambiguatedDefPathData;
|
||||
use middle::free_region::FreeRegionMap;
|
||||
use middle::lang_items;
|
||||
use middle::region::RegionMaps;
|
||||
use middle::resolve_lifetime;
|
||||
use middle::stability;
|
||||
|
|
@ -231,7 +232,11 @@ pub struct TypeckTables<'tcx> {
|
|||
/// of the struct - this is needed because it is non-trivial to
|
||||
/// normalize while preserving regions. This table is used only in
|
||||
/// MIR construction and hence is not serialized to metadata.
|
||||
pub fru_field_types: NodeMap<Vec<Ty<'tcx>>>
|
||||
pub fru_field_types: NodeMap<Vec<Ty<'tcx>>>,
|
||||
|
||||
/// Maps a cast expression to its kind. This is keyed on the
|
||||
/// *from* expression of the cast, not the cast itself.
|
||||
pub cast_kinds: NodeMap<ty::cast::CastKind>,
|
||||
}
|
||||
|
||||
impl<'tcx> TypeckTables<'tcx> {
|
||||
|
|
@ -246,7 +251,8 @@ impl<'tcx> TypeckTables<'tcx> {
|
|||
closure_tys: NodeMap(),
|
||||
closure_kinds: NodeMap(),
|
||||
liberated_fn_sigs: NodeMap(),
|
||||
fru_field_types: NodeMap()
|
||||
fru_field_types: NodeMap(),
|
||||
cast_kinds: NodeMap(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -533,10 +539,6 @@ pub struct GlobalCtxt<'tcx> {
|
|||
/// expression defining the closure.
|
||||
pub closure_kinds: RefCell<DepTrackingMap<maps::ClosureKinds<'tcx>>>,
|
||||
|
||||
/// Maps a cast expression to its kind. This is keyed on the
|
||||
/// *from* expression of the cast, not the cast itself.
|
||||
pub cast_kinds: RefCell<NodeMap<ty::cast::CastKind>>,
|
||||
|
||||
/// Maps Fn items to a collection of fragment infos.
|
||||
///
|
||||
/// The main goal is to identify data (each of which may be moved
|
||||
|
|
@ -792,7 +794,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
custom_coerce_unsized_kinds: RefCell::new(DefIdMap()),
|
||||
closure_tys: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
|
||||
closure_kinds: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
|
||||
cast_kinds: RefCell::new(NodeMap()),
|
||||
fragment_infos: RefCell::new(DefIdMap()),
|
||||
crate_name: Symbol::intern(crate_name),
|
||||
data_layout: data_layout,
|
||||
|
|
@ -1088,7 +1089,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
|
|||
pub fn print_debug_stats(self) {
|
||||
sty_debug_print!(
|
||||
self,
|
||||
TyAdt, TyBox, TyArray, TySlice, TyRawPtr, TyRef, TyFnDef, TyFnPtr,
|
||||
TyAdt, TyArray, TySlice, TyRawPtr, TyRef, TyFnDef, TyFnPtr,
|
||||
TyDynamic, TyClosure, TyTuple, TyParam, TyInfer, TyProjection, TyAnon);
|
||||
|
||||
println!("Substs interner: #{}", self.interners.substs.borrow().len());
|
||||
|
|
@ -1336,7 +1337,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
|
||||
pub fn mk_box(self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
self.mk_ty(TyBox(ty))
|
||||
let def_id = self.require_lang_item(lang_items::OwnedBoxLangItem);
|
||||
let adt_def = self.lookup_adt_def(def_id);
|
||||
let substs = self.mk_substs(iter::once(Kind::from(ty)));
|
||||
self.mk_ty(TyAdt(adt_def, substs))
|
||||
}
|
||||
|
||||
pub fn mk_ptr(self, tm: TypeAndMut<'tcx>) -> Ty<'tcx> {
|
||||
|
|
|
|||
|
|
@ -181,7 +181,6 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> {
|
|||
ty::TyTuple(ref tys) if tys.is_empty() => self.to_string(),
|
||||
|
||||
ty::TyAdt(def, _) => format!("{} `{}`", def.descr(), tcx.item_path_str(def.did)),
|
||||
ty::TyBox(_) => "box".to_string(),
|
||||
ty::TyArray(_, n) => format!("array of {} elements", n),
|
||||
ty::TySlice(_) => "slice".to_string(),
|
||||
ty::TyRawPtr(_) => "*-ptr".to_string(),
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@
|
|||
use hir::def_id::DefId;
|
||||
use ty::{self, Ty, TyCtxt};
|
||||
use syntax::ast;
|
||||
use middle::lang_items::OwnedBoxLangItem;
|
||||
|
||||
use self::SimplifiedType::*;
|
||||
|
||||
|
|
@ -69,10 +68,6 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
|||
// view of possibly unifying
|
||||
simplify_type(tcx, mt.ty, can_simplify_params)
|
||||
}
|
||||
ty::TyBox(_) => {
|
||||
// treat like we would treat `Box`
|
||||
Some(AdtSimplifiedType(tcx.require_lang_item(OwnedBoxLangItem)))
|
||||
}
|
||||
ty::TyClosure(def_id, _) => {
|
||||
Some(ClosureSimplifiedType(def_id))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ impl FlagComputation {
|
|||
self.add_region(r);
|
||||
}
|
||||
|
||||
&ty::TyBox(tt) | &ty::TyArray(tt, _) | &ty::TySlice(tt) => {
|
||||
&ty::TyArray(tt, _) | &ty::TySlice(tt) => {
|
||||
self.add_ty(tt)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -191,11 +191,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
|
|||
}
|
||||
}
|
||||
TyRef(_, ref tm) => {
|
||||
if tcx.sess.features.borrow().never_type {
|
||||
tm.ty.uninhabited_from(visited, tcx)
|
||||
} else {
|
||||
DefIdForest::empty()
|
||||
}
|
||||
tm.ty.uninhabited_from(visited, tcx)
|
||||
}
|
||||
|
||||
_ => DefIdForest::empty(),
|
||||
|
|
|
|||
|
|
@ -314,8 +314,7 @@ pub fn characteristic_def_id_of_type(ty: Ty) -> Option<DefId> {
|
|||
ty::TyDynamic(data, ..) => data.principal().map(|p| p.def_id()),
|
||||
|
||||
ty::TyArray(subty, _) |
|
||||
ty::TySlice(subty) |
|
||||
ty::TyBox(subty) => characteristic_def_id_of_type(subty),
|
||||
ty::TySlice(subty) => characteristic_def_id_of_type(subty),
|
||||
|
||||
ty::TyRawPtr(mt) |
|
||||
ty::TyRef(_, mt) => characteristic_def_id_of_type(mt.ty),
|
||||
|
|
|
|||
|
|
@ -1053,6 +1053,23 @@ impl<'a, 'gcx, 'tcx> Layout {
|
|||
let dl = &tcx.data_layout;
|
||||
assert!(!ty.has_infer_types());
|
||||
|
||||
let ptr_layout = |pointee: Ty<'gcx>| {
|
||||
let non_zero = !ty.is_unsafe_ptr();
|
||||
let pointee = normalize_associated_type(infcx, pointee);
|
||||
if pointee.is_sized(tcx, &infcx.parameter_environment, DUMMY_SP) {
|
||||
Ok(Scalar { value: Pointer, non_zero: non_zero })
|
||||
} else {
|
||||
let unsized_part = tcx.struct_tail(pointee);
|
||||
let meta = match unsized_part.sty {
|
||||
ty::TySlice(_) | ty::TyStr => {
|
||||
Int(dl.ptr_sized_integer())
|
||||
}
|
||||
ty::TyDynamic(..) => Pointer,
|
||||
_ => return Err(LayoutError::Unknown(unsized_part))
|
||||
};
|
||||
Ok(FatPointer { metadata: meta, non_zero: non_zero })
|
||||
}
|
||||
};
|
||||
|
||||
let layout = match ty.sty {
|
||||
// Basic scalars.
|
||||
|
|
@ -1082,24 +1099,12 @@ impl<'a, 'gcx, 'tcx> Layout {
|
|||
},
|
||||
|
||||
// Potentially-fat pointers.
|
||||
ty::TyBox(pointee) |
|
||||
ty::TyRef(_, ty::TypeAndMut { ty: pointee, .. }) |
|
||||
ty::TyRawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
|
||||
let non_zero = !ty.is_unsafe_ptr();
|
||||
let pointee = normalize_associated_type(infcx, pointee);
|
||||
if pointee.is_sized(tcx, &infcx.parameter_environment, DUMMY_SP) {
|
||||
Scalar { value: Pointer, non_zero: non_zero }
|
||||
} else {
|
||||
let unsized_part = tcx.struct_tail(pointee);
|
||||
let meta = match unsized_part.sty {
|
||||
ty::TySlice(_) | ty::TyStr => {
|
||||
Int(dl.ptr_sized_integer())
|
||||
}
|
||||
ty::TyDynamic(..) => Pointer,
|
||||
_ => return Err(LayoutError::Unknown(unsized_part))
|
||||
};
|
||||
FatPointer { metadata: meta, non_zero: non_zero }
|
||||
}
|
||||
ptr_layout(pointee)?
|
||||
}
|
||||
ty::TyAdt(def, _) if def.is_box() => {
|
||||
ptr_layout(ty.boxed_ty())?
|
||||
}
|
||||
|
||||
// Arrays and slices.
|
||||
|
|
@ -1560,26 +1565,32 @@ impl<'a, 'gcx, 'tcx> SizeSkeleton<'gcx> {
|
|||
Err(err) => err
|
||||
};
|
||||
|
||||
let ptr_skeleton = |pointee: Ty<'gcx>| {
|
||||
let non_zero = !ty.is_unsafe_ptr();
|
||||
let tail = tcx.struct_tail(pointee);
|
||||
match tail.sty {
|
||||
ty::TyParam(_) | ty::TyProjection(_) => {
|
||||
assert!(tail.has_param_types() || tail.has_self_ty());
|
||||
Ok(SizeSkeleton::Pointer {
|
||||
non_zero: non_zero,
|
||||
tail: tcx.erase_regions(&tail)
|
||||
})
|
||||
}
|
||||
_ => {
|
||||
bug!("SizeSkeleton::compute({}): layout errored ({}), yet \
|
||||
tail `{}` is not a type parameter or a projection",
|
||||
ty, err, tail)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
match ty.sty {
|
||||
ty::TyBox(pointee) |
|
||||
ty::TyRef(_, ty::TypeAndMut { ty: pointee, .. }) |
|
||||
ty::TyRawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
|
||||
let non_zero = !ty.is_unsafe_ptr();
|
||||
let tail = tcx.struct_tail(pointee);
|
||||
match tail.sty {
|
||||
ty::TyParam(_) | ty::TyProjection(_) => {
|
||||
assert!(tail.has_param_types() || tail.has_self_ty());
|
||||
Ok(SizeSkeleton::Pointer {
|
||||
non_zero: non_zero,
|
||||
tail: tcx.erase_regions(&tail)
|
||||
})
|
||||
}
|
||||
_ => {
|
||||
bug!("SizeSkeleton::compute({}): layout errored ({}), yet \
|
||||
tail `{}` is not a type parameter or a projection",
|
||||
ty, err, tail)
|
||||
}
|
||||
}
|
||||
ptr_skeleton(pointee)
|
||||
}
|
||||
ty::TyAdt(def, _) if def.is_box() => {
|
||||
ptr_skeleton(ty.boxed_ty())
|
||||
}
|
||||
|
||||
ty::TyAdt(def, substs) => {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@
|
|||
// except according to those terms.
|
||||
|
||||
pub use self::Variance::*;
|
||||
pub use self::DtorKind::*;
|
||||
pub use self::AssociatedItemContainer::*;
|
||||
pub use self::BorrowKind::*;
|
||||
pub use self::IntVarValue::*;
|
||||
|
|
@ -120,21 +119,6 @@ pub struct Resolutions {
|
|||
pub maybe_unused_trait_imports: NodeSet,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum DtorKind {
|
||||
NoDtor,
|
||||
TraitDtor
|
||||
}
|
||||
|
||||
impl DtorKind {
|
||||
pub fn is_present(&self) -> bool {
|
||||
match *self {
|
||||
TraitDtor => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
pub enum AssociatedItemContainer {
|
||||
TraitContainer(DefId),
|
||||
|
|
@ -514,7 +498,7 @@ pub enum BorrowKind {
|
|||
|
||||
/// Data must be immutable but not aliasable. This kind of borrow
|
||||
/// cannot currently be expressed by the user and is used only in
|
||||
/// implicit closure bindings. It is needed when you the closure
|
||||
/// implicit closure bindings. It is needed when the closure
|
||||
/// is borrowing or mutating a mutable referent, e.g.:
|
||||
///
|
||||
/// let x: &mut isize = ...;
|
||||
|
|
@ -592,24 +576,6 @@ pub enum IntVarValue {
|
|||
UintType(ast::UintTy),
|
||||
}
|
||||
|
||||
/// Default region to use for the bound of objects that are
|
||||
/// supplied as the value for this type parameter. This is derived
|
||||
/// from `T:'a` annotations appearing in the type definition. If
|
||||
/// this is `None`, then the default is inherited from the
|
||||
/// surrounding context. See RFC #599 for details.
|
||||
#[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
|
||||
pub enum ObjectLifetimeDefault<'tcx> {
|
||||
/// Require an explicit annotation. Occurs when multiple
|
||||
/// `T:'a` constraints are found.
|
||||
Ambiguous,
|
||||
|
||||
/// Use the base default, typically 'static, but in a fn body it is a fresh variable
|
||||
BaseDefault,
|
||||
|
||||
/// Use the given region as the default.
|
||||
Specific(&'tcx Region),
|
||||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable)]
|
||||
pub struct TypeParameterDef<'tcx> {
|
||||
pub name: Name,
|
||||
|
|
@ -617,7 +583,6 @@ pub struct TypeParameterDef<'tcx> {
|
|||
pub index: u32,
|
||||
pub default_def_id: DefId, // for use in error reporing about defaults
|
||||
pub default: Option<Ty<'tcx>>,
|
||||
pub object_lifetime_default: ObjectLifetimeDefault<'tcx>,
|
||||
|
||||
/// `pure_wrt_drop`, set by the (unsafe) `#[may_dangle]` attribute
|
||||
/// on generic parameter `T`, asserts data behind the parameter
|
||||
|
|
@ -625,12 +590,11 @@ pub struct TypeParameterDef<'tcx> {
|
|||
pub pure_wrt_drop: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable)]
|
||||
pub struct RegionParameterDef<'tcx> {
|
||||
#[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
|
||||
pub struct RegionParameterDef {
|
||||
pub name: Name,
|
||||
pub def_id: DefId,
|
||||
pub index: u32,
|
||||
pub bounds: Vec<&'tcx ty::Region>,
|
||||
|
||||
/// `pure_wrt_drop`, set by the (unsafe) `#[may_dangle]` attribute
|
||||
/// on generic parameter `'a`, asserts data of lifetime `'a`
|
||||
|
|
@ -638,7 +602,7 @@ pub struct RegionParameterDef<'tcx> {
|
|||
pub pure_wrt_drop: bool,
|
||||
}
|
||||
|
||||
impl<'tcx> RegionParameterDef<'tcx> {
|
||||
impl RegionParameterDef {
|
||||
pub fn to_early_bound_region_data(&self) -> ty::EarlyBoundRegion {
|
||||
ty::EarlyBoundRegion {
|
||||
index: self.index,
|
||||
|
|
@ -659,7 +623,7 @@ pub struct Generics<'tcx> {
|
|||
pub parent: Option<DefId>,
|
||||
pub parent_regions: u32,
|
||||
pub parent_types: u32,
|
||||
pub regions: Vec<RegionParameterDef<'tcx>>,
|
||||
pub regions: Vec<RegionParameterDef>,
|
||||
pub types: Vec<TypeParameterDef<'tcx>>,
|
||||
pub has_self: bool,
|
||||
}
|
||||
|
|
@ -677,7 +641,7 @@ impl<'tcx> Generics<'tcx> {
|
|||
self.parent_count() + self.own_count()
|
||||
}
|
||||
|
||||
pub fn region_param(&self, param: &EarlyBoundRegion) -> &RegionParameterDef<'tcx> {
|
||||
pub fn region_param(&self, param: &EarlyBoundRegion) -> &RegionParameterDef {
|
||||
&self.regions[param.index as usize - self.has_self as usize]
|
||||
}
|
||||
|
||||
|
|
@ -1322,9 +1286,11 @@ bitflags! {
|
|||
const IS_SIMD = 1 << 4,
|
||||
const IS_FUNDAMENTAL = 1 << 5,
|
||||
const IS_UNION = 1 << 6,
|
||||
const IS_BOX = 1 << 7,
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct VariantDef {
|
||||
/// The variant's DefId. If this is a tuple-like struct,
|
||||
/// this is the DefId of the struct's ctor.
|
||||
|
|
@ -1335,6 +1301,7 @@ pub struct VariantDef {
|
|||
pub ctor_kind: CtorKind,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct FieldDef {
|
||||
pub did: DefId,
|
||||
pub name: Name,
|
||||
|
|
@ -1394,6 +1361,9 @@ impl<'a, 'gcx, 'tcx> AdtDef {
|
|||
if Some(did) == tcx.lang_items.phantom_data() {
|
||||
flags = flags | AdtFlags::IS_PHANTOM_DATA;
|
||||
}
|
||||
if Some(did) == tcx.lang_items.owned_box() {
|
||||
flags = flags | AdtFlags::IS_BOX;
|
||||
}
|
||||
match kind {
|
||||
AdtKind::Enum => flags = flags | AdtFlags::IS_ENUM,
|
||||
AdtKind::Union => flags = flags | AdtFlags::IS_UNION,
|
||||
|
|
@ -1486,9 +1456,15 @@ impl<'a, 'gcx, 'tcx> AdtDef {
|
|||
self.flags.get().intersects(AdtFlags::IS_PHANTOM_DATA)
|
||||
}
|
||||
|
||||
/// Returns true if this is Box<T>.
|
||||
#[inline]
|
||||
pub fn is_box(&self) -> bool {
|
||||
self.flags.get().intersects(AdtFlags::IS_BOX)
|
||||
}
|
||||
|
||||
/// Returns whether this type has a destructor.
|
||||
pub fn has_dtor(&self) -> bool {
|
||||
self.dtor_kind().is_present()
|
||||
self.destructor.get().is_some()
|
||||
}
|
||||
|
||||
/// Asserts this is a struct and returns the struct's unique
|
||||
|
|
@ -1551,13 +1527,6 @@ impl<'a, 'gcx, 'tcx> AdtDef {
|
|||
self.destructor.set(Some(dtor));
|
||||
}
|
||||
|
||||
pub fn dtor_kind(&self) -> DtorKind {
|
||||
match self.destructor.get() {
|
||||
Some(_) => TraitDtor,
|
||||
None => NoDtor,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a simpler type such that `Self: Sized` if and only
|
||||
/// if that type is Sized, or `TyErr` if this type is recursive.
|
||||
///
|
||||
|
|
@ -1659,7 +1628,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
|
|||
-> Vec<Ty<'tcx>> {
|
||||
let result = match ty.sty {
|
||||
TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) |
|
||||
TyBox(..) | TyRawPtr(..) | TyRef(..) | TyFnDef(..) | TyFnPtr(_) |
|
||||
TyRawPtr(..) | TyRef(..) | TyFnDef(..) | TyFnPtr(_) |
|
||||
TyArray(..) | TyClosure(..) | TyNever => {
|
||||
vec![]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -167,7 +167,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
ty::TyFloat(..) | // OutlivesScalar
|
||||
ty::TyNever | // ...
|
||||
ty::TyAdt(..) | // OutlivesNominalType
|
||||
ty::TyBox(..) | // OutlivesNominalType (ish)
|
||||
ty::TyAnon(..) | // OutlivesNominalType (ish)
|
||||
ty::TyStr | // OutlivesScalar (ish)
|
||||
ty::TyArray(..) | // ...
|
||||
|
|
|
|||
|
|
@ -418,12 +418,6 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
|
|||
Ok(tcx.mk_closure_from_closure_substs(a_id, substs))
|
||||
}
|
||||
|
||||
(&ty::TyBox(a_inner), &ty::TyBox(b_inner)) =>
|
||||
{
|
||||
let typ = relation.relate(&a_inner, &b_inner)?;
|
||||
Ok(tcx.mk_box(typ))
|
||||
}
|
||||
|
||||
(&ty::TyRawPtr(ref a_mt), &ty::TyRawPtr(ref b_mt)) =>
|
||||
{
|
||||
let mt = relation.relate(a_mt, b_mt)?;
|
||||
|
|
|
|||
|
|
@ -353,7 +353,7 @@ macro_rules! CopyImpls {
|
|||
}
|
||||
}
|
||||
|
||||
CopyImpls! { (), hir::Unsafety, abi::Abi }
|
||||
CopyImpls! { (), hir::Unsafety, abi::Abi, ty::RegionParameterDef }
|
||||
|
||||
impl<'tcx, T:TypeFoldable<'tcx>, U:TypeFoldable<'tcx>> TypeFoldable<'tcx> for (T, U) {
|
||||
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> (T, U) {
|
||||
|
|
@ -468,7 +468,6 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Slice<Ty<'tcx>> {
|
|||
impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
|
||||
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
|
||||
let sty = match self.sty {
|
||||
ty::TyBox(typ) => ty::TyBox(typ.fold_with(folder)),
|
||||
ty::TyRawPtr(tm) => ty::TyRawPtr(tm.fold_with(folder)),
|
||||
ty::TyArray(typ, sz) => ty::TyArray(typ.fold_with(folder), sz),
|
||||
ty::TySlice(typ) => ty::TySlice(typ.fold_with(folder)),
|
||||
|
|
@ -506,7 +505,6 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
|
|||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
match self.sty {
|
||||
ty::TyBox(typ) => typ.visit_with(visitor),
|
||||
ty::TyRawPtr(ref tm) => tm.visit_with(visitor),
|
||||
ty::TyArray(typ, _sz) => typ.visit_with(visitor),
|
||||
ty::TySlice(typ) => typ.visit_with(visitor),
|
||||
|
|
@ -726,52 +724,12 @@ impl<'tcx> TypeFoldable<'tcx> for ty::TypeParameterDef<'tcx> {
|
|||
index: self.index,
|
||||
default: self.default.fold_with(folder),
|
||||
default_def_id: self.default_def_id,
|
||||
object_lifetime_default: self.object_lifetime_default.fold_with(folder),
|
||||
pure_wrt_drop: self.pure_wrt_drop,
|
||||
}
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
self.default.visit_with(visitor) ||
|
||||
self.object_lifetime_default.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for ty::ObjectLifetimeDefault<'tcx> {
|
||||
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
|
||||
match *self {
|
||||
ty::ObjectLifetimeDefault::Ambiguous =>
|
||||
ty::ObjectLifetimeDefault::Ambiguous,
|
||||
|
||||
ty::ObjectLifetimeDefault::BaseDefault =>
|
||||
ty::ObjectLifetimeDefault::BaseDefault,
|
||||
|
||||
ty::ObjectLifetimeDefault::Specific(r) =>
|
||||
ty::ObjectLifetimeDefault::Specific(r.fold_with(folder)),
|
||||
}
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
match *self {
|
||||
ty::ObjectLifetimeDefault::Specific(r) => r.visit_with(visitor),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for ty::RegionParameterDef<'tcx> {
|
||||
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
|
||||
ty::RegionParameterDef {
|
||||
name: self.name,
|
||||
def_id: self.def_id,
|
||||
index: self.index,
|
||||
bounds: self.bounds.fold_with(folder),
|
||||
pure_wrt_drop: self.pure_wrt_drop,
|
||||
}
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
self.bounds.visit_with(visitor)
|
||||
self.default.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -115,12 +115,6 @@ pub enum TypeVariants<'tcx> {
|
|||
/// definition and not a concrete use of it.
|
||||
TyAdt(&'tcx AdtDef, &'tcx Substs<'tcx>),
|
||||
|
||||
/// `Box<T>`; this is nominally a struct in the documentation, but is
|
||||
/// special-cased internally. For example, it is possible to implicitly
|
||||
/// move the contents of a box out of that box, and methods of any type
|
||||
/// can have type `Box<Self>`.
|
||||
TyBox(Ty<'tcx>),
|
||||
|
||||
/// The pointee of a string slice. Written as `str`.
|
||||
TyStr,
|
||||
|
||||
|
|
@ -134,7 +128,7 @@ pub enum TypeVariants<'tcx> {
|
|||
TyRawPtr(TypeAndMut<'tcx>),
|
||||
|
||||
/// A reference; a pointer with an associated lifetime. Written as
|
||||
/// `&a mut T` or `&'a T`.
|
||||
/// `&'a mut T` or `&'a T`.
|
||||
TyRef(&'tcx Region, TypeAndMut<'tcx>),
|
||||
|
||||
/// The anonymous type of a function declaration/definition. Each
|
||||
|
|
@ -1139,10 +1133,17 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn is_unique(&self) -> bool {
|
||||
pub fn is_box(&self) -> bool {
|
||||
match self.sty {
|
||||
TyBox(_) => true,
|
||||
_ => false
|
||||
TyAdt(def, _) => def.is_box(),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn boxed_ty(&self) -> Ty<'tcx> {
|
||||
match self.sty {
|
||||
TyAdt(def, substs) if def.is_box() => substs.type_at(0),
|
||||
_ => bug!("`boxed_ty` is called on non-box type {:?}", self),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1247,9 +1248,9 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
|
|||
-> Option<TypeAndMut<'tcx>>
|
||||
{
|
||||
match self.sty {
|
||||
TyBox(ty) => {
|
||||
TyAdt(def, _) if def.is_box() => {
|
||||
Some(TypeAndMut {
|
||||
ty: ty,
|
||||
ty: self.boxed_ty(),
|
||||
mutbl: if pref == ty::PreferMutLvalue {
|
||||
hir::MutMutable
|
||||
} else {
|
||||
|
|
@ -1349,7 +1350,6 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
|
|||
TyInt(_) |
|
||||
TyUint(_) |
|
||||
TyFloat(_) |
|
||||
TyBox(_) |
|
||||
TyStr |
|
||||
TyArray(..) |
|
||||
TySlice(_) |
|
||||
|
|
|
|||
|
|
@ -481,7 +481,6 @@ impl<'a, 'gcx, 'tcx, W> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tcx, W>
|
|||
TyBool |
|
||||
TyChar |
|
||||
TyStr |
|
||||
TyBox(_) |
|
||||
TySlice(_) => {}
|
||||
|
||||
TyError |
|
||||
|
|
@ -563,7 +562,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
|
|||
mutbl: hir::MutImmutable, ..
|
||||
}) => Some(false),
|
||||
|
||||
TyStr | TyBox(..) | TyRef(_, TypeAndMut {
|
||||
TyStr | TyRef(_, TypeAndMut {
|
||||
mutbl: hir::MutMutable, ..
|
||||
}) => Some(true),
|
||||
|
||||
|
|
@ -606,7 +605,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
|
|||
// Fast-path for primitive types
|
||||
let result = match self.sty {
|
||||
TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) |
|
||||
TyBox(..) | TyRawPtr(..) | TyRef(..) | TyFnDef(..) | TyFnPtr(_) |
|
||||
TyRawPtr(..) | TyRef(..) | TyFnDef(..) | TyFnPtr(_) |
|
||||
TyArray(..) | TyTuple(..) | TyClosure(..) | TyNever => Some(true),
|
||||
|
||||
TyStr | TyDynamic(..) | TySlice(_) => Some(false),
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) {
|
|||
ty::TyBool | ty::TyChar | ty::TyInt(_) | ty::TyUint(_) | ty::TyFloat(_) |
|
||||
ty::TyStr | ty::TyInfer(_) | ty::TyParam(_) | ty::TyNever | ty::TyError => {
|
||||
}
|
||||
ty::TyBox(ty) | ty::TyArray(ty, _) | ty::TySlice(ty) => {
|
||||
ty::TyArray(ty, _) | ty::TySlice(ty) => {
|
||||
stack.push(ty);
|
||||
}
|
||||
ty::TyRawPtr(ref mt) | ty::TyRef(_, ref mt) => {
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue