diff --git a/.travis.yml b/.travis.yml index 5d56379dccebf..c5372609e9bc6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -54,7 +54,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 + RUST_CONFIGURE_ARGS="--build=x86_64-apple-darwin --enable-sanitizers" SRC=. RUSTC_RETRY_LINKER_ON_SEGFAULT=1 SCCACHE_ERROR_LOG=/tmp/sccache.log @@ -98,7 +98,7 @@ matrix: install: *osx_install_sccache - env: > RUST_CHECK_TARGET=dist - RUST_CONFIGURE_ARGS="--target=aarch64-apple-ios,armv7-apple-ios,armv7s-apple-ios,i386-apple-ios,x86_64-apple-ios --enable-extended" + RUST_CONFIGURE_ARGS="--target=aarch64-apple-ios,armv7-apple-ios,armv7s-apple-ios,i386-apple-ios,x86_64-apple-ios --enable-extended --enable-sanitizers" SRC=. DEPLOY=1 RUSTC_RETRY_LINKER_ON_SEGFAULT=1 diff --git a/appveyor.yml b/appveyor.yml index f0589b0e64561..ab973a82b7ade 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -35,13 +35,13 @@ environment: RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-ninja SCRIPT: python x.py test MINGW_URL: https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror - MINGW_ARCHIVE: i686-6.2.0-release-posix-dwarf-rt_v5-rev1.7z + MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev1.7z MINGW_DIR: mingw32 - MSYS_BITS: 64 SCRIPT: python x.py test RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-ninja MINGW_URL: https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror - MINGW_ARCHIVE: x86_64-6.2.0-release-posix-seh-rt_v5-rev1.7z + MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev1.7z MINGW_DIR: mingw64 # 32/64 bit MSVC and GNU deployment @@ -60,14 +60,14 @@ environment: RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-extended --enable-ninja SCRIPT: python x.py dist MINGW_URL: https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror - MINGW_ARCHIVE: i686-6.2.0-release-posix-dwarf-rt_v5-rev1.7z + MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev1.7z MINGW_DIR: mingw32 DEPLOY: 1 - MSYS_BITS: 64 SCRIPT: python x.py dist RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-extended --enable-ninja MINGW_URL: https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror - MINGW_ARCHIVE: x86_64-6.2.0-release-posix-seh-rt_v5-rev1.7z + MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev1.7z MINGW_DIR: mingw64 DEPLOY: 1 @@ -96,6 +96,26 @@ install: - if defined MINGW_URL 7z x -y %MINGW_ARCHIVE% > nul - if defined MINGW_URL set PATH=%CD%\%MINGW_DIR%\bin;C:\msys64\usr\bin;%PATH% + # Here we do a pretty heinous thing which is to mangle the MinGW installation + # we just had above. Currently, as of this writing, we're using MinGW-w64 + # builds of gcc, and that's currently at 6.3.0. We use 6.3.0 as it appears to + # be the first version which contains a fix for #40546, builds randomly + # failing during LLVM due to ar.exe/ranlib.exe failures. + # + # Unfortunately, though, 6.3.0 *also* is the first version of MinGW-w64 builds + # to contain a regression in gdb (#40184). As a result if we were to use the + # gdb provided (7.11.1) then we would fail all debuginfo tests. + # + # In order to fix spurious failures (pretty high priority) we use 6.3.0. To + # avoid disabling gdb tests we download an *old* version of gdb, specifically + # that found inside the 6.2.0 distribution. We then overwrite the 6.3.0 gdb + # with the 6.2.0 gdb to get tests passing. + # + # Note that we don't literally overwrite the gdb.exe binary because it appears + # to just use gdborig.exe, so that's the binary we deal with instead. + - if defined MINGW_URL appveyor-retry appveyor DownloadFile %MINGW_URL%/2017-04-20-%MSYS_BITS%bits-gdborig.exe + - if defined MINGW_URL mv 2017-04-20-%MSYS_BITS%bits-gdborig.exe %MINGW_DIR%\bin\gdborig.exe + # Otherwise pull in the MinGW installed on appveyor - if NOT defined MINGW_URL set PATH=C:\msys64\mingw%MSYS_BITS%\bin;C:\msys64\usr\bin;%PATH% diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 3233a73b007cc..e5f8143b41871 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -367,6 +367,9 @@ def build_bootstrap(self): env["DYLD_LIBRARY_PATH"] = os.path.join(self.bin_root(), "lib") + \ (os.pathsep + env["DYLD_LIBRARY_PATH"]) \ if "DYLD_LIBRARY_PATH" in env else "" + env["LIBRARY_PATH"] = os.path.join(self.bin_root(), "lib") + \ + (os.pathsep + env["LIBRARY_PATH"]) \ + if "LIBRARY_PATH" in env else "" env["PATH"] = os.path.join(self.bin_root(), "bin") + \ os.pathsep + env["PATH"] if not os.path.isfile(self.cargo()): @@ -407,7 +410,11 @@ def build_triple(self): # The goal here is to come up with the same triple as LLVM would, # at least for the subset of platforms we're willing to target. if ostype == 'Linux': - ostype = 'unknown-linux-gnu' + os = subprocess.check_output(['uname', '-o']).strip().decode(default_encoding) + if os == 'Android': + ostype = 'linux-android' + else: + ostype = 'unknown-linux-gnu' elif ostype == 'FreeBSD': ostype = 'unknown-freebsd' elif ostype == 'DragonFly': @@ -464,15 +471,21 @@ def build_triple(self): cputype = 'i686' elif cputype in {'xscale', 'arm'}: cputype = 'arm' + if ostype == 'linux-android': + ostype = 'linux-androideabi' elif cputype == 'armv6l': cputype = 'arm' - ostype += 'eabihf' + if ostype == 'linux-android': + ostype = 'linux-androideabi' + else: + ostype += 'eabihf' elif cputype in {'armv7l', 'armv8l'}: cputype = 'armv7' - ostype += 'eabihf' - elif cputype == 'aarch64': - cputype = 'aarch64' - elif cputype == 'arm64': + if ostype == 'linux-android': + ostype = 'linux-androideabi' + else: + ostype += 'eabihf' + elif cputype in {'aarch64', 'arm64'}: cputype = 'aarch64' elif cputype == 'mips': if sys.byteorder == 'big': diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index cd87b27d4f1aa..6f1de62d07ee3 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -115,6 +115,13 @@ pub fn std_link(build: &Build, if target.contains("musl") && !target.contains("mips") { copy_musl_third_party_objects(build, target, &libdir); } + + if build.config.sanitizers && compiler.stage != 0 && target == "x86_64-apple-darwin" { + // The sanitizers are only built in stage1 or above, so the dylibs will + // be missing in stage0 and causes panic. See the `std()` function above + // for reason why the sanitizers are not built in stage0. + copy_apple_sanitizer_dylibs(&build.native_dir(target), "osx", &libdir); + } } /// Copies the crt(1,i,n).o startup objects @@ -126,6 +133,18 @@ fn copy_musl_third_party_objects(build: &Build, target: &str, into: &Path) { } } +fn copy_apple_sanitizer_dylibs(native_dir: &Path, platform: &str, into: &Path) { + for &sanitizer in &["asan", "tsan"] { + let filename = format!("libclang_rt.{}_{}_dynamic.dylib", sanitizer, platform); + let mut src_path = native_dir.join(sanitizer); + src_path.push("build"); + src_path.push("lib"); + src_path.push("darwin"); + src_path.push(&filename); + copy(&src_path, &into.join(filename)); + } +} + /// Build and prepare startup objects like rsbegin.o and rsend.o /// /// These are primarily used on Windows right now for linking executables/dlls. diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 4328c4e3f1d4c..ada8d4df604e3 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -254,7 +254,12 @@ pub fn debugger_scripts(build: &Build, install(&build.src.join("src/etc/").join(file), &dst, 0o644); }; if host.contains("windows-msvc") { - // no debugger scripts + // windbg debugger scripts + install(&build.src.join("src/etc/rust-windbg.cmd"), &sysroot.join("bin"), + 0o755); + + cp_debugger_script("natvis/libcore.natvis"); + cp_debugger_script("natvis/libcollections.natvis"); } else { cp_debugger_script("debugger_pretty_printers_common.py"); diff --git a/src/bootstrap/metadata.rs b/src/bootstrap/metadata.rs index 5918fe41e7c8b..7b6b01655df58 100644 --- a/src/bootstrap/metadata.rs +++ b/src/bootstrap/metadata.rs @@ -58,6 +58,7 @@ fn build_krate(build: &mut Build, krate: &str) { // the dependency graph and what `-p` arguments there are. let mut cargo = Command::new(&build.cargo); cargo.arg("metadata") + .arg("--format-version").arg("1") .arg("--manifest-path").arg(build.src.join(krate).join("Cargo.toml")); let output = output(&mut cargo); let output: Output = json::decode(&output).unwrap(); diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs index dab20f44bc361..e01c06b10fcd6 100644 --- a/src/bootstrap/util.rs +++ b/src/bootstrap/util.rs @@ -139,6 +139,8 @@ pub fn dylib_path_var() -> &'static str { "PATH" } else if cfg!(target_os = "macos") { "DYLD_LIBRARY_PATH" + } else if cfg!(target_os = "haiku") { + "LIBRARY_PATH" } else { "LD_LIBRARY_PATH" } diff --git a/src/build_helper/lib.rs b/src/build_helper/lib.rs index cb58a916fb797..da00b970da977 100644 --- a/src/build_helper/lib.rs +++ b/src/build_helper/lib.rs @@ -198,7 +198,11 @@ pub fn native_lib_boilerplate(src_name: &str, let out_dir = env::var_os("RUSTBUILD_NATIVE_DIR").unwrap_or(env::var_os("OUT_DIR").unwrap()); let out_dir = PathBuf::from(out_dir).join(out_name); t!(create_dir_racy(&out_dir)); - println!("cargo:rustc-link-lib=static={}", link_name); + if link_name.contains('=') { + println!("cargo:rustc-link-lib={}", link_name); + } else { + println!("cargo:rustc-link-lib=static={}", link_name); + } println!("cargo:rustc-link-search=native={}", out_dir.join(search_subdir).display()); let timestamp = out_dir.join("rustbuild.timestamp"); @@ -209,6 +213,21 @@ pub fn native_lib_boilerplate(src_name: &str, } } +pub fn sanitizer_lib_boilerplate(sanitizer_name: &str) -> Result { + let (link_name, search_path) = match &*env::var("TARGET").unwrap() { + "x86_64-unknown-linux-gnu" => ( + format!("clang_rt.{}-x86_64", sanitizer_name), + "build/lib/linux", + ), + "x86_64-apple-darwin" => ( + format!("dylib=clang_rt.{}_osx_dynamic", sanitizer_name), + "build/lib/darwin", + ), + _ => return Err(()), + }; + native_lib_boilerplate("compiler-rt", sanitizer_name, &link_name, search_path) +} + fn dir_up_to_date(src: &Path, threshold: &FileTime) -> bool { t!(fs::read_dir(src)).map(|e| t!(e)).all(|e| { let meta = t!(e.metadata()); diff --git a/src/doc/index.md b/src/doc/index.md index 1294c1a8c59e7..fd5b120e81fae 100644 --- a/src/doc/index.md +++ b/src/doc/index.md @@ -32,16 +32,21 @@ nicknamed 'The Rust Bookshelf.' * [The Rustonomicon][nomicon] is your guidebook to the dark arts of unsafe Rust. * [The Reference][ref] is not a formal spec, but is more detailed and comprehensive than the book. +Initially, documentation lands in the Unstable Book, and then, as part of the +stabilization process, is moved into the Book, Nomicon, or Reference. + Another few words about the reference: it is guaranteed to be accurate, but not -complete. We now have a policy that all new features must be included in the -reference before stabilization; however, we are still back-filling things that -landed before then. That work is being tracked [here][38643]. +complete. We have a policy that features must have documentation to be stabilized, +but we did not always have this policy, and so there are some stable things that +are not yet in the reference. We're working on back-filling things that landed +before this policy was put into place. That work is being tracked +[here][refchecklist]. [Rust Learning]: https://github.com/ctjhoa/rust-learning [Docs.rs]: https://docs.rs/ [api]: std/index.html [ref]: reference/index.html -[38643]: https://github.com/rust-lang/rust/issues/38643 +[refchecklist]: https://github.com/rust-lang-nursery/reference/issues/9 [err]: error-index.html [book]: book/index.html [nomicon]: nomicon/index.html diff --git a/src/doc/unstable-book/src/SUMMARY.md b/src/doc/unstable-book/src/SUMMARY.md index 1adc59b84eac0..4a5d850d66dc7 100644 --- a/src/doc/unstable-book/src/SUMMARY.md +++ b/src/doc/unstable-book/src/SUMMARY.md @@ -160,6 +160,7 @@ - [linked_list_extras](library-features/linked-list-extras.md) - [lookup_host](library-features/lookup-host.md) - [manually_drop](library-features/manually-drop.md) + - [more_io_inner_methods](library-features/more-io-inner-methods.md) - [mpsc_select](library-features/mpsc-select.md) - [n16](library-features/n16.md) - [never_type_impls](library-features/never-type-impls.md) diff --git a/src/doc/unstable-book/src/library-features/more-io-inner-methods.md b/src/doc/unstable-book/src/library-features/more-io-inner-methods.md new file mode 100644 index 0000000000000..c84f40e7ee551 --- /dev/null +++ b/src/doc/unstable-book/src/library-features/more-io-inner-methods.md @@ -0,0 +1,11 @@ +# `more_io_inner_methods` + +The tracking issue for this feature is: [#41519] + +[#41519]: https://github.com/rust-lang/rust/issues/41519 + +------------------------ + +This feature enables several internal accessor methods on structures in +`std::io` including `Take::{get_ref, get_mut}` and `Chain::{into_inner, get_ref, +get_mut}`. diff --git a/src/etc/rust-windbg.cmd b/src/etc/rust-windbg.cmd new file mode 100644 index 0000000000000..4cdd6b9860996 --- /dev/null +++ b/src/etc/rust-windbg.cmd @@ -0,0 +1,18 @@ +@echo off +setlocal + +REM Copyright 2014 The Rust Project Developers. See the COPYRIGHT +REM file at the top-level directory of this distribution and at +REM http://rust-lang.org/COPYRIGHT. +REM +REM Licensed under the Apache License, Version 2.0 or the MIT license +REM , at your +REM option. This file may not be copied, modified, or distributed +REM except according to those terms. + +for /f "delims=" %%i in ('rustc --print=sysroot') do set rustc_sysroot=%%i + +set rust_etc=%rustc_sysroot%\lib\rustlib\etc + +windbg -c ".nvload %rust_etc%\libcore.natvis;.nvload %rust_etc%\libcollections.natvis;" %* \ No newline at end of file diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index e5964385b1253..9bb8482d66f88 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -275,7 +275,9 @@ use Bound::{Excluded, Included, Unbounded}; /// removed data to be erased for security purposes. Even if you drop a `Vec`, its /// buffer may simply be reused by another `Vec`. Even if you zero a `Vec`'s memory /// first, that may not actually happen because the optimizer does not consider -/// this a side-effect that must be preserved. +/// this a side-effect that must be preserved. There is one case which we will +/// not break, however: using `unsafe` code to write to the excess capacity, +/// and then increasing the length to match, is always valid. /// /// `Vec` does not currently guarantee the order in which elements are dropped /// (the order has changed in the past, and may change again). @@ -1147,7 +1149,8 @@ impl Vec { self.truncate(0) } - /// Returns the number of elements in the vector. + /// Returns the number of elements in the vector, also referred to + /// as its 'length'. /// /// # Examples /// diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index 3ad91ef15ea7b..b3f4d75c4da61 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -629,8 +629,9 @@ pub trait Iterator { /// /// Note that the underlying iterator is still advanced when [`peek`] is /// called for the first time: In order to retrieve the next element, - /// [`next`] is called on the underlying iterator, hence any side effects of - /// the [`next`] method will occur. + /// [`next`] is called on the underlying iterator, hence any side effects (i.e. + /// anything other than fetching the next value) of the [`next`] method + /// will occur. /// /// [`peek`]: struct.Peekable.html#method.peek /// [`next`]: ../../std/iter/trait.Iterator.html#tymethod.next diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index 687c477f19e4c..bd831d638c0c4 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -86,12 +86,12 @@ macro_rules! step_impl_unsigned { #[inline] fn replace_one(&mut self) -> Self { - mem::replace(self, 0) + mem::replace(self, 1) } #[inline] fn replace_zero(&mut self) -> Self { - mem::replace(self, 1) + mem::replace(self, 0) } #[inline] @@ -157,12 +157,12 @@ macro_rules! step_impl_signed { #[inline] fn replace_one(&mut self) -> Self { - mem::replace(self, 0) + mem::replace(self, 1) } #[inline] fn replace_zero(&mut self) -> Self { - mem::replace(self, 1) + mem::replace(self, 0) } #[inline] @@ -206,12 +206,12 @@ macro_rules! step_impl_no_between { #[inline] fn replace_one(&mut self) -> Self { - mem::replace(self, 0) + mem::replace(self, 1) } #[inline] fn replace_zero(&mut self) -> Self { - mem::replace(self, 1) + mem::replace(self, 0) } #[inline] diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index 08442f9bcbff5..001fa304cd08f 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -1082,3 +1082,41 @@ fn test_chain_fold() { assert_eq!(&[2, 3, 1, 2, 0], &result[..]); } +#[test] +fn test_step_replace_unsigned() { + let mut x = 4u32; + let y = x.replace_zero(); + assert_eq!(x, 0); + assert_eq!(y, 4); + + x = 5; + let y = x.replace_one(); + assert_eq!(x, 1); + assert_eq!(y, 5); +} + +#[test] +fn test_step_replace_signed() { + let mut x = 4i32; + let y = x.replace_zero(); + assert_eq!(x, 0); + assert_eq!(y, 4); + + x = 5; + let y = x.replace_one(); + assert_eq!(x, 1); + assert_eq!(y, 5); +} + +#[test] +fn test_step_replace_no_between() { + let mut x = 4u128; + let y = x.replace_zero(); + assert_eq!(x, 0); + assert_eq!(y, 4); + + x = 5; + let y = x.replace_one(); + assert_eq!(x, 1); + assert_eq!(y, 5); +} \ No newline at end of file diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index 528ab3bc84523..f0c46a6f194d5 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -20,6 +20,7 @@ #![feature(fixed_size_array)] #![feature(flt2dec)] #![feature(fmt_internals)] +#![feature(i128_type)] #![feature(iter_rfind)] #![feature(libc)] #![feature(nonzero)] @@ -30,6 +31,7 @@ #![feature(sort_internals)] #![feature(sort_unstable)] #![feature(step_by)] +#![feature(step_trait)] #![feature(test)] #![feature(try_from)] #![feature(unicode)] diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index fadb1844008c0..462fd57cbf17f 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -51,7 +51,7 @@ pub struct Config { pub uint_type: UintTy, } -#[derive(Clone, Hash)] +#[derive(Clone, Hash, Debug)] pub enum Sanitizer { Address, Leak, diff --git a/src/librustc_asan/build.rs b/src/librustc_asan/build.rs index 2df2e001e6ff2..3a80baa0485f5 100644 --- a/src/librustc_asan/build.rs +++ b/src/librustc_asan/build.rs @@ -12,14 +12,13 @@ extern crate build_helper; extern crate cmake; use std::env; -use build_helper::native_lib_boilerplate; +use build_helper::sanitizer_lib_boilerplate; use cmake::Config; fn main() { if let Some(llvm_config) = env::var_os("LLVM_CONFIG") { - let native = match native_lib_boilerplate("compiler-rt", "asan", "clang_rt.asan-x86_64", - "build/lib/linux") { + let native = match sanitizer_lib_boilerplate("asan") { Ok(native) => native, _ => return, }; diff --git a/src/librustc_back/dynamic_lib.rs b/src/librustc_back/dynamic_lib.rs index 38e60060925e6..e6f305c22b2d4 100644 --- a/src/librustc_back/dynamic_lib.rs +++ b/src/librustc_back/dynamic_lib.rs @@ -68,6 +68,8 @@ impl DynamicLibrary { "PATH" } else if cfg!(target_os = "macos") { "DYLD_LIBRARY_PATH" + } else if cfg!(target_os = "haiku") { + "LIBRARY_PATH" } else { "LD_LIBRARY_PATH" } diff --git a/src/librustc_back/target/haiku_base.rs b/src/librustc_back/target/haiku_base.rs index bfdc9faaa8a73..8e7f463563c38 100644 --- a/src/librustc_back/target/haiku_base.rs +++ b/src/librustc_back/target/haiku_base.rs @@ -16,9 +16,10 @@ pub fn opts() -> TargetOptions { linker: "cc".to_string(), dynamic_linking: true, executables: true, - has_rpath: true, + has_rpath: false, target_family: Some("unix".to_string()), linker_is_gnu: true, + no_integrated_as: true, .. Default::default() } } diff --git a/src/librustc_data_structures/flock.rs b/src/librustc_data_structures/flock.rs index 26417e3ba7cd1..32f0fd4199776 100644 --- a/src/librustc_data_structures/flock.rs +++ b/src/librustc_data_structures/flock.rs @@ -113,6 +113,7 @@ mod imp { pub l_sysid: libc::c_int, } + pub const F_RDLCK: libc::c_short = 0x0040; pub const F_UNLCK: libc::c_short = 0x0200; pub const F_WRLCK: libc::c_short = 0x0400; pub const F_SETLK: libc::c_int = 0x0080; diff --git a/src/librustc_lsan/build.rs b/src/librustc_lsan/build.rs index 005163f41026c..da53571a24390 100644 --- a/src/librustc_lsan/build.rs +++ b/src/librustc_lsan/build.rs @@ -12,14 +12,13 @@ extern crate build_helper; extern crate cmake; use std::env; -use build_helper::native_lib_boilerplate; +use build_helper::sanitizer_lib_boilerplate; use cmake::Config; fn main() { if let Some(llvm_config) = env::var_os("LLVM_CONFIG") { - let native = match native_lib_boilerplate("compiler-rt", "lsan", "clang_rt.lsan-x86_64", - "build/lib/linux") { + let native = match sanitizer_lib_boilerplate("lsan") { Ok(native) => native, _ => return, }; diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 7bc0e8a512be0..966e814e33790 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -799,11 +799,26 @@ impl<'a> CrateLoader<'a> { fn inject_sanitizer_runtime(&mut self) { if let Some(ref sanitizer) = self.sess.opts.debugging_opts.sanitizer { - // Sanitizers can only be used with x86_64 Linux executables linked - // to `std` - if self.sess.target.target.llvm_target != "x86_64-unknown-linux-gnu" { - self.sess.err(&format!("Sanitizers only work with the \ - `x86_64-unknown-linux-gnu` target.")); + // Sanitizers can only be used on some tested platforms with + // executables linked to `std` + const ASAN_SUPPORTED_TARGETS: &[&str] = &["x86_64-unknown-linux-gnu", + "x86_64-apple-darwin"]; + const TSAN_SUPPORTED_TARGETS: &[&str] = &["x86_64-unknown-linux-gnu", + "x86_64-apple-darwin"]; + const LSAN_SUPPORTED_TARGETS: &[&str] = &["x86_64-unknown-linux-gnu"]; + const MSAN_SUPPORTED_TARGETS: &[&str] = &["x86_64-unknown-linux-gnu"]; + + let supported_targets = match *sanitizer { + Sanitizer::Address => ASAN_SUPPORTED_TARGETS, + Sanitizer::Thread => TSAN_SUPPORTED_TARGETS, + Sanitizer::Leak => LSAN_SUPPORTED_TARGETS, + Sanitizer::Memory => MSAN_SUPPORTED_TARGETS, + }; + if !supported_targets.contains(&&*self.sess.target.target.llvm_target) { + self.sess.err(&format!("{:?}Sanitizer only works with the `{}` target", + sanitizer, + supported_targets.join("` or `") + )); return } diff --git a/src/librustc_msan/build.rs b/src/librustc_msan/build.rs index c438b5250463b..dcadbe86966e7 100644 --- a/src/librustc_msan/build.rs +++ b/src/librustc_msan/build.rs @@ -12,14 +12,13 @@ extern crate build_helper; extern crate cmake; use std::env; -use build_helper::native_lib_boilerplate; +use build_helper::sanitizer_lib_boilerplate; use cmake::Config; fn main() { if let Some(llvm_config) = env::var_os("LLVM_CONFIG") { - let native = match native_lib_boilerplate("compiler-rt", "msan", "clang_rt.msan-x86_64", - "build/lib/linux") { + let native = match sanitizer_lib_boilerplate("msan") { Ok(native) => native, _ => return, }; diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index 7c0522a9c8cf8..e42e69d2a76e2 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -1122,6 +1122,19 @@ fn add_upstream_rust_crates(cmd: &mut Linker, cnum: CrateNum) { let src = sess.cstore.used_crate_source(cnum); let cratepath = &src.rlib.unwrap().0; + + if sess.target.target.options.is_like_osx { + // On Apple platforms, the sanitizer is always built as a dylib, and + // LLVM will link to `@rpath/*.dylib`, so we need to specify an + // rpath to the library as well (the rpath should be absolute, see + // PR #41352 for details). + // + // FIXME: Remove this logic into librustc_*san once Cargo supports it + let rpath = cratepath.parent().unwrap(); + let rpath = rpath.to_str().expect("non-utf8 component in path"); + cmd.args(&["-Wl,-rpath".into(), "-Xlinker".into(), rpath.into()]); + } + let dst = tmpdir.join(cratepath.file_name().unwrap()); let cfg = archive_config(sess, &dst, Some(cratepath)); let mut archive = ArchiveBuilder::new(cfg); diff --git a/src/librustc_tsan/build.rs b/src/librustc_tsan/build.rs index 055b344d2e947..5ea52f17a0fde 100644 --- a/src/librustc_tsan/build.rs +++ b/src/librustc_tsan/build.rs @@ -12,14 +12,13 @@ extern crate build_helper; extern crate cmake; use std::env; -use build_helper::native_lib_boilerplate; +use build_helper::sanitizer_lib_boilerplate; use cmake::Config; fn main() { if let Some(llvm_config) = env::var_os("LLVM_CONFIG") { - let native = match native_lib_boilerplate("compiler-rt", "tsan", "clang_rt.tsan-x86_64", - "build/lib/linux") { + let native = match sanitizer_lib_boilerplate("tsan") { Ok(native) => native, _ => return, }; diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index 46511452a7237..717892be2abad 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -23,6 +23,10 @@ compiler_builtins = { path = "../libcompiler_builtins" } std_unicode = { path = "../libstd_unicode" } unwind = { path = "../libunwind" } +[target.x86_64-apple-darwin.dependencies] +rustc_asan = { path = "../librustc_asan" } +rustc_tsan = { path = "../librustc_tsan" } + [target.x86_64-unknown-linux-gnu.dependencies] rustc_asan = { path = "../librustc_asan" } rustc_lsan = { path = "../librustc_lsan" } diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index cd096c115ba5a..e2832873e2e67 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -466,6 +466,9 @@ pub trait Read { /// variant will be returned. If an error is returned then it must be /// guaranteed that no bytes were read. /// + /// An error of the `ErrorKind::Interrupted` kind is non-fatal and the read + /// operation should be retried if there is nothing else to do. + /// /// # Examples /// /// [`File`][file]s implement `Read`: @@ -481,7 +484,7 @@ pub trait Read { /// let mut f = File::open("foo.txt")?; /// let mut buffer = [0; 10]; /// - /// // read 10 bytes + /// // read up to 10 bytes /// f.read(&mut buffer[..])?; /// # Ok(()) /// # } @@ -885,6 +888,9 @@ pub trait Write { /// It is **not** considered an error if the entire buffer could not be /// written to this writer. /// + /// An error of the `ErrorKind::Interrupted` kind is non-fatal and the + /// write operation should be retried if there is nothing else to do. + /// /// # Examples /// /// ``` @@ -894,6 +900,7 @@ pub trait Write { /// # fn foo() -> std::io::Result<()> { /// let mut buffer = File::create("foo.txt")?; /// + /// // Writes some prefix of the byte string, not necessarily all of it. /// buffer.write(b"some bytes")?; /// # Ok(()) /// # } @@ -929,14 +936,17 @@ pub trait Write { /// Attempts to write an entire buffer into this write. /// - /// This method will continuously call `write` while there is more data to - /// write. This method will not return until the entire buffer has been - /// successfully written or an error occurs. The first error generated from - /// this method will be returned. + /// This method will continuously call `write` until there is no more data + /// to be written or an error of non-`ErrorKind::Interrupted` kind is + /// returned. This method will not return until the entire buffer has been + /// successfully written or such an error occurs. The first error that is + /// not of `ErrorKind::Interrupted` kind generated from this method will be + /// returned. /// /// # Errors /// - /// This function will return the first error that `write` returns. + /// This function will return the first error of + /// non-`ErrorKind::Interrupted` kind that `write` returns. /// /// # Examples /// @@ -1494,6 +1504,87 @@ pub struct Chain { done_first: bool, } +impl Chain { + /// Consumes the `Chain`, returning the wrapped readers. + /// + /// # Examples + /// + /// ``` + /// #![feature(more_io_inner_methods)] + /// + /// # use std::io; + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// # fn foo() -> io::Result<()> { + /// let mut foo_file = File::open("foo.txt")?; + /// let mut bar_file = File::open("bar.txt")?; + /// + /// let chain = foo_file.chain(bar_file); + /// let (foo_file, bar_file) = chain.into_inner(); + /// # Ok(()) + /// # } + /// ``` + #[unstable(feature = "more_io_inner_methods", issue="41519")] + pub fn into_inner(self) -> (T, U) { + (self.first, self.second) + } + + /// Gets references to the underlying readers in this `Chain`. + /// + /// # Examples + /// + /// ``` + /// #![feature(more_io_inner_methods)] + /// + /// # use std::io; + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// # fn foo() -> io::Result<()> { + /// let mut foo_file = File::open("foo.txt")?; + /// let mut bar_file = File::open("bar.txt")?; + /// + /// let chain = foo_file.chain(bar_file); + /// let (foo_file, bar_file) = chain.get_ref(); + /// # Ok(()) + /// # } + /// ``` + #[unstable(feature = "more_io_inner_methods", issue="41519")] + pub fn get_ref(&self) -> (&T, &U) { + (&self.first, &self.second) + } + + /// Gets mutable references to the underlying readers in this `Chain`. + /// + /// Care should be taken to avoid modifying the internal I/O state of the + /// underlying readers as doing so may corrupt the internal state of this + /// `Chain`. + /// + /// # Examples + /// + /// ``` + /// #![feature(more_io_inner_methods)] + /// + /// # use std::io; + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// # fn foo() -> io::Result<()> { + /// let mut foo_file = File::open("foo.txt")?; + /// let mut bar_file = File::open("bar.txt")?; + /// + /// let mut chain = foo_file.chain(bar_file); + /// let (foo_file, bar_file) = chain.get_mut(); + /// # Ok(()) + /// # } + /// ``` + #[unstable(feature = "more_io_inner_methods", issue="41519")] + pub fn get_mut(&mut self) -> (&mut T, &mut U) { + (&mut self.first, &mut self.second) + } +} + #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Chain { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -1606,6 +1697,64 @@ impl Take { pub fn into_inner(self) -> T { self.inner } + + /// Gets a reference to the underlying reader. + /// + /// # Examples + /// + /// ``` + /// #![feature(more_io_inner_methods)] + /// + /// use std::io; + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// # fn foo() -> io::Result<()> { + /// let mut file = File::open("foo.txt")?; + /// + /// let mut buffer = [0; 5]; + /// let mut handle = file.take(5); + /// handle.read(&mut buffer)?; + /// + /// let file = handle.get_ref(); + /// # Ok(()) + /// # } + /// ``` + #[unstable(feature = "more_io_inner_methods", issue="41519")] + pub fn get_ref(&self) -> &T { + &self.inner + } + + /// Gets a mutable reference to the underlying reader. + /// + /// Care should be taken to avoid modifying the internal I/O state of the + /// underlying reader as doing so may corrupt the internal limit of this + /// `Take`. + /// + /// # Examples + /// + /// ``` + /// #![feature(more_io_inner_methods)] + /// + /// use std::io; + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// # fn foo() -> io::Result<()> { + /// let mut file = File::open("foo.txt")?; + /// + /// let mut buffer = [0; 5]; + /// let mut handle = file.take(5); + /// handle.read(&mut buffer)?; + /// + /// let file = handle.get_mut(); + /// # Ok(()) + /// # } + /// ``` + #[unstable(feature = "more_io_inner_methods", issue="41519")] + pub fn get_mut(&mut self) -> &mut T { + &mut self.inner + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs index bc315d54100e4..bc4e8598bbaec 100644 --- a/src/libstd/net/tcp.rs +++ b/src/libstd/net/tcp.rs @@ -73,6 +73,7 @@ pub struct TcpStream(net_imp::TcpStream); /// # Examples /// /// ```no_run +/// # use std::io; /// use std::net::{TcpListener, TcpStream}; /// /// let listener = TcpListener::bind("127.0.0.1:80").unwrap(); @@ -81,15 +82,13 @@ pub struct TcpStream(net_imp::TcpStream); /// // ... /// } /// +/// # fn process() -> io::Result<()> { /// // accept connections and process them serially /// for stream in listener.incoming() { -/// match stream { -/// Ok(stream) => { -/// handle_client(stream); -/// } -/// Err(e) => { /* connection failed */ } -/// } +/// handle_client(stream?); /// } +/// # Ok(()) +/// # } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub struct TcpListener(net_imp::TcpListener); diff --git a/src/libstd/sys/unix/time.rs b/src/libstd/sys/unix/time.rs index a08cec38f732d..a1ad94872de5c 100644 --- a/src/libstd/sys/unix/time.rs +++ b/src/libstd/sys/unix/time.rs @@ -157,7 +157,7 @@ mod inner { pub fn sub_duration(&self, other: &Duration) -> Instant { Instant { t: self.t.checked_sub(dur2intervals(other)) - .expect("overflow when adding duration to instant"), + .expect("overflow when subtracting duration from instant"), } } } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 1baf0d1b54ce1..afdb0cc4fdb79 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -57,9 +57,11 @@ use tokenstream::{self, Delimited, ThinTokenStream, TokenTree, TokenStream}; use symbol::{Symbol, keywords}; use util::ThinVec; +use std::cmp; use std::collections::HashSet; -use std::{cmp, mem, slice}; +use std::mem; use std::path::{self, Path, PathBuf}; +use std::slice; bitflags! { flags Restrictions: u8 { @@ -5363,24 +5365,25 @@ impl<'a> Parser<'a> { } let mut err = self.diagnostic().struct_span_err(id_sp, "cannot declare a new module at this location"); - let this_module = match self.directory.path.file_name() { - Some(file_name) => file_name.to_str().unwrap().to_owned(), - None => self.root_module_name.as_ref().unwrap().clone(), - }; - err.span_note(id_sp, - &format!("maybe move this module `{0}` to its own directory \ - via `{0}{1}mod.rs`", - this_module, - path::MAIN_SEPARATOR)); + if id_sp != syntax_pos::DUMMY_SP { + let src_path = PathBuf::from(self.sess.codemap().span_to_filename(id_sp)); + if let Some(stem) = src_path.file_stem() { + let mut dest_path = src_path.clone(); + dest_path.set_file_name(stem); + dest_path.push("mod.rs"); + err.span_note(id_sp, + &format!("maybe move this module `{}` to its own \ + directory via `{}`", src_path.to_string_lossy(), + dest_path.to_string_lossy())); + } + } if paths.path_exists { err.span_note(id_sp, &format!("... or maybe `use` the module `{}` instead \ of possibly redeclaring it", paths.name)); - Err(err) - } else { - Err(err) } + Err(err) } else { paths.result.map_err(|err| self.span_fatal_err(id_sp, err)) } diff --git a/src/libunwind/build.rs b/src/libunwind/build.rs index 9b8099d55a024..be9aa6c5d40ba 100644 --- a/src/libunwind/build.rs +++ b/src/libunwind/build.rs @@ -39,5 +39,7 @@ fn main() { println!("cargo:rustc-link-lib=static-nobundle=pthread"); } else if target.contains("fuchsia") { println!("cargo:rustc-link-lib=unwind"); + } else if target.contains("haiku") { + println!("cargo:rustc-link-lib=gcc_s"); } } diff --git a/src/test/run-make/sanitizer-address/Makefile b/src/test/run-make/sanitizer-address/Makefile index 5931145f3a47d..61b25df1451b3 100644 --- a/src/test/run-make/sanitizer-address/Makefile +++ b/src/test/run-make/sanitizer-address/Makefile @@ -1,11 +1,19 @@ -include ../tools.mk -# NOTE the address sanitizer only supports x86_64 linux -ifdef SANITIZER_SUPPORT -all: - $(RUSTC) -g -Z sanitizer=address -Z print-link-args overflow.rs | grep -q librustc_asan - $(TMPDIR)/overflow 2>&1 | grep -q stack-buffer-overflow +# NOTE the address sanitizer only supports x86_64 linux and macOS + +ifeq ($(TARGET),x86_64-apple-darwin) +ASAN_SUPPORT=$(SANITIZER_SUPPORT) +EXTRA_RUSTFLAG=-C rpath else -all: +ifeq ($(TARGET),x86_64-unknown-linux-gnu) +ASAN_SUPPORT=$(SANITIZER_SUPPORT) +EXTRA_RUSTFLAG= +endif +endif +all: +ifeq ($(ASAN_SUPPORT),1) + $(RUSTC) -g -Z sanitizer=address -Z print-link-args $(EXTRA_RUSTFLAG) overflow.rs | grep -q librustc_asan + $(TMPDIR)/overflow 2>&1 | grep -q stack-buffer-overflow endif diff --git a/src/test/run-make/sanitizer-invalid-target/Makefile b/src/test/run-make/sanitizer-invalid-target/Makefile index 6a1ce8bab2fb6..82e32f0995202 100644 --- a/src/test/run-make/sanitizer-invalid-target/Makefile +++ b/src/test/run-make/sanitizer-invalid-target/Makefile @@ -1,4 +1,4 @@ -include ../tools.mk all: - $(RUSTC) -Z sanitizer=leak --target i686-unknown-linux-gnu hello.rs 2>&1 | grep -q 'Sanitizers only work with the `x86_64-unknown-linux-gnu` target' + $(RUSTC) -Z sanitizer=leak --target i686-unknown-linux-gnu hello.rs 2>&1 | grep -q 'LeakSanitizer only works with the `x86_64-unknown-linux-gnu` target' diff --git a/src/test/run-make/sanitizer-leak/Makefile b/src/test/run-make/sanitizer-leak/Makefile index f02d948fdc84f..b18dd1d45eda4 100644 --- a/src/test/run-make/sanitizer-leak/Makefile +++ b/src/test/run-make/sanitizer-leak/Makefile @@ -1,10 +1,10 @@ -include ../tools.mk -ifdef SANITIZER_SUPPORT all: +ifeq ($(TARGET),x86_64-unknown-linux-gnu) +ifdef SANITIZER_SUPPORT $(RUSTC) -C opt-level=1 -g -Z sanitizer=leak -Z print-link-args leak.rs | grep -q librustc_lsan $(TMPDIR)/leak 2>&1 | grep -q 'detected memory leaks' -else -all: - endif +endif + diff --git a/src/test/run-make/sanitizer-memory/Makefile b/src/test/run-make/sanitizer-memory/Makefile index 08682e5975e51..7502ef0e7a7b7 100644 --- a/src/test/run-make/sanitizer-memory/Makefile +++ b/src/test/run-make/sanitizer-memory/Makefile @@ -1,10 +1,10 @@ -include ../tools.mk -ifdef SANITIZER_SUPPORT all: +ifeq ($(TARGET),x86_64-unknown-linux-gnu) +ifdef SANITIZER_SUPPORT $(RUSTC) -g -Z sanitizer=memory -Z print-link-args uninit.rs | grep -q librustc_msan $(TMPDIR)/uninit 2>&1 | grep -q use-of-uninitialized-value -else -all: - endif +endif + diff --git a/src/test/run-make/sysroot-crates-are-unstable/Makefile b/src/test/run-make/sysroot-crates-are-unstable/Makefile index 2bdc76e01db1a..4b7052f9b9493 100644 --- a/src/test/run-make/sysroot-crates-are-unstable/Makefile +++ b/src/test/run-make/sysroot-crates-are-unstable/Makefile @@ -1,7 +1,7 @@ -include ../tools.mk -# This is a whitelist of crates which are stable, we don't check for the -# instability of these crates as they're all stable! +# This is a whitelist of files which are stable crates or simply are not crates, +# we don't check for the instability of these crates as they're all stable! STABLE_CRATES := \ std \ core \ @@ -9,7 +9,8 @@ STABLE_CRATES := \ rsbegin.o \ rsend.o \ dllcrt2.o \ - crt2.o + crt2.o \ + clang_rt.%_dynamic.dylib # Generate a list of all crates in the sysroot. To do this we list all files in # rustc's sysroot, look at the filename, strip everything after the `-`, and diff --git a/src/test/ui/invalid-module-declaration/auxiliary/foo/bar.rs b/src/test/ui/invalid-module-declaration/auxiliary/foo/bar.rs new file mode 100644 index 0000000000000..4b6b4f5ebf82f --- /dev/null +++ b/src/test/ui/invalid-module-declaration/auxiliary/foo/bar.rs @@ -0,0 +1,11 @@ +// 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. + +pub mod baz; diff --git a/src/test/ui/invalid-module-declaration/auxiliary/foo/mod.rs b/src/test/ui/invalid-module-declaration/auxiliary/foo/mod.rs new file mode 100644 index 0000000000000..6d77fb60a35de --- /dev/null +++ b/src/test/ui/invalid-module-declaration/auxiliary/foo/mod.rs @@ -0,0 +1,11 @@ +// 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. + +pub mod bar; diff --git a/src/test/ui/invalid-module-declaration/invalid-module-declaration.rs b/src/test/ui/invalid-module-declaration/invalid-module-declaration.rs new file mode 100644 index 0000000000000..c15cfb8cc8e22 --- /dev/null +++ b/src/test/ui/invalid-module-declaration/invalid-module-declaration.rs @@ -0,0 +1,20 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-tidy-linelength + +// error-pattern: cannot declare a new module at this location +// error-pattern: maybe move this module + +mod auxiliary { + mod foo; +} + +fn main() {} diff --git a/src/test/ui/invalid-module-declaration/invalid-module-declaration.stderr b/src/test/ui/invalid-module-declaration/invalid-module-declaration.stderr new file mode 100644 index 0000000000000..3e9b21cdb740f --- /dev/null +++ b/src/test/ui/invalid-module-declaration/invalid-module-declaration.stderr @@ -0,0 +1,14 @@ +error: cannot declare a new module at this location + --> $DIR/auxiliary/foo/bar.rs:11:9 + | +11 | pub mod baz; + | ^^^ + | +note: maybe move this module `$DIR/auxiliary/foo/bar.rs` to its own directory via `$DIR/auxiliary/foo/bar/mod.rs` + --> $DIR/auxiliary/foo/bar.rs:11:9 + | +11 | pub mod baz; + | ^^^ + +error: aborting due to previous error + diff --git a/src/tools/compiletest/src/procsrv.rs b/src/tools/compiletest/src/procsrv.rs index 3d8f2296236a2..dbda8f4d802c0 100644 --- a/src/tools/compiletest/src/procsrv.rs +++ b/src/tools/compiletest/src/procsrv.rs @@ -20,6 +20,8 @@ pub fn dylib_env_var() -> &'static str { "PATH" } else if cfg!(target_os = "macos") { "DYLD_LIBRARY_PATH" + } else if cfg!(target_os = "haiku") { + "LIBRARY_PATH" } else { "LD_LIBRARY_PATH" }