diff --git a/.gitmodules b/.gitmodules index 038237aa179a9..bf9bdd9a5b4b0 100644 --- a/.gitmodules +++ b/.gitmodules @@ -2,9 +2,6 @@ path = src/llvm url = https://github.com/rust-lang/llvm.git branch = master -[submodule "src/jemalloc"] - path = src/jemalloc - url = https://github.com/rust-lang/jemalloc.git [submodule "src/rust-installer"] path = src/tools/rust-installer url = https://github.com/rust-lang/rust-installer.git @@ -64,4 +61,4 @@ path = src/tools/clang url = https://github.com/rust-lang-nursery/clang.git branch = rust-release-80-v1 - \ No newline at end of file + diff --git a/.travis.yml b/.travis.yml index ec8060b9f56aa..3457e8a8043d0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,7 +30,7 @@ matrix: - env: > RUST_CHECK_TARGET=dist - RUST_CONFIGURE_ARGS="--enable-extended --enable-profiler --enable-lldb" + RUST_CONFIGURE_ARGS="--enable-extended --enable-profiler --enable-lldb --set rust.jemalloc" SRC=. DEPLOY_ALT=1 RUSTC_RETRY_LINKER_ON_SEGFAULT=1 @@ -53,7 +53,7 @@ matrix: # version that we're using, 8.2, cannot compile LLVM for OSX 10.7. - env: > RUST_CHECK_TARGET=check - RUST_CONFIGURE_ARGS="--build=x86_64-apple-darwin --enable-sanitizers --enable-profiler" + RUST_CONFIGURE_ARGS="--build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc" SRC=. RUSTC_RETRY_LINKER_ON_SEGFAULT=1 MACOSX_DEPLOYMENT_TARGET=10.8 @@ -67,7 +67,7 @@ matrix: - env: > RUST_CHECK_TARGET=check - RUST_CONFIGURE_ARGS=--build=i686-apple-darwin + RUST_CONFIGURE_ARGS="--build=i686-apple-darwin --set rust.jemalloc" SRC=. RUSTC_RETRY_LINKER_ON_SEGFAULT=1 MACOSX_DEPLOYMENT_TARGET=10.8 @@ -87,7 +87,7 @@ matrix: # OSX 10.7 and `xcode7` is the latest Xcode able to compile LLVM for 10.7. - env: > RUST_CHECK_TARGET=dist - RUST_CONFIGURE_ARGS="--build=i686-apple-darwin --enable-full-tools --enable-profiler --enable-lldb" + RUST_CONFIGURE_ARGS="--build=i686-apple-darwin --enable-full-tools --enable-profiler --enable-lldb --set rust.jemalloc" SRC=. DEPLOY=1 RUSTC_RETRY_LINKER_ON_SEGFAULT=1 @@ -102,7 +102,7 @@ matrix: - 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-full-tools --enable-sanitizers --enable-profiler --enable-lldb" + RUST_CONFIGURE_ARGS="--target=aarch64-apple-ios,armv7-apple-ios,armv7s-apple-ios,i386-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --enable-lldb --set rust.jemalloc" SRC=. DEPLOY=1 RUSTC_RETRY_LINKER_ON_SEGFAULT=1 diff --git a/RELEASES.md b/RELEASES.md index 70a7dab72272f..fa9169cac7e63 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -102,7 +102,7 @@ Misc [cargo/5878]: https://github.com/rust-lang/cargo/pull/5878/ [cargo/5984]: https://github.com/rust-lang/cargo/pull/5984/ [cargo/5995]: https://github.com/rust-lang/cargo/pull/5995/ -[proc-macros]: https://doc.rust-lang.org/book/2018-edition/ch19-06-macros.html +[proc-macros]: https://doc.rust-lang.org/nightly/book/2018-edition/ch19-06-macros.html [`Ipv4Addr::BROADCAST`]: https://doc.rust-lang.org/nightly/std/net/struct.Ipv4Addr.html#associatedconstant.BROADCAST [`Ipv4Addr::LOCALHOST`]: https://doc.rust-lang.org/nightly/std/net/struct.Ipv4Addr.html#associatedconstant.LOCALHOST diff --git a/config.toml.example b/config.toml.example index e8cb0cba6b1f9..247b2d3ce80f9 100644 --- a/config.toml.example +++ b/config.toml.example @@ -296,12 +296,6 @@ # Adding debuginfo makes them several times larger. #debuginfo-tools = false -# Whether or not jemalloc is built and enabled -#use-jemalloc = true - -# Whether or not jemalloc is built with its debug option set -#debug-jemalloc = false - # Whether or not `panic!`s generate backtraces (RUST_BACKTRACE) #backtrace = true @@ -398,6 +392,10 @@ # generally only set for releases #remap-debuginfo = false +# Link the compiler against `jemalloc`, where on Linux and OSX it should +# override the default allocator for rustc and LLVM. +#jemalloc = false + # ============================================================================= # Options for specific targets # @@ -437,10 +435,6 @@ # not, you can specify an explicit file name for it. #llvm-filecheck = "/path/to/FileCheck" -# Path to the custom jemalloc static library to link into the standard library -# by default. This is only used if jemalloc is still enabled above -#jemalloc = "/path/to/jemalloc/libjemalloc_pic.a" - # If this target is for Android, this option will be required to specify where # the NDK for the target lives. This is used to find the C compiler to link and # build native code. diff --git a/src/Cargo.lock b/src/Cargo.lock index dd21108352792..3629525b429e3 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -15,17 +15,6 @@ dependencies = [ "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "alloc_jemalloc" -version = "0.0.0" -dependencies = [ - "build_helper 0.1.0", - "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.0.0", - "core 0.0.0", - "libc 0.0.0", -] - [[package]] name = "alloc_system" version = "0.0.0" @@ -784,6 +773,11 @@ dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "fs_extra" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "fst" version = "0.3.0" @@ -995,6 +989,16 @@ name = "itoa" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "jemalloc-sys" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "jobserver" version = "0.1.11" @@ -2180,6 +2184,7 @@ dependencies = [ "arena 0.0.0", "env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)", "graphviz 0.0.0", + "jemalloc-sys 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2679,7 +2684,6 @@ name = "std" version = "0.0.0" dependencies = [ "alloc 0.0.0", - "alloc_jemalloc 0.0.0", "alloc_system 0.0.0", "build_helper 0.1.0", "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3236,6 +3240,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" "checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" "checksum fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" +"checksum fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5f2a4a2034423744d2cc7ca2068453168dcdb82c438419e639a26bd87839c674" "checksum fst 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d94485a00b1827b861dd9d1a2cc9764f9044d4c535514c0760a5a2012ef3399f" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" @@ -3258,6 +3263,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum is-match 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7e5b386aef33a1c677be65237cb9d32c3f3ef56bd035949710c4bb13083eb053" "checksum itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)" = "f58856976b776fedd95533137617a02fb25719f40e7d9b01c7043cd65474f450" "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" +"checksum jemalloc-sys 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "bfc62c8e50e381768ce8ee0428ee53741929f7ebd73e4d83f669bcf7693e00ae" "checksum jobserver 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "60af5f849e1981434e4a31d3d782c4774ae9b434ce55b101a96ecfd09147e8be" "checksum json 0.11.13 (registry+https://github.com/rust-lang/crates.io-index)" = "9ad0485404155f45cce53a40d4b2d6ac356418300daed05273d9e26f91c390be" "checksum jsonrpc-core 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ddf83704f4e79979a424d1082dd2c1e52683058056c9280efa19ac5f6bc9033c" diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index ffc5adbebb34f..02f8dcb2dce5f 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -712,11 +712,6 @@ def update_submodules(self): backends = self.get_toml('codegen-backends') if backends is None or not 'emscripten' in backends: continue - if module.endswith("jemalloc"): - if self.get_toml('use-jemalloc') == 'false': - continue - if self.get_toml('jemalloc'): - continue if module.endswith("lld"): config = self.get_toml('lld') if config is None or config == 'false': diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 69d45acdedaf9..25f12ea34f203 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -158,16 +158,7 @@ pub fn std_cargo(builder: &Builder, .arg("--manifest-path") .arg(builder.src.join("src/rustc/compiler_builtins_shim/Cargo.toml")); } else { - let mut features = builder.std_features(); - - // When doing a local rebuild we tell cargo that we're stage1 rather than - // stage0. This works fine if the local rust and being-built rust have the - // same view of what the default allocator is, but fails otherwise. Since - // we don't have a way to express an allocator preference yet, work - // around the issue in the case of a local rebuild with jemalloc disabled. - if compiler.stage == 0 && builder.local_rebuild && !builder.config.use_jemalloc { - features.push_str(" force_alloc_system"); - } + let features = builder.std_features(); if compiler.stage != 0 && builder.config.sanitizers { // This variable is used by the sanitizer runtime crates, e.g. @@ -188,11 +179,6 @@ pub fn std_cargo(builder: &Builder, .arg("--manifest-path") .arg(builder.src.join("src/libstd/Cargo.toml")); - if let Some(target) = builder.config.target_config.get(&target) { - if let Some(ref jemalloc) = target.jemalloc { - cargo.env("JEMALLOC_OVERRIDE", jemalloc); - } - } if target.contains("musl") { if let Some(p) = builder.musl_root(target) { cargo.env("MUSL_ROOT", p); diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index a9d330e06a15d..2a75265e88381 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -115,6 +115,7 @@ pub struct Config { pub hosts: Vec>, pub targets: Vec>, pub local_rebuild: bool, + pub jemalloc: bool, // dist misc pub dist_sign_folder: Option, @@ -122,8 +123,6 @@ pub struct Config { pub dist_gpg_password_file: Option, // libstd features - pub debug_jemalloc: bool, - pub use_jemalloc: bool, pub backtrace: bool, // support for RUST_BACKTRACE pub wasm_syscall: bool, @@ -165,7 +164,6 @@ pub struct Target { pub llvm_config: Option, /// Some(path to FileCheck) if one was specified. pub llvm_filecheck: Option, - pub jemalloc: Option, pub cc: Option, pub cxx: Option, pub ar: Option, @@ -262,7 +260,7 @@ struct Llvm { link_jobs: Option, link_shared: Option, version_suffix: Option, - clang_cl: Option + clang_cl: Option, } #[derive(Deserialize, Default, Clone)] @@ -300,8 +298,6 @@ struct Rust { debuginfo_only_std: Option, debuginfo_tools: Option, experimental_parallel_queries: Option, - debug_jemalloc: Option, - use_jemalloc: Option, backtrace: Option, default_linker: Option, channel: Option, @@ -327,6 +323,7 @@ struct Rust { backtrace_on_ice: Option, verify_llvm_ir: Option, remap_debuginfo: Option, + jemalloc: Option, } /// TOML representation of how each build target is configured. @@ -335,7 +332,6 @@ struct Rust { struct TomlTarget { llvm_config: Option, llvm_filecheck: Option, - jemalloc: Option, cc: Option, cxx: Option, ar: Option, @@ -361,7 +357,6 @@ impl Config { config.llvm_enabled = true; config.llvm_optimize = true; config.llvm_version_check = true; - config.use_jemalloc = true; config.backtrace = true; config.rust_optimize = true; config.rust_optimize_tests = true; @@ -497,7 +492,6 @@ impl Config { let mut debuginfo_only_std = None; let mut debuginfo_tools = None; let mut debug = None; - let mut debug_jemalloc = None; let mut debuginfo = None; let mut debug_assertions = None; let mut optimize = None; @@ -539,12 +533,11 @@ impl Config { debuginfo_tools = rust.debuginfo_tools; optimize = rust.optimize; ignore_git = rust.ignore_git; - debug_jemalloc = rust.debug_jemalloc; set(&mut config.rust_optimize_tests, rust.optimize_tests); set(&mut config.rust_debuginfo_tests, rust.debuginfo_tests); set(&mut config.codegen_tests, rust.codegen_tests); set(&mut config.rust_rpath, rust.rpath); - set(&mut config.use_jemalloc, rust.use_jemalloc); + set(&mut config.jemalloc, rust.jemalloc); set(&mut config.backtrace, rust.backtrace); set(&mut config.channel, rust.channel.clone()); set(&mut config.rust_dist_src, rust.dist_src); @@ -592,9 +585,6 @@ impl Config { if let Some(ref s) = cfg.llvm_filecheck { target.llvm_filecheck = Some(config.src.join(s)); } - if let Some(ref s) = cfg.jemalloc { - target.jemalloc = Some(config.src.join(s)); - } if let Some(ref s) = cfg.android_ndk { target.ndk = Some(config.src.join(s)); } @@ -640,7 +630,6 @@ impl Config { config.rust_debuginfo_tools = debuginfo_tools.unwrap_or(false); let default = debug == Some(true); - config.debug_jemalloc = debug_jemalloc.unwrap_or(default); config.rust_debuginfo = debuginfo.unwrap_or(default); config.rust_debug_assertions = debug_assertions.unwrap_or(default); diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index 0cf84a62986a5..78e6ad1a5d202 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -82,7 +82,6 @@ def v(*args): o("debuginfo-lines", "rust.debuginfo-lines", "build with line number debugger metadata") o("debuginfo-only-std", "rust.debuginfo-only-std", "build only libstd with debugging information") o("debuginfo-tools", "rust.debuginfo-tools", "build extended tools with debugging information") -o("debug-jemalloc", "rust.debug-jemalloc", "build jemalloc with --enable-debug --enable-fill") v("save-toolstates", "rust.save-toolstates", "save build and test status of external tools into this file") v("prefix", "install.prefix", "set installation prefix") @@ -99,7 +98,6 @@ def v(*args): v("llvm-config", None, "set path to llvm-config") v("llvm-filecheck", None, "set path to LLVM's FileCheck utility") v("python", "build.python", "set path to python") -v("jemalloc-root", None, "set directory where libjemalloc_pic.a is located") v("android-cross-path", "target.arm-linux-androideabi.android-ndk", "Android NDK standalone path (deprecated)") v("i686-linux-android-ndk", "target.i686-linux-android.android-ndk", @@ -148,7 +146,6 @@ def v(*args): # Many of these are saved below during the "writing configuration" step # (others are conditionally saved). o("manage-submodules", "build.submodules", "let the build manage the git submodules") -o("jemalloc", "rust.use-jemalloc", "build liballoc with jemalloc") o("full-bootstrap", "build.full-bootstrap", "build three compilers instead of two") o("extended", "build.extended", "build an extended rust tool set") @@ -330,8 +327,6 @@ def set(key, value): set('target.{}.llvm-config'.format(build()), value) elif option.name == 'llvm-filecheck': set('target.{}.llvm-filecheck'.format(build()), value) - elif option.name == 'jemalloc-root': - set('target.{}.jemalloc'.format(build()), value + '/libjemalloc_pic.a') elif option.name == 'tools': set('build.tools', value.split(',')) elif option.name == 'host': diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 4de899ee2d599..850b0494ea525 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -859,7 +859,6 @@ impl Step for Src { "src/build_helper", "src/dlmalloc", "src/liballoc", - "src/liballoc_jemalloc", "src/liballoc_system", "src/libbacktrace", "src/libcompiler_builtins", @@ -878,13 +877,11 @@ impl Step for Src { "src/rustc/dlmalloc_shim", "src/libtest", "src/libterm", - "src/jemalloc", "src/libprofiler_builtins", "src/stdsimd", ]; let std_src_dirs_exclude = [ "src/libcompiler_builtins/compiler-rt/test", - "src/jemalloc/test/unit", ]; copy_src_dirs(builder, &std_src_dirs[..], &std_src_dirs_exclude[..], &dst_src); diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 4e26c98a62759..c225ef3827180 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -516,12 +516,6 @@ impl Build { fn std_features(&self) -> String { let mut features = "panic-unwind".to_string(); - if self.config.debug_jemalloc { - features.push_str(" debug-jemalloc"); - } - if self.config.use_jemalloc { - features.push_str(" jemalloc"); - } if self.config.backtrace { features.push_str(" backtrace"); } @@ -537,8 +531,8 @@ impl Build { /// Get the space-separated set of activated features for the compiler. fn rustc_features(&self) -> String { let mut features = String::new(); - if self.config.use_jemalloc { - features.push_str(" jemalloc"); + if self.config.jemalloc { + features.push_str("jemalloc"); } features } @@ -791,7 +785,7 @@ impl Build { // If we're compiling on macOS then we add a few unconditional flags // indicating that we want libc++ (more filled out than libstdc++) and // we want to compile for 10.7. This way we can ensure that - // LLVM/jemalloc/etc are all properly compiled. + // LLVM/etc are all properly compiled. if target.contains("apple-darwin") { base.push("-stdlib=libc++".into()); } diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index 724cb5841f48f..ed8956ce3e051 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -152,12 +152,6 @@ pub fn check(build: &mut Build) { if !build.config.dry_run { cmd_finder.must_have(build.cxx(*host).unwrap()); } - - // The msvc hosts don't use jemalloc, turn it off globally to - // avoid packaging the dummy liballoc_jemalloc on that platform. - if host.contains("msvc") { - build.config.use_jemalloc = false; - } } // Externally configured LLVM requires FileCheck to exist diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index fe04a91011ee5..a2b2cc263810c 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -1504,8 +1504,7 @@ impl Step for CrateNotDefault { type Output = (); fn should_run(run: ShouldRun) -> ShouldRun { - run.path("src/liballoc_jemalloc") - .path("src/librustc_asan") + run.path("src/librustc_asan") .path("src/librustc_lsan") .path("src/librustc_msan") .path("src/librustc_tsan") @@ -1522,7 +1521,6 @@ impl Step for CrateNotDefault { target: run.target, test_kind, krate: match run.path { - _ if run.path.ends_with("src/liballoc_jemalloc") => "alloc_jemalloc", _ if run.path.ends_with("src/librustc_asan") => "rustc_asan", _ if run.path.ends_with("src/librustc_lsan") => "rustc_lsan", _ if run.path.ends_with("src/librustc_msan") => "rustc_msan", @@ -1561,7 +1559,6 @@ impl Step for Crate { run = run.krate("test"); for krate in run.builder.in_tree_crates("std") { if krate.is_local(&run.builder) - && !krate.name.contains("jemalloc") && !(krate.name.starts_with("rustc_") && krate.name.ends_with("san")) && krate.name != "dlmalloc" { diff --git a/src/ci/docker/dist-i686-linux/Dockerfile b/src/ci/docker/dist-i686-linux/Dockerfile index d99e409e42671..8df49f364a372 100644 --- a/src/ci/docker/dist-i686-linux/Dockerfile +++ b/src/ci/docker/dist-i686-linux/Dockerfile @@ -98,7 +98,8 @@ ENV RUST_CONFIGURE_ARGS \ --enable-sanitizers \ --enable-profiler \ --set target.i686-unknown-linux-gnu.linker=clang \ - --build=i686-unknown-linux-gnu + --build=i686-unknown-linux-gnu \ + --set rust.jemalloc ENV SCRIPT python2.7 ../x.py dist --build $HOSTS --host $HOSTS --target $HOSTS ENV CARGO_TARGET_I686_UNKNOWN_LINUX_GNU_LINKER=clang diff --git a/src/ci/docker/dist-x86_64-linux/Dockerfile b/src/ci/docker/dist-x86_64-linux/Dockerfile index 8696f72e0e388..0a2dae72f7382 100644 --- a/src/ci/docker/dist-x86_64-linux/Dockerfile +++ b/src/ci/docker/dist-x86_64-linux/Dockerfile @@ -101,7 +101,8 @@ ENV RUST_CONFIGURE_ARGS \ --set target.x86_64-unknown-linux-gnu.linker=clang \ --set target.x86_64-unknown-linux-gnu.ar=/rustroot/bin/llvm-ar \ --set target.x86_64-unknown-linux-gnu.ranlib=/rustroot/bin/llvm-ranlib \ - --set llvm.thin-lto=true + --set llvm.thin-lto=true \ + --set rust.jemalloc ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS ENV CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER=clang diff --git a/src/jemalloc b/src/jemalloc deleted file mode 160000 index 1f5a28755e301..0000000000000 --- a/src/jemalloc +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 1f5a28755e301ac581e2048011e4e0ff3da482ef diff --git a/src/liballoc/tests/heap.rs b/src/liballoc/tests/heap.rs index 6fa88ce969a0e..b6be38107da7f 100644 --- a/src/liballoc/tests/heap.rs +++ b/src/liballoc/tests/heap.rs @@ -12,9 +12,6 @@ use alloc_system::System; use std::alloc::{Global, Alloc, Layout}; /// https://github.com/rust-lang/rust/issues/45955 -/// -/// Note that `#[global_allocator]` is not used, -/// so `liballoc_jemalloc` is linked (on some platforms). #[test] fn alloc_system_overaligned_request() { check_overalign_requests(System) diff --git a/src/liballoc_jemalloc/Cargo.toml b/src/liballoc_jemalloc/Cargo.toml deleted file mode 100644 index 7986d5dd2eb54..0000000000000 --- a/src/liballoc_jemalloc/Cargo.toml +++ /dev/null @@ -1,24 +0,0 @@ -[package] -authors = ["The Rust Project Developers"] -name = "alloc_jemalloc" -version = "0.0.0" -build = "build.rs" -links = "jemalloc" - -[lib] -name = "alloc_jemalloc" -path = "lib.rs" -test = false -doc = false - -[dependencies] -core = { path = "../libcore" } -libc = { path = "../rustc/libc_shim" } -compiler_builtins = { path = "../rustc/compiler_builtins_shim" } - -[build-dependencies] -build_helper = { path = "../build_helper" } -cc = "1.0.1" - -[features] -debug = [] diff --git a/src/liballoc_jemalloc/build.rs b/src/liballoc_jemalloc/build.rs deleted file mode 100644 index fbda425a70bf5..0000000000000 --- a/src/liballoc_jemalloc/build.rs +++ /dev/null @@ -1,151 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![deny(warnings)] - -extern crate build_helper; -extern crate cc; - -use std::env; -use std::path::PathBuf; -use std::process::Command; -use build_helper::{run, native_lib_boilerplate}; - -fn main() { - // 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 - // changes between targets, it invalidates the fingerprint of - // std's build script (this is a cargo bug); so we must ensure - // 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("bitrig") || target.contains("emscripten") || target.contains("fuchsia") || - target.contains("msvc") || target.contains("openbsd") || target.contains("redox") || - target.contains("rumprun") || target.contains("wasm32") { - println!("cargo:rustc-cfg=dummy_jemalloc"); - return; - } - - // CloudABI ships with a copy of jemalloc that has been patched to - // work well with sandboxing. Don't attempt to build our own copy, - // as it won't build. - if target.contains("cloudabi") { - return; - } - - if target.contains("android") { - println!("cargo:rustc-link-lib=gcc"); - } else if !target.contains("windows") && !target.contains("musl") { - println!("cargo:rustc-link-lib=pthread"); - } - - if let Some(jemalloc) = env::var_os("JEMALLOC_OVERRIDE") { - let jemalloc = PathBuf::from(jemalloc); - println!("cargo:rustc-link-search=native={}", - jemalloc.parent().unwrap().display()); - let stem = jemalloc.file_stem().unwrap().to_str().unwrap(); - let name = jemalloc.file_name().unwrap().to_str().unwrap(); - let kind = if name.ends_with(".a") { - "static" - } else { - "dylib" - }; - println!("cargo:rustc-link-lib={}={}", kind, &stem[3..]); - return; - } - - let link_name = if target.contains("windows") { "jemalloc" } else { "jemalloc_pic" }; - let native = match native_lib_boilerplate("jemalloc", "jemalloc", link_name, "lib") { - Ok(native) => native, - _ => return, - }; - - let mut cmd = Command::new("sh"); - cmd.arg(native.src_dir.join("configure") - .to_str() - .unwrap() - .replace("C:\\", "/c/") - .replace("\\", "/")) - .current_dir(&native.out_dir) - // jemalloc generates Makefile deps using GCC's "-MM" flag. This means - // that GCC will run the preprocessor, and only the preprocessor, over - // jemalloc's source files. If we don't specify CPPFLAGS, then at least - // on ARM that step fails with a "Missing implementation for 32-bit - // atomic operations" error. This is because no "-march" flag will be - // passed to GCC, and then GCC won't define the - // "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4" macro that jemalloc needs to - // select an atomic operation implementation. - .env("CPPFLAGS", env::var_os("CFLAGS").unwrap_or_default()); - - if target.contains("ios") { - cmd.arg("--disable-tls"); - } else if target.contains("android") { - // We force android to have prefixed symbols because apparently - // replacement of the libc allocator doesn't quite work. When this was - // tested (unprefixed symbols), it was found that the `realpath` - // function in libc would allocate with libc malloc (not jemalloc - // malloc), and then the standard library would free with jemalloc free, - // causing a segfault. - // - // If the test suite passes, however, without symbol prefixes then we - // should be good to go! - cmd.arg("--with-jemalloc-prefix=je_"); - cmd.arg("--disable-tls"); - } else if target.contains("dragonfly") || target.contains("musl") { - cmd.arg("--with-jemalloc-prefix=je_"); - } - - if cfg!(feature = "debug") { - // Enable jemalloc assertions. - cmd.arg("--enable-debug"); - } - - cmd.arg(format!("--host={}", build_helper::gnu_target(&target))); - cmd.arg(format!("--build={}", build_helper::gnu_target(&host))); - - // for some reason, jemalloc configure doesn't detect this value - // automatically for this target - if target == "sparc64-unknown-linux-gnu" { - cmd.arg("--with-lg-quantum=4"); - } - - run(&mut cmd); - - let mut make = Command::new(build_helper::make(&host)); - make.current_dir(&native.out_dir) - .arg("build_lib_static"); - - // These are intended for mingw32-make which we don't use - if cfg!(windows) { - make.env_remove("MAKEFLAGS").env_remove("MFLAGS"); - } - - // mingw make seems... buggy? unclear... - if !host.contains("windows") { - make.arg("-j") - .arg(env::var("NUM_JOBS").expect("NUM_JOBS was not set")); - } - - run(&mut make); - - // 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"); - cc::Build::new() - .flag("-fvisibility=hidden") - .file("pthread_atfork_dummy.c") - .compile("pthread_atfork_dummy"); - } -} diff --git a/src/liballoc_jemalloc/lib.rs b/src/liballoc_jemalloc/lib.rs deleted file mode 100644 index 0065e84a7ad1a..0000000000000 --- a/src/liballoc_jemalloc/lib.rs +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![no_std] -#![allow(unused_attributes)] -#![unstable(feature = "alloc_jemalloc", - reason = "implementation detail of std, does not provide any public API", - issue = "0")] -#![feature(core_intrinsics)] -#![feature(libc)] -#![feature(linkage)] -#![feature(nll)] -#![feature(staged_api)] -#![feature(rustc_attrs)] -#![cfg_attr(dummy_jemalloc, allow(dead_code, unused_extern_crates))] -#![cfg_attr(not(dummy_jemalloc), feature(allocator_api))] -#![rustc_alloc_kind = "exe"] - -extern crate libc; - -#[cfg(not(dummy_jemalloc))] -pub use contents::*; -#[cfg(not(dummy_jemalloc))] -mod contents { - use libc::{c_int, c_void, size_t}; - - // Note that the symbols here are prefixed by default on macOS and Windows (we - // don't explicitly request it), and on Android and DragonFly we explicitly - // request it as unprefixing cause segfaults (mismatches in allocators). - extern "C" { - #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios", - target_os = "dragonfly", target_os = "windows", target_env = "musl"), - link_name = "je_mallocx")] - fn mallocx(size: size_t, flags: c_int) -> *mut c_void; - #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios", - target_os = "dragonfly", target_os = "windows", target_env = "musl"), - link_name = "je_calloc")] - fn calloc(size: size_t, flags: c_int) -> *mut c_void; - #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios", - target_os = "dragonfly", target_os = "windows", target_env = "musl"), - link_name = "je_rallocx")] - fn rallocx(ptr: *mut c_void, size: size_t, flags: c_int) -> *mut c_void; - #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios", - target_os = "dragonfly", target_os = "windows", target_env = "musl"), - link_name = "je_sdallocx")] - fn sdallocx(ptr: *mut c_void, size: size_t, flags: c_int); - } - - const MALLOCX_ZERO: c_int = 0x40; - - // The minimum alignment guaranteed by the architecture. This value is used to - // add fast paths for low alignment values. - #[cfg(all(any(target_arch = "arm", - target_arch = "mips", - target_arch = "powerpc")))] - const MIN_ALIGN: usize = 8; - #[cfg(all(any(target_arch = "x86", - target_arch = "x86_64", - target_arch = "aarch64", - target_arch = "powerpc64", - target_arch = "mips64", - target_arch = "s390x", - target_arch = "sparc64")))] - const MIN_ALIGN: usize = 16; - - // MALLOCX_ALIGN(a) macro - fn mallocx_align(a: usize) -> c_int { - a.trailing_zeros() as c_int - } - - fn align_to_flags(align: usize, size: usize) -> c_int { - if align <= MIN_ALIGN && align <= size { - 0 - } else { - mallocx_align(align) - } - } - - // for symbol names src/librustc/middle/allocator.rs - // for signatures src/librustc_allocator/lib.rs - - // linkage directives are provided as part of the current compiler allocator - // ABI - - #[rustc_std_internal_symbol] - pub unsafe extern fn __rde_alloc(size: usize, align: usize) -> *mut u8 { - let flags = align_to_flags(align, size); - let ptr = mallocx(size as size_t, flags) as *mut u8; - ptr - } - - #[rustc_std_internal_symbol] - pub unsafe extern fn __rde_dealloc(ptr: *mut u8, - size: usize, - align: usize) { - let flags = align_to_flags(align, size); - sdallocx(ptr as *mut c_void, size, flags); - } - - #[rustc_std_internal_symbol] - pub unsafe extern fn __rde_realloc(ptr: *mut u8, - _old_size: usize, - align: usize, - new_size: usize) -> *mut u8 { - let flags = align_to_flags(align, new_size); - let ptr = rallocx(ptr as *mut c_void, new_size, flags) as *mut u8; - ptr - } - - #[rustc_std_internal_symbol] - pub unsafe extern fn __rde_alloc_zeroed(size: usize, align: usize) -> *mut u8 { - let ptr = if align <= MIN_ALIGN && align <= size { - calloc(size as size_t, 1) as *mut u8 - } else { - let flags = align_to_flags(align, size) | MALLOCX_ZERO; - mallocx(size as size_t, flags) as *mut u8 - }; - ptr - } -} diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 202a4284f4c82..266b1c4d4a084 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -233,6 +233,12 @@ declare_lint! { "detect mut variables which don't need to be mutable" } +declare_lint! { + pub UNCONDITIONAL_RECURSION, + Warn, + "functions that cannot return without calling themselves" +} + declare_lint! { pub SINGLE_USE_LIFETIMES, Allow, @@ -402,6 +408,7 @@ impl LintPass for HardwiredLints { DEPRECATED, UNUSED_UNSAFE, UNUSED_MUT, + UNCONDITIONAL_RECURSION, SINGLE_USE_LIFETIMES, UNUSED_LIFETIMES, UNUSED_LABELS, diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 13e6f7a4c745a..9d3f37bc36a9d 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -93,6 +93,7 @@ use util::nodemap::ItemLocalSet; #[derive(Clone, Debug, PartialEq)] pub enum Categorization<'tcx> { Rvalue(ty::Region<'tcx>), // temporary val, argument is its scope + ThreadLocal(ty::Region<'tcx>), // value that cannot move, but still restricted in scope StaticItem, Upvar(Upvar), // upvar referenced by closure env Local(ast::NodeId), // local variable @@ -268,6 +269,7 @@ impl<'tcx> cmt_<'tcx> { Categorization::Deref(ref base_cmt, _) => { base_cmt.immutability_blame() } + Categorization::ThreadLocal(..) | Categorization::StaticItem => { // Do we want to do something here? None @@ -715,17 +717,23 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { } Def::Static(def_id, mutbl) => { - // `#[thread_local]` statics may not outlive the current function. - for attr in &self.tcx.get_attrs(def_id)[..] { - if attr.check_name("thread_local") { - return Ok(self.cat_rvalue_node(hir_id, span, expr_ty)); - } - } + // `#[thread_local]` statics may not outlive the current function, but + // they also cannot be moved out of. + let is_thread_local = self.tcx.get_attrs(def_id)[..] + .iter() + .any(|attr| attr.check_name("thread_local")); + + let cat = if is_thread_local { + let re = self.temporary_scope(hir_id.local_id); + Categorization::ThreadLocal(re) + } else { + Categorization::StaticItem + }; Ok(cmt_ { hir_id, - span:span, - cat:Categorization::StaticItem, + span, + cat, mutbl: if mutbl { McDeclared } else { McImmutable}, ty:expr_ty, note: NoteNone @@ -1408,6 +1416,7 @@ impl<'tcx> cmt_<'tcx> { match self.cat { Categorization::Rvalue(..) | Categorization::StaticItem | + Categorization::ThreadLocal(..) | Categorization::Local(..) | Categorization::Deref(_, UnsafePtr(..)) | Categorization::Deref(_, BorrowedPtr(..)) | @@ -1439,6 +1448,7 @@ impl<'tcx> cmt_<'tcx> { } Categorization::Rvalue(..) | + Categorization::ThreadLocal(..) | Categorization::Local(..) | Categorization::Upvar(..) | Categorization::Deref(_, UnsafePtr(..)) => { // yes, it's aliasable, but... @@ -1485,6 +1495,9 @@ impl<'tcx> cmt_<'tcx> { Categorization::StaticItem => { "static item".into() } + Categorization::ThreadLocal(..) => { + "thread-local static item".into() + } Categorization::Rvalue(..) => { "non-place".into() } diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 9d296e67da1ae..cf93fff400226 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -69,6 +69,24 @@ impl<'tcx> HasLocalDecls<'tcx> for Mir<'tcx> { } } +/// The various "big phases" that MIR goes through. +/// +/// Warning: ordering of variants is significant +#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub enum MirPhase { + Build = 0, + Const = 1, + Validated = 2, + Optimized = 3, +} + +impl MirPhase { + /// Gets the index of the current MirPhase within the set of all MirPhases. + pub fn phase_index(&self) -> usize { + *self as usize + } +} + /// Lowered representation of a single function. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Mir<'tcx> { @@ -76,6 +94,13 @@ pub struct Mir<'tcx> { /// that indexes into this vector. basic_blocks: IndexVec>, + /// Records how far through the "desugaring and optimization" process this particular + /// MIR has traversed. This is particularly useful when inlining, since in that context + /// we instantiate the promoted constants and add them to our promoted vector -- but those + /// promoted items have already been optimized, whereas ours have not. This field allows + /// us to see the difference and forego optimization on the inlined promoted items. + pub phase: MirPhase, + /// List of source scopes; these are referenced by statements /// and used for debuginfo. Indexed by a `SourceScope`. pub source_scopes: IndexVec, @@ -151,6 +176,7 @@ impl<'tcx> Mir<'tcx> { ); Mir { + phase: MirPhase::Build, basic_blocks, source_scopes, source_scope_local_data, @@ -368,6 +394,7 @@ pub enum Safety { } impl_stable_hash_for!(struct Mir<'tcx> { + phase, basic_blocks, source_scopes, source_scope_local_data, @@ -616,6 +643,13 @@ impl_stable_hash_for!(enum self::ImplicitSelfKind { None }); +impl_stable_hash_for!(enum self::MirPhase { + Build, + Const, + Validated, + Optimized, +}); + mod binding_form_impl { use ich::StableHashingContext; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult}; @@ -2786,6 +2820,7 @@ pub enum ClosureOutlivesSubject<'tcx> { CloneTypeFoldableAndLiftImpls! { BlockTailInfo, + MirPhase, Mutability, SourceInfo, UpvarDecl, @@ -2798,6 +2833,7 @@ CloneTypeFoldableAndLiftImpls! { BraceStructTypeFoldableImpl! { impl<'tcx> TypeFoldable<'tcx> for Mir<'tcx> { + phase, basic_blocks, source_scopes, source_scope_local_data, diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs index d9b64527700fc..1fc9ee07a1ae4 100644 --- a/src/librustc_borrowck/borrowck/check_loans.rs +++ b/src/librustc_borrowck/borrowck/check_loans.rs @@ -377,6 +377,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { // by-move upvars, which is local data for generators Categorization::Upvar(..) => true, + Categorization::ThreadLocal(region) | Categorization::Rvalue(region) => { // Rvalues promoted to 'static are no longer local if let RegionKind::ReStatic = *region { diff --git a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs index ffc4fbfb4c9cb..7bb5f411752fe 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs @@ -177,6 +177,7 @@ fn check_and_get_illegal_move_origin<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, match cmt.cat { Categorization::Deref(_, mc::BorrowedPtr(..)) | Categorization::Deref(_, mc::UnsafePtr(..)) | + Categorization::ThreadLocal(..) | Categorization::StaticItem => { Some(cmt.clone()) } diff --git a/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs b/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs index c9dcc0d9fa266..6ef5d65d10dca 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs @@ -70,6 +70,7 @@ impl<'a, 'tcx> GuaranteeLifetimeContext<'a, 'tcx> { match cmt.cat { Categorization::Rvalue(..) | + Categorization::ThreadLocal(..) | Categorization::Local(..) | // L-Local Categorization::Upvar(..) | Categorization::Deref(_, mc::BorrowedPtr(..)) | // L-Deref-Borrowed @@ -105,6 +106,7 @@ impl<'a, 'tcx> GuaranteeLifetimeContext<'a, 'tcx> { //! rooting etc, and presuming `cmt` is not mutated. match cmt.cat { + Categorization::ThreadLocal(temp_scope) | Categorization::Rvalue(temp_scope) => { temp_scope } diff --git a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs index b29ab55f9ba78..e1a4473539c8c 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs @@ -145,6 +145,8 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &'a BorrowckCtxt<'a, 'tcx>, match move_from.cat { Categorization::Deref(_, mc::BorrowedPtr(..)) | Categorization::Deref(_, mc::UnsafePtr(..)) | + Categorization::Deref(_, mc::Unique) | + Categorization::ThreadLocal(..) | Categorization::StaticItem => { bccx.cannot_move_out_of( move_from.span, &move_from.descriptive_string(bccx.tcx), Origin::Ast) @@ -166,7 +168,10 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &'a BorrowckCtxt<'a, 'tcx>, } } } - _ => { + + Categorization::Rvalue(..) | + Categorization::Local(..) | + Categorization::Upvar(..) => { span_bug!(move_from.span, "this path should not cause illegal move"); } } diff --git a/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs b/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs index d9784cc2177fd..52c7ebb4beb02 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs @@ -70,6 +70,12 @@ impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> { RestrictionResult::Safe } + Categorization::ThreadLocal(..) => { + // Thread-locals are statics that have a scope, with + // no underlying structure to provide restrictions. + RestrictionResult::Safe + } + Categorization::Local(local_id) => { // R-Variable, locally declared let lp = new_lp(LpVar(local_id)); diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index da5c5f47c08ac..8ac46d344d767 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -520,6 +520,7 @@ pub fn opt_loan_path_is_field<'tcx>(cmt: &mc::cmt_<'tcx>) -> (Option { (None, false) } diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 846d505641103..3680810ea79f7 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -21,7 +21,7 @@ use abi; use value::Value; use llvm; -use llvm::debuginfo::{DIType, DIFile, DIScope, DIDescriptor, +use llvm::debuginfo::{DIArray, DIType, DIFile, DIScope, DIDescriptor, DICompositeType, DILexicalBlock, DIFlags}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; @@ -34,6 +34,7 @@ use rustc::ty::Instance; use common::CodegenCx; use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt}; use rustc::ty::layout::{self, Align, LayoutOf, PrimitiveExt, Size, TyLayout}; +use rustc::ty::subst::UnpackedKind; use rustc::session::config; use rustc::util::nodemap::FxHashMap; use rustc_fs_util::path2cstr; @@ -266,6 +267,7 @@ impl RecursiveTypeDescription<'ll, 'tcx> { // ... and attach them to the stub to complete it. set_members_of_composite_type(cx, + unfinished_type, metadata_stub, member_descriptions); return MetadataCreationResult::new(metadata_stub, true); @@ -1174,6 +1176,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { member_description_factory.create_member_descriptions(cx); set_members_of_composite_type(cx, + self.enum_type, variant_type_metadata, member_descriptions); vec![ @@ -1204,6 +1207,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { .create_member_descriptions(cx); set_members_of_composite_type(cx, + self.enum_type, variant_type_metadata, member_descriptions); MemberDescription { @@ -1231,6 +1235,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { member_description_factory.create_member_descriptions(cx); set_members_of_composite_type(cx, + self.enum_type, variant_type_metadata, variant_member_descriptions); @@ -1534,13 +1539,15 @@ fn composite_type_metadata( containing_scope); // ... and immediately create and add the member descriptions. set_members_of_composite_type(cx, + composite_type, composite_type_metadata, member_descriptions); composite_type_metadata } -fn set_members_of_composite_type(cx: &CodegenCx<'ll, '_>, +fn set_members_of_composite_type(cx: &CodegenCx<'ll, 'tcx>, + composite_type: Ty<'tcx>, composite_type_metadata: &'ll DICompositeType, member_descriptions: Vec>) { // In some rare cases LLVM metadata uniquing would lead to an existing type @@ -1580,10 +1587,57 @@ fn set_members_of_composite_type(cx: &CodegenCx<'ll, '_>, }) .collect(); + let type_params = compute_type_parameters(cx, composite_type); unsafe { let type_array = create_DIArray(DIB(cx), &member_metadata[..]); - llvm::LLVMRustDICompositeTypeSetTypeArray( - DIB(cx), composite_type_metadata, type_array); + llvm::LLVMRustDICompositeTypeReplaceArrays( + DIB(cx), composite_type_metadata, Some(type_array), type_params); + } +} + +// Compute the type parameters for a type, if any, for the given +// metadata. +fn compute_type_parameters(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>) -> Option<&'ll DIArray> { + if let ty::Adt(def, substs) = ty.sty { + if !substs.types().next().is_none() { + let generics = cx.tcx.generics_of(def.did); + let names = get_parameter_names(cx, generics); + let template_params: Vec<_> = substs.iter().zip(names).filter_map(|(kind, name)| { + if let UnpackedKind::Type(ty) = kind.unpack() { + let actual_type = cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty); + let actual_type_metadata = + type_metadata(cx, actual_type, syntax_pos::DUMMY_SP); + let name = SmallCStr::new(&name.as_str()); + Some(unsafe { + + Some(llvm::LLVMRustDIBuilderCreateTemplateTypeParameter( + DIB(cx), + None, + name.as_ptr(), + actual_type_metadata, + unknown_file_metadata(cx), + 0, + 0, + )) + }) + } else { + None + } + }).collect(); + + return Some(create_DIArray(DIB(cx), &template_params[..])); + } + } + return None; + + fn get_parameter_names(cx: &CodegenCx, + generics: &ty::Generics) + -> Vec { + let mut names = generics.parent.map_or(vec![], |def_id| { + get_parameter_names(cx, cx.tcx.generics_of(def_id)) + }); + names.extend(generics.params.iter().map(|param| param.name)); + names } } diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs index 0b98fa4eaf551..11414604d955c 100644 --- a/src/librustc_codegen_llvm/llvm/ffi.rs +++ b/src/librustc_codegen_llvm/llvm/ffi.rs @@ -1419,9 +1419,10 @@ extern "C" { LineNo: c_uint) -> &'a DINameSpace; - pub fn LLVMRustDICompositeTypeSetTypeArray(Builder: &DIBuilder<'a>, - CompositeType: &'a DIType, - TypeArray: &'a DIArray); + pub fn LLVMRustDICompositeTypeReplaceArrays(Builder: &DIBuilder<'a>, + CompositeType: &'a DIType, + Elements: Option<&'a DIArray>, + Params: Option<&'a DIArray>); pub fn LLVMRustDIBuilderCreateDebugLocation(Context: &'a Context, diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml index 470c8b03d0bca..1e32f5ef6f0b6 100644 --- a/src/librustc_driver/Cargo.toml +++ b/src/librustc_driver/Cargo.toml @@ -38,3 +38,8 @@ syntax = { path = "../libsyntax" } smallvec = { version = "0.6.5", features = ["union"] } syntax_ext = { path = "../libsyntax_ext" } syntax_pos = { path = "../libsyntax_pos" } + +[dependencies.jemalloc-sys] +version = '0.1.8' +optional = true +features = ['unprefixed_malloc_on_supported_platforms'] diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 276b7290c2ef0..e8fdaddaeb89c 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -64,6 +64,14 @@ extern crate syntax; extern crate syntax_ext; extern crate syntax_pos; +// Note that the linkage here should be all that we need, on Linux we're not +// prefixing the symbols here so this should naturally override our default +// allocator. On OSX it should override via the zone allocator. We shouldn't +// enable this by default on other platforms, so other platforms aren't handled +// here yet. +#[cfg(feature = "jemalloc-sys")] +extern crate jemalloc_sys; + use driver::CompileController; use pretty::{PpMode, UserIdentifiedItem}; diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index bc5f688729c36..19f9168cf0a0e 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -30,10 +30,7 @@ use rustc::hir::def::Def; use rustc::hir::def_id::DefId; -use rustc::cfg; -use rustc::ty::subst::Substs; use rustc::ty::{self, Ty}; -use rustc::traits; use hir::Node; use util::nodemap::NodeSet; use lint::{LateContext, LintContext, LintArray}; @@ -844,279 +841,6 @@ impl EarlyLintPass for UnusedDocComment { } } -declare_lint! { - pub UNCONDITIONAL_RECURSION, - Warn, - "functions that cannot return without calling themselves" -} - -#[derive(Copy, Clone)] -pub struct UnconditionalRecursion; - - -impl LintPass for UnconditionalRecursion { - fn get_lints(&self) -> LintArray { - lint_array![UNCONDITIONAL_RECURSION] - } -} - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion { - fn check_fn(&mut self, - cx: &LateContext, - fn_kind: FnKind, - _: &hir::FnDecl, - body: &hir::Body, - sp: Span, - id: ast::NodeId) { - let method = match fn_kind { - FnKind::ItemFn(..) => None, - FnKind::Method(..) => { - Some(cx.tcx.associated_item(cx.tcx.hir.local_def_id(id))) - } - // closures can't recur, so they don't matter. - FnKind::Closure(_) => return, - }; - - // Walk through this function (say `f`) looking to see if - // every possible path references itself, i.e. the function is - // called recursively unconditionally. This is done by trying - // to find a path from the entry node to the exit node that - // *doesn't* call `f` by traversing from the entry while - // pretending that calls of `f` are sinks (i.e. ignoring any - // exit edges from them). - // - // NB. this has an edge case with non-returning statements, - // like `loop {}` or `panic!()`: control flow never reaches - // the exit node through these, so one can have a function - // that never actually calls itself but is still picked up by - // this lint: - // - // fn f(cond: bool) { - // if !cond { panic!() } // could come from `assert!(cond)` - // f(false) - // } - // - // In general, functions of that form may be able to call - // itself a finite number of times and then diverge. The lint - // considers this to be an error for two reasons, (a) it is - // easier to implement, and (b) it seems rare to actually want - // to have behaviour like the above, rather than - // e.g. accidentally recursing after an assert. - - let cfg = cfg::CFG::new(cx.tcx, &body); - - let mut work_queue = vec![cfg.entry]; - let mut reached_exit_without_self_call = false; - let mut self_call_spans = vec![]; - let mut visited = FxHashSet::default(); - - while let Some(idx) = work_queue.pop() { - if idx == cfg.exit { - // found a path! - reached_exit_without_self_call = true; - break; - } - - let cfg_id = idx.node_id(); - if visited.contains(&cfg_id) { - // already done - continue; - } - visited.insert(cfg_id); - - // is this a recursive call? - let local_id = cfg.graph.node_data(idx).id(); - if local_id != hir::DUMMY_ITEM_LOCAL_ID { - let node_id = cx.tcx.hir.hir_to_node_id(hir::HirId { - owner: body.value.hir_id.owner, - local_id - }); - let self_recursive = match method { - Some(ref method) => expr_refers_to_this_method(cx, method, node_id), - None => expr_refers_to_this_fn(cx, id, node_id), - }; - if self_recursive { - self_call_spans.push(cx.tcx.hir.span(node_id)); - // this is a self call, so we shouldn't explore past - // this node in the CFG. - continue; - } - } - - // add the successors of this node to explore the graph further. - for (_, edge) in cfg.graph.outgoing_edges(idx) { - let target_idx = edge.target(); - let target_cfg_id = target_idx.node_id(); - if !visited.contains(&target_cfg_id) { - work_queue.push(target_idx) - } - } - } - - // Check the number of self calls because a function that - // doesn't return (e.g. calls a `-> !` function or `loop { /* - // no break */ }`) shouldn't be linted unless it actually - // recurs. - if !reached_exit_without_self_call && !self_call_spans.is_empty() { - let sp = cx.tcx.sess.source_map().def_span(sp); - let mut db = cx.struct_span_lint(UNCONDITIONAL_RECURSION, - sp, - "function cannot return without recursing"); - db.span_label(sp, "cannot return without recursing"); - // offer some help to the programmer. - for call in &self_call_spans { - db.span_label(*call, "recursive call site"); - } - db.help("a `loop` may express intention better if this is on purpose"); - db.emit(); - } - - // all done - return; - - // Functions for identifying if the given Expr NodeId `id` - // represents a call to the function `fn_id`/method `method`. - - fn expr_refers_to_this_fn(cx: &LateContext, fn_id: ast::NodeId, id: ast::NodeId) -> bool { - match cx.tcx.hir.get(id) { - Node::Expr(&hir::Expr { node: hir::ExprKind::Call(ref callee, _), .. }) => { - let def = if let hir::ExprKind::Path(ref qpath) = callee.node { - cx.tables.qpath_def(qpath, callee.hir_id) - } else { - return false; - }; - match def { - Def::Local(..) | Def::Upvar(..) => false, - _ => def.def_id() == cx.tcx.hir.local_def_id(fn_id) - } - } - _ => false, - } - } - - // Check if the expression `id` performs a call to `method`. - fn expr_refers_to_this_method(cx: &LateContext, - method: &ty::AssociatedItem, - id: ast::NodeId) - -> bool { - use rustc::ty::adjustment::*; - - // Ignore non-expressions. - let expr = if let Node::Expr(e) = cx.tcx.hir.get(id) { - e - } else { - return false; - }; - - // Check for overloaded autoderef method calls. - let mut source = cx.tables.expr_ty(expr); - for adjustment in cx.tables.expr_adjustments(expr) { - if let Adjust::Deref(Some(deref)) = adjustment.kind { - let (def_id, substs) = deref.method_call(cx.tcx, source); - if method_call_refers_to_method(cx, method, def_id, substs, id) { - return true; - } - } - source = adjustment.target; - } - - // Check for method calls and overloaded operators. - if cx.tables.is_method_call(expr) { - let hir_id = cx.tcx.hir.definitions().node_to_hir_id(id); - if let Some(def) = cx.tables.type_dependent_defs().get(hir_id) { - let def_id = def.def_id(); - let substs = cx.tables.node_substs(hir_id); - if method_call_refers_to_method(cx, method, def_id, substs, id) { - return true; - } - } else { - cx.tcx.sess.delay_span_bug(expr.span, - "no type-dependent def for method call"); - } - } - - // Check for calls to methods via explicit paths (e.g. `T::method()`). - match expr.node { - hir::ExprKind::Call(ref callee, _) => { - let def = if let hir::ExprKind::Path(ref qpath) = callee.node { - cx.tables.qpath_def(qpath, callee.hir_id) - } else { - return false; - }; - match def { - Def::Method(def_id) => { - let substs = cx.tables.node_substs(callee.hir_id); - method_call_refers_to_method(cx, method, def_id, substs, id) - } - _ => false, - } - } - _ => false, - } - } - - // Check if the method call to the method with the ID `callee_id` - // and instantiated with `callee_substs` refers to method `method`. - fn method_call_refers_to_method<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, - method: &ty::AssociatedItem, - callee_id: DefId, - callee_substs: &Substs<'tcx>, - expr_id: ast::NodeId) - -> bool { - let tcx = cx.tcx; - let callee_item = tcx.associated_item(callee_id); - - match callee_item.container { - // This is an inherent method, so the `def_id` refers - // directly to the method definition. - ty::ImplContainer(_) => callee_id == method.def_id, - - // A trait method, from any number of possible sources. - // Attempt to select a concrete impl before checking. - ty::TraitContainer(trait_def_id) => { - let trait_ref = ty::TraitRef::from_method(tcx, trait_def_id, callee_substs); - let trait_ref = ty::Binder::bind(trait_ref); - let span = tcx.hir.span(expr_id); - let obligation = - traits::Obligation::new(traits::ObligationCause::misc(span, expr_id), - cx.param_env, - trait_ref.to_poly_trait_predicate()); - - tcx.infer_ctxt().enter(|infcx| { - let mut selcx = traits::SelectionContext::new(&infcx); - match selcx.select(&obligation) { - // The method comes from a `T: Trait` bound. - // If `T` is `Self`, then this call is inside - // a default method definition. - Ok(Some(traits::VtableParam(_))) => { - let on_self = trait_ref.self_ty().is_self(); - // We can only be recursing in a default - // method if we're being called literally - // on the `Self` type. - on_self && callee_id == method.def_id - } - - // The `impl` is known, so we check that with a - // special case: - Ok(Some(traits::VtableImpl(vtable_impl))) => { - let container = ty::ImplContainer(vtable_impl.impl_def_id); - // It matches if it comes from the same impl, - // and has the same method name. - container == method.container && - callee_item.ident.name == method.ident.name - } - - // There's no way to know if this call is - // recursive, so we assume it's not. - _ => false, - } - }) - } - } - } - } -} - declare_lint! { PLUGIN_AS_LIBRARY, Warn, @@ -1724,7 +1448,6 @@ impl LintPass for SoftLints { MISSING_DEBUG_IMPLEMENTATIONS, ANONYMOUS_PARAMETERS, UNUSED_DOC_COMMENTS, - UNCONDITIONAL_RECURSION, PLUGIN_AS_LIBRARY, NO_MANGLE_CONST_ITEMS, NO_MANGLE_GENERIC_ITEMS, diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 5bf2b76e66849..f289acc032be8 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -144,7 +144,6 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { UnusedAllocation: UnusedAllocation, MissingCopyImplementations: MissingCopyImplementations, UnstableFeatures: UnstableFeatures, - UnconditionalRecursion: UnconditionalRecursion, InvalidNoMangleItems: InvalidNoMangleItems, PluginAsLibrary: PluginAsLibrary, MutableTransmutes: MutableTransmutes, diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 26f977c6b59d1..a855c94707880 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -340,7 +340,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let source_map = self.tcx.sess.source_map(); let all_source_files = source_map.files(); - let (working_dir, working_dir_was_remapped) = self.tcx.sess.working_dir.clone(); + let (working_dir, _cwd_remapped) = self.tcx.sess.working_dir.clone(); let adapted = all_source_files.iter() .filter(|source_file| { @@ -349,32 +349,26 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { !source_file.is_imported() }) .map(|source_file| { - // When exporting SourceFiles, we expand all paths to absolute - // paths because any relative paths are potentially relative to - // a wrong directory. - // However, if a path has been modified via - // `--remap-path-prefix` we assume the user has already set - // things up the way they want and don't touch the path values - // anymore. match source_file.name { + // This path of this SourceFile has been modified by + // path-remapping, so we use it verbatim (and avoid + // cloning the whole map in the process). + _ if source_file.name_was_remapped => source_file.clone(), + + // Otherwise expand all paths to absolute paths because + // any relative paths are potentially relative to a + // wrong directory. FileName::Real(ref name) => { - if source_file.name_was_remapped || - (name.is_relative() && working_dir_was_remapped) { - // This path of this SourceFile has been modified by - // path-remapping, so we use it verbatim (and avoid cloning - // the whole map in the process). - source_file.clone() - } else { - let mut adapted = (**source_file).clone(); - adapted.name = Path::new(&working_dir).join(name).into(); - adapted.name_hash = { - let mut hasher: StableHasher = StableHasher::new(); - adapted.name.hash(&mut hasher); - hasher.finish() - }; - Lrc::new(adapted) - } + let mut adapted = (**source_file).clone(); + adapted.name = Path::new(&working_dir).join(name).into(); + adapted.name_hash = { + let mut hasher: StableHasher = StableHasher::new(); + adapted.name.hash(&mut hasher); + hasher.finish() + }; + Lrc::new(adapted) }, + // expanded code, not from a file _ => source_file.clone(), } diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 6ef8b15545872..ddea7e5226024 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -1831,7 +1831,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { | Write(wk @ WriteKind::StorageDeadOrDrop) | Write(wk @ WriteKind::MutableBorrow(BorrowKind::Shared)) | Write(wk @ WriteKind::MutableBorrow(BorrowKind::Shallow)) => { - if let Err(_place_err) = self.is_mutable(place, is_local_mutation_allowed) { + if let (Err(_place_err), true) = ( + self.is_mutable(place, is_local_mutation_allowed), + self.errors_buffer.is_empty() + ) { if self.infcx.tcx.migrate_borrowck() { // rust-lang/rust#46908: In pure NLL mode this // code path should be unreachable (and thus @@ -1855,12 +1858,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { location, ); } else { - self.infcx.tcx.sess.delay_span_bug( + span_bug!( span, - &format!( - "Accessing `{:?}` with the kind `{:?}` shouldn't be possible", - place, kind - ), + "Accessing `{:?}` with the kind `{:?}` shouldn't be possible", + place, + kind, ); } } diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs index b71b131570d7b..7afe2c67adc9b 100644 --- a/src/librustc_mir/borrow_check/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/mutability_errors.rs @@ -180,9 +180,9 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { AccessKind::Move => { err = self.infcx.tcx .cannot_move_out_of(span, &(item_msg + &reason), Origin::Mir); - act = "move"; - acted_on = "moved"; - span + err.span_label(span, "cannot move"); + err.buffer(&mut self.errors_buffer); + return; } AccessKind::Mutate => { err = self.infcx.tcx diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 9e78932bffea6..e6dd0107e9198 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -35,6 +35,8 @@ use syntax_pos::Span; use transform::MirSource; use util as mir_util; +use super::lints; + /// Construct the MIR for a given def-id. pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'tcx> { let id = tcx.hir.as_local_node_id(def_id).unwrap(); @@ -176,6 +178,8 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t mir_util::dump_mir(tcx, None, "mir_map", &0, MirSource::item(def_id), &mir, |_, _| Ok(()) ); + lints::check(tcx, &mir, def_id); + mir }) } diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs index f7043487c51a6..cfccb950e8276 100644 --- a/src/librustc_mir/dataflow/impls/borrows.rs +++ b/src/librustc_mir/dataflow/impls/borrows.rs @@ -184,7 +184,6 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { } crate fn borrows(&self) -> &IndexVec> { &self.borrow_set.borrows } - pub fn scope_tree(&self) -> &Lrc { &self.scope_tree } pub fn location(&self, idx: BorrowIndex) -> &Location { &self.borrow_set.borrows[idx].reserve_location diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs index da4bd780eb4fa..c19145636e6da 100644 --- a/src/librustc_mir/dataflow/mod.rs +++ b/src/librustc_mir/dataflow/mod.rs @@ -724,20 +724,6 @@ impl<'a, 'tcx, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation } } } - - pub fn new_from_sets(mir: &'a Mir<'tcx>, - dead_unwinds: &'a BitSet, - sets: AllSets, - denotation: D) -> Self { - DataflowAnalysis { - mir, - dead_unwinds, - flow_state: DataflowState { - sets: sets, - operator: denotation, - } - } - } } impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index 77483ad184ba6..d53bb1dc4d63a 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -931,12 +931,37 @@ impl<'tcx> IntRange<'tcx> { } } -// Return a set of constructors equivalent to `all_ctors \ used_ctors`. +// A request for missing constructor data in terms of either: +// - whether or not there any missing constructors; or +// - the actual set of missing constructors. +#[derive(PartialEq)] +enum MissingCtorsInfo { + Emptiness, + Ctors, +} + +// Used by `compute_missing_ctors`. +#[derive(Debug, PartialEq)] +enum MissingCtors<'tcx> { + Empty, + NonEmpty, + + // Note that the Vec can be empty. + Ctors(Vec>), +} + +// When `info` is `MissingCtorsInfo::Ctors`, compute a set of constructors +// equivalent to `all_ctors \ used_ctors`. When `info` is +// `MissingCtorsInfo::Emptiness`, just determines if that set is empty or not. +// (The split logic gives a performance win, because we always need to know if +// the set is empty, but we rarely need the full set, and it can be expensive +// to compute the full set.) fn compute_missing_ctors<'a, 'tcx: 'a>( + info: MissingCtorsInfo, tcx: TyCtxt<'a, 'tcx, 'tcx>, all_ctors: &Vec>, used_ctors: &Vec>, -) -> Vec> { +) -> MissingCtors<'tcx> { let mut missing_ctors = vec![]; for req_ctor in all_ctors { @@ -965,10 +990,22 @@ fn compute_missing_ctors<'a, 'tcx: 'a>( // We add `refined_ctors` instead of `req_ctor`, because then we can // provide more detailed error information about precisely which // ranges have been omitted. - missing_ctors.extend(refined_ctors); + if info == MissingCtorsInfo::Emptiness { + if !refined_ctors.is_empty() { + // The set is non-empty; return early. + return MissingCtors::NonEmpty; + } + } else { + missing_ctors.extend(refined_ctors); + } } - missing_ctors + if info == MissingCtorsInfo::Emptiness { + // If we reached here, the set is empty. + MissingCtors::Empty + } else { + MissingCtors::Ctors(missing_ctors) + } } /// Algorithm from http://moscova.inria.fr/~maranget/papers/warn/index.html @@ -1081,20 +1118,23 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>, // feature flag is not present, so this is only // needed for that case. - // Find those constructors that are not matched by any non-wildcard patterns in the - // current column. - let missing_ctors = compute_missing_ctors(cx.tcx, &all_ctors, &used_ctors); + // Missing constructors are those that are not matched by any + // non-wildcard patterns in the current column. We always determine if + // the set is empty, but we only fully construct them on-demand, + // because they're rarely used and can be big. + let cheap_missing_ctors = + compute_missing_ctors(MissingCtorsInfo::Emptiness, cx.tcx, &all_ctors, &used_ctors); let is_privately_empty = all_ctors.is_empty() && !cx.is_uninhabited(pcx.ty); let is_declared_nonexhaustive = cx.is_non_exhaustive_enum(pcx.ty) && !cx.is_local(pcx.ty); - debug!("missing_ctors={:#?} is_privately_empty={:#?} is_declared_nonexhaustive={:#?}", - missing_ctors, is_privately_empty, is_declared_nonexhaustive); + debug!("cheap_missing_ctors={:#?} is_privately_empty={:#?} is_declared_nonexhaustive={:#?}", + cheap_missing_ctors, is_privately_empty, is_declared_nonexhaustive); // For privately empty and non-exhaustive enums, we work as if there were an "extra" // `_` constructor for the type, so we can never match over all constructors. let is_non_exhaustive = is_privately_empty || is_declared_nonexhaustive; - if missing_ctors.is_empty() && !is_non_exhaustive { + if cheap_missing_ctors == MissingCtors::Empty && !is_non_exhaustive { split_grouped_constructors(cx.tcx, all_ctors, matrix, pcx.ty).into_iter().map(|c| { is_useful_specialized(cx, matrix, v, c, pcx.ty, witness) }).find(|result| result.is_useful()).unwrap_or(NotUseful) @@ -1165,15 +1205,22 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>, witness }).collect() } else { - pats.into_iter().flat_map(|witness| { - missing_ctors.iter().map(move |ctor| { - // Extends the witness with a "wild" version of this - // constructor, that matches everything that can be built with - // it. For example, if `ctor` is a `Constructor::Variant` for - // `Option::Some`, this pushes the witness for `Some(_)`. - witness.clone().push_wild_constructor(cx, ctor, pcx.ty) - }) - }).collect() + let expensive_missing_ctors = + compute_missing_ctors(MissingCtorsInfo::Ctors, cx.tcx, &all_ctors, + &used_ctors); + if let MissingCtors::Ctors(missing_ctors) = expensive_missing_ctors { + pats.into_iter().flat_map(|witness| { + missing_ctors.iter().map(move |ctor| { + // Extends the witness with a "wild" version of this + // constructor, that matches everything that can be built with + // it. For example, if `ctor` is a `Constructor::Variant` for + // `Option::Some`, this pushes the witness for `Some(_)`. + witness.clone().push_wild_constructor(cx, ctor, pcx.ty) + }) + }).collect() + } else { + bug!("cheap missing ctors") + } }; UsefulWithWitness(new_witnesses) } diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index 2f44dff2e22c3..75417982aa189 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -79,6 +79,7 @@ mod borrow_check; mod build; mod dataflow; mod hair; +mod lints; mod shim; pub mod transform; pub mod util; diff --git a/src/librustc_mir/lints.rs b/src/librustc_mir/lints.rs new file mode 100644 index 0000000000000..4c7938504c10f --- /dev/null +++ b/src/librustc_mir/lints.rs @@ -0,0 +1,156 @@ +// Copyright 2018 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use rustc_data_structures::bit_set::BitSet; +use rustc::hir::def_id::DefId; +use rustc::hir::intravisit::FnKind; +use rustc::hir::map::blocks::FnLikeNode; +use rustc::lint::builtin::UNCONDITIONAL_RECURSION; +use rustc::mir::{self, Mir, TerminatorKind}; +use rustc::ty::{AssociatedItem, AssociatedItemContainer, Instance, TyCtxt, TyKind}; +use rustc::ty::subst::Substs; + +pub fn check(tcx: TyCtxt<'a, 'tcx, 'tcx>, + mir: &Mir<'tcx>, + def_id: DefId) { + let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); + + if let Some(fn_like_node) = FnLikeNode::from_node(tcx.hir.get(node_id)) { + check_fn_for_unconditional_recursion(tcx, fn_like_node.kind(), mir, def_id); + } +} + +fn check_fn_for_unconditional_recursion(tcx: TyCtxt<'a, 'tcx, 'tcx>, + fn_kind: FnKind, + mir: &Mir<'tcx>, + def_id: DefId) { + if let FnKind::Closure(_) = fn_kind { + // closures can't recur, so they don't matter. + return; + } + + //FIXME(#54444) rewrite this lint to use the dataflow framework + + // Walk through this function (say `f`) looking to see if + // every possible path references itself, i.e. the function is + // called recursively unconditionally. This is done by trying + // to find a path from the entry node to the exit node that + // *doesn't* call `f` by traversing from the entry while + // pretending that calls of `f` are sinks (i.e. ignoring any + // exit edges from them). + // + // NB. this has an edge case with non-returning statements, + // like `loop {}` or `panic!()`: control flow never reaches + // the exit node through these, so one can have a function + // that never actually calls itself but is still picked up by + // this lint: + // + // fn f(cond: bool) { + // if !cond { panic!() } // could come from `assert!(cond)` + // f(false) + // } + // + // In general, functions of that form may be able to call + // itself a finite number of times and then diverge. The lint + // considers this to be an error for two reasons, (a) it is + // easier to implement, and (b) it seems rare to actually want + // to have behaviour like the above, rather than + // e.g. accidentally recursing after an assert. + + let basic_blocks = mir.basic_blocks(); + let mut reachable_without_self_call_queue = vec![mir::START_BLOCK]; + let mut reached_exit_without_self_call = false; + let mut self_call_locations = vec![]; + let mut visited = BitSet::new_empty(basic_blocks.len()); + + let param_env = tcx.param_env(def_id); + let trait_substs_count = + match tcx.opt_associated_item(def_id) { + Some(AssociatedItem { + container: AssociatedItemContainer::TraitContainer(trait_def_id), + .. + }) => tcx.generics_of(trait_def_id).count(), + _ => 0 + }; + let caller_substs = &Substs::identity_for_item(tcx, def_id)[..trait_substs_count]; + + while let Some(bb) = reachable_without_self_call_queue.pop() { + if visited.contains(bb) { + //already done + continue; + } + + visited.insert(bb); + + let block = &basic_blocks[bb]; + + if let Some(ref terminator) = block.terminator { + match terminator.kind { + TerminatorKind::Call { ref func, .. } => { + let func_ty = func.ty(mir, tcx); + + if let TyKind::FnDef(fn_def_id, substs) = func_ty.sty { + let (call_fn_id, call_substs) = + if let Some(instance) = Instance::resolve(tcx, + param_env, + fn_def_id, + substs) { + (instance.def_id(), instance.substs) + } else { + (fn_def_id, substs) + }; + + let is_self_call = + call_fn_id == def_id && + &call_substs[..caller_substs.len()] == caller_substs; + + if is_self_call { + self_call_locations.push(terminator.source_info); + + //this is a self call so we shouldn't explore + //further down this path + continue; + } + } + }, + TerminatorKind::Abort | TerminatorKind::Return => { + //found a path! + reached_exit_without_self_call = true; + break; + } + _ => {} + } + + for successor in terminator.successors() { + reachable_without_self_call_queue.push(*successor); + } + } + } + + // Check the number of self calls because a function that + // doesn't return (e.g. calls a `-> !` function or `loop { /* + // no break */ }`) shouldn't be linted unless it actually + // recurs. + if !reached_exit_without_self_call && !self_call_locations.is_empty() { + let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); + let sp = tcx.sess.source_map().def_span(tcx.hir.span(node_id)); + let mut db = tcx.struct_span_lint_node(UNCONDITIONAL_RECURSION, + node_id, + sp, + "function cannot return without recursing"); + db.span_label(sp, "cannot return without recursing"); + // offer some help to the programmer. + for location in &self_call_locations { + db.span_label(location.span, "recursive call site"); + } + db.help("a `loop` may express intention better if this is on purpose"); + db.emit(); + } +} diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index d18836999dccf..46c73c27fe10d 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -11,7 +11,7 @@ use borrow_check::nll::type_check; use build; use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; -use rustc::mir::{Mir, Promoted}; +use rustc::mir::{Mir, MirPhase, Promoted}; use rustc::ty::TyCtxt; use rustc::ty::query::Providers; use rustc::ty::steal::Steal; @@ -155,53 +155,69 @@ pub trait MirPass { mir: &mut Mir<'tcx>); } -pub macro run_passes($tcx:ident, $mir:ident, $def_id:ident, $suite_index:expr; $($pass:expr,)*) {{ - let suite_index: usize = $suite_index; - let run_passes = |mir: &mut _, promoted| { +pub fn run_passes( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + mir: &mut Mir<'tcx>, + def_id: DefId, + mir_phase: MirPhase, + passes: &[&dyn MirPass], +) { + let phase_index = mir_phase.phase_index(); + + let run_passes = |mir: &mut Mir<'tcx>, promoted| { + if mir.phase >= mir_phase { + return; + } + let source = MirSource { - def_id: $def_id, - promoted + def_id, + promoted, }; let mut index = 0; let mut run_pass = |pass: &dyn MirPass| { let run_hooks = |mir: &_, index, is_after| { - dump_mir::on_mir_pass($tcx, &format_args!("{:03}-{:03}", suite_index, index), + dump_mir::on_mir_pass(tcx, &format_args!("{:03}-{:03}", phase_index, index), &pass.name(), source, mir, is_after); }; run_hooks(mir, index, false); - pass.run_pass($tcx, source, mir); + pass.run_pass(tcx, source, mir); run_hooks(mir, index, true); index += 1; }; - $(run_pass(&$pass);)* + + for pass in passes { + run_pass(*pass); + } + + mir.phase = mir_phase; }; - run_passes(&mut $mir, None); + run_passes(mir, None); - for (index, promoted_mir) in $mir.promoted.iter_enumerated_mut() { + for (index, promoted_mir) in mir.promoted.iter_enumerated_mut() { run_passes(promoted_mir, Some(index)); - // Let's make sure we don't miss any nested instances - assert!(promoted_mir.promoted.is_empty()); + //Let's make sure we don't miss any nested instances + assert!(promoted_mir.promoted.is_empty()) } -}} +} fn mir_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Steal> { // Unsafety check uses the raw mir, so make sure it is run let _ = tcx.unsafety_check_result(def_id); let mut mir = tcx.mir_built(def_id).steal(); - run_passes![tcx, mir, def_id, 0; + run_passes(tcx, &mut mir, def_id, MirPhase::Const, &[ // Remove all `EndRegion` statements that are not involved in borrows. - cleanup_post_borrowck::CleanEndRegions, + &cleanup_post_borrowck::CleanEndRegions, // What we need to do constant evaluation. - simplify::SimplifyCfg::new("initial"), - type_check::TypeckMir, - rustc_peek::SanityCheck, - uniform_array_move_out::UniformArrayMoveOut, - ]; + &simplify::SimplifyCfg::new("initial"), + &type_check::TypeckMir, + &rustc_peek::SanityCheck, + &uniform_array_move_out::UniformArrayMoveOut, + ]); tcx.alloc_steal_mir(mir) } @@ -214,11 +230,11 @@ fn mir_validated<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx } let mut mir = tcx.mir_const(def_id).steal(); - run_passes![tcx, mir, def_id, 1; + run_passes(tcx, &mut mir, def_id, MirPhase::Validated, &[ // What we need to run borrowck etc. - qualify_consts::QualifyAndPromoteConstants, - simplify::SimplifyCfg::new("qualify-consts"), - ]; + &qualify_consts::QualifyAndPromoteConstants, + &simplify::SimplifyCfg::new("qualify-consts"), + ]); tcx.alloc_steal_mir(mir) } @@ -232,59 +248,59 @@ fn optimized_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx } let mut mir = tcx.mir_validated(def_id).steal(); - run_passes![tcx, mir, def_id, 2; + run_passes(tcx, &mut mir, def_id, MirPhase::Optimized, &[ // Remove all things not needed by analysis - no_landing_pads::NoLandingPads, - simplify_branches::SimplifyBranches::new("initial"), - remove_noop_landing_pads::RemoveNoopLandingPads, + &no_landing_pads::NoLandingPads, + &simplify_branches::SimplifyBranches::new("initial"), + &remove_noop_landing_pads::RemoveNoopLandingPads, // Remove all `AscribeUserType` statements. - cleanup_post_borrowck::CleanAscribeUserType, + &cleanup_post_borrowck::CleanAscribeUserType, // Remove all `FakeRead` statements and the borrows that are only // used for checking matches - cleanup_post_borrowck::CleanFakeReadsAndBorrows, - simplify::SimplifyCfg::new("early-opt"), + &cleanup_post_borrowck::CleanFakeReadsAndBorrows, + &simplify::SimplifyCfg::new("early-opt"), // These next passes must be executed together - add_call_guards::CriticalCallEdges, - elaborate_drops::ElaborateDrops, - no_landing_pads::NoLandingPads, + &add_call_guards::CriticalCallEdges, + &elaborate_drops::ElaborateDrops, + &no_landing_pads::NoLandingPads, // AddValidation needs to run after ElaborateDrops and before EraseRegions, and it needs // an AllCallEdges pass right before it. - add_call_guards::AllCallEdges, - add_validation::AddValidation, + &add_call_guards::AllCallEdges, + &add_validation::AddValidation, // AddMovesForPackedDrops needs to run after drop // elaboration. - add_moves_for_packed_drops::AddMovesForPackedDrops, + &add_moves_for_packed_drops::AddMovesForPackedDrops, - simplify::SimplifyCfg::new("elaborate-drops"), + &simplify::SimplifyCfg::new("elaborate-drops"), // No lifetime analysis based on borrowing can be done from here on out. // From here on out, regions are gone. - erase_regions::EraseRegions, + &erase_regions::EraseRegions, - lower_128bit::Lower128Bit, + &lower_128bit::Lower128Bit, // Optimizations begin. - uniform_array_move_out::RestoreSubsliceArrayMoveOut, - inline::Inline, + &uniform_array_move_out::RestoreSubsliceArrayMoveOut, + &inline::Inline, // Lowering generator control-flow and variables // has to happen before we do anything else to them. - generator::StateTransform, - - instcombine::InstCombine, - const_prop::ConstProp, - simplify_branches::SimplifyBranches::new("after-const-prop"), - deaggregator::Deaggregator, - copy_prop::CopyPropagation, - remove_noop_landing_pads::RemoveNoopLandingPads, - simplify::SimplifyCfg::new("final"), - simplify::SimplifyLocals, - - add_call_guards::CriticalCallEdges, - dump_mir::Marker("PreCodegen"), - ]; + &generator::StateTransform, + + &instcombine::InstCombine, + &const_prop::ConstProp, + &simplify_branches::SimplifyBranches::new("after-const-prop"), + &deaggregator::Deaggregator, + ©_prop::CopyPropagation, + &remove_noop_landing_pads::RemoveNoopLandingPads, + &simplify::SimplifyCfg::new("final"), + &simplify::SimplifyLocals, + + &add_call_guards::CriticalCallEdges, + &dump_mir::Marker("PreCodegen"), + ]); tcx.alloc_mir(mir) } diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs index 5e9169e86a98d..ca58239df8eac 100644 --- a/src/librustc_passes/rvalue_promotion.rs +++ b/src/librustc_passes/rvalue_promotion.rs @@ -663,6 +663,7 @@ impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for CheckCrateVisitor<'a, 'gcx> { let mut cur = cmt; loop { match cur.cat { + Categorization::ThreadLocal(..) | Categorization::Rvalue(..) => { if loan_cause == euv::MatchDiscriminant { // Ignore the dummy immutable borrow created by EUV. diff --git a/src/librustc_target/Cargo.toml b/src/librustc_target/Cargo.toml index bb686e914a048..684ea4c78978c 100644 --- a/src/librustc_target/Cargo.toml +++ b/src/librustc_target/Cargo.toml @@ -13,6 +13,3 @@ bitflags = "1.0" log = "0.4" rustc_cratesio_shim = { path = "../librustc_cratesio_shim" } serialize = { path = "../libserialize" } - -[features] -jemalloc = [] diff --git a/src/librustc_target/spec/apple_base.rs b/src/librustc_target/spec/apple_base.rs index 38b3f2528fe86..8774c15ff0121 100644 --- a/src/librustc_target/spec/apple_base.rs +++ b/src/librustc_target/spec/apple_base.rs @@ -44,7 +44,6 @@ pub fn opts() -> TargetOptions { dll_suffix: ".dylib".to_string(), archive_format: "bsd".to_string(), pre_link_args: LinkArgs::new(), - exe_allocation_crate: super::maybe_jemalloc(), has_elf_tls: version >= (10, 7), abi_return_struct_as_int: true, emit_debug_gdb_scripts: false, diff --git a/src/librustc_target/spec/apple_ios_base.rs b/src/librustc_target/spec/apple_ios_base.rs index 296eaca7c7df0..e926e4913d634 100644 --- a/src/librustc_target/spec/apple_ios_base.rs +++ b/src/librustc_target/spec/apple_ios_base.rs @@ -99,10 +99,6 @@ pub fn opts(arch: Arch) -> Result { pre_link_args, has_elf_tls: false, eliminate_frame_pointer: false, - // The following line is a workaround for jemalloc 4.5 being broken on - // ios. jemalloc 5.0 is supposed to fix this. - // see https://github.com/rust-lang/rust/issues/45262 - exe_allocation_crate: None, .. super::apple_base::opts() }) } diff --git a/src/librustc_target/spec/cloudabi_base.rs b/src/librustc_target/spec/cloudabi_base.rs index 2ffa74e737fd5..fb78cf495e22a 100644 --- a/src/librustc_target/spec/cloudabi_base.rs +++ b/src/librustc_target/spec/cloudabi_base.rs @@ -38,7 +38,6 @@ pub fn opts() -> TargetOptions { // dynamic linking. tls_model: "local-exec".to_string(), relro_level: RelroLevel::Full, - exe_allocation_crate: super::maybe_jemalloc(), .. Default::default() } } diff --git a/src/librustc_target/spec/dragonfly_base.rs b/src/librustc_target/spec/dragonfly_base.rs index 32eac8663afac..a9e317b7cb8a7 100644 --- a/src/librustc_target/spec/dragonfly_base.rs +++ b/src/librustc_target/spec/dragonfly_base.rs @@ -33,7 +33,6 @@ pub fn opts() -> TargetOptions { pre_link_args: args, position_independent_executables: true, relro_level: RelroLevel::Full, - exe_allocation_crate: super::maybe_jemalloc(), .. Default::default() } } diff --git a/src/librustc_target/spec/freebsd_base.rs b/src/librustc_target/spec/freebsd_base.rs index 04b8a6e706064..c8a2946da50a5 100644 --- a/src/librustc_target/spec/freebsd_base.rs +++ b/src/librustc_target/spec/freebsd_base.rs @@ -34,7 +34,6 @@ pub fn opts() -> TargetOptions { position_independent_executables: true, eliminate_frame_pointer: false, // FIXME 43575 relro_level: RelroLevel::Full, - exe_allocation_crate: super::maybe_jemalloc(), abi_return_struct_as_int: true, .. Default::default() } diff --git a/src/librustc_target/spec/linux_base.rs b/src/librustc_target/spec/linux_base.rs index 4a9cd9e2f3233..01f65d5736322 100644 --- a/src/librustc_target/spec/linux_base.rs +++ b/src/librustc_target/spec/linux_base.rs @@ -36,7 +36,6 @@ pub fn opts() -> TargetOptions { pre_link_args: args, position_independent_executables: true, relro_level: RelroLevel::Full, - exe_allocation_crate: super::maybe_jemalloc(), has_elf_tls: true, .. Default::default() } diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index 9ee4582fabf7b..91cb9b1a9dc1d 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -1270,14 +1270,6 @@ impl ToJson for Target { } } -fn maybe_jemalloc() -> Option { - if cfg!(feature = "jemalloc") { - Some("alloc_jemalloc".to_string()) - } else { - None - } -} - /// Either a target triple string or a path to a JSON file. #[derive(PartialEq, Clone, Debug, Hash, RustcEncodable, RustcDecodable)] pub enum TargetTriple { diff --git a/src/librustc_target/spec/solaris_base.rs b/src/librustc_target/spec/solaris_base.rs index c14cc3f5bc3be..93b889d5d399e 100644 --- a/src/librustc_target/spec/solaris_base.rs +++ b/src/librustc_target/spec/solaris_base.rs @@ -18,7 +18,6 @@ pub fn opts() -> TargetOptions { has_rpath: true, target_family: Some("unix".to_string()), is_like_solaris: true, - exe_allocation_crate: super::maybe_jemalloc(), .. Default::default() } diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 80b4ba6240d33..212ee2698e012 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -1243,6 +1243,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { | Categorization::StaticItem | Categorization::Upvar(..) | Categorization::Local(..) + | Categorization::ThreadLocal(..) | Categorization::Rvalue(..) => { // These are all "base cases" with independent lifetimes // that are not subject to inference diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index 99effce4ee08d..df994ad9e55c4 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -401,6 +401,7 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> { Categorization::Deref(_, mc::UnsafePtr(..)) | Categorization::StaticItem | + Categorization::ThreadLocal(..) | Categorization::Rvalue(..) | Categorization::Local(_) | Categorization::Upvar(..) => { @@ -431,6 +432,7 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> { Categorization::Deref(_, mc::UnsafePtr(..)) | Categorization::StaticItem | + Categorization::ThreadLocal(..) | Categorization::Rvalue(..) | Categorization::Local(_) | Categorization::Upvar(..) => {} diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 9990d2ee2b676..ea84e874b1a5b 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -13,7 +13,7 @@ use constrained_type_params::{identify_constrained_type_params, Parameter}; use hir::def_id::DefId; use rustc::traits::{self, ObligationCauseCode}; -use rustc::ty::{self, Lift, Ty, TyCtxt, GenericParamDefKind, TypeFoldable}; +use rustc::ty::{self, Lift, Ty, TyCtxt, TyKind, GenericParamDefKind, TypeFoldable}; use rustc::ty::subst::{Subst, Substs}; use rustc::ty::util::ExplicitSelf; use rustc::util::nodemap::{FxHashSet, FxHashMap}; @@ -119,14 +119,14 @@ pub fn check_item_well_formed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: Def check_item_fn(tcx, item); } hir::ItemKind::Static(ref ty, ..) => { - check_item_type(tcx, item.id, ty.span); + check_item_type(tcx, item.id, ty.span, false); } hir::ItemKind::Const(ref ty, ..) => { - check_item_type(tcx, item.id, ty.span); + check_item_type(tcx, item.id, ty.span, false); } hir::ItemKind::ForeignMod(ref module) => for it in module.items.iter() { if let hir::ForeignItemKind::Static(ref ty, ..) = it.node { - check_item_type(tcx, it.id, ty.span); + check_item_type(tcx, it.id, ty.span, true); } }, hir::ItemKind::Struct(ref struct_def, ref ast_generics) => { @@ -340,23 +340,33 @@ fn check_item_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item: &hir::Item) { }) } -fn check_item_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId, ty_span: Span) { +fn check_item_type<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + item_id: ast::NodeId, + ty_span: Span, + allow_foreign_ty: bool, +) { debug!("check_item_type: {:?}", item_id); for_id(tcx, item_id, ty_span).with_fcx(|fcx, _this| { let ty = fcx.tcx.type_of(fcx.tcx.hir.local_def_id(item_id)); let item_ty = fcx.normalize_associated_types_in(ty_span, &ty); + let mut forbid_unsized = true; + if allow_foreign_ty { + if let TyKind::Foreign(_) = tcx.struct_tail(item_ty).sty { + forbid_unsized = false; + } + } + fcx.register_wf_obligation(item_ty, ty_span, ObligationCauseCode::MiscObligation); - fcx.register_bound( - item_ty, - fcx.tcx.require_lang_item(lang_items::SizedTraitLangItem), - traits::ObligationCause::new( - ty_span, - fcx.body_id, - traits::MiscObligation, - ), - ); + if forbid_unsized { + fcx.register_bound( + item_ty, + fcx.tcx.require_lang_item(lang_items::SizedTraitLangItem), + traits::ObligationCause::new(ty_span, fcx.body_id, traits::MiscObligation), + ); + } vec![] // no implied bounds in a const etc }); diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index 87b4527a2a739..6522261fe1e7c 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -28,9 +28,12 @@ use syntax::parse; use syntax_pos::{Span, FileName}; /// Highlights `src`, returning the HTML output. -pub fn render_with_highlighting(src: &str, class: Option<&str>, - extension: Option<&str>, - tooltip: Option<(&str, &str)>) -> String { +pub fn render_with_highlighting( + src: &str, + class: Option<&str>, + extension: Option<&str>, + tooltip: Option<(&str, &str)>, +) -> String { debug!("highlighting: ================\n{}\n==============", src); let sess = parse::ParseSess::new(FilePathMapping::empty()); let fm = sess.source_map().new_source_file(FileName::Custom("stdin".to_string()), @@ -384,9 +387,9 @@ impl Class { } fn write_header(class: Option<&str>, out: &mut dyn Write) -> io::Result<()> { - write!(out, "
\n", class.unwrap_or(""))
+    write!(out, "
\n", class.unwrap_or(""))
 }
 
 fn write_footer(out: &mut dyn Write) -> io::Result<()> {
-    write!(out, "
\n") + write!(out, "
\n") } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index dda0f37c3f95b..ea51c46a332cb 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1709,6 +1709,7 @@ impl<'a> Settings<'a> { ("method-docs", "Auto-hide item methods' documentation", false), ("go-to-only-result", "Directly go to item in search if there is only one result", false), + ("line-numbers", "Show line numbers on code examples", false), ], root_path, suffix, diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 6307dda454da8..9d1a5c3837830 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -2093,6 +2093,7 @@ return wrapper; } + var hideItemDeclarations = getCurrentValue('rustdoc-item-declarations') === "false"; onEach(document.getElementsByClassName('docblock'), function(e) { if (hasClass(e, 'autohide')) { var wrap = e.previousElementSibling; @@ -2116,16 +2117,14 @@ } } if (e.parentNode.id === "main") { - var otherMessage; + var otherMessage = ''; var fontSize; var extraClass; - var show = true; if (hasClass(e, "type-decl")) { fontSize = "20px"; otherMessage = ' Show declaration'; - show = getCurrentValue('rustdoc-item-declarations') === "false"; - if (!show) { + if (hideItemDeclarations === false) { extraClass = 'collapsed'; } } else if (hasClass(e, "non-exhaustive")) { @@ -2142,8 +2141,12 @@ extraClass = "marg-left"; } - e.parentNode.insertBefore(createToggle(otherMessage, fontSize, extraClass, show), e); - if (otherMessage && show) { + e.parentNode.insertBefore(createToggle(otherMessage, + fontSize, + extraClass, + hideItemDeclarations), + e); + if (otherMessage.length > 0 && hideItemDeclarations === true) { collapseDocs(e.previousSibling.childNodes[0], "toggle"); } } @@ -2186,13 +2189,33 @@ }); } + // To avoid checking on "rustdoc-item-attributes" value on every loop... + var itemAttributesFunc = function() {}; + if (getCurrentValue("rustdoc-item-attributes") !== "false") { + itemAttributesFunc = function(x) { + collapseDocs(x.previousSibling.childNodes[0], "toggle"); + }; + } onEach(document.getElementById('main').getElementsByClassName('attributes'), function(i_e) { i_e.parentNode.insertBefore(createToggleWrapper(toggle.cloneNode(true)), i_e); - if (getCurrentValue("rustdoc-item-attributes") !== "false") { - collapseDocs(i_e.previousSibling.childNodes[0], "toggle"); - } + itemAttributesFunc(i_e); }); + // To avoid checking on "rustdoc-line-numbers" value on every loop... + var lineNumbersFunc = function() {}; + if (getCurrentValue("rustdoc-line-numbers") === "true") { + lineNumbersFunc = function(x) { + var count = x.textContent.split('\n').length; + var elems = []; + for (var i = 0; i < count; ++i) { + elems.push(i + 1); + } + var node = document.createElement('pre'); + addClass(node, 'line-number'); + node.innerHTML = elems.join('\n'); + x.parentNode.insertBefore(node, x); + }; + } onEach(document.getElementsByClassName('rust-example-rendered'), function(e) { if (hasClass(e, 'compile_fail')) { e.addEventListener("mouseover", function(event) { @@ -2209,6 +2232,7 @@ e.previousElementSibling.childNodes[0].style.color = ''; }); } + lineNumbersFunc(e); }); function showModal(content) { diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 63740ea729131..c0951d9f8401e 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -282,6 +282,24 @@ nav.sub { padding-left: 0; } +.example-wrap { + display: inline-flex; + width: 100%; +} + +.example-wrap > pre.line-number { + overflow: initial; + border: 1px solid; + border-top-left-radius: 5px; + border-bottom-left-radius: 5px; + padding: 13px 8px; + text-align: right; +} + +.example-wrap > pre.rust { + width: 100%; +} + #search { margin-left: 230px; position: relative; diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css index 8e4890d905817..4a8950b236c62 100644 --- a/src/librustdoc/html/static/themes/dark.css +++ b/src/librustdoc/html/static/themes/dark.css @@ -233,6 +233,10 @@ pre.rust .question-mark { color: #ff9011; } +.example-wrap > pre.line-number { + border-color: #4a4949; +} + a.test-arrow { background-color: rgba(78, 139, 202, 0.2); } diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css index 2742faab017bf..b3b0b6b2ea9e8 100644 --- a/src/librustdoc/html/static/themes/light.css +++ b/src/librustdoc/html/static/themes/light.css @@ -227,6 +227,10 @@ pre.rust .question-mark { color: #ff9011; } +.example-wrap > pre.line-number { + border-color: #c7c7c7; +} + a.test-arrow { background-color: rgba(78, 139, 202, 0.2); } diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index cd1e3438fc372..0f22459b34349 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -14,7 +14,6 @@ crate-type = ["dylib", "rlib"] [dependencies] alloc = { path = "../liballoc" } -alloc_jemalloc = { path = "../liballoc_jemalloc", optional = true } alloc_system = { path = "../liballoc_system" } panic_unwind = { path = "../libpanic_unwind", optional = true } panic_abort = { path = "../libpanic_abort" } @@ -43,9 +42,6 @@ build_helper = { path = "../build_helper" } [features] backtrace = [] -debug-jemalloc = ["alloc_jemalloc/debug"] -jemalloc = ["alloc_jemalloc"] -force_alloc_system = [] panic-unwind = ["panic_unwind"] profiler = ["profiler_builtins"] diff --git a/src/libstd/alloc.rs b/src/libstd/alloc.rs index 31fc9ed3f772d..1ff342fa7a7be 100644 --- a/src/libstd/alloc.rs +++ b/src/libstd/alloc.rs @@ -13,13 +13,10 @@ //! In a given program, the standard library has one “global” memory allocator //! that is used for example by `Box` and `Vec`. //! -//! Currently the default global allocator is unspecified. -//! The compiler may link to a version of [jemalloc] on some platforms, -//! but this is not guaranteed. -//! Libraries, however, like `cdylib`s and `staticlib`s are guaranteed -//! to use the [`System`] by default. +//! Currently the default global allocator is unspecified. Libraries, however, +//! like `cdylib`s and `staticlib`s are guaranteed to use the [`System`] by +//! default. //! -//! [jemalloc]: https://github.com/jemalloc/jemalloc //! [`System`]: struct.System.html //! //! # The `#[global_allocator]` attribute diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index a4db879680566..935ddb791fb9b 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -313,14 +313,7 @@ #![default_lib_allocator] -// Always use alloc_system during stage0 since we don't know if the alloc_* -// crate the stage0 compiler will pick by default is enabled (e.g. -// if the user has disabled jemalloc in `./configure`). -// `force_alloc_system` is *only* intended as a workaround for local rebuilds -// with a rustc without jemalloc. -// FIXME(#44236) shouldn't need MSVC logic -#[cfg(all(not(target_env = "msvc"), - any(all(stage0, not(test)), feature = "force_alloc_system")))] +#[cfg(stage0)] #[global_allocator] static ALLOC: alloc_system::System = alloc_system::System; diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 805aa9bef227d..a28d114bda784 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -792,15 +792,15 @@ fn check_matcher_core(sess: &ParseSess, if let TokenTree::MetaVarDecl(_, ref name, ref frag_spec) = *token { for next_token in &suffix_first.tokens { match is_in_follow(next_token, &frag_spec.as_str()) { - Err((msg, help)) => { + IsInFollow::Invalid(msg, help) => { sess.span_diagnostic.struct_span_err(next_token.span(), &msg) .help(help).emit(); // don't bother reporting every source of // conflict for a particular element of `last`. continue 'each_last; } - Ok(true) => {} - Ok(false) => { + IsInFollow::Yes => {} + IsInFollow::No(ref possible) => { let may_be = if last.tokens.len() == 1 && suffix_first.tokens.len() == 1 { @@ -809,15 +809,41 @@ fn check_matcher_core(sess: &ParseSess, "may be" }; - sess.span_diagnostic.span_err( - next_token.span(), + let sp = next_token.span(); + let mut err = sess.span_diagnostic.struct_span_err( + sp, &format!("`${name}:{frag}` {may_be} followed by `{next}`, which \ is not allowed for `{frag}` fragments", name=name, frag=frag_spec, next=quoted_tt_to_string(next_token), - may_be=may_be) + may_be=may_be), ); + err.span_label( + sp, + format!("not allowed after `{}` fragments", frag_spec), + ); + let msg = "allowed there are: "; + match &possible[..] { + &[] => {} + &[t] => { + err.note(&format!( + "only {} is allowed after `{}` fragments", + t, + frag_spec, + )); + } + ts => { + err.note(&format!( + "{}{} or {}", + msg, + ts[..ts.len() - 1].iter().map(|s| *s) + .collect::>().join(", "), + ts[ts.len() - 1], + )); + } + } + err.emit(); } } } @@ -860,6 +886,12 @@ fn frag_can_be_followed_by_any(frag: &str) -> bool { } } +enum IsInFollow { + Yes, + No(Vec<&'static str>), + Invalid(String, &'static str), +} + /// True if `frag` can legally be followed by the token `tok`. For /// fragments that can consume an unbounded number of tokens, `tok` /// must be within a well-defined follow set. This is intended to @@ -868,81 +900,99 @@ fn frag_can_be_followed_by_any(frag: &str) -> bool { /// break macros that were relying on that binary operator as a /// separator. // when changing this do not forget to update doc/book/macros.md! -fn is_in_follow(tok: "ed::TokenTree, frag: &str) -> Result { +fn is_in_follow(tok: "ed::TokenTree, frag: &str) -> IsInFollow { use self::quoted::TokenTree; if let TokenTree::Token(_, token::CloseDelim(_)) = *tok { // closing a token tree can never be matched by any fragment; // iow, we always require that `(` and `)` match, etc. - Ok(true) + IsInFollow::Yes } else { match frag { "item" => { // since items *must* be followed by either a `;` or a `}`, we can // accept anything after them - Ok(true) + IsInFollow::Yes }, "block" => { // anything can follow block, the braces provide an easy boundary to // maintain - Ok(true) + IsInFollow::Yes }, - "stmt" | "expr" => match *tok { - TokenTree::Token(_, ref tok) => match *tok { - FatArrow | Comma | Semi => Ok(true), - _ => Ok(false) - }, - _ => Ok(false), + "stmt" | "expr" => { + let tokens = vec!["`=>`", "`,`", "`;`"]; + match *tok { + TokenTree::Token(_, ref tok) => match *tok { + FatArrow | Comma | Semi => IsInFollow::Yes, + _ => IsInFollow::No(tokens), + }, + _ => IsInFollow::No(tokens), + } }, - "pat" => match *tok { - TokenTree::Token(_, ref tok) => match *tok { - FatArrow | Comma | Eq | BinOp(token::Or) => Ok(true), - Ident(i, false) if i.name == "if" || i.name == "in" => Ok(true), - _ => Ok(false) - }, - _ => Ok(false), + "pat" => { + let tokens = vec!["`=>`", "`,`", "`=`", "`|`", "`if`", "`in`"]; + match *tok { + TokenTree::Token(_, ref tok) => match *tok { + FatArrow | Comma | Eq | BinOp(token::Or) => IsInFollow::Yes, + Ident(i, false) if i.name == "if" || i.name == "in" => IsInFollow::Yes, + _ => IsInFollow::No(tokens), + }, + _ => IsInFollow::No(tokens), + } }, - "path" | "ty" => match *tok { - TokenTree::Token(_, ref tok) => match *tok { - OpenDelim(token::DelimToken::Brace) | OpenDelim(token::DelimToken::Bracket) | - Comma | FatArrow | Colon | Eq | Gt | BinOp(token::Shr) | Semi | - BinOp(token::Or) => Ok(true), - Ident(i, false) if i.name == "as" || i.name == "where" => Ok(true), - _ => Ok(false) - }, - TokenTree::MetaVarDecl(_, _, frag) if frag.name == "block" => Ok(true), - _ => Ok(false), + "path" | "ty" => { + let tokens = vec![ + "`{`", "`[`", "`=>`", "`,`", "`>`","`=`", "`:`", "`;`", "`|`", "`as`", + "`where`", + ]; + match *tok { + TokenTree::Token(_, ref tok) => match *tok { + OpenDelim(token::DelimToken::Brace) | + OpenDelim(token::DelimToken::Bracket) | + Comma | FatArrow | Colon | Eq | Gt | BinOp(token::Shr) | Semi | + BinOp(token::Or) => IsInFollow::Yes, + Ident(i, false) if i.name == "as" || i.name == "where" => IsInFollow::Yes, + _ => IsInFollow::No(tokens), + }, + TokenTree::MetaVarDecl(_, _, frag) if frag.name == "block" => IsInFollow::Yes, + _ => IsInFollow::No(tokens), + } }, "ident" | "lifetime" => { // being a single token, idents and lifetimes are harmless - Ok(true) + IsInFollow::Yes }, "literal" => { // literals may be of a single token, or two tokens (negative numbers) - Ok(true) + IsInFollow::Yes }, "meta" | "tt" => { // being either a single token or a delimited sequence, tt is // harmless - Ok(true) + IsInFollow::Yes }, "vis" => { // Explicitly disallow `priv`, on the off chance it comes back. + let tokens = vec!["`,`", "an ident", "a type"]; match *tok { TokenTree::Token(_, ref tok) => match *tok { - Comma => Ok(true), - Ident(i, is_raw) if is_raw || i.name != "priv" => Ok(true), - ref tok => Ok(tok.can_begin_type()) + Comma => IsInFollow::Yes, + Ident(i, is_raw) if is_raw || i.name != "priv" => IsInFollow::Yes, + ref tok => if tok.can_begin_type() { + IsInFollow::Yes + } else { + IsInFollow::No(tokens) + } }, TokenTree::MetaVarDecl(_, _, frag) if frag.name == "ident" || frag.name == "ty" - || frag.name == "path" => Ok(true), - _ => Ok(false) + || frag.name == "path" => IsInFollow::Yes, + _ => IsInFollow::No(tokens), } }, - "" => Ok(true), // keywords::Invalid - _ => Err((format!("invalid fragment specifier `{}`", frag), - VALID_FRAGMENT_NAMES_MSG)) + "" => IsInFollow::Yes, // keywords::Invalid + _ => IsInFollow::Invalid(format!("invalid fragment specifier `{}`", frag), + VALID_FRAGMENT_NAMES_MSG), } } } diff --git a/src/rustc/Cargo.toml b/src/rustc/Cargo.toml index 9ccd37a6a4592..ec822fddef3eb 100644 --- a/src/rustc/Cargo.toml +++ b/src/rustc/Cargo.toml @@ -12,4 +12,4 @@ rustc_target = { path = "../librustc_target" } rustc_driver = { path = "../librustc_driver" } [features] -jemalloc = ["rustc_target/jemalloc"] +jemalloc = ['rustc_driver/jemalloc-sys'] diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index bf7afa1b6c068..96a34a41dbad3 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -870,11 +870,13 @@ LLVMRustDIBuilderCreateNameSpace(LLVMRustDIBuilderRef Builder, } extern "C" void -LLVMRustDICompositeTypeSetTypeArray(LLVMRustDIBuilderRef Builder, - LLVMMetadataRef CompositeTy, - LLVMMetadataRef TyArray) { +LLVMRustDICompositeTypeReplaceArrays(LLVMRustDIBuilderRef Builder, + LLVMMetadataRef CompositeTy, + LLVMMetadataRef Elements, + LLVMMetadataRef Params) { DICompositeType *Tmp = unwrapDI(CompositeTy); - Builder->replaceArrays(Tmp, DINodeArray(unwrap(TyArray))); + Builder->replaceArrays(Tmp, DINodeArray(unwrap(Elements)), + DINodeArray(unwrap(Params))); } extern "C" LLVMValueRef diff --git a/src/test/codegen/generic-debug.rs b/src/test/codegen/generic-debug.rs new file mode 100644 index 0000000000000..9d5dbf1cc0a09 --- /dev/null +++ b/src/test/codegen/generic-debug.rs @@ -0,0 +1,28 @@ +// Copyright 2018 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-tidy-linelength +// ignore-windows + +// compile-flags: -g -C no-prepopulate-passes + +// CHECK-LABEL: @main +// CHECK: {{.*}}DICompositeType{{.*}}tag: DW_TAG_structure_type,{{.*}}name: "Generic",{{.*}} +// CHECK: {{.*}}DITemplateTypeParameter{{.*}}name: "Type",{{.*}} + +#![allow(dead_code)] +#![allow(unused_variables)] +#![allow(unused_assignments)] + +pub struct Generic(Type); + +fn main () { + let generic = Generic(10); +} diff --git a/src/liballoc_jemalloc/pthread_atfork_dummy.c b/src/test/codegen/remap_path_prefix/auxiliary/xcrate-generic.rs similarity index 69% rename from src/liballoc_jemalloc/pthread_atfork_dummy.c rename to src/test/codegen/remap_path_prefix/auxiliary/xcrate-generic.rs index 4e3df0ab26c37..6c477a407812a 100644 --- a/src/liballoc_jemalloc/pthread_atfork_dummy.c +++ b/src/test/codegen/remap_path_prefix/auxiliary/xcrate-generic.rs @@ -8,9 +8,9 @@ // 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; -} +// ignore-tidy-linelength +// compile-flags: -g --remap-path-prefix={{cwd}}=/the/aux-cwd --remap-path-prefix={{src-base}}/remap_path_prefix/auxiliary=/the/aux-src + +#![crate_type = "lib"] + +pub fn foo() {} diff --git a/src/test/codegen/remap_path_prefix/xcrate-generic.rs b/src/test/codegen/remap_path_prefix/xcrate-generic.rs new file mode 100644 index 0000000000000..f206df9813165 --- /dev/null +++ b/src/test/codegen/remap_path_prefix/xcrate-generic.rs @@ -0,0 +1,25 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-windows +// ignore-tidy-linelength +// compile-flags: -g -C metadata=foo -C no-prepopulate-passes +// aux-build:xcrate-generic.rs + +#![crate_type = "lib"] + +extern crate xcrate_generic; + +pub fn foo() { + xcrate_generic::foo::(); +} + +// Here we check that local debuginfo is mapped correctly. +// CHECK: !DIFile(filename: "/the/aux-src/xcrate-generic.rs", directory: "") diff --git a/src/test/rustdoc/deprecated-impls.rs b/src/test/rustdoc/deprecated-impls.rs index bcf0645766b30..3fb83bff91604 100644 --- a/src/test/rustdoc/deprecated-impls.rs +++ b/src/test/rustdoc/deprecated-impls.rs @@ -109,7 +109,7 @@ impl Bar for Foo2 { // @has - '//*[@class="stab deprecated"]' 'Deprecated since 1.0.5: fn_def_with_doc' // @has - 'fn_def_with_doc short' - // @!has - 'fn_def_with full' + // @!has - 'fn_def_with_doc full' fn fn_def_with_doc() {} // @has - '//*[@class="stab deprecated"]' 'Deprecated since 1.0.6: fn_def_without_doc' diff --git a/src/test/rustdoc/escape-rust-expr.rs b/src/test/rustdoc/dont-show-const-contents.rs similarity index 64% rename from src/test/rustdoc/escape-rust-expr.rs rename to src/test/rustdoc/dont-show-const-contents.rs index 4594eb95ea18e..1392c62b4abb1 100644 --- a/src/test/rustdoc/escape-rust-expr.rs +++ b/src/test/rustdoc/dont-show-const-contents.rs @@ -8,8 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Test that we HTML-escape Rust expressions, where HTML special chars -// can occur, and we know it's definitely not markup. +// Test that the contents of constants are not displayed as part of the +// documentation. -// @!has escape_rust_expr/constant.CONST_S.html '//pre[@class="rust const"]' '"