diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 7ca7ef4bd720c..5f10b1aeddb7b 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -472,6 +472,8 @@ def build_triple(self): ostype += 'abi64' elif cputype in {'powerpc', 'ppc', 'ppc64'}: cputype = 'powerpc' + elif cputype == 'sparcv9': + pass elif cputype in {'amd64', 'x86_64', 'x86-64', 'x64'}: cputype = 'x86_64' else: diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 0b1a1f39d8d42..f1261e5e7d4ea 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -21,7 +21,7 @@ use std::fs::{self, File}; use std::path::{Path, PathBuf}; use std::process::Command; -use build_helper::{output, mtime}; +use build_helper::{output, mtime, up_to_date}; use filetime::FileTime; use util::{exe, libdir, is_dylib, copy}; @@ -132,21 +132,29 @@ pub fn build_startup_objects(build: &Build, for_compiler: &Compiler, target: &st let compiler = Compiler::new(0, &build.config.build); let compiler_path = build.compiler_path(&compiler); - let into = build.sysroot_libdir(for_compiler, target); - t!(fs::create_dir_all(&into)); - - for file in t!(fs::read_dir(build.src.join("src/rtstartup"))) { - let file = t!(file); - let mut cmd = Command::new(&compiler_path); - build.run(cmd.env("RUSTC_BOOTSTRAP", "1") - .arg("--target").arg(target) - .arg("--emit=obj") - .arg("--out-dir").arg(&into) - .arg(file.path())); + let src_dir = &build.src.join("src/rtstartup"); + let dst_dir = &build.native_dir(target).join("rtstartup"); + let sysroot_dir = &build.sysroot_libdir(for_compiler, target); + t!(fs::create_dir_all(dst_dir)); + t!(fs::create_dir_all(sysroot_dir)); + + for file in &["rsbegin", "rsend"] { + let src_file = &src_dir.join(file.to_string() + ".rs"); + let dst_file = &dst_dir.join(file.to_string() + ".o"); + if !up_to_date(src_file, dst_file) { + let mut cmd = Command::new(&compiler_path); + build.run(cmd.env("RUSTC_BOOTSTRAP", "1") + .arg("--target").arg(target) + .arg("--emit=obj") + .arg("--out-dir").arg(dst_dir) + .arg(src_file)); + } + + copy(dst_file, &sysroot_dir.join(file.to_string() + ".o")); } for obj in ["crt2.o", "dllcrt2.o"].iter() { - copy(&compiler_file(build.cc(target), obj), &into.join(obj)); + copy(&compiler_file(build.cc(target), obj), &sysroot_dir.join(obj)); } } diff --git a/src/ci/docker/cross/Dockerfile b/src/ci/docker/cross/Dockerfile index 52c5b83f26322..8d0f1d913b2ed 100644 --- a/src/ci/docker/cross/Dockerfile +++ b/src/ci/docker/cross/Dockerfile @@ -3,12 +3,12 @@ FROM ubuntu:16.04 RUN apt-get update && apt-get install -y --no-install-recommends \ g++ \ make \ + ninja-build \ file \ curl \ ca-certificates \ - python2.7 \ + python2.7-dev \ git \ - cmake \ sudo \ xz-utils \ zlib1g-dev \ @@ -19,7 +19,15 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ bzip2 \ patch \ libssl-dev \ - pkg-config + pkg-config \ + swig \ + libedit-dev \ + libncurses5-dev + +# CMake 3.8.0 is the first version with official support for Fuchsia, +# which is needed to build the Fuchsia toolchain. +RUN curl -L https://cmake.org/files/v3.8/cmake-3.8.0-rc1-Linux-x86_64.tar.gz | \ + tar xzf - -C /usr/local --strip-components=1 ENV SCCACHE_DIGEST=7237e38e029342fa27b7ac25412cb9d52554008b12389727320bd533fd7f05b6a96d55485f305caf95e5c8f5f97c3313e10012ccad3e752aba2518f3522ba783 RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | \ @@ -31,6 +39,10 @@ RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-ini ENTRYPOINT ["/usr/bin/dumb-init", "--"] WORKDIR /tmp +COPY shared.sh /tmp/ + +COPY build-fuchsia.sh /tmp/ +RUN ./build-fuchsia.sh COPY build-rumprun.sh /tmp/ RUN ./build-rumprun.sh @@ -65,10 +77,18 @@ ENV TARGETS=$TARGETS,arm-unknown-linux-musleabi ENV TARGETS=$TARGETS,arm-unknown-linux-musleabihf ENV TARGETS=$TARGETS,armv7-unknown-linux-musleabihf ENV TARGETS=$TARGETS,sparc64-unknown-linux-gnu +ENV TARGETS=$TARGETS,x86_64-unknown-fuchsia +ENV TARGETS=$TARGETS,aarch64-unknown-fuchsia ENV CC_mipsel_unknown_linux_musl=mipsel-openwrt-linux-gcc \ CC_mips_unknown_linux_musl=mips-openwrt-linux-gcc \ - CC_sparc64_unknown_linux_gnu=sparc64-linux-gnu-gcc + CC_sparc64_unknown_linux_gnu=sparc64-linux-gnu-gcc \ + AR_x86_64_unknown_fuchsia=x86_64-unknown-fuchsia-ar \ + CC_x86_64_unknown_fuchsia=x86_64-unknown-fuchsia-clang \ + CXX_x86_64_unknown_fuchsia=x86_64-unknown-fuchsia-clang++ \ + AR_aarch64_unknown_fuchsia=aarch64-unknown-fuchsia-ar \ + CC_aarch64_unknown_fuchsia=aarch64-unknown-fuchsia-clang \ + CXX_aarch64_unknown_fuchsia=aarch64-unknown-fuchsia-clang++ # Suppress some warnings in the openwrt toolchains we downloaded ENV STAGING_DIR=/tmp diff --git a/src/ci/docker/cross/build-fuchsia.sh b/src/ci/docker/cross/build-fuchsia.sh new file mode 100755 index 0000000000000..cf6ecb0c48b5e --- /dev/null +++ b/src/ci/docker/cross/build-fuchsia.sh @@ -0,0 +1,114 @@ +#!/bin/bash +# Copyright 2017 The Rust Project Developers. See the COPYRIGHT +# file at the top-level directory of this distribution and at +# http://rust-lang.org/COPYRIGHT. +# +# Licensed under the Apache License, Version 2.0 or the MIT license +# , at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + +set -ex +source shared.sh + +# Download sources +SRCS=( + "https://fuchsia.googlesource.com/magenta magenta 29f09e6" + "https://fuchsia.googlesource.com/third_party/llvm llvm 0f6af23" + "https://fuchsia.googlesource.com/third_party/clang llvm/tools/clang 71b73d0" + "https://fuchsia.googlesource.com/third_party/lld llvm/tools/lld af25ab9" + "https://fuchsia.googlesource.com/third_party/lldb llvm/tools/lldb 90fe975" + "https://fuchsia.googlesource.com/third_party/compiler-rt llvm/runtimes/compiler-rt 2edda55" + "https://fuchsia.googlesource.com/third_party/libcxx llvm/runtimes/libcxx b7fd0be" + "https://fuchsia.googlesource.com/third_party/libcxxabi llvm/runtimes/libcxxabi 66c8647" + "https://fuchsia.googlesource.com/third_party/libunwind llvm/runtimes/libunwind 43ce8ac" +) + +fetch() { + mkdir -p $2 + pushd $2 > /dev/null + curl -sL $1/+archive/$3.tar.gz | tar xzf - + popd > /dev/null +} + +for i in "${SRCS[@]}"; do + fetch $i +done + +# Build toolchain +cd llvm +mkdir build +cd build +hide_output cmake -GNinja \ + -DFUCHSIA_SYSROOT=${PWD}/../../magenta/third_party/ulib/musl \ + -C ../tools/clang/cmake/caches/Fuchsia.cmake \ + .. +hide_output ninja stage2-distribution +hide_output ninja stage2-install-distribution +cd ../.. + +# Build sysroot +rm -rf llvm/runtimes/compiler-rt +./magenta/scripts/download-toolchain + +build_sysroot() { + local arch="$1" + + case "${arch}" in + x86_64) tgt="magenta-pc-x86-64" ;; + aarch64) tgt="magenta-qemu-arm64" ;; + esac + + hide_output make -C magenta -j$(getconf _NPROCESSORS_ONLN) $tgt + dst=/usr/local/${arch}-unknown-fuchsia + mkdir -p $dst + cp -r magenta/build-${tgt}/sysroot/include $dst/ + cp -r magenta/build-${tgt}/sysroot/lib $dst/ + + cd llvm + mkdir build-runtimes-${arch} + cd build-runtimes-${arch} + hide_output cmake -GNinja \ + -DCMAKE_C_COMPILER=clang \ + -DCMAKE_CXX_COMPILER=clang++ \ + -DCMAKE_AR=/usr/local/bin/llvm-ar \ + -DCMAKE_RANLIB=/usr/local/bin/llvm-ranlib \ + -DCMAKE_INSTALL_PREFIX= \ + -DLLVM_MAIN_SRC_DIR=${PWD}/.. \ + -DLLVM_BINARY_DIR=${PWD}/../build \ + -DLLVM_ENABLE_WERROR=OFF \ + -DCMAKE_BUILD_TYPE=Release \ + -DLLVM_INCLUDE_TESTS=ON \ + -DCMAKE_SYSTEM_NAME=Fuchsia \ + -DCMAKE_C_COMPILER_TARGET=${arch}-fuchsia \ + -DCMAKE_CXX_COMPILER_TARGET=${arch}-fuchsia \ + -DUNIX=1 \ + -DLIBCXX_HAS_MUSL_LIBC=ON \ + -DLIBCXXABI_USE_LLVM_UNWINDER=ON \ + -DCMAKE_SYSROOT=${dst} \ + -DCMAKE_C_COMPILER_FORCED=TRUE \ + -DCMAKE_CXX_COMPILER_FORCED=TRUE \ + -DLLVM_ENABLE_LIBCXX=ON \ + -DCMAKE_EXE_LINKER_FLAGS="-nodefaultlibs -lc" \ + -DCMAKE_SHARED_LINKER_FLAGS="$(clang --target=${arch}-fuchsia -print-libgcc-file-name)" \ + ../runtimes + hide_output env DESTDIR="${dst}" ninja install + cd ../.. +} + +build_sysroot "x86_64" +build_sysroot "aarch64" + +rm -rf magenta llvm + +for arch in x86_64 aarch64; do + for tool in clang clang++; do + cat >/usr/local/bin/${arch}-unknown-fuchsia-${tool} < or the MIT license +# , at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + +hide_output() { + set +x + on_err=" +echo ERROR: An error was encountered with the build. +cat /tmp/build.log +exit 1 +" + trap "$on_err" ERR + bash -c "while true; do sleep 30; echo \$(date) - building ...; done" & + PING_LOOP_PID=$! + "$@" &> /tmp/build.log + trap - ERR + kill $PING_LOOP_PID + set -x +} diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index e92eb4ff7bdd4..10bc5ab88c93f 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -1629,6 +1629,43 @@ impl hash::Hash for String { } } +/// Implements the `+` operator for concatenating two strings. +/// +/// This consumes the `String` on the left-hand side and re-uses its buffer (growing it if +/// necessary). This is done to avoid allocating a new `String` and copying the entire contents on +/// every operation, which would lead to `O(n^2)` running time when building an `n`-byte string by +/// repeated concatenation. +/// +/// The string on the right-hand side is only borrowed; its contents are copied into the returned +/// `String`. +/// +/// # Examples +/// +/// Concatenating two `String`s takes the first by value and borrows the second: +/// +/// ``` +/// let a = String::from("hello"); +/// let b = String::from(" world"); +/// let c = a + &b; +/// // `a` is moved and can no longer be used here. +/// ``` +/// +/// If you want to keep using the first `String`, you can clone it and append to the clone instead: +/// +/// ``` +/// let a = String::from("hello"); +/// let b = String::from(" world"); +/// let c = a.clone() + &b; +/// // `a` is still valid here. +/// ``` +/// +/// Concatenating `&str` slices can be done by converting the first to a `String`: +/// +/// ``` +/// let a = "hello"; +/// let b = " world"; +/// let c = a.to_string() + b; +/// ``` #[stable(feature = "rust1", since = "1.0.0")] impl<'a> Add<&'a str> for String { type Output = String; @@ -1640,6 +1677,11 @@ impl<'a> Add<&'a str> for String { } } +/// Implements the `+=` operator for appending to a `String`. +/// +/// This has the same behavior as the [`push_str()`] method. +/// +/// [`push_str()`]: struct.String.html#method.push_str #[stable(feature = "stringaddassign", since = "1.12.0")] impl<'a> AddAssign<&'a str> for String { #[inline] diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 9e3f117f9b20e..bc7f562452d3b 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -1776,6 +1776,7 @@ array_impls! { 30 31 32 } +/// Implements comparison of vectors, lexicographically. #[stable(feature = "rust1", since = "1.0.0")] impl PartialOrd for Vec { #[inline] @@ -1787,6 +1788,7 @@ impl PartialOrd for Vec { #[stable(feature = "rust1", since = "1.0.0")] impl Eq for Vec {} +/// Implements ordering of vectors, lexicographically. #[stable(feature = "rust1", since = "1.0.0")] impl Ord for Vec { #[inline] diff --git a/src/libcompiler_builtins/build.rs b/src/libcompiler_builtins/build.rs index 5360bbdeacd6a..16ecf88256670 100644 --- a/src/libcompiler_builtins/build.rs +++ b/src/libcompiler_builtins/build.rs @@ -92,7 +92,15 @@ fn main() { // compiler-rt's build system already cfg.flag("-fno-builtin"); cfg.flag("-fvisibility=hidden"); - cfg.flag("-fomit-frame-pointer"); + // Accepted practice on Solaris is to never omit frame pointer so that + // system observability tools work as expected. In addition, at least + // on Solaris, -fomit-frame-pointer on sparcv9 appears to generate + // references to data outside of the current stack frame. A search of + // the gcc bug database provides a variety of issues surrounding + // -fomit-frame-pointer on non-x86 platforms. + if !target.contains("solaris") && !target.contains("sparc") { + cfg.flag("-fomit-frame-pointer"); + } cfg.flag("-ffreestanding"); cfg.define("VISIBILITY_HIDDEN", None); } diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index 3e0b842557353..0331c5d4ba401 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -2202,6 +2202,7 @@ impl PartialEq<[B]> for [A] where A: PartialEq { #[stable(feature = "rust1", since = "1.0.0")] impl Eq for [T] {} +/// Implements comparison of vectors lexicographically. #[stable(feature = "rust1", since = "1.0.0")] impl Ord for [T] { fn cmp(&self, other: &[T]) -> Ordering { @@ -2209,6 +2210,7 @@ impl Ord for [T] { } } +/// Implements comparison of vectors lexicographically. #[stable(feature = "rust1", since = "1.0.0")] impl PartialOrd for [T] { fn partial_cmp(&self, other: &[T]) -> Option { diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 49a6b1b5fceb7..925cd84154a2e 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -1366,6 +1366,13 @@ mod traits { use ops; use str::eq_slice; + /// Implements ordering of strings. + /// + /// Strings are ordered lexicographically by their byte values. This orders Unicode code + /// points based on their positions in the code charts. This is not necessarily the same as + /// "alphabetical" order, which varies by language and locale. Sorting strings according to + /// culturally-accepted standards requires locale-specific data that is outside the scope of + /// the `str` type. #[stable(feature = "rust1", since = "1.0.0")] impl Ord for str { #[inline] @@ -1387,6 +1394,13 @@ mod traits { #[stable(feature = "rust1", since = "1.0.0")] impl Eq for str {} + /// Implements comparison operations on strings. + /// + /// Strings are compared lexicographically by their byte values. This compares Unicode code + /// points based on their positions in the code charts. This is not necessarily the same as + /// "alphabetical" order, which varies by language and locale. Comparing strings according to + /// culturally-accepted standards requires locale-specific data that is outside the scope of + /// the `str` type. #[stable(feature = "rust1", since = "1.0.0")] impl PartialOrd for str { #[inline] diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs index 1d5d1e3ab2fc7..0c179469448fe 100644 --- a/src/librustc_back/target/mod.rs +++ b/src/librustc_back/target/mod.rs @@ -200,6 +200,7 @@ supported_targets! { ("armv7s-apple-ios", armv7s_apple_ios), ("x86_64-sun-solaris", x86_64_sun_solaris), + ("sparcv9-sun-solaris", sparcv9_sun_solaris), ("x86_64-pc-windows-gnu", x86_64_pc_windows_gnu), ("i686-pc-windows-gnu", i686_pc_windows_gnu), diff --git a/src/librustc_back/target/sparcv9_sun_solaris.rs b/src/librustc_back/target/sparcv9_sun_solaris.rs new file mode 100644 index 0000000000000..c88e5a402f2f5 --- /dev/null +++ b/src/librustc_back/target/sparcv9_sun_solaris.rs @@ -0,0 +1,35 @@ +// 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. + +use target::{Target, TargetResult}; + +pub fn target() -> TargetResult { + let mut base = super::solaris_base::opts(); + base.pre_link_args.push("-m64".to_string()); + // llvm calls this "v9" + base.cpu = "v9".to_string(); + base.max_atomic_width = Some(64); + + Ok(Target { + llvm_target: "sparcv9-sun-solaris".to_string(), + target_endian: "big".to_string(), + target_pointer_width: "64".to_string(), + data_layout: "E-m:e-i64:64-n32:64-S128".to_string(), + // Use "sparc64" instead of "sparcv9" here, since the former is already + // used widely in the source base. If we ever needed ABI + // differentiation from the sparc64, we could, but that would probably + // just be confusing. + arch: "sparc64".to_string(), + target_os: "solaris".to_string(), + target_env: "".to_string(), + target_vendor: "sun".to_string(), + options: base, + }) +} diff --git a/src/librustc_passes/static_recursion.rs b/src/librustc_passes/static_recursion.rs index 1ef8a5b0080f3..fc05471ead30b 100644 --- a/src/librustc_passes/static_recursion.rs +++ b/src/librustc_passes/static_recursion.rs @@ -18,7 +18,6 @@ use rustc::hir::def::{Def, CtorKind}; use rustc::util::nodemap::{NodeMap, NodeSet}; use syntax::ast; -use syntax::feature_gate::{GateIssue, emit_feature_err}; use syntax_pos::Span; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::hir; @@ -43,7 +42,7 @@ impl<'a, 'hir: 'a> Visitor<'hir> for CheckCrateVisitor<'a, 'hir> { match it.node { hir::ItemStatic(..) | hir::ItemConst(..) => { - let mut recursion_visitor = CheckItemRecursionVisitor::new(self, &it.span); + let mut recursion_visitor = CheckItemRecursionVisitor::new(self); recursion_visitor.visit_item(it); } hir::ItemEnum(ref enum_def, ref generics) => { @@ -52,8 +51,7 @@ impl<'a, 'hir: 'a> Visitor<'hir> for CheckCrateVisitor<'a, 'hir> { // less redundant output. for variant in &enum_def.variants { if let Some(_) = variant.node.disr_expr { - let mut recursion_visitor = CheckItemRecursionVisitor::new(self, - &variant.span); + let mut recursion_visitor = CheckItemRecursionVisitor::new(self); recursion_visitor.populate_enum_discriminants(enum_def); recursion_visitor.visit_variant(variant, generics, it.id); } @@ -68,7 +66,7 @@ impl<'a, 'hir: 'a> Visitor<'hir> for CheckCrateVisitor<'a, 'hir> { match ti.node { hir::TraitItemKind::Const(_, ref default) => { if let Some(_) = *default { - let mut recursion_visitor = CheckItemRecursionVisitor::new(self, &ti.span); + let mut recursion_visitor = CheckItemRecursionVisitor::new(self); recursion_visitor.visit_trait_item(ti); } } @@ -80,7 +78,7 @@ impl<'a, 'hir: 'a> Visitor<'hir> for CheckCrateVisitor<'a, 'hir> { fn visit_impl_item(&mut self, ii: &'hir hir::ImplItem) { match ii.node { hir::ImplItemKind::Const(..) => { - let mut recursion_visitor = CheckItemRecursionVisitor::new(self, &ii.span); + let mut recursion_visitor = CheckItemRecursionVisitor::new(self); recursion_visitor.visit_impl_item(ii); } _ => {} @@ -105,7 +103,6 @@ pub fn check_crate<'hir>(sess: &Session, hir_map: &hir_map::Map<'hir>) -> Compil } struct CheckItemRecursionVisitor<'a, 'b: 'a, 'hir: 'b> { - root_span: &'b Span, sess: &'b Session, hir_map: &'b hir_map::Map<'hir>, discriminant_map: &'a mut NodeMap>, @@ -114,9 +111,8 @@ struct CheckItemRecursionVisitor<'a, 'b: 'a, 'hir: 'b> { } impl<'a, 'b: 'a, 'hir: 'b> CheckItemRecursionVisitor<'a, 'b, 'hir> { - fn new(v: &'a mut CheckCrateVisitor<'b, 'hir>, span: &'b Span) -> Self { + fn new(v: &'a mut CheckCrateVisitor<'b, 'hir>) -> Self { CheckItemRecursionVisitor { - root_span: span, sess: v.sess, hir_map: v.hir_map, discriminant_map: &mut v.discriminant_map, @@ -143,15 +139,7 @@ impl<'a, 'b: 'a, 'hir: 'b> CheckItemRecursionVisitor<'a, 'b, 'hir> { false } }); - if any_static { - if !self.sess.features.borrow().static_recursion { - emit_feature_err(&self.sess.parse_sess, - "static_recursion", - *self.root_span, - GateIssue::Language, - "recursive static"); - } - } else { + if !any_static { struct_span_err!(self.sess, span, E0265, "recursive constant") .span_label(span, &format!("recursion not allowed in constant")) .emit(); diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 1c37067d7f69d..c7000ee1e40e7 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -12,7 +12,7 @@ use std::env; use std::ffi::OsString; use std::io::prelude::*; use std::io; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::panic::{self, AssertUnwindSafe}; use std::process::Command; use std::rc::Rc; @@ -485,7 +485,15 @@ impl Collector { pub fn get_filename(&self) -> String { if let Some(ref codemap) = self.codemap { - codemap.span_to_filename(self.position) + let filename = codemap.span_to_filename(self.position); + if let Ok(cur_dir) = env::current_dir() { + if let Ok(path) = Path::new(&filename).strip_prefix(&cur_dir) { + if let Some(path) = path.to_str() { + return path.to_owned(); + } + } + } + filename } else if let Some(ref filename) = self.filename { filename.clone() } else { diff --git a/src/libstd/build.rs b/src/libstd/build.rs index 0fca374f6e6d1..038dea77f3ead 100644 --- a/src/libstd/build.rs +++ b/src/libstd/build.rs @@ -59,6 +59,10 @@ fn main() { println!("cargo:rustc-link-lib=userenv"); println!("cargo:rustc-link-lib=shell32"); } else if target.contains("fuchsia") { + // use system-provided libbacktrace + if cfg!(feature = "backtrace") { + println!("cargo:rustc-link-lib=backtrace"); + } println!("cargo:rustc-link-lib=magenta"); println!("cargo:rustc-link-lib=mxio"); println!("cargo:rustc-link-lib=launchpad"); // for std::process diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index fd5827b4c0753..f0738fe9b7033 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -182,12 +182,12 @@ impl DefaultResizePolicy { // ---------------------- // To protect against degenerate performance scenarios (including DOS attacks), // the implementation includes an adaptive behavior that can resize the map -// early (before its capacity is exceeded) when suspiciously long probe or -// forward shifts sequences are encountered. +// early (before its capacity is exceeded) when suspiciously long probe sequences +// are encountered. // // With this algorithm in place it would be possible to turn a CPU attack into // a memory attack due to the aggressive resizing. To prevent that the -// adaptive behavior only triggers when the map occupancy is half the maximum occupancy. +// adaptive behavior only triggers when the map is at least half full. // This reduces the effectiveness of the algorithm but also makes it completely safe. // // The previous safety measure also prevents degenerate interactions with @@ -195,16 +195,11 @@ impl DefaultResizePolicy { // DOS attack. // const DISPLACEMENT_THRESHOLD: usize = 128; -const FORWARD_SHIFT_THRESHOLD: usize = 512; // -// The thresholds of 128 and 512 are chosen to minimize the chance of exceeding them. +// The threshold of 128 is chosen to minimize the chance of exceeding it. // In particular, we want that chance to be less than 10^-8 with a load of 90%. // For displacement, the smallest constant that fits our needs is 90, -// so we round that up to 128. For the number of forward-shifted buckets, -// we choose k=512. Keep in mind that the run length is a sum of the displacement and -// the number of forward-shifted buckets, so its threshold is 128+512=640. -// Even though the probability of having a run length of more than 640 buckets may be -// higher than the probability we want, it should be low enough. +// so we round that up to 128. // // At a load factor of α, the odds of finding the target bucket after exactly n // unsuccesful probes[1] are @@ -212,16 +207,12 @@ const FORWARD_SHIFT_THRESHOLD: usize = 512; // Pr_α{displacement = n} = // (1 - α) / α * ∑_{k≥1} e^(-kα) * (kα)^(k+n) / (k + n)! * (1 - kα / (k + n + 1)) // -// We use this formula to find the probability of loading half of triggering the adaptive behavior +// We use this formula to find the probability of triggering the adaptive behavior // // Pr_0.909{displacement > 128} = 1.601 * 10^-11 // -// FIXME: Extend with math for shift threshold in [2] -// // 1. Alfredo Viola (2005). Distributional analysis of Robin Hood linear probing // hashing with buckets. -// 2. http://www.cs.tau.ac.il/~zwick/Adv-Alg-2015/Linear-Probing.pdf - /// A hash map implementation which uses linear probing with Robin Hood bucket /// stealing. @@ -494,7 +485,7 @@ fn robin_hood<'a, K: 'a, V: 'a>(bucket: FullBucketMut<'a, K, V>, mut hash: SafeHash, mut key: K, mut val: V) - -> (usize, &'a mut V) { + -> &'a mut V { let start_index = bucket.index(); let size = bucket.table().size(); // Save the *starting point*. @@ -519,7 +510,6 @@ fn robin_hood<'a, K: 'a, V: 'a>(bucket: FullBucketMut<'a, K, V>, Empty(bucket) => { // Found a hole! let bucket = bucket.put(hash, key, val); - let end_index = bucket.index(); // Now that it's stolen, just read the value's pointer // right out of the table! Go back to the *starting point*. // @@ -527,7 +517,7 @@ fn robin_hood<'a, K: 'a, V: 'a>(bucket: FullBucketMut<'a, K, V>, // bucket, which is a FullBucket on top of a // FullBucketMut, into just one FullBucketMut. The "table" // refers to the inner FullBucketMut in this context. - return (end_index - start_index, bucket.into_table().into_mut_refs().1); + return bucket.into_table().into_mut_refs().1; } Full(bucket) => bucket, }; @@ -2128,18 +2118,16 @@ impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> { pub fn insert(self, value: V) -> &'a mut V { match self.elem { NeqElem(bucket, disp) => { - let (shift, v_ref) = robin_hood(bucket, disp, self.hash, self.key, value); - if disp >= DISPLACEMENT_THRESHOLD || shift >= FORWARD_SHIFT_THRESHOLD { + if disp >= DISPLACEMENT_THRESHOLD { *self.long_probes = true; } - v_ref + robin_hood(bucket, disp, self.hash, self.key, value) }, NoElem(bucket, disp) => { if disp >= DISPLACEMENT_THRESHOLD { *self.long_probes = true; } - let bucket = bucket.put(self.hash, self.key, value); - bucket.into_mut_refs().1 + bucket.put(self.hash, self.key, value).into_mut_refs().1 }, } } diff --git a/src/libstd/sync/barrier.rs b/src/libstd/sync/barrier.rs index fc4fd4ce92b1b..f15e7ff891684 100644 --- a/src/libstd/sync/barrier.rs +++ b/src/libstd/sync/barrier.rs @@ -14,6 +14,8 @@ use sync::{Mutex, Condvar}; /// A barrier enables multiple threads to synchronize the beginning /// of some computation. /// +/// # Examples +/// /// ``` /// use std::sync::{Arc, Barrier}; /// use std::thread; @@ -50,8 +52,19 @@ struct BarrierState { /// A result returned from wait. /// -/// Currently this opaque structure only has one method, `.is_leader()`. Only +/// Currently this opaque structure only has one method, [`.is_leader()`]. Only /// one thread will receive a result that will return `true` from this function. +/// +/// [`.is_leader()`]: #method.is_leader +/// +/// # Examples +/// +/// ``` +/// use std::sync::Barrier; +/// +/// let barrier = Barrier::new(1); +/// let barrier_wait_result = barrier.wait(); +/// ``` #[stable(feature = "rust1", since = "1.0.0")] pub struct BarrierWaitResult(bool); @@ -65,8 +78,18 @@ impl fmt::Debug for Barrier { impl Barrier { /// Creates a new barrier that can block a given number of threads. /// - /// A barrier will block `n`-1 threads which call `wait` and then wake up - /// all threads at once when the `n`th thread calls `wait`. + /// A barrier will block `n`-1 threads which call [`wait`] and then wake up + /// all threads at once when the `n`th thread calls [`wait`]. + /// + /// [`wait`]: #method.wait + /// + /// # Examples + /// + /// ``` + /// use std::sync::Barrier; + /// + /// let barrier = Barrier::new(10); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn new(n: usize) -> Barrier { Barrier { @@ -84,10 +107,37 @@ impl Barrier { /// Barriers are re-usable after all threads have rendezvoused once, and can /// be used continuously. /// - /// A single (arbitrary) thread will receive a `BarrierWaitResult` that - /// returns `true` from `is_leader` when returning from this function, and + /// A single (arbitrary) thread will receive a [`BarrierWaitResult`] that + /// returns `true` from [`is_leader`] when returning from this function, and /// all other threads will receive a result that will return `false` from - /// `is_leader` + /// [`is_leader`]. + /// + /// [`BarrierWaitResult`]: struct.BarrierWaitResult.html + /// [`is_leader`]: struct.BarrierWaitResult.html#method.is_leader + /// + /// # Examples + /// + /// ``` + /// use std::sync::{Arc, Barrier}; + /// use std::thread; + /// + /// let mut handles = Vec::with_capacity(10); + /// let barrier = Arc::new(Barrier::new(10)); + /// for _ in 0..10 { + /// let c = barrier.clone(); + /// // The same messages will be printed together. + /// // You will NOT see any interleaving. + /// handles.push(thread::spawn(move|| { + /// println!("before wait"); + /// c.wait(); + /// println!("after wait"); + /// })); + /// } + /// // Wait for other threads to finish. + /// for handle in handles { + /// handle.join().unwrap(); + /// } + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn wait(&self) -> BarrierWaitResult { let mut lock = self.lock.lock().unwrap(); @@ -120,10 +170,22 @@ impl fmt::Debug for BarrierWaitResult { } impl BarrierWaitResult { - /// Returns whether this thread from `wait` is the "leader thread". + /// Returns whether this thread from [`wait`] is the "leader thread". /// /// Only one thread will have `true` returned from their result, all other /// threads will have `false` returned. + /// + /// [`wait`]: struct.Barrier.html#method.wait + /// + /// # Examples + /// + /// ``` + /// use std::sync::Barrier; + /// + /// let barrier = Barrier::new(1); + /// let barrier_wait_result = barrier.wait(); + /// println!("{:?}", barrier_wait_result.is_leader()); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn is_leader(&self) -> bool { self.0 } } diff --git a/src/libstd/sys/unix/process/magenta.rs b/src/libstd/sys/unix/process/magenta.rs index a81bedcad22ff..08a827ce08142 100644 --- a/src/libstd/sys/unix/process/magenta.rs +++ b/src/libstd/sys/unix/process/magenta.rs @@ -111,7 +111,7 @@ extern { pub fn mx_handle_duplicate(handle: mx_handle_t, rights: mx_rights_t, out: *const mx_handle_t) -> mx_handle_t; - pub fn mx_handle_wait_one(handle: mx_handle_t, signals: mx_signals_t, timeout: mx_time_t, + pub fn mx_object_wait_one(handle: mx_handle_t, signals: mx_signals_t, timeout: mx_time_t, pending: *mut mx_signals_t) -> mx_status_t; pub fn mx_object_get_info(handle: mx_handle_t, topic: u32, buffer: *mut c_void, diff --git a/src/libstd/sys/unix/process/process_fuchsia.rs b/src/libstd/sys/unix/process/process_fuchsia.rs index 0bb2e0c1a83d4..608e44ca9e86e 100644 --- a/src/libstd/sys/unix/process/process_fuchsia.rs +++ b/src/libstd/sys/unix/process/process_fuchsia.rs @@ -151,7 +151,7 @@ impl Process { let mut avail: mx_size_t = 0; unsafe { - mx_cvt(mx_handle_wait_one(self.handle.raw(), MX_TASK_TERMINATED, + mx_cvt(mx_object_wait_one(self.handle.raw(), MX_TASK_TERMINATED, MX_TIME_INFINITE, ptr::null_mut()))?; mx_cvt(mx_object_get_info(self.handle.raw(), MX_INFO_PROCESS, &mut proc_info as *mut _ as *mut libc::c_void, @@ -174,7 +174,7 @@ impl Process { let mut avail: mx_size_t = 0; unsafe { - let status = mx_handle_wait_one(self.handle.raw(), MX_TASK_TERMINATED, + let status = mx_object_wait_one(self.handle.raw(), MX_TASK_TERMINATED, 0, ptr::null_mut()); match status { 0 => { }, // Success diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 93e320c45223c..2bc066d3fea55 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -235,7 +235,7 @@ pub use self::local::{LocalKey, LocalKeyState}; pub struct Builder { // A name for the thread-to-be, for identification in panic messages name: Option, - // The size of the stack for the spawned thread + // The size of the stack for the spawned thread in bytes stack_size: Option, } @@ -289,14 +289,17 @@ impl Builder { self } - /// Sets the size of the stack for the new thread. + /// Sets the size of the stack (in bytes) for the new thread. + /// + /// The actual stack size may be greater than this value if + /// the platform specifies minimal stack size. /// /// # Examples /// /// ``` /// use std::thread; /// - /// let builder = thread::Builder::new().stack_size(10); + /// let builder = thread::Builder::new().stack_size(32 * 1024); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn stack_size(mut self, size: usize) -> Builder { diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index b7be084fa0bab..0d41020e1f33e 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -200,9 +200,6 @@ declare_features! ( // rustc internal (active, prelude_import, "1.2.0", None), - // Allows the definition recursive static items. - (active, static_recursion, "1.3.0", Some(29719)), - // Allows default type parameters to influence type inference. (active, default_type_parameter_fallback, "1.3.0", Some(27336)), @@ -387,6 +384,8 @@ declare_features! ( (accepted, static_in_const, "1.17.0", Some(35897)), // Allows field shorthands (`x` meaning `x: x`) in struct literal expressions. (accepted, field_init_shorthand, "1.17.0", Some(37340)), + // Allows the definition recursive static items. + (accepted, static_recursion, "1.17.0", Some(29719)), ); // If you change this, please modify src/doc/unstable-book as well. You must // move that documentation into the relevant place in the other docs, and diff --git a/src/test/compile-fail/asm-bad-clobber.rs b/src/test/compile-fail/asm-bad-clobber.rs index cb931329051f9..145662fd87c9e 100644 --- a/src/test/compile-fail/asm-bad-clobber.rs +++ b/src/test/compile-fail/asm-bad-clobber.rs @@ -13,6 +13,7 @@ // ignore-aarch64 // ignore-s390x // ignore-emscripten +// ignore-powerpc #![feature(asm, rustc_attrs)] diff --git a/src/test/compile-fail/asm-in-bad-modifier.rs b/src/test/compile-fail/asm-in-bad-modifier.rs index 7ba5beac21340..f0467e75223be 100644 --- a/src/test/compile-fail/asm-in-bad-modifier.rs +++ b/src/test/compile-fail/asm-in-bad-modifier.rs @@ -10,6 +10,7 @@ // ignore-s390x // ignore-emscripten +// ignore-powerpc #![feature(asm)] diff --git a/src/test/compile-fail/asm-misplaced-option.rs b/src/test/compile-fail/asm-misplaced-option.rs index bafbf625e3517..37a267535317c 100644 --- a/src/test/compile-fail/asm-misplaced-option.rs +++ b/src/test/compile-fail/asm-misplaced-option.rs @@ -13,6 +13,7 @@ // ignore-aarch64 // ignore-s390x // ignore-emscripten +// ignore-powerpc #![feature(asm, rustc_attrs)] diff --git a/src/test/compile-fail/asm-out-assign-imm.rs b/src/test/compile-fail/asm-out-assign-imm.rs index 161c0b977ff0c..3c4a5dcb7b038 100644 --- a/src/test/compile-fail/asm-out-assign-imm.rs +++ b/src/test/compile-fail/asm-out-assign-imm.rs @@ -10,6 +10,7 @@ // ignore-s390x // ignore-emscripten +// ignore-powerpc #![feature(asm)] diff --git a/src/test/compile-fail/asm-out-no-modifier.rs b/src/test/compile-fail/asm-out-no-modifier.rs index cb8fb19a7c7f0..acf575c003a7d 100644 --- a/src/test/compile-fail/asm-out-no-modifier.rs +++ b/src/test/compile-fail/asm-out-no-modifier.rs @@ -10,6 +10,7 @@ // ignore-s390x // ignore-emscripten +// ignore-powerpc #![feature(asm)] diff --git a/src/test/compile-fail/asm-out-read-uninit.rs b/src/test/compile-fail/asm-out-read-uninit.rs index 42bff4c633aa9..bd180f6e5ebd9 100644 --- a/src/test/compile-fail/asm-out-read-uninit.rs +++ b/src/test/compile-fail/asm-out-read-uninit.rs @@ -10,6 +10,7 @@ // ignore-s390x // ignore-emscripten +// ignore-powerpc #![feature(asm)] diff --git a/src/test/compile-fail/feature-gate-static_recursion.rs b/src/test/compile-fail/feature-gate-static_recursion.rs deleted file mode 100644 index bd20c891d8ed3..0000000000000 --- a/src/test/compile-fail/feature-gate-static_recursion.rs +++ /dev/null @@ -1,49 +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. - -static mut S: *const u8 = unsafe { &S as *const *const u8 as *const u8 }; -//~^ ERROR recursive static (see issue #29719) - -struct StaticDoubleLinked { - prev: &'static StaticDoubleLinked, - next: &'static StaticDoubleLinked, - data: i32, - head: bool, -} - -static L1: StaticDoubleLinked = StaticDoubleLinked{prev: &L3, next: &L2, data: 1, head: true}; -//~^ ERROR recursive static (see issue #29719) -//~^^ ERROR recursive static (see issue #29719) -//~^^^ ERROR recursive static (see issue #29719) -static L2: StaticDoubleLinked = StaticDoubleLinked{prev: &L1, next: &L3, data: 2, head: false}; -static L3: StaticDoubleLinked = StaticDoubleLinked{prev: &L2, next: &L1, data: 3, head: false}; - - -pub fn main() { - unsafe { assert_eq!(S, *(S as *const *const u8)); } - - let mut test_vec = Vec::new(); - let mut cur = &L1; - loop { - test_vec.push(cur.data); - cur = cur.next; - if cur.head { break } - } - assert_eq!(&test_vec, &[1,2,3]); - - let mut test_vec = Vec::new(); - let mut cur = &L1; - loop { - cur = cur.prev; - test_vec.push(cur.data); - if cur.head { break } - } - assert_eq!(&test_vec, &[3,2,1]); -} diff --git a/src/test/compile-fail/issue-3008-2.rs b/src/test/compile-fail/issue-3008-2.rs index 38b5fcbb3db0e..3bc8413cbca73 100644 --- a/src/test/compile-fail/issue-3008-2.rs +++ b/src/test/compile-fail/issue-3008-2.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(static_recursion)] - enum foo { foo_(bar) } struct bar { x: bar } //~^ ERROR E0072 diff --git a/src/test/compile-fail/static-recursion-gate.rs b/src/test/compile-fail/static-recursion-gate.rs deleted file mode 100644 index 29b5689fa93fd..0000000000000 --- a/src/test/compile-fail/static-recursion-gate.rs +++ /dev/null @@ -1,16 +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. - -static mut S: *const u8 = unsafe { &S as *const *const u8 as *const u8 }; -//~^ ERROR recursive static - -pub fn main() { - unsafe { assert_eq!(S, *(S as *const *const u8)); } -} diff --git a/src/test/run-pass/issue-2063-resource.rs b/src/test/run-pass/issue-2063-resource.rs index aa9a7afc37f8a..c3a0dc67e83ed 100644 --- a/src/test/run-pass/issue-2063-resource.rs +++ b/src/test/run-pass/issue-2063-resource.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(static_recursion)] - // test that autoderef of a type like this does not // cause compiler to loop. Note that no instances // of such a type could ever be constructed. diff --git a/src/test/run-pass/issue-2063.rs b/src/test/run-pass/issue-2063.rs index 48da7ecc5089d..5be4f8e8e7384 100644 --- a/src/test/run-pass/issue-2063.rs +++ b/src/test/run-pass/issue-2063.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(static_recursion)] - // test that autoderef of a type like this does not // cause compiler to loop. Note that no instances // of such a type could ever be constructed. diff --git a/src/test/run-pass/static-recursive.rs b/src/test/run-pass/static-recursive.rs index f3db102ea5a49..4a6ba984eef0a 100644 --- a/src/test/run-pass/static-recursive.rs +++ b/src/test/run-pass/static-recursive.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(static_recursion)] - static mut S: *const u8 = unsafe { &S as *const *const u8 as *const u8 }; struct StaticDoubleLinked { diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 991cd02d215dc..eba77429f3dbb 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -45,6 +45,7 @@ static HOSTS: &'static [&'static str] = &[ static TARGETS: &'static [&'static str] = &[ "aarch64-apple-ios", + "aarch64-unknown-fuchsia", "aarch64-linux-android", "aarch64-unknown-linux-gnu", "arm-linux-androideabi", @@ -86,6 +87,7 @@ static TARGETS: &'static [&'static str] = &[ "x86_64-pc-windows-msvc", "x86_64-rumprun-netbsd", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", "x86_64-unknown-linux-musl", "x86_64-unknown-netbsd", diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index c9bdcd408ead7..1ec0838d45f76 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1987,12 +1987,22 @@ actual:\n\ fn check_rustdoc_test_option(&self, res: ProcRes) { let mut other_files = Vec::new(); let mut files: HashMap> = HashMap::new(); - files.insert(self.testpaths.file.to_str().unwrap().to_owned(), + let cwd = env::current_dir().unwrap(); + files.insert(self.testpaths.file.strip_prefix(&cwd) + .unwrap_or(&self.testpaths.file) + .to_str() + .unwrap() + .replace('\\', "/"), self.get_lines(&self.testpaths.file, Some(&mut other_files))); for other_file in other_files { let mut path = self.testpaths.file.clone(); path.set_file_name(&format!("{}.rs", other_file)); - files.insert(path.to_str().unwrap().to_owned(), self.get_lines(&path, None)); + files.insert(path.strip_prefix(&cwd) + .unwrap_or(&path) + .to_str() + .unwrap() + .replace('\\', "/"), + self.get_lines(&path, None)); } let mut tested = 0; @@ -2002,7 +2012,8 @@ actual:\n\ let tmp: Vec<&str> = s.split(" - ").collect(); if tmp.len() == 2 { let path = tmp[0].rsplit("test ").next().unwrap(); - if let Some(ref mut v) = files.get_mut(path) { + if let Some(ref mut v) = files.get_mut( + &path.replace('\\', "/")) { tested += 1; let mut iter = tmp[1].split("(line "); iter.next();