diff --git a/README.md b/README.md
index f2385f315186f..b79c9703f44ef 100644
--- a/README.md
+++ b/README.md
@@ -89,6 +89,7 @@ build.
$ pacman -S git \
make \
diffutils \
+ tar \
mingw-w64-x86_64-python2 \
mingw-w64-x86_64-cmake \
mingw-w64-x86_64-gcc
diff --git a/RELEASES.md b/RELEASES.md
index 8817d7f88a738..e6f18f9f7ba55 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -1,3 +1,259 @@
+Version 1.12.0 (2016-09-29)
+===========================
+
+Highlights
+----------
+
+* [`rustc` translates code to LLVM IR via its own "middle" IR (MIR)]
+ (https://github.com/rust-lang/rust/pull/34096).
+ This translation pass is far simpler than the previous AST->LLVM pass, and
+ creates opportunities to perform new optimizations directly on the MIR. It
+ was previously described [on the Rust blog]
+ (https://blog.rust-lang.org/2016/04/19/MIR.html).
+* [`rustc` presents a new, more readable error format, along with
+ machine-readable JSON error output for use by IDEs]
+ (https://github.com/rust-lang/rust/pull/35401).
+ Most common editors supporting Rust have been updated to work with it. It was
+ previously described [on the Rust blog]
+ (https://blog.rust-lang.org/2016/08/10/Shape-of-errors-to-come.html).
+
+Compiler
+--------
+
+* [`rustc` translates code to LLVM IR via its own "middle" IR (MIR)]
+ (https://github.com/rust-lang/rust/pull/34096).
+ This translation pass is far simpler than the previous AST->LLVM pass, and
+ creates opportunities to perform new optimizations directly on the MIR. It
+ was previously described [on the Rust blog]
+ (https://blog.rust-lang.org/2016/04/19/MIR.html).
+* [Print the Rust target name, not the LLVM target name, with
+ `--print target-list`]
+ (https://github.com/rust-lang/rust/pull/35489)
+* [The computation of `TypeId` is correct in some cases where it was previously
+ producing inconsistent results]
+ (https://github.com/rust-lang/rust/pull/35267)
+* [The `mips-unknown-linux-gnu` target uses hardware floating point by default]
+ (https://github.com/rust-lang/rust/pull/34910)
+* [The `rustc` arguments, `--print target-cpus`, `--print target-features`,
+ `--print relocation-models`, and `--print code-models` print the available
+ options to the `-C target-cpu`, `-C target-feature`, `-C relocation-model` and
+ `-C code-model` code generation arguments]
+ (https://github.com/rust-lang/rust/pull/34845)
+* [`rustc` supports three new MUSL targets on ARM: `arm-unknown-linux-musleabi`,
+ `arm-unknown-linux-musleabihf`, and `armv7-unknown-linux-musleabihf`]
+ (https://github.com/rust-lang/rust/pull/35060).
+ These targets produce statically-linked binaries. There are no binary release
+ builds yet though.
+
+Diagnostics
+-----------
+
+* [`rustc` presents a new, more readable error format, along with
+ machine-readable JSON error output for use by IDEs]
+ (https://github.com/rust-lang/rust/pull/35401).
+ Most common editors supporting Rust have been updated to work with it. It was
+ previously described [on the Rust blog]
+ (https://blog.rust-lang.org/2016/08/10/Shape-of-errors-to-come.html).
+* [In error descriptions, references are now described in plain English,
+ instead of as "&-ptr"]
+ (https://github.com/rust-lang/rust/pull/35611)
+* [In error type descriptions, unknown numeric types are named `{integer}` or
+ `{float}` instead of `_`]
+ (https://github.com/rust-lang/rust/pull/35080)
+* [`rustc` emits a clearer error when inner attributes follow a doc comment]
+ (https://github.com/rust-lang/rust/pull/34676)
+
+Language
+--------
+
+* [`macro_rules!` invocations can be made within `macro_rules!` invocations]
+ (https://github.com/rust-lang/rust/pull/34925)
+* [`macro_rules!` meta-variables are hygienic]
+ (https://github.com/rust-lang/rust/pull/35453)
+* [`macro_rules!` `tt` matchers can be reparsed correctly, making them much more
+ useful]
+ (https://github.com/rust-lang/rust/pull/34908)
+* [`macro_rules!` `stmt` matchers correctly consume the entire contents when
+ inside non-braces invocations]
+ (https://github.com/rust-lang/rust/pull/34886)
+* [Semicolons are properly required as statement delimeters inside
+ `macro_rules!` invocations]
+ (https://github.com/rust-lang/rust/pull/34660)
+* [`cfg_attr` works on `path` attributes]
+ (https://github.com/rust-lang/rust/pull/34546)
+
+Stabilized APIs
+---------------
+
+* [`Cell::as_ptr`]
+ (https://doc.rust-lang.org/std/cell/struct.Cell.html#method.as_ptr)
+* [`RefCell::as_ptr`]
+ (https://doc.rust-lang.org/std/cell/struct.RefCell.html#method.as_ptr)
+* [`IpAddr::is_unspecified`]
+ (https://doc.rust-lang.org/std/net/enum.IpAddr.html#method.is_unspecified)
+* [`IpAddr::is_loopback`]
+ (https://doc.rust-lang.org/std/net/enum.IpAddr.html#method.is_loopback)
+* [`IpAddr::is_multicast`]
+ (https://doc.rust-lang.org/std/net/enum.IpAddr.html#method.is_multicast)
+* [`Ipv4Addr::is_unspecified`]
+ (https://doc.rust-lang.org/std/net/struct.Ipv4Addr.html#method.is_unspecified)
+* [`Ipv6Addr::octets`]
+ (https://doc.rust-lang.org/std/net/struct.Ipv6Addr.html#method.octets)
+* [`LinkedList::contains`]
+ (https://doc.rust-lang.org/std/collections/linked_list/struct.LinkedList.html#method.contains)
+* [`VecDeque::contains`]
+ (https://doc.rust-lang.org/std/collections/vec_deque/struct.VecDeque.html#method.contains)
+* [`ExitStatusExt::from_raw`]
+ (https://doc.rust-lang.org/std/os/unix/process/trait.ExitStatusExt.html#tymethod.from_raw).
+ Both on Unix and Windows.
+* [`Receiver::recv_timeout`]
+ (https://doc.rust-lang.org/std/sync/mpsc/struct.Receiver.html#method.recv_timeout)
+* [`RecvTimeoutError`]
+ (https://doc.rust-lang.org/std/sync/mpsc/enum.RecvTimeoutError.html)
+* [`BinaryHeap::peek_mut`]
+ (https://doc.rust-lang.org/std/collections/binary_heap/struct.BinaryHeap.html#method.peek_mut)
+* [`PeekMut`]
+ (https://doc.rust-lang.org/std/collections/binary_heap/struct.PeekMut.html)
+* [`iter::Product`]
+ (https://doc.rust-lang.org/std/iter/trait.Product.html)
+* [`iter::Sum`]
+ (https://doc.rust-lang.org/std/iter/trait.Sum.html)
+* [`OccupiedEntry::remove_entry`]
+ (https://doc.rust-lang.org/std/collections/btree_map/struct.OccupiedEntry.html#method.remove_entry)
+* [`VacantEntry::into_key`]
+ (https://doc.rust-lang.org/std/collections/btree_map/struct.VacantEntry.html#method.into_key)
+
+Libraries
+---------
+
+* [The `format!` macro and friends now allow a single argument to be formatted
+ in multiple styles]
+ (https://github.com/rust-lang/rust/pull/33642)
+* [The lifetime bounds on `[T]::binary_search_by` and
+ `[T]::binary_search_by_key` have been adjusted to be more flexible]
+ (https://github.com/rust-lang/rust/pull/34762)
+* [`Option` implements `From` for its contained type]
+ (https://github.com/rust-lang/rust/pull/34828)
+* [`Cell`, `RefCell` and `UnsafeCell` implement `From` for their contained type]
+ (https://github.com/rust-lang/rust/pull/35392)
+* [`RwLock` panics if the reader count overflows]
+ (https://github.com/rust-lang/rust/pull/35378)
+* [`vec_deque::Drain`, `hash_map::Drain` and `hash_set::Drain` are covariant]
+ (https://github.com/rust-lang/rust/pull/35354)
+* [`vec::Drain` and `binary_heap::Drain` are covariant]
+ (https://github.com/rust-lang/rust/pull/34951)
+* [`Cow` implements `FromIterator` for `char`, `&str` and `String`]
+ (https://github.com/rust-lang/rust/pull/35064)
+* [Sockets on Linux are correctly closed in subprocesses via `SOCK_CLOEXEC`]
+ (https://github.com/rust-lang/rust/pull/34946)
+* [`hash_map::Entry`, `hash_map::VacantEntry` and `hash_map::OccupiedEntry`
+ implement `Debug`]
+ (https://github.com/rust-lang/rust/pull/34937)
+* [`btree_map::Entry`, `btree_map::VacantEntry` and `btree_map::OccupiedEntry`
+ implement `Debug`]
+ (https://github.com/rust-lang/rust/pull/34885)
+* [`String` implements `AddAssign`]
+ (https://github.com/rust-lang/rust/pull/34890)
+* [Variadic `extern fn` pointers implement the `Clone`, `PartialEq`, `Eq`,
+ `PartialOrd`, `Ord`, `Hash`, `fmt::Pointer`, and `fmt::Debug` traits]
+ (https://github.com/rust-lang/rust/pull/34879)
+* [`FileType` implements `Debug`]
+ (https://github.com/rust-lang/rust/pull/34757)
+* [References to `Mutex` and `RwLock` are unwind-safe]
+ (https://github.com/rust-lang/rust/pull/34756)
+* [`mpsc::sync_channel` `Receiver`s return any available message before
+ reporting a disconnect]
+ (https://github.com/rust-lang/rust/pull/34731)
+* [Unicode definitions have been updated to 9.0]
+ (https://github.com/rust-lang/rust/pull/34599)
+* [`env` iterators implement `DoubleEndedIterator`]
+ (https://github.com/rust-lang/rust/pull/33312)
+
+Cargo
+-----
+
+* [Support local mirrors of registries]
+ (https://github.com/rust-lang/cargo/pull/2857)
+* [Add support for command aliases]
+ (https://github.com/rust-lang/cargo/pull/2679)
+* [Allow `opt-level="s"` / `opt-level="z"` in profile overrides]
+ (https://github.com/rust-lang/cargo/pull/3007)
+* [Make `cargo doc --open --target` work as expected]
+ (https://github.com/rust-lang/cargo/pull/2988)
+* [Speed up noop registry updates]
+ (https://github.com/rust-lang/cargo/pull/2974)
+* [Update OpenSSL]
+ (https://github.com/rust-lang/cargo/pull/2971)
+* [Fix `--panic=abort` with plugins]
+ (https://github.com/rust-lang/cargo/pull/2954)
+* [Always pass `-C metadata` to the compiler]
+ (https://github.com/rust-lang/cargo/pull/2946)
+* [Fix depending on git repos with workspaces]
+ (https://github.com/rust-lang/cargo/pull/2938)
+* [Add a `--lib` flag to `cargo new`]
+ (https://github.com/rust-lang/cargo/pull/2921)
+* [Add `http.cainfo` for custom certs]
+ (https://github.com/rust-lang/cargo/pull/2917)
+* [Indicate the compilation profile after compiling]
+ (https://github.com/rust-lang/cargo/pull/2909)
+* [Allow enabling features for dependencies with `--features`]
+ (https://github.com/rust-lang/cargo/pull/2876)
+* [Add `--jobs` flag to `cargo package`]
+ (https://github.com/rust-lang/cargo/pull/2867)
+* [Add `--dry-run` to `cargo publish`]
+ (https://github.com/rust-lang/cargo/pull/2849)
+* [Add support for `RUSTDOCFLAGS`]
+ (https://github.com/rust-lang/cargo/pull/2794)
+
+Performance
+-----------
+
+* [`panic::catch_unwind` is more optimized]
+ (https://github.com/rust-lang/rust/pull/35444)
+* [`panic::catch_unwind` no longer accesses thread-local storage on entry]
+ (https://github.com/rust-lang/rust/pull/34866)
+
+Tooling
+-------
+
+* [Test binaries now support a `--test-threads` argument to specify the number
+ of threads used to run tests, and which acts the same as the
+ `RUST_TEST_THREADS` environment variable]
+ (https://github.com/rust-lang/rust/pull/35414)
+* [The test runner now emits a warning when tests run over 60 seconds]
+ (https://github.com/rust-lang/rust/pull/35405)
+* [rustdoc: Fix methods in search results]
+ (https://github.com/rust-lang/rust/pull/34752)
+* [`rust-lldb` warns about unsupported versions of LLDB]
+ (https://github.com/rust-lang/rust/pull/34646)
+* [Rust releases now come with source packages that can be installed by rustup
+ via `rustup component add rust-src`]
+ (https://github.com/rust-lang/rust/pull/34366).
+ The resulting source code can be used by tools and IDES, located in the
+ sysroot under `lib/rustlib/src`.
+
+Misc
+----
+
+* [The compiler can now be built against LLVM 3.9]
+ (https://github.com/rust-lang/rust/pull/35594)
+* Many minor improvements to the documentation.
+* [The Rust exception handling "personality" routine is now written in Rust]
+ (https://github.com/rust-lang/rust/pull/34832)
+
+Compatibility Notes
+-------------------
+
+* [When printing Windows `OsStr`s, unpaired surrogate codepoints are escaped
+ with the lowercase format instead of the uppercase]
+ (https://github.com/rust-lang/rust/pull/35084)
+* [When formatting strings, if "precision" is specified, the "fill",
+ "align" and "width" specifiers are no longer ignored]
+ (https://github.com/rust-lang/rust/pull/34544)
+* [The `Debug` impl for strings no longer escapes all non-ASCII characters]
+ (https://github.com/rust-lang/rust/pull/34485)
+
+
Version 1.11.0 (2016-08-18)
===========================
@@ -629,7 +885,7 @@ Cargo
Performance
-----------
-* [The time complexity of comparing variables for equivalence during type
+* [The time complexity of comparing variables for equivalence during type
unification is reduced from _O_(_n_!) to _O_(_n_)][1.9tu]. This leads
to major compilation time improvement in some scenarios.
* [`ToString` is specialized for `str`, giving it the same performance
diff --git a/appveyor.yml b/appveyor.yml
new file mode 100644
index 0000000000000..686c48abb30cd
--- /dev/null
+++ b/appveyor.yml
@@ -0,0 +1,110 @@
+environment:
+ matrix:
+ # 32/64 bit MSVC
+ - MSYS_BITS: 64
+ TARGET: x86_64-pc-windows-msvc
+ CHECK: check
+ CONFIGURE_ARGS: --enable-llvm-assertions --enable-debug-assertions
+ - MSYS_BITS: 32
+ TARGET: i686-pc-windows-msvc
+ CHECK: check
+ CONFIGURE_ARGS: --enable-llvm-assertions --enable-debug-assertions
+
+ # MSVC rustbuild
+ - MSYS_BITS: 64
+ CONFIGURE_ARGS: --enable-rustbuild --enable-llvm-assertions --enable-debug-assertions
+ TARGET: x86_64-pc-windows-msvc
+ CHECK: check
+
+ # MSVC cargotest
+ - MSYS_BITS: 64
+ CONFIGURE_ARGS: --enable-rustbuild --enable-llvm-assertions --enable-debug-assertions
+ TARGET: x86_64-pc-windows-msvc
+ CHECK: check-cargotest
+
+ # 32/64-bit MinGW builds.
+ #
+ # The MinGW builds unfortunately have to both download a custom toolchain and
+ # avoid the one installed by AppVeyor by default. Interestingly, though, for
+ # different reasons!
+ #
+ # For 32-bit the installed gcc toolchain on AppVeyor uses the pthread
+ # threading model. This is unfortunately not what we want, and if we compile
+ # with it then there's lots of link errors in the standard library (undefined
+ # references to pthread symbols).
+ #
+ # For 64-bit the installed gcc toolchain is currently 5.3.0 which
+ # unfortunately segfaults on Windows with --enable-llvm-assertions (segfaults
+ # in LLVM). See rust-lang/rust#28445 for more information, but to work around
+ # this we go back in time to 4.9.2 specifically.
+ #
+ # Finally, note that the downloads below are all in the `rust-lang-ci` S3
+ # bucket, but they cleraly didn't originate there! The downloads originally
+ # came from the mingw-w64 SourceForge download site. Unfortunately
+ # SourceForge is notoriously flaky, so we mirror it on our own infrastructure.
+ #
+ # And as a final point of note, the 32-bit MinGW build using the makefiles do
+ # *not* use debug assertions and llvm assertions. This is because they take
+ # too long on appveyor and this is tested by rustbuild below.
+ - MSYS_BITS: 32
+ TARGET: i686-pc-windows-gnu
+ CHECK: check
+ MINGW_URL: https://s3.amazonaws.com/rust-lang-ci
+ MINGW_ARCHIVE: i686-4.9.2-release-win32-dwarf-rt_v4-rev4.7z
+ MINGW_DIR: mingw32
+
+ - MSYS_BITS: 32
+ CONFIGURE_ARGS: --enable-rustbuild --enable-llvm-assertions --enable-debug-assertions
+ TARGET: i686-pc-windows-gnu
+ CHECK: check
+ MINGW_URL: https://s3.amazonaws.com/rust-lang-ci
+ MINGW_ARCHIVE: i686-4.9.2-release-win32-dwarf-rt_v4-rev4.7z
+ MINGW_DIR: mingw32
+
+ - MSYS_BITS: 64
+ CONFIGURE_ARGS: --enable-llvm-assertions --enable-debug-assertions
+ TARGET: x86_64-pc-windows-gnu
+ CHECK: check
+ MINGW_URL: https://s3.amazonaws.com/rust-lang-ci
+ MINGW_ARCHIVE: x86_64-4.9.2-release-win32-seh-rt_v4-rev4.7z
+ MINGW_DIR: mingw64
+
+clone_depth: 1
+build: false
+
+install:
+ # If we need to download a custom MinGW, do so here and set the path
+ # appropriately.
+ #
+ # Note that this *also* means that we're not using what is typically
+ # /mingw32/bin/python2.7.exe, which is a "correct" python interpreter where
+ # /usr/bin/python2.7.exe is not. To ensure we use the right interpreter we
+ # move `C:\Python27` ahead in PATH and then also make sure the `python2.7.exe`
+ # file exists in there (which it doesn't by default).
+ - if defined MINGW_URL appveyor DownloadFile %MINGW_URL%/%MINGW_ARCHIVE%
+ - if defined MINGW_URL 7z x -y %MINGW_ARCHIVE% > nul
+ - if defined MINGW_URL set PATH=C:\Python27;%CD%\%MINGW_DIR%\bin;C:\msys64\usr\bin;%PATH%
+ - if defined MINGW_URL copy C:\Python27\python.exe C:\Python27\python2.7.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%
+
+test_script:
+ - sh ./configure
+ %CONFIGURE_ARGS%
+ --build=%TARGET%
+ - bash -c "make -j$(nproc)"
+ - bash -c "make %CHECK% -j$(nproc)"
+
+cache:
+ - build/%TARGET%/llvm -> src/rustllvm/llvm-auto-clean-trigger
+ - "%TARGET%/llvm -> src/rustllvm/llvm-auto-clean-trigger"
+
+branches:
+ only:
+ - auto
+
+# init:
+# - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
+# on_finish:
+# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
diff --git a/configure b/configure
index a8bd3acdff1ac..2bc8c72e3ea1c 100755
--- a/configure
+++ b/configure
@@ -437,6 +437,10 @@ case $CFG_OSTYPE in
CFG_CPUTYPE=$(isainfo -n)
;;
+ Haiku)
+ CFG_OSTYPE=unknown-haiku
+ ;;
+
MINGW*)
# msys' `uname` does not print gcc configuration, but prints msys
# configuration. so we cannot believe `uname -m`:
@@ -532,6 +536,10 @@ case $CFG_CPUTYPE in
CFG_CPUTYPE=x86_64
;;
+ BePC)
+ CFG_CPUTYPE=i686
+ ;;
+
*)
err "unknown CPU type: $CFG_CPUTYPE"
esac
@@ -628,6 +636,7 @@ opt_nosave optimize-llvm 1 "build optimized LLVM"
opt_nosave llvm-assertions 0 "build LLVM with assertions"
opt_nosave debug-assertions 0 "build with debugging assertions"
opt_nosave debuginfo 0 "build with debugger metadata"
+opt_nosave debuginfo-lines 0 "build with line number debugger metadata"
opt_nosave debug-jemalloc 0 "build jemalloc with --enable-debug --enable-fill"
valopt localstatedir "/var/lib" "local state directory"
@@ -637,7 +646,6 @@ valopt datadir "${CFG_PREFIX}/share" "install data"
valopt infodir "${CFG_PREFIX}/share/info" "install additional info"
valopt llvm-root "" "set LLVM root"
valopt python "" "set path to python"
-valopt nodejs "" "set path to nodejs"
valopt jemalloc-root "" "set directory where libjemalloc_pic.a is located"
valopt build "${DEFAULT_BUILD}" "GNUs ./configure syntax LLVM build triple"
valopt android-cross-path "" "Android NDK standalone path (deprecated)"
@@ -646,7 +654,12 @@ valopt arm-linux-androideabi-ndk "" "arm-linux-androideabi NDK standalone path"
valopt armv7-linux-androideabi-ndk "" "armv7-linux-androideabi NDK standalone path"
valopt aarch64-linux-android-ndk "" "aarch64-linux-android NDK standalone path"
valopt nacl-cross-path "" "NaCl SDK path (Pepper Canary is recommended). Must be absolute!"
-valopt musl-root "/usr/local" "MUSL root installation directory"
+valopt musl-root "/usr/local" "MUSL root installation directory (deprecated)"
+valopt musl-root-x86_64 "/usr/local" "x86_64-unknown-linux-musl install directory"
+valopt musl-root-i686 "/usr/local" "i686-unknown-linux-musl install directory"
+valopt musl-root-arm "/usr/local" "arm-unknown-linux-musleabi install directory"
+valopt musl-root-armhf "/usr/local" "arm-unknown-linux-musleabihf install directory"
+valopt musl-root-armv7 "/usr/local" "armv7-unknown-linux-musleabihf install directory"
valopt extra-filename "" "Additional data that is hashed and passed to the -C extra-filename flag"
if [ -e ${CFG_SRC_DIR}.git ]
@@ -676,7 +689,7 @@ valopt_nosave local-rust-root "/usr/local" "set prefix for local rust binary"
valopt_nosave host "${CFG_BUILD}" "GNUs ./configure syntax LLVM host triples"
valopt_nosave target "${CFG_HOST}" "GNUs ./configure syntax LLVM target triples"
valopt_nosave mandir "${CFG_PREFIX}/share/man" "install man pages in PATH"
-valopt_nosave docdir "${CFG_PREFIX}/share/doc/rust" "install man pages in PATH"
+valopt_nosave docdir "${CFG_PREFIX}/share/doc/rust" "install documentation in PATH"
# On Windows this determines root of the subtree for target libraries.
# Host runtime libs always go to 'bin'.
@@ -709,8 +722,27 @@ case "$CFG_RELEASE_CHANNEL" in
nightly )
msg "overriding settings for $CFG_RELEASE_CHANNEL"
CFG_ENABLE_LLVM_ASSERTIONS=1
+
+ # FIXME(#37364) shouldn't have to disable this on windows-gnu
+ case "$CFG_BUILD" in
+ *-pc-windows-gnu)
+ ;;
+ *)
+ CFG_ENABLE_DEBUGINFO_LINES=1
+ ;;
+ esac
+ ;;
+ beta | stable)
+ msg "overriding settings for $CFG_RELEASE_CHANNEL"
+ case "$CFG_BUILD" in
+ *-pc-windows-gnu)
+ ;;
+ *)
+ CFG_ENABLE_DEBUGINFO_LINES=1
+ ;;
+ esac
;;
- dev | beta | stable)
+ dev)
;;
*)
err "release channel must be 'dev', 'nightly', 'beta' or 'stable'"
@@ -740,6 +772,7 @@ if [ -n "$CFG_DISABLE_OPTIMIZE_LLVM" ]; then putvar CFG_DISABLE_OPTIMIZE_LLVM; f
if [ -n "$CFG_ENABLE_LLVM_ASSERTIONS" ]; then putvar CFG_ENABLE_LLVM_ASSERTIONS; fi
if [ -n "$CFG_ENABLE_DEBUG_ASSERTIONS" ]; then putvar CFG_ENABLE_DEBUG_ASSERTIONS; fi
if [ -n "$CFG_ENABLE_DEBUGINFO" ]; then putvar CFG_ENABLE_DEBUGINFO; fi
+if [ -n "$CFG_ENABLE_DEBUGINFO_LINES" ]; then putvar CFG_ENABLE_DEBUGINFO_LINES; fi
if [ -n "$CFG_ENABLE_DEBUG_JEMALLOC" ]; then putvar CFG_ENABLE_DEBUG_JEMALLOC; fi
step_msg "looking for build programs"
@@ -754,9 +787,6 @@ if [ $(echo $python_version | grep -c '^Python 2\.7') -ne 1 ]; then
err "Found $python_version, but Python 2.7 is required"
fi
-# Checking for node, but not required
-probe CFG_NODEJS nodejs node
-
# If we have no git directory then we are probably a tarball distribution
# and shouldn't attempt to load submodules
if [ ! -e ${CFG_SRC_DIR}.git ]
@@ -1208,14 +1238,6 @@ do
fi
;;
-
- x86_64-*-musl | arm-*-musleabi)
- if [ ! -f $CFG_MUSL_ROOT/lib/libc.a ]
- then
- err "musl libc $CFG_MUSL_ROOT/lib/libc.a not found"
- fi
- ;;
-
*-msvc)
# There are three builds of cmake on windows: MSVC, MinGW and Cygwin
# The Cygwin build does not have generators for Visual Studio, so
@@ -1634,8 +1656,8 @@ do
("ccache gcc")
LLVM_CXX_32="ccache"
LLVM_CC_32="ccache"
- LLVM_CXX_32_ARG1="clang++"
- LLVM_CC_32_ARG1="clang"
+ LLVM_CXX_32_ARG1="g++"
+ LLVM_CC_32_ARG1="gcc"
LLVM_CXX_64="ccache"
LLVM_CC_64="ccache"
@@ -1760,7 +1782,7 @@ do
CMAKE_ARGS="$CMAKE_ARGS -DLLVM_ENABLE_ASSERTIONS=ON"
fi
- CMAKE_ARGS="$CMAKE_ARGS -DLLVM_TARGETS_TO_BUILD='X86;ARM;AArch64;Mips;PowerPC;SystemZ'"
+ CMAKE_ARGS="$CMAKE_ARGS -DLLVM_TARGETS_TO_BUILD='X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend'"
CMAKE_ARGS="$CMAKE_ARGS -G '$CFG_CMAKE_GENERATOR'"
CMAKE_ARGS="$CMAKE_ARGS $CFG_LLVM_SRC_DIR"
diff --git a/mk/cfg/aarch64-unknown-fuchsia.mk b/mk/cfg/aarch64-unknown-fuchsia.mk
new file mode 100644
index 0000000000000..34aee77ae2107
--- /dev/null
+++ b/mk/cfg/aarch64-unknown-fuchsia.mk
@@ -0,0 +1 @@
+# rustbuild-only target
diff --git a/mk/cfg/i686-unknown-haiku.mk b/mk/cfg/i686-unknown-haiku.mk
new file mode 100644
index 0000000000000..cbacbff070e88
--- /dev/null
+++ b/mk/cfg/i686-unknown-haiku.mk
@@ -0,0 +1,27 @@
+# i686-unknown-haiku configuration
+CROSS_PREFIX_i686-unknown-haiku=i586-pc-haiku-
+CC_i686-unknown-haiku=$(CC)
+CXX_i686-unknown-haiku=$(CXX)
+CPP_i686-unknown-haiku=$(CPP)
+AR_i686-unknown-haiku=$(AR)
+CFG_LIB_NAME_i686-unknown-haiku=lib$(1).so
+CFG_STATIC_LIB_NAME_i686-unknown-haiku=lib$(1).a
+CFG_LIB_GLOB_i686-unknown-haiku=lib$(1)-*.so
+CFG_LIB_DSYM_GLOB_i686-unknown-haiku=lib$(1)-*.dylib.dSYM
+CFG_CFLAGS_i686-unknown-haiku := -m32 $(CFLAGS)
+CFG_GCCISH_CFLAGS_i686-unknown-haiku := -Wall -Werror -g -fPIC -m32 $(CFLAGS)
+CFG_GCCISH_CXXFLAGS_i686-unknown-haiku := -fno-rtti $(CXXFLAGS)
+CFG_GCCISH_LINK_FLAGS_i686-unknown-haiku := -shared -fPIC -ldl -pthread -lrt -g -m32
+CFG_GCCISH_PRE_LIB_FLAGS_i686-unknown-haiku := -Wl,-whole-archive
+CFG_GCCISH_POST_LIB_FLAGS_i686-unknown-haiku := -Wl,-no-whole-archive
+CFG_DEF_SUFFIX_i686-unknown-haiku := .linux.def
+CFG_LLC_FLAGS_i686-unknown-haiku :=
+CFG_INSTALL_NAME_i686-unknown-haiku =
+CFG_EXE_SUFFIX_i686-unknown-haiku =
+CFG_WINDOWSY_i686-unknown-haiku :=
+CFG_UNIXY_i686-unknown-haiku := 1
+CFG_PATH_MUNGE_i686-unknown-haiku := true
+CFG_LDPATH_i686-unknown-haiku :=
+CFG_RUN_i686-unknown-haiku=$(2)
+CFG_RUN_TARG_i686-unknown-haiku=$(call CFG_RUN_i686-unknown-haiku,,$(2))
+CFG_GNU_TRIPLE_i686-unknown-haiku := i686-unknown-haiku
diff --git a/mk/cfg/wasm32-unknown-emscripten.mk b/mk/cfg/wasm32-unknown-emscripten.mk
new file mode 100644
index 0000000000000..997bdfbf03ab1
--- /dev/null
+++ b/mk/cfg/wasm32-unknown-emscripten.mk
@@ -0,0 +1,24 @@
+# wasm32-unknown-emscripten configuration
+CC_wasm32-unknown-emscripten=emcc
+CXX_wasm32-unknown-emscripten=em++
+CPP_wasm32-unknown-emscripten=$(CPP)
+AR_wasm32-unknown-emscripten=emar
+CFG_LIB_NAME_wasm32-unknown-emscripten=lib$(1).so
+CFG_STATIC_LIB_NAME_wasm32-unknown-emscripten=lib$(1).a
+CFG_LIB_GLOB_wasm32-unknown-emscripten=lib$(1)-*.so
+CFG_LIB_DSYM_GLOB_wasm32-unknown-emscripten=lib$(1)-*.dylib.dSYM
+CFG_JEMALLOC_CFLAGS_wasm32-unknown-emscripten := -m32 $(CFLAGS)
+CFG_GCCISH_CFLAGS_wasm32-unknown-emscripten := -g -fPIC -m32 -s BINARYEN=1 $(CFLAGS)
+CFG_GCCISH_CXXFLAGS_wasm32-unknown-emscripten := -fno-rtti -s BINARYEN=1 $(CXXFLAGS)
+CFG_GCCISH_LINK_FLAGS_wasm32-unknown-emscripten := -shared -fPIC -ldl -pthread -lrt -g -m32 -s BINARYEN=1
+CFG_GCCISH_DEF_FLAG_wasm32-unknown-emscripten := -Wl,--export-dynamic,--dynamic-list=
+CFG_LLC_FLAGS_wasm32-unknown-emscripten :=
+CFG_INSTALL_NAME_wasm32-unknown-emscripten =
+CFG_EXE_SUFFIX_wasm32-unknown-emscripten =
+CFG_WINDOWSY_wasm32-unknown-emscripten :=
+CFG_UNIXY_wasm32-unknown-emscripten := 1
+CFG_LDPATH_wasm32-unknown-emscripten :=
+CFG_RUN_wasm32-unknown-emscripten=$(2)
+CFG_RUN_TARG_wasm32-unknown-emscripten=$(call CFG_RUN_wasm32-unknown-emscripten,,$(2))
+CFG_GNU_TRIPLE_wasm32-unknown-emscripten := wasm32-unknown-emscripten
+CFG_DISABLE_JEMALLOC_wasm32-unknown-emscripten := 1
diff --git a/mk/cfg/x86_64-unknown-fuchsia.mk b/mk/cfg/x86_64-unknown-fuchsia.mk
new file mode 100644
index 0000000000000..34aee77ae2107
--- /dev/null
+++ b/mk/cfg/x86_64-unknown-fuchsia.mk
@@ -0,0 +1 @@
+# rustbuild-only target
diff --git a/mk/cfg/x86_64-unknown-haiku.mk b/mk/cfg/x86_64-unknown-haiku.mk
new file mode 100644
index 0000000000000..4c2d888be06fb
--- /dev/null
+++ b/mk/cfg/x86_64-unknown-haiku.mk
@@ -0,0 +1,27 @@
+# x86_64-unknown-haiku configuration
+CROSS_PREFIX_x86_64-unknown-haiku=x86_64-unknown-haiku-
+CC_x86_64-unknown-haiku=$(CC)
+CXX_x86_64-unknown-haiku=$(CXX)
+CPP_x86_64-unknown-haiku=$(CPP)
+AR_x86_64-unknown-haiku=$(AR)
+CFG_LIB_NAME_x86_64-unknown-haiku=lib$(1).so
+CFG_STATIC_LIB_NAME_x86_64-unknown-haiku=lib$(1).a
+CFG_LIB_GLOB_x86_64-unknown-haiku=lib$(1)-*.so
+CFG_LIB_DSYM_GLOB_x86_64-unknown-haiku=lib$(1)-*.dylib.dSYM
+CFG_CFLAGS_x86_64-unknown-haiku := -m64 $(CFLAGS)
+CFG_GCCISH_CFLAGS_x86_64-unknown-haiku := -Wall -Werror -g -fPIC -m64 $(CFLAGS)
+CFG_GCCISH_CXXFLAGS_x86_64-unknown-haiku := -fno-rtti $(CXXFLAGS)
+CFG_GCCISH_LINK_FLAGS_x86_64-unknown-haiku := -shared -fPIC -ldl -pthread -lrt -g -m64
+CFG_GCCISH_PRE_LIB_FLAGS_x86_64-unknown-haiku := -Wl,-whole-archive
+CFG_GCCISH_POST_LIB_FLAGS_x86_64-unknown-haiku := -Wl,-no-whole-archive
+CFG_DEF_SUFFIX_x86_64-unknown-haiku := .linux.def
+CFG_LLC_FLAGS_x86_64-unknown-haiku :=
+CFG_INSTALL_NAME_x86_64-unknown-haiku =
+CFG_EXE_SUFFIX_x86_64-unknown-haiku =
+CFG_WINDOWSY_x86_64-unknown-haiku :=
+CFG_UNIXY_x86_64-unknown-haiku := 1
+CFG_PATH_MUNGE_x86_64-unknown-haiku := true
+CFG_LDPATH_x86_64-unknown-haiku :=
+CFG_RUN_x86_64-unknown-haiku=$(2)
+CFG_RUN_TARG_x86_64-unknown-haiku=$(call CFG_RUN_x86_64-unknown-haiku,,$(2))
+CFG_GNU_TRIPLE_x86_64-unknown-haiku := x86_64-unknown-haiku
diff --git a/mk/crates.mk b/mk/crates.mk
index d2c79441d866f..25192bfd27a44 100644
--- a/mk/crates.mk
+++ b/mk/crates.mk
@@ -59,9 +59,9 @@ RUSTC_CRATES := rustc rustc_typeck rustc_mir rustc_borrowck rustc_resolve rustc_
rustc_trans rustc_back rustc_llvm rustc_privacy rustc_lint \
rustc_data_structures rustc_platform_intrinsics rustc_errors \
rustc_plugin rustc_metadata rustc_passes rustc_save_analysis \
- rustc_const_eval rustc_const_math rustc_incremental rustc_macro
-HOST_CRATES := syntax syntax_ext proc_macro syntax_pos $(RUSTC_CRATES) rustdoc fmt_macros \
- flate arena graphviz rbml log serialize
+ rustc_const_eval rustc_const_math rustc_incremental proc_macro
+HOST_CRATES := syntax syntax_ext proc_macro_tokens proc_macro_plugin syntax_pos $(RUSTC_CRATES) \
+ rustdoc fmt_macros flate arena graphviz log serialize
TOOLS := compiletest rustdoc rustc rustbook error_index_generator
DEPS_core :=
@@ -96,21 +96,21 @@ DEPS_getopts := std
DEPS_graphviz := std
DEPS_log := std
DEPS_num := std
-DEPS_rbml := std log serialize
DEPS_serialize := std log
DEPS_term := std
DEPS_test := std getopts term native:rust_test_helpers
DEPS_syntax := std term serialize log arena libc rustc_bitflags rustc_unicode rustc_errors syntax_pos
-DEPS_syntax_ext := syntax syntax_pos rustc_errors fmt_macros rustc_macro
-DEPS_proc_macro := syntax syntax_pos rustc_plugin log
+DEPS_syntax_ext := syntax syntax_pos rustc_errors fmt_macros proc_macro
DEPS_syntax_pos := serialize
+DEPS_proc_macro_tokens := syntax syntax_pos log
+DEPS_proc_macro_plugin := syntax syntax_pos rustc_plugin log proc_macro_tokens
DEPS_rustc_const_math := std syntax log serialize
DEPS_rustc_const_eval := rustc_const_math rustc syntax log serialize \
rustc_back graphviz syntax_pos
-DEPS_rustc := syntax fmt_macros flate arena serialize getopts rbml \
+DEPS_rustc := syntax fmt_macros flate arena serialize getopts \
log graphviz rustc_llvm rustc_back rustc_data_structures\
rustc_const_math syntax_pos rustc_errors
DEPS_rustc_back := std syntax flate log libc
@@ -119,15 +119,15 @@ DEPS_rustc_data_structures := std log serialize libc
DEPS_rustc_driver := arena flate getopts graphviz libc rustc rustc_back rustc_borrowck \
rustc_typeck rustc_mir rustc_resolve log syntax serialize rustc_llvm \
rustc_trans rustc_privacy rustc_lint rustc_plugin \
- rustc_metadata syntax_ext proc_macro \
+ rustc_metadata syntax_ext proc_macro_plugin \
rustc_passes rustc_save_analysis rustc_const_eval \
- rustc_incremental syntax_pos rustc_errors rustc_macro
+ rustc_incremental syntax_pos rustc_errors proc_macro rustc_data_structures
DEPS_rustc_errors := log libc serialize syntax_pos
DEPS_rustc_lint := rustc log syntax syntax_pos rustc_const_eval
DEPS_rustc_llvm := native:rustllvm libc std rustc_bitflags
-DEPS_rustc_macro := std syntax
-DEPS_rustc_metadata := rustc syntax syntax_pos rustc_errors rbml rustc_const_math \
- rustc_macro syntax_ext
+DEPS_proc_macro := std syntax
+DEPS_rustc_metadata := rustc syntax syntax_pos rustc_errors rustc_const_math \
+ proc_macro syntax_ext
DEPS_rustc_passes := syntax syntax_pos rustc core rustc_const_eval rustc_errors
DEPS_rustc_mir := rustc syntax syntax_pos rustc_const_math rustc_const_eval rustc_bitflags
DEPS_rustc_resolve := arena rustc log syntax syntax_pos rustc_errors
@@ -137,7 +137,7 @@ DEPS_rustc_privacy := rustc log syntax syntax_pos
DEPS_rustc_trans := arena flate getopts graphviz libc rustc rustc_back \
log syntax serialize rustc_llvm rustc_platform_intrinsics \
rustc_const_math rustc_const_eval rustc_incremental rustc_errors syntax_pos
-DEPS_rustc_incremental := rbml rustc syntax_pos serialize rustc_data_structures
+DEPS_rustc_incremental := rustc syntax_pos serialize rustc_data_structures
DEPS_rustc_save_analysis := rustc log syntax syntax_pos serialize
DEPS_rustc_typeck := rustc syntax syntax_pos rustc_platform_intrinsics rustc_const_math \
rustc_const_eval rustc_errors
diff --git a/mk/llvm.mk b/mk/llvm.mk
index d6f812049e03c..5a91f5fcaa483 100644
--- a/mk/llvm.mk
+++ b/mk/llvm.mk
@@ -36,22 +36,27 @@ endif
# If CFG_LLVM_ROOT is defined then we don't build LLVM ourselves
ifeq ($(CFG_LLVM_ROOT),)
-LLVM_STAMP_$(1) = $$(CFG_LLVM_BUILD_DIR_$(1))/llvm-auto-clean-stamp
+LLVM_STAMP_$(1) = $(S)src/rustllvm/llvm-auto-clean-trigger
LLVM_DONE_$(1) = $$(CFG_LLVM_BUILD_DIR_$(1))/llvm-finished-building
$$(LLVM_CONFIG_$(1)): $$(LLVM_DONE_$(1))
-$$(LLVM_DONE_$(1)): $$(LLVM_DEPS_TARGET_$(1)) $$(LLVM_STAMP_$(1))
- @$$(call E, cmake: llvm)
ifneq ($$(CFG_NINJA),)
- $$(Q)$$(CFG_NINJA) -C $$(CFG_LLVM_BUILD_DIR_$(1))
+BUILD_LLVM_$(1) := $$(CFG_NINJA) -C $$(CFG_LLVM_BUILD_DIR_$(1))
else ifeq ($$(findstring msvc,$(1)),msvc)
- $$(Q)$$(CFG_CMAKE) --build $$(CFG_LLVM_BUILD_DIR_$(1)) \
- --config $$(LLVM_BUILD_CONFIG_MODE)
+BUILD_LLVM_$(1) := $$(CFG_CMAKE) --build $$(CFG_LLVM_BUILD_DIR_$(1)) \
+ --config $$(LLVM_BUILD_CONFIG_MODE)
else
- $$(Q)$$(MAKE) -C $$(CFG_LLVM_BUILD_DIR_$(1))
+BUILD_LLVM_$(1) := $$(MAKE) -C $$(CFG_LLVM_BUILD_DIR_$(1))
endif
- $$(Q)touch $$@
+
+$$(LLVM_DONE_$(1)): $$(LLVM_DEPS_TARGET_$(1)) $$(LLVM_STAMP_$(1))
+ @$$(call E, cmake: llvm)
+ $$(Q)if ! cmp $$(LLVM_STAMP_$(1)) $$(LLVM_DONE_$(1)); then \
+ $$(MAKE) clean-llvm$(1); \
+ $$(BUILD_LLVM_$(1)); \
+ fi
+ $$(Q)cp $$(LLVM_STAMP_$(1)) $$@
ifneq ($$(CFG_NINJA),)
clean-llvm$(1):
@@ -75,17 +80,6 @@ endif
$$(LLVM_AR_$(1)): $$(LLVM_CONFIG_$(1))
-# This is used to independently force an LLVM clean rebuild
-# when we changed something not otherwise captured by builtin
-# dependencies. In these cases, commit a change that touches
-# the stamp in the source dir.
-$$(LLVM_STAMP_$(1)): $$(S)src/rustllvm/llvm-auto-clean-trigger
- @$$(call E, make: cleaning llvm)
- $$(Q)touch $$@.start_time
- $$(Q)$$(MAKE) clean-llvm$(1)
- @$$(call E, make: done cleaning llvm)
- touch -r $$@.start_time $$@ && rm $$@.start_time
-
ifeq ($$(CFG_ENABLE_LLVM_STATIC_STDCPP),1)
LLVM_STDCPP_RUSTFLAGS_$(1) = -L "$$(dir $$(shell $$(CC_$(1)) $$(CFG_GCCISH_CFLAGS_$(1)) \
-print-file-name=lib$(CFG_STDCPP_NAME).a))"
diff --git a/mk/main.mk b/mk/main.mk
index 275dbb55d7483..a5e3764122003 100644
--- a/mk/main.mk
+++ b/mk/main.mk
@@ -13,7 +13,7 @@
######################################################################
# The version number
-CFG_RELEASE_NUM=1.13.0
+CFG_RELEASE_NUM=1.14.0
# An optional number to put after the label, e.g. '.2' -> '-beta.2'
# NB Make sure it starts with a dot to conform to semver pre-release
@@ -53,34 +53,16 @@ endif
# versions in the same place
CFG_FILENAME_EXTRA=$(shell printf '%s' $(CFG_RELEASE)$(CFG_EXTRA_FILENAME) | $(CFG_HASH_COMMAND))
-# A magic value that allows the compiler to use unstable features during the
-# bootstrap even when doing so would normally be an error because of feature
-# staging or because the build turns on warnings-as-errors and unstable features
-# default to warnings. The build has to match this key in an env var.
-#
-# This value is keyed off the release to ensure that all compilers for one
-# particular release have the same bootstrap key. Note that this is
-# intentionally not "secure" by any definition, this is largely just a deterrent
-# from users enabling unstable features on the stable compiler.
-CFG_BOOTSTRAP_KEY=$(CFG_FILENAME_EXTRA)
-
-# If local-rust is the same as the current version, then force a local-rebuild
+# If local-rust is the same major.minor as the current version, then force a local-rebuild
ifdef CFG_ENABLE_LOCAL_RUST
-ifeq ($(CFG_RELEASE),\
- $(shell $(S)src/etc/local_stage0.sh --print-rustc-release $(CFG_LOCAL_RUST_ROOT)))
- CFG_INFO := $(info cfg: auto-detected local-rebuild $(CFG_RELEASE))
+SEMVER_PREFIX=$(shell echo $(CFG_RELEASE_NUM) | grep -E -o '^[[:digit:]]+\.[[:digit:]]+')
+LOCAL_RELEASE=$(shell $(S)src/etc/local_stage0.sh --print-rustc-release $(CFG_LOCAL_RUST_ROOT))
+ifneq (,$(filter $(SEMVER_PREFIX).%,$(LOCAL_RELEASE)))
+ CFG_INFO := $(info cfg: auto-detected local-rebuild using $(LOCAL_RELEASE))
CFG_ENABLE_LOCAL_REBUILD = 1
endif
endif
-# The stage0 compiler needs to use the previous key recorded in src/stage0.txt,
-# except for local-rebuild when it just uses the same current key.
-ifdef CFG_ENABLE_LOCAL_REBUILD
-CFG_BOOTSTRAP_KEY_STAGE0=$(CFG_BOOTSTRAP_KEY)
-else
-CFG_BOOTSTRAP_KEY_STAGE0=$(shell sed -ne 's/^rustc_key: //p' $(S)src/stage0.txt)
-endif
-
# The name of the package to use for creating tarballs, installers etc.
CFG_PACKAGE_NAME=rustc-$(CFG_PACKAGE_VERS)
@@ -160,6 +142,9 @@ endif
ifdef CFG_ENABLE_DEBUGINFO
$(info cfg: enabling debuginfo (CFG_ENABLE_DEBUGINFO))
CFG_RUSTC_FLAGS += -g
+else ifdef CFG_ENABLE_DEBUGINFO_LINES
+ $(info cfg: enabling line number debuginfo (CFG_ENABLE_DEBUGINFO_LINES))
+ CFG_RUSTC_FLAGS += -Cdebuginfo=1
endif
ifdef SAVE_TEMPS
@@ -300,7 +285,7 @@ endif
# LLVM macros
######################################################################
-LLVM_OPTIONAL_COMPONENTS=x86 arm aarch64 mips powerpc pnacl systemz
+LLVM_OPTIONAL_COMPONENTS=x86 arm aarch64 mips powerpc pnacl systemz jsbackend
LLVM_REQUIRED_COMPONENTS=ipo bitreader bitwriter linker asmparser mcjit \
interpreter instrumentation
@@ -387,13 +372,16 @@ CFG_INFO := $(info cfg: disabling unstable features (CFG_DISABLE_UNSTABLE_FEATUR
# Turn on feature-staging
export CFG_DISABLE_UNSTABLE_FEATURES
# Subvert unstable feature lints to do the self-build
-export RUSTC_BOOTSTRAP_KEY:=$(CFG_BOOTSTRAP_KEY)
+export RUSTC_BOOTSTRAP
endif
-export CFG_BOOTSTRAP_KEY
ifdef CFG_MUSL_ROOT
export CFG_MUSL_ROOT
endif
+# FIXME: Transitionary measure to bootstrap using the old bootstrap logic.
+# Remove this once the bootstrap compiler uses the new login in Issue #36548.
+export RUSTC_BOOTSTRAP_KEY=62b3e239
+
######################################################################
# Per-stage targets and runner
######################################################################
@@ -512,10 +500,14 @@ ifeq ($$(OSTYPE_$(3)),apple-darwin)
else
ifeq ($$(CFG_WINDOWSY_$(3)),1)
LD_LIBRARY_PATH_ENV_NAME$(1)_T_$(2)_H_$(3) := PATH
+else
+ifeq ($$(OSTYPE_$(3)),unknown-haiku)
+ LD_LIBRARY_PATH_ENV_NAME$(1)_T_$(2)_H_$(3) := LIBRARY_PATH
else
LD_LIBRARY_PATH_ENV_NAME$(1)_T_$(2)_H_$(3) := LD_LIBRARY_PATH
endif
endif
+endif
LD_LIBRARY_PATH_ENV_HOSTDIR$(1)_T_$(2)_H_$(3) := \
$$(CURDIR)/$$(HLIB$(1)_H_$(3)):$$(CFG_LLVM_INST_DIR_$(3))/lib
@@ -633,7 +625,8 @@ ALL_TARGET_RULES = $(foreach target,$(CFG_TARGET), \
$(foreach host,$(CFG_HOST), \
all-target-$(target)-host-$(host)))
-all: $(ALL_TARGET_RULES) $(GENERATED) docs
+all-no-docs: $(ALL_TARGET_RULES) $(GENERATED)
+all: all-no-docs docs
######################################################################
# Build system documentation
diff --git a/mk/target.mk b/mk/target.mk
index 2a08b7b046534..1b139909ab458 100644
--- a/mk/target.mk
+++ b/mk/target.mk
@@ -42,23 +42,6 @@ $(foreach host,$(CFG_HOST), \
$(foreach crate,$(CRATES), \
$(eval $(call RUST_CRATE_FULLDEPS,$(stage),$(target),$(host),$(crate)))))))
-# $(1) stage
-# $(2) target
-# $(3) host
-define DEFINE_BOOTSTRAP_KEY
-BOOTSTRAP_KEY$(1)_T_$(2)_H_$(3) := $$(CFG_BOOTSTRAP_KEY)
-ifeq ($(1),0)
-ifeq ($(3),$$(CFG_BUILD))
-BOOTSTRAP_KEY$(1)_T_$(2)_H_$(3) := $$(CFG_BOOTSTRAP_KEY_STAGE0)
-endif
-endif
-endef
-
-$(foreach host,$(CFG_TARGET), \
- $(foreach target,$(CFG_TARGET), \
- $(foreach stage,$(STAGES), \
- $(eval $(call DEFINE_BOOTSTRAP_KEY,$(stage),$(target),$(host))))))
-
# RUST_TARGET_STAGE_N template: This defines how target artifacts are built
# for all stage/target architecture combinations. This is one giant rule which
# works as follows:
@@ -83,8 +66,6 @@ $(foreach host,$(CFG_TARGET), \
define RUST_TARGET_STAGE_N
$$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$(4): CFG_COMPILER_HOST_TRIPLE = $(2)
-$$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$(4): \
- export RUSTC_BOOTSTRAP_KEY := $$(BOOTSTRAP_KEY$(1)_T_$(2)_H_$(3))
$$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$(4): \
$$(CRATEFILE_$(4)) \
$$(CRATE_FULLDEPS_$(1)_T_$(2)_H_$(3)_$(4)) \
@@ -132,8 +113,6 @@ endef
# $(4) - name of the tool being built
define TARGET_TOOL
-$$(TBIN$(1)_T_$(2)_H_$(3))/$(4)$$(X_$(2)): \
- export RUSTC_BOOTSTRAP_KEY := $$(BOOTSTRAP_KEY$(1)_T_$(2)_H_$(3))
$$(TBIN$(1)_T_$(2)_H_$(3))/$(4)$$(X_$(2)): \
$$(TOOL_SOURCE_$(4)) \
$$(TOOL_INPUTS_$(4)) \
diff --git a/mk/tests.mk b/mk/tests.mk
index c135aa9b8fb95..1957c989eb0d4 100644
--- a/mk/tests.mk
+++ b/mk/tests.mk
@@ -27,7 +27,7 @@ TEST_TARGET_CRATES = $(filter-out core rustc_unicode alloc_system libc \
panic_abort,$(TARGET_CRATES)) \
collectionstest coretest
TEST_DOC_CRATES = $(DOC_CRATES) arena flate fmt_macros getopts graphviz \
- log rand rbml serialize syntax term test
+ log rand serialize syntax term test
TEST_HOST_CRATES = $(filter-out rustc_typeck rustc_borrowck rustc_resolve \
rustc_trans rustc_lint,\
$(HOST_CRATES))
@@ -632,6 +632,7 @@ endif
# is a separate choice from whether to pass `-g` when building the
# compiler and standard library themselves.
CTEST_RUSTC_FLAGS := $$(subst -g,,$$(CTEST_RUSTC_FLAGS))
+CTEST_RUSTC_FLAGS := $$(subst -Cdebuginfo=1,,$$(CTEST_RUSTC_FLAGS))
ifdef CFG_ENABLE_DEBUGINFO_TESTS
CTEST_RUSTC_FLAGS += -g
endif
diff --git a/src/Cargo.lock b/src/Cargo.lock
new file mode 100644
index 0000000000000..5826995cc3cfc
--- /dev/null
+++ b/src/Cargo.lock
@@ -0,0 +1,765 @@
+[root]
+name = "unwind"
+version = "0.0.0"
+dependencies = [
+ "core 0.0.0",
+ "libc 0.0.0",
+]
+
+[[package]]
+name = "alloc"
+version = "0.0.0"
+dependencies = [
+ "core 0.0.0",
+]
+
+[[package]]
+name = "alloc_jemalloc"
+version = "0.0.0"
+dependencies = [
+ "build_helper 0.1.0",
+ "core 0.0.0",
+ "gcc 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.0.0",
+]
+
+[[package]]
+name = "alloc_system"
+version = "0.0.0"
+dependencies = [
+ "core 0.0.0",
+ "libc 0.0.0",
+]
+
+[[package]]
+name = "arena"
+version = "0.0.0"
+
+[[package]]
+name = "bootstrap"
+version = "0.0.0"
+dependencies = [
+ "build_helper 0.1.0",
+ "cmake 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.38 (git+https://github.com/alexcrichton/gcc-rs)",
+ "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "md5 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num_cpus 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "build_helper"
+version = "0.1.0"
+
+[[package]]
+name = "cargotest"
+version = "0.1.0"
+
+[[package]]
+name = "cmake"
+version = "0.1.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "gcc 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "collections"
+version = "0.0.0"
+dependencies = [
+ "alloc 0.0.0",
+ "core 0.0.0",
+ "rustc_unicode 0.0.0",
+]
+
+[[package]]
+name = "compiler_builtins"
+version = "0.0.0"
+dependencies = [
+ "core 0.0.0",
+ "gcc 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "compiletest"
+version = "0.0.0"
+dependencies = [
+ "env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serialize 0.0.0",
+]
+
+[[package]]
+name = "core"
+version = "0.0.0"
+
+[[package]]
+name = "env_logger"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "error_index_generator"
+version = "0.0.0"
+
+[[package]]
+name = "filetime"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "flate"
+version = "0.0.0"
+dependencies = [
+ "build_helper 0.1.0",
+ "gcc 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "fmt_macros"
+version = "0.0.0"
+
+[[package]]
+name = "gcc"
+version = "0.3.38"
+source = "git+https://github.com/alexcrichton/gcc-rs#be620ac6d3ddb498cd0c700d5312c6a4c3c19597"
+
+[[package]]
+name = "gcc"
+version = "0.3.38"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "getopts"
+version = "0.0.0"
+
+[[package]]
+name = "getopts"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "graphviz"
+version = "0.0.0"
+
+[[package]]
+name = "idna"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "matches 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-bidi 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-normalization 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "kernel32-sys"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "libc"
+version = "0.0.0"
+dependencies = [
+ "core 0.0.0",
+]
+
+[[package]]
+name = "libc"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "linkchecker"
+version = "0.1.0"
+dependencies = [
+ "url 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "log"
+version = "0.0.0"
+
+[[package]]
+name = "log"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "matches"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "md5"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "num_cpus"
+version = "0.2.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "panic_abort"
+version = "0.0.0"
+dependencies = [
+ "core 0.0.0",
+ "libc 0.0.0",
+]
+
+[[package]]
+name = "panic_unwind"
+version = "0.0.0"
+dependencies = [
+ "alloc 0.0.0",
+ "core 0.0.0",
+ "libc 0.0.0",
+ "unwind 0.0.0",
+]
+
+[[package]]
+name = "proc_macro"
+version = "0.0.0"
+dependencies = [
+ "syntax 0.0.0",
+]
+
+[[package]]
+name = "proc_macro_plugin"
+version = "0.0.0"
+dependencies = [
+ "log 0.0.0",
+ "proc_macro_tokens 0.0.0",
+ "rustc_plugin 0.0.0",
+ "syntax 0.0.0",
+ "syntax_pos 0.0.0",
+]
+
+[[package]]
+name = "proc_macro_tokens"
+version = "0.0.0"
+dependencies = [
+ "log 0.0.0",
+ "syntax 0.0.0",
+ "syntax_pos 0.0.0",
+]
+
+[[package]]
+name = "rand"
+version = "0.0.0"
+dependencies = [
+ "core 0.0.0",
+]
+
+[[package]]
+name = "rustbook"
+version = "0.0.0"
+
+[[package]]
+name = "rustc"
+version = "0.0.0"
+dependencies = [
+ "arena 0.0.0",
+ "flate 0.0.0",
+ "fmt_macros 0.0.0",
+ "graphviz 0.0.0",
+ "log 0.0.0",
+ "rustc_back 0.0.0",
+ "rustc_bitflags 0.0.0",
+ "rustc_const_math 0.0.0",
+ "rustc_data_structures 0.0.0",
+ "rustc_errors 0.0.0",
+ "rustc_llvm 0.0.0",
+ "serialize 0.0.0",
+ "syntax 0.0.0",
+ "syntax_pos 0.0.0",
+]
+
+[[package]]
+name = "rustc-main"
+version = "0.0.0"
+dependencies = [
+ "rustc_back 0.0.0",
+ "rustc_driver 0.0.0",
+ "rustdoc 0.0.0",
+]
+
+[[package]]
+name = "rustc-serialize"
+version = "0.3.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "rustc_back"
+version = "0.0.0"
+dependencies = [
+ "log 0.0.0",
+ "serialize 0.0.0",
+ "syntax 0.0.0",
+]
+
+[[package]]
+name = "rustc_bitflags"
+version = "0.0.0"
+
+[[package]]
+name = "rustc_borrowck"
+version = "0.0.0"
+dependencies = [
+ "graphviz 0.0.0",
+ "log 0.0.0",
+ "rustc 0.0.0",
+ "rustc_data_structures 0.0.0",
+ "rustc_errors 0.0.0",
+ "rustc_mir 0.0.0",
+ "syntax 0.0.0",
+ "syntax_pos 0.0.0",
+]
+
+[[package]]
+name = "rustc_const_eval"
+version = "0.0.0"
+dependencies = [
+ "arena 0.0.0",
+ "graphviz 0.0.0",
+ "log 0.0.0",
+ "rustc 0.0.0",
+ "rustc_back 0.0.0",
+ "rustc_const_math 0.0.0",
+ "rustc_data_structures 0.0.0",
+ "rustc_errors 0.0.0",
+ "serialize 0.0.0",
+ "syntax 0.0.0",
+ "syntax_pos 0.0.0",
+]
+
+[[package]]
+name = "rustc_const_math"
+version = "0.0.0"
+dependencies = [
+ "log 0.0.0",
+ "serialize 0.0.0",
+ "syntax 0.0.0",
+]
+
+[[package]]
+name = "rustc_data_structures"
+version = "0.0.0"
+dependencies = [
+ "log 0.0.0",
+ "serialize 0.0.0",
+]
+
+[[package]]
+name = "rustc_driver"
+version = "0.0.0"
+dependencies = [
+ "arena 0.0.0",
+ "flate 0.0.0",
+ "graphviz 0.0.0",
+ "log 0.0.0",
+ "proc_macro_plugin 0.0.0",
+ "rustc 0.0.0",
+ "rustc_back 0.0.0",
+ "rustc_borrowck 0.0.0",
+ "rustc_const_eval 0.0.0",
+ "rustc_data_structures 0.0.0",
+ "rustc_errors 0.0.0",
+ "rustc_incremental 0.0.0",
+ "rustc_lint 0.0.0",
+ "rustc_llvm 0.0.0",
+ "rustc_metadata 0.0.0",
+ "rustc_mir 0.0.0",
+ "rustc_passes 0.0.0",
+ "rustc_plugin 0.0.0",
+ "rustc_privacy 0.0.0",
+ "rustc_resolve 0.0.0",
+ "rustc_save_analysis 0.0.0",
+ "rustc_trans 0.0.0",
+ "rustc_typeck 0.0.0",
+ "serialize 0.0.0",
+ "syntax 0.0.0",
+ "syntax_ext 0.0.0",
+ "syntax_pos 0.0.0",
+]
+
+[[package]]
+name = "rustc_errors"
+version = "0.0.0"
+dependencies = [
+ "log 0.0.0",
+ "serialize 0.0.0",
+ "syntax_pos 0.0.0",
+]
+
+[[package]]
+name = "rustc_incremental"
+version = "0.0.0"
+dependencies = [
+ "graphviz 0.0.0",
+ "log 0.0.0",
+ "rustc 0.0.0",
+ "rustc_data_structures 0.0.0",
+ "serialize 0.0.0",
+ "syntax 0.0.0",
+ "syntax_pos 0.0.0",
+]
+
+[[package]]
+name = "rustc_lint"
+version = "0.0.0"
+dependencies = [
+ "log 0.0.0",
+ "rustc 0.0.0",
+ "rustc_back 0.0.0",
+ "rustc_const_eval 0.0.0",
+ "syntax 0.0.0",
+ "syntax_pos 0.0.0",
+]
+
+[[package]]
+name = "rustc_llvm"
+version = "0.0.0"
+dependencies = [
+ "build_helper 0.1.0",
+ "gcc 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc_bitflags 0.0.0",
+]
+
+[[package]]
+name = "rustc_metadata"
+version = "0.0.0"
+dependencies = [
+ "flate 0.0.0",
+ "log 0.0.0",
+ "proc_macro 0.0.0",
+ "rustc 0.0.0",
+ "rustc_back 0.0.0",
+ "rustc_const_math 0.0.0",
+ "rustc_data_structures 0.0.0",
+ "rustc_errors 0.0.0",
+ "rustc_llvm 0.0.0",
+ "serialize 0.0.0",
+ "syntax 0.0.0",
+ "syntax_ext 0.0.0",
+ "syntax_pos 0.0.0",
+]
+
+[[package]]
+name = "rustc_mir"
+version = "0.0.0"
+dependencies = [
+ "graphviz 0.0.0",
+ "log 0.0.0",
+ "rustc 0.0.0",
+ "rustc_back 0.0.0",
+ "rustc_bitflags 0.0.0",
+ "rustc_const_eval 0.0.0",
+ "rustc_const_math 0.0.0",
+ "rustc_data_structures 0.0.0",
+ "syntax 0.0.0",
+ "syntax_pos 0.0.0",
+]
+
+[[package]]
+name = "rustc_passes"
+version = "0.0.0"
+dependencies = [
+ "log 0.0.0",
+ "rustc 0.0.0",
+ "rustc_const_eval 0.0.0",
+ "rustc_const_math 0.0.0",
+ "rustc_errors 0.0.0",
+ "syntax 0.0.0",
+ "syntax_pos 0.0.0",
+]
+
+[[package]]
+name = "rustc_platform_intrinsics"
+version = "0.0.0"
+
+[[package]]
+name = "rustc_plugin"
+version = "0.0.0"
+dependencies = [
+ "log 0.0.0",
+ "rustc 0.0.0",
+ "rustc_back 0.0.0",
+ "rustc_bitflags 0.0.0",
+ "rustc_errors 0.0.0",
+ "rustc_metadata 0.0.0",
+ "syntax 0.0.0",
+ "syntax_pos 0.0.0",
+]
+
+[[package]]
+name = "rustc_privacy"
+version = "0.0.0"
+dependencies = [
+ "rustc 0.0.0",
+ "syntax 0.0.0",
+ "syntax_pos 0.0.0",
+]
+
+[[package]]
+name = "rustc_resolve"
+version = "0.0.0"
+dependencies = [
+ "arena 0.0.0",
+ "log 0.0.0",
+ "rustc 0.0.0",
+ "rustc_errors 0.0.0",
+ "syntax 0.0.0",
+ "syntax_pos 0.0.0",
+]
+
+[[package]]
+name = "rustc_save_analysis"
+version = "0.0.0"
+dependencies = [
+ "log 0.0.0",
+ "rustc 0.0.0",
+ "serialize 0.0.0",
+ "syntax 0.0.0",
+ "syntax_pos 0.0.0",
+]
+
+[[package]]
+name = "rustc_trans"
+version = "0.0.0"
+dependencies = [
+ "arena 0.0.0",
+ "flate 0.0.0",
+ "graphviz 0.0.0",
+ "log 0.0.0",
+ "rustc 0.0.0",
+ "rustc_back 0.0.0",
+ "rustc_const_eval 0.0.0",
+ "rustc_const_math 0.0.0",
+ "rustc_data_structures 0.0.0",
+ "rustc_errors 0.0.0",
+ "rustc_incremental 0.0.0",
+ "rustc_llvm 0.0.0",
+ "rustc_platform_intrinsics 0.0.0",
+ "serialize 0.0.0",
+ "syntax 0.0.0",
+ "syntax_pos 0.0.0",
+]
+
+[[package]]
+name = "rustc_typeck"
+version = "0.0.0"
+dependencies = [
+ "arena 0.0.0",
+ "fmt_macros 0.0.0",
+ "log 0.0.0",
+ "rustc 0.0.0",
+ "rustc_back 0.0.0",
+ "rustc_const_eval 0.0.0",
+ "rustc_const_math 0.0.0",
+ "rustc_errors 0.0.0",
+ "rustc_platform_intrinsics 0.0.0",
+ "syntax 0.0.0",
+ "syntax_pos 0.0.0",
+]
+
+[[package]]
+name = "rustc_unicode"
+version = "0.0.0"
+dependencies = [
+ "core 0.0.0",
+]
+
+[[package]]
+name = "rustdoc"
+version = "0.0.0"
+dependencies = [
+ "arena 0.0.0",
+ "build_helper 0.1.0",
+ "gcc 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.0.0",
+ "rustc 0.0.0",
+ "rustc_back 0.0.0",
+ "rustc_const_eval 0.0.0",
+ "rustc_const_math 0.0.0",
+ "rustc_data_structures 0.0.0",
+ "rustc_driver 0.0.0",
+ "rustc_errors 0.0.0",
+ "rustc_lint 0.0.0",
+ "rustc_metadata 0.0.0",
+ "rustc_resolve 0.0.0",
+ "rustc_trans 0.0.0",
+ "serialize 0.0.0",
+ "syntax 0.0.0",
+ "syntax_pos 0.0.0",
+]
+
+[[package]]
+name = "serialize"
+version = "0.0.0"
+dependencies = [
+ "log 0.0.0",
+]
+
+[[package]]
+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",
+ "collections 0.0.0",
+ "compiler_builtins 0.0.0",
+ "core 0.0.0",
+ "gcc 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.0.0",
+ "panic_abort 0.0.0",
+ "panic_unwind 0.0.0",
+ "rand 0.0.0",
+ "rustc_unicode 0.0.0",
+ "unwind 0.0.0",
+]
+
+[[package]]
+name = "std_shim"
+version = "0.1.0"
+dependencies = [
+ "core 0.0.0",
+ "std 0.0.0",
+]
+
+[[package]]
+name = "syntax"
+version = "0.0.0"
+dependencies = [
+ "log 0.0.0",
+ "rustc_bitflags 0.0.0",
+ "rustc_errors 0.0.0",
+ "serialize 0.0.0",
+ "syntax_pos 0.0.0",
+]
+
+[[package]]
+name = "syntax_ext"
+version = "0.0.0"
+dependencies = [
+ "fmt_macros 0.0.0",
+ "log 0.0.0",
+ "proc_macro 0.0.0",
+ "rustc_errors 0.0.0",
+ "syntax 0.0.0",
+ "syntax_pos 0.0.0",
+]
+
+[[package]]
+name = "syntax_pos"
+version = "0.0.0"
+dependencies = [
+ "serialize 0.0.0",
+]
+
+[[package]]
+name = "term"
+version = "0.0.0"
+
+[[package]]
+name = "test"
+version = "0.0.0"
+dependencies = [
+ "getopts 0.0.0",
+ "term 0.0.0",
+]
+
+[[package]]
+name = "test_shim"
+version = "0.1.0"
+dependencies = [
+ "test 0.0.0",
+]
+
+[[package]]
+name = "tidy"
+version = "0.1.0"
+
+[[package]]
+name = "toml"
+version = "0.1.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "unicode-bidi"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "matches 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "unicode-normalization"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "url"
+version = "1.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "idna 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "matches 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "winapi"
+version = "0.2.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "winapi-build"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[metadata]
+"checksum cmake 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "dfcf5bcece56ef953b8ea042509e9dcbdfe97820b7e20d86beb53df30ed94978"
+"checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f"
+"checksum filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "5363ab8e4139b8568a6237db5248646e5a8a2f89bd5ccb02092182b11fd3e922"
+"checksum gcc 0.3.38 (git+https://github.com/alexcrichton/gcc-rs)" = ""
+"checksum gcc 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)" = "553f11439bdefe755bf366b264820f1da70f3aaf3924e594b886beb9c831bcf5"
+"checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685"
+"checksum idna 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1053236e00ce4f668aeca4a769a09b3bf5a682d802abd6f3cb39374f6b162c11"
+"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
+"checksum libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "044d1360593a78f5c8e5e710beccdc24ab71d1f01bc19a29bcacdba22e8475d8"
+"checksum log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ab83497bf8bf4ed2a74259c1c802351fcd67a65baa86394b6ba73c36f4838054"
+"checksum matches 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bcc3ad8109fa4b522f9b0cd81440422781f564aaf8c195de6b9d6642177ad0dd"
+"checksum md5 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a5539a8dee9b4ae308c9c406a379838b435a8f2c84cf9fedc6d5a576be9888db"
+"checksum num_cpus 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "cee7e88156f3f9e19bdd598f8d6c9db7bf4078f99f8381f43a55b09648d1a6e3"
+"checksum rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)" = "6159e4e6e559c81bd706afe9c8fd68f547d3e851ce12e76b1de7914bab61691b"
+"checksum toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)" = "0590d72182e50e879c4da3b11c6488dae18fccb1ae0c7a3eda18e16795844796"
+"checksum unicode-bidi 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c1f7ceb96afdfeedee42bade65a0d585a6a0106f681b6749c8ff4daa8df30b3f"
+"checksum unicode-normalization 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "26643a2f83bac55f1976fb716c10234485f9202dcd65cfbdf9da49867b271172"
+"checksum url 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9ba5a45db1d2e0effb7a1c00cc73ffc63a973da8c7d1fcd5b46f24285ade6c54"
+"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
+"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
diff --git a/src/Cargo.toml b/src/Cargo.toml
new file mode 100644
index 0000000000000..dbd2f7743dc08
--- /dev/null
+++ b/src/Cargo.toml
@@ -0,0 +1,13 @@
+[workspace]
+members = [
+ "bootstrap",
+ "rustc",
+ "rustc/std_shim",
+ "rustc/test_shim",
+ "tools/cargotest",
+ "tools/compiletest",
+ "tools/error_index_generator",
+ "tools/linkchecker",
+ "tools/rustbook",
+ "tools/tidy",
+]
diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock
deleted file mode 100644
index 36b94e4ebea32..0000000000000
--- a/src/bootstrap/Cargo.lock
+++ /dev/null
@@ -1,180 +0,0 @@
-[root]
-name = "bootstrap"
-version = "0.0.0"
-dependencies = [
- "build_helper 0.1.0",
- "cmake 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
- "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "gcc 0.3.31 (git+https://github.com/alexcrichton/gcc-rs)",
- "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
- "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "md5 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 0.1.73 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
- "toml 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "aho-corasick"
-version = "0.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "build_helper"
-version = "0.1.0"
-
-[[package]]
-name = "cmake"
-version = "0.1.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "gcc 0.3.31 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "filetime"
-version = "0.1.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "gcc"
-version = "0.3.31"
-source = "git+https://github.com/alexcrichton/gcc-rs#b8e2400883f1a2749b323354dad372cdd1c838c7"
-
-[[package]]
-name = "gcc"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "getopts"
-version = "0.2.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "kernel32-sys"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "libc"
-version = "0.2.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "md5"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "memchr"
-version = "0.1.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "num_cpus"
-version = "0.2.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "regex"
-version = "0.1.73"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "aho-corasick 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex-syntax 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "thread_local 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "regex-syntax"
-version = "0.3.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "rustc-serialize"
-version = "0.3.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "thread-id"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "thread_local"
-version = "0.2.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "toml"
-version = "0.1.28"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "utf8-ranges"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "winapi"
-version = "0.2.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "winapi-build"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[metadata]
-"checksum aho-corasick 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2b3fb52b09c1710b961acb35390d514be82e4ac96a9969a8e38565a29b878dc9"
-"checksum cmake 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "dfcf5bcece56ef953b8ea042509e9dcbdfe97820b7e20d86beb53df30ed94978"
-"checksum filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "5363ab8e4139b8568a6237db5248646e5a8a2f89bd5ccb02092182b11fd3e922"
-"checksum gcc 0.3.31 (git+https://github.com/alexcrichton/gcc-rs)" = ""
-"checksum gcc 0.3.31 (registry+https://github.com/rust-lang/crates.io-index)" = "cfe877476e53690ebb0ce7325d0bf43e198d9500291b54b3c65e518de5039b07"
-"checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685"
-"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
-"checksum libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "55f3730be7e803cf350d32061958171731c2395831fbd67a61083782808183e0"
-"checksum md5 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a5539a8dee9b4ae308c9c406a379838b435a8f2c84cf9fedc6d5a576be9888db"
-"checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20"
-"checksum num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "51fedae97a05f7353612fe017ab705a37e6db8f4d67c5c6fe739a9e70d6eed09"
-"checksum regex 0.1.73 (registry+https://github.com/rust-lang/crates.io-index)" = "56b7ee9f764ecf412c6e2fff779bca4b22980517ae335a21aeaf4e32625a5df2"
-"checksum regex-syntax 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "31040aad7470ad9d8c46302dcffba337bb4289ca5da2e3cd6e37b64109a85199"
-"checksum rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)" = "6159e4e6e559c81bd706afe9c8fd68f547d3e851ce12e76b1de7914bab61691b"
-"checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03"
-"checksum thread_local 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "55dd963dbaeadc08aa7266bf7f91c3154a7805e32bb94b820b769d2ef3b4744d"
-"checksum toml 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "fcd27a04ca509aff336ba5eb2abc58d456f52c4ff64d9724d88acb85ead560b6"
-"checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f"
-"checksum winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4dfaaa8fbdaa618fa6914b59b2769d690dd7521920a18d84b42d254678dd5fd4"
-"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml
index b19545590b9c0..c96690754387b 100644
--- a/src/bootstrap/Cargo.toml
+++ b/src/bootstrap/Cargo.toml
@@ -27,9 +27,10 @@ num_cpus = "0.2"
toml = "0.1"
getopts = "0.2"
rustc-serialize = "0.3"
-winapi = "0.2"
-kernel32-sys = "0.2"
gcc = { git = "https://github.com/alexcrichton/gcc-rs" }
libc = "0.2"
md5 = "0.1"
-regex = "0.1.73"
+
+[target.'cfg(windows)'.dependencies]
+winapi = "0.2"
+kernel32-sys = "0.2"
diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs
index 175e32125f272..879eca60cc751 100644
--- a/src/bootstrap/bin/rustc.rs
+++ b/src/bootstrap/bin/rustc.rs
@@ -36,8 +36,9 @@ fn main() {
let args = env::args_os().skip(1).collect::>();
// Detect whether or not we're a build script depending on whether --target
// is passed (a bit janky...)
- let target = args.windows(2).find(|w| &*w[0] == "--target")
- .and_then(|w| w[1].to_str());
+ let target = args.windows(2)
+ .find(|w| &*w[0] == "--target")
+ .and_then(|w| w[1].to_str());
let version = args.iter().find(|w| &**w == "-vV");
// Build scripts always use the snapshot compiler which is guaranteed to be
@@ -55,23 +56,24 @@ fn main() {
} else {
("RUSTC_REAL", "RUSTC_LIBDIR")
};
- let stage = env::var("RUSTC_STAGE").unwrap();
+ let stage = env::var("RUSTC_STAGE").expect("RUSTC_STAGE was not set");
- let rustc = env::var_os(rustc).unwrap();
- let libdir = env::var_os(libdir).unwrap();
+ let rustc = env::var_os(rustc).unwrap_or_else(|| panic!("{:?} was not set", rustc));
+ let libdir = env::var_os(libdir).unwrap_or_else(|| panic!("{:?} was not set", libdir));
let mut dylib_path = bootstrap::util::dylib_path();
dylib_path.insert(0, PathBuf::from(libdir));
let mut cmd = Command::new(rustc);
cmd.args(&args)
- .arg("--cfg").arg(format!("stage{}", stage))
- .env(bootstrap::util::dylib_path_var(),
- env::join_paths(&dylib_path).unwrap());
+ .arg("--cfg")
+ .arg(format!("stage{}", stage))
+ .env(bootstrap::util::dylib_path_var(),
+ env::join_paths(&dylib_path).unwrap());
if let Some(target) = target {
// The stage0 compiler has a special sysroot distinct from what we
// actually downloaded, so we just always pass the `--sysroot` option.
- cmd.arg("--sysroot").arg(env::var_os("RUSTC_SYSROOT").unwrap());
+ cmd.arg("--sysroot").arg(env::var_os("RUSTC_SYSROOT").expect("RUSTC_SYSROOT was not set"));
// When we build Rust dylibs they're all intended for intermediate
// usage, so make sure we pass the -Cprefer-dynamic flag instead of
@@ -101,11 +103,9 @@ fn main() {
// This... is a bit of a hack how we detect this. Ideally this
// information should be encoded in the crate I guess? Would likely
// require an RFC amendment to RFC 1513, however.
- let is_panic_abort = args.windows(2).any(|a| {
- &*a[0] == "--crate-name" && &*a[1] == "panic_abort"
- });
- // FIXME(stage0): remove this `stage != "0"` condition
- if is_panic_abort && stage != "0" {
+ let is_panic_abort = args.windows(2)
+ .any(|a| &*a[0] == "--crate-name" && &*a[1] == "panic_abort");
+ if is_panic_abort {
cmd.arg("-C").arg("panic=abort");
}
@@ -113,9 +113,11 @@ fn main() {
// code.
if env::var("RUSTC_DEBUGINFO") == Ok("true".to_string()) {
cmd.arg("-g");
+ } else if env::var("RUSTC_DEBUGINFO_LINES") == Ok("true".to_string()) {
+ cmd.arg("-Cdebuginfo=1");
}
let debug_assertions = match env::var("RUSTC_DEBUG_ASSERTIONS") {
- Ok(s) => if s == "true" {"y"} else {"n"},
+ Ok(s) => if s == "true" { "y" } else { "n" },
Err(..) => "n",
};
cmd.arg("-C").arg(format!("debug-assertions={}", debug_assertions));
diff --git a/src/bootstrap/bin/rustdoc.rs b/src/bootstrap/bin/rustdoc.rs
index 79629bfd71711..67358e540dad0 100644
--- a/src/bootstrap/bin/rustdoc.rs
+++ b/src/bootstrap/bin/rustdoc.rs
@@ -20,21 +20,23 @@ use std::path::PathBuf;
fn main() {
let args = env::args_os().skip(1).collect::>();
- let rustdoc = env::var_os("RUSTDOC_REAL").unwrap();
- let libdir = env::var_os("RUSTC_LIBDIR").unwrap();
+ let rustdoc = env::var_os("RUSTDOC_REAL").expect("RUSTDOC_REAL was not set");
+ let libdir = env::var_os("RUSTC_LIBDIR").expect("RUSTC_LIBDIR was not set");
+ let stage = env::var("RUSTC_STAGE").expect("RUSTC_STAGE was not set");
let mut dylib_path = bootstrap::util::dylib_path();
dylib_path.insert(0, PathBuf::from(libdir));
let mut cmd = Command::new(rustdoc);
cmd.args(&args)
- .arg("--cfg").arg(format!("stage{}", env::var("RUSTC_STAGE").unwrap()))
- .arg("--cfg").arg("dox")
- .env(bootstrap::util::dylib_path_var(),
- env::join_paths(&dylib_path).unwrap());
+ .arg("--cfg")
+ .arg(format!("stage{}", stage))
+ .arg("--cfg")
+ .arg("dox")
+ .env(bootstrap::util::dylib_path_var(),
+ env::join_paths(&dylib_path).unwrap());
std::process::exit(match cmd.status() {
Ok(s) => s.code().unwrap_or(1),
Err(e) => panic!("\n\nfailed to run {:?}: {}\n\n", cmd, e),
})
}
-
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index 17a7c9ca66a26..2c2260a8e60c7 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -131,7 +131,8 @@ def stage0_data(rust_root):
def format_build_time(duration):
return str(datetime.timedelta(seconds=int(duration)))
-class RustBuild:
+
+class RustBuild(object):
def download_stage0(self):
cache_dst = os.path.join(self.build_dir, "cache")
rustc_cache = os.path.join(cache_dst, self.stage0_rustc_date())
@@ -142,7 +143,7 @@ def download_stage0(self):
os.makedirs(cargo_cache)
if self.rustc().startswith(self.bin_root()) and \
- (not os.path.exists(self.rustc()) or self.rustc_out_of_date()):
+ (not os.path.exists(self.rustc()) or self.rustc_out_of_date()):
if os.path.exists(self.bin_root()):
shutil.rmtree(self.bin_root())
channel = self.stage0_rustc_channel()
@@ -165,7 +166,7 @@ def download_stage0(self):
f.write(self.stage0_rustc_date())
if self.cargo().startswith(self.bin_root()) and \
- (not os.path.exists(self.cargo()) or self.cargo_out_of_date()):
+ (not os.path.exists(self.cargo()) or self.cargo_out_of_date()):
channel = self.stage0_cargo_channel()
filename = "cargo-{}-{}.tar.gz".format(channel, self.build)
url = "https://static.rust-lang.org/cargo-dist/" + self.stage0_cargo_date()
@@ -238,8 +239,8 @@ def rustc(self):
def get_string(self, line):
start = line.find('"')
- end = start + 1 + line[start+1:].find('"')
- return line[start+1:end]
+ end = start + 1 + line[start + 1:].find('"')
+ return line[start + 1:end]
def exe_suffix(self):
if sys.platform == 'win32':
@@ -269,6 +270,7 @@ def run(self, args, env):
sys.exit(ret)
def build_triple(self):
+ default_encoding = sys.getdefaultencoding()
config = self.get_toml('build')
if config:
return config
@@ -276,8 +278,8 @@ def build_triple(self):
if config:
return config
try:
- ostype = subprocess.check_output(['uname', '-s']).strip()
- cputype = subprocess.check_output(['uname', '-m']).strip()
+ ostype = subprocess.check_output(['uname', '-s']).strip().decode(default_encoding)
+ cputype = subprocess.check_output(['uname', '-m']).strip().decode(default_encoding)
except (subprocess.CalledProcessError, WindowsError):
if sys.platform == 'win32':
return 'x86_64-pc-windows-msvc'
@@ -289,7 +291,8 @@ def build_triple(self):
# Darwin's `uname -s` lies and always returns i386. We have to use
# sysctl instead.
if ostype == 'Darwin' and cputype == 'i686':
- sysctl = subprocess.check_output(['sysctl', 'hw.optional.x86_64'])
+ args = ['sysctl', 'hw.optional.x86_64']
+ sysctl = subprocess.check_output(args).decode(default_encoding)
if ': 1' in sysctl:
cputype = 'x86_64'
diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs
index 2b9d717cbd48d..af76a49fed045 100644
--- a/src/bootstrap/check.rs
+++ b/src/bootstrap/check.rs
@@ -13,19 +13,44 @@
//! This file implements the various regression test suites that we execute on
//! our CI.
+use std::collections::{HashMap, HashSet};
use std::env;
-use std::fs::{self, File};
-use std::io::prelude::*;
+use std::fs;
use std::path::{PathBuf, Path};
use std::process::Command;
use build_helper::output;
+use rustc_serialize::json;
use {Build, Compiler, Mode};
use util::{self, dylib_path, dylib_path_var};
const ADB_TEST_DIR: &'static str = "/data/tmp";
+#[derive(RustcDecodable)]
+struct Output {
+ packages: Vec,
+ resolve: Resolve,
+}
+
+#[derive(RustcDecodable)]
+struct Package {
+ id: String,
+ name: String,
+ source: Option,
+}
+
+#[derive(RustcDecodable)]
+struct Resolve {
+ nodes: Vec,
+}
+
+#[derive(RustcDecodable)]
+struct ResolveNode {
+ id: String,
+ dependencies: Vec,
+}
+
/// Runs the `linkchecker` tool as compiled in `stage` by the `host` compiler.
///
/// This tool in `src/tools` will verify the validity of all our links in the
@@ -108,6 +133,10 @@ pub fn compiletest(build: &Build,
cmd.arg("--host").arg(compiler.host);
cmd.arg("--llvm-filecheck").arg(build.llvm_filecheck(&build.config.build));
+ if let Some(nodejs) = build.config.nodejs.as_ref() {
+ cmd.arg("--nodejs").arg(nodejs);
+ }
+
let mut flags = vec!["-Crpath".to_string()];
if build.config.rust_optimize_tests {
flags.push("-O".to_string());
@@ -185,7 +214,7 @@ pub fn compiletest(build: &Build,
}
}
}
- build.add_bootstrap_key(compiler, &mut cmd);
+ build.add_bootstrap_key(&mut cmd);
cmd.arg("--adb-path").arg("adb");
cmd.arg("--adb-test-dir").arg(ADB_TEST_DIR);
@@ -259,56 +288,74 @@ fn markdown_test(build: &Build, compiler: &Compiler, markdown: &Path) {
/// It essentially is the driver for running `cargo test`.
///
/// Currently this runs all tests for a DAG by passing a bunch of `-p foo`
-/// arguments, and those arguments are discovered from `Cargo.lock`.
+/// arguments, and those arguments are discovered from `cargo metadata`.
pub fn krate(build: &Build,
compiler: &Compiler,
target: &str,
mode: Mode) {
- let (name, path, features) = match mode {
- Mode::Libstd => ("libstd", "src/rustc/std_shim", build.std_features()),
- Mode::Libtest => ("libtest", "src/rustc/test_shim", String::new()),
- Mode::Librustc => ("librustc", "src/rustc", build.rustc_features()),
+ let (name, path, features, root) = match mode {
+ Mode::Libstd => {
+ ("libstd", "src/rustc/std_shim", build.std_features(), "std_shim")
+ }
+ Mode::Libtest => {
+ ("libtest", "src/rustc/test_shim", String::new(), "test_shim")
+ }
+ Mode::Librustc => {
+ ("librustc", "src/rustc", build.rustc_features(), "rustc-main")
+ }
_ => panic!("can only test libraries"),
};
println!("Testing {} stage{} ({} -> {})", name, compiler.stage,
compiler.host, target);
+ // Run `cargo metadata` to figure out what crates we're testing.
+ //
+ // Down below we're going to call `cargo test`, but to test the right set
+ // of packages we're going to have to know what `-p` arguments to pass it
+ // to know what crates to test. Here we run `cargo metadata` to learn about
+ // the dependency graph and what `-p` arguments there are.
+ let mut cargo = Command::new(&build.cargo);
+ cargo.arg("metadata")
+ .arg("--manifest-path").arg(build.src.join(path).join("Cargo.toml"));
+ let output = output(&mut cargo);
+ let output: Output = json::decode(&output).unwrap();
+ let id2pkg = output.packages.iter()
+ .map(|pkg| (&pkg.id, pkg))
+ .collect::>();
+ let id2deps = output.resolve.nodes.iter()
+ .map(|node| (&node.id, &node.dependencies))
+ .collect::>();
+
// Build up the base `cargo test` command.
+ //
+ // Pass in some standard flags then iterate over the graph we've discovered
+ // in `cargo metadata` with the maps above and figure out what `-p`
+ // arguments need to get passed.
let mut cargo = build.cargo(compiler, mode, target, "test");
cargo.arg("--manifest-path")
.arg(build.src.join(path).join("Cargo.toml"))
.arg("--features").arg(features);
- // Generate a list of `-p` arguments to pass to the `cargo test` invocation
- // by crawling the corresponding Cargo.lock file.
- let lockfile = build.src.join(path).join("Cargo.lock");
- let mut contents = String::new();
- t!(t!(File::open(&lockfile)).read_to_string(&mut contents));
- let mut lines = contents.lines();
- while let Some(line) = lines.next() {
- let prefix = "name = \"";
- if !line.starts_with(prefix) {
+ let mut visited = HashSet::new();
+ let root_pkg = output.packages.iter().find(|p| p.name == root).unwrap();
+ let mut next = vec![&root_pkg.id];
+ while let Some(id) = next.pop() {
+ // Skip any packages with sources listed, as these come from crates.io
+ // and we shouldn't be testing them.
+ if id2pkg[id].source.is_some() {
continue
}
- lines.next(); // skip `version = ...`
-
- // skip crates.io or otherwise non-path crates
- if let Some(line) = lines.next() {
- if line.starts_with("source") {
- continue
- }
- }
-
- let crate_name = &line[prefix.len()..line.len() - 1];
-
// Right now jemalloc is our only target-specific crate in the sense
// that it's not present on all platforms. Custom skip it here for now,
// but if we add more this probably wants to get more generalized.
- if crate_name.contains("jemalloc") {
- continue
+ if !id.contains("jemalloc") {
+ cargo.arg("-p").arg(&id2pkg[id].name);
+ }
+ for dep in id2deps[id] {
+ if visited.insert(dep) {
+ next.push(dep);
+ }
}
-
- cargo.arg("-p").arg(crate_name);
}
// The tests are going to run with the *target* libraries, so we need to
@@ -323,6 +370,9 @@ pub fn krate(build: &Build,
if target.contains("android") {
build.run(cargo.arg("--no-run"));
krate_android(build, compiler, target, mode);
+ } else if target.contains("emscripten") {
+ build.run(cargo.arg("--no-run"));
+ krate_emscripten(build, compiler, target, mode);
} else {
cargo.args(&build.flags.args);
build.run(&mut cargo);
@@ -371,6 +421,35 @@ fn krate_android(build: &Build,
}
}
+fn krate_emscripten(build: &Build,
+ compiler: &Compiler,
+ target: &str,
+ mode: Mode) {
+ let mut tests = Vec::new();
+ let out_dir = build.cargo_out(compiler, mode, target);
+ find_tests(&out_dir, target, &mut tests);
+ find_tests(&out_dir.join("deps"), target, &mut tests);
+
+ for test in tests {
+ let test_file_name = test.to_string_lossy().into_owned();
+ println!("running {}", test_file_name);
+ let nodejs = build.config.nodejs.as_ref().expect("nodejs not configured");
+ let status = Command::new(nodejs)
+ .arg(&test_file_name)
+ .stderr(::std::process::Stdio::inherit())
+ .status();
+ match status {
+ Ok(status) => {
+ if !status.success() {
+ panic!("some tests failed");
+ }
+ }
+ Err(e) => panic!(format!("failed to execute command: {}", e)),
+ };
+ }
+ }
+
+
fn find_tests(dir: &Path,
target: &str,
dst: &mut Vec) {
@@ -381,7 +460,8 @@ fn find_tests(dir: &Path,
}
let filename = e.file_name().into_string().unwrap();
if (target.contains("windows") && filename.ends_with(".exe")) ||
- (!target.contains("windows") && !filename.contains(".")) {
+ (!target.contains("windows") && !filename.contains(".")) ||
+ (target.contains("emscripten") && filename.contains(".js")){
dst.push(e.path());
}
}
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index 9de438cfa7d50..ff8e4757bd1f1 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -25,7 +25,7 @@ use std::process::Command;
use build_helper::output;
use filetime::FileTime;
-use util::{exe, staticlib, libdir, mtime, is_dylib, copy};
+use util::{exe, libdir, mtime, is_dylib, copy};
use {Build, Compiler, Mode};
/// Build the standard library.
@@ -40,20 +40,6 @@ pub fn std<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
let libdir = build.sysroot_libdir(compiler, target);
let _ = fs::remove_dir_all(&libdir);
t!(fs::create_dir_all(&libdir));
- // FIXME(stage0) remove this `if` after the next snapshot
- // The stage0 compiler still passes the `-lcompiler-rt` flag to the linker but now `bootstrap`
- // never builds a `libcopmiler-rt.a`! We'll fill the hole by simply copying stage0's
- // `libcompiler-rt.a` to where the stage1's one is expected (though we could as well just use
- // an empty `.a` archive). Note that the symbols of that stage0 `libcompiler-rt.a` won't make
- // it to the final binary because now `libcore.rlib` also contains the symbols that
- // `libcompiler-rt.a` provides. Since that rlib appears first in the linker arguments, its
- // symbols are used instead of `libcompiler-rt.a`'s.
- if compiler.stage == 0 {
- let rtlib = &staticlib("compiler-rt", target);
- let src = build.rustc.parent().unwrap().parent().unwrap().join("lib").join("rustlib")
- .join(target).join("lib").join(rtlib);
- copy(&src, &libdir.join(rtlib));
- }
// Some platforms have startup objects that may be required to produce the
// libstd dynamic library, for example.
@@ -104,16 +90,16 @@ pub fn std_link(build: &Build,
add_to_sysroot(&out_dir, &libdir);
if target.contains("musl") && !target.contains("mips") {
- copy_musl_third_party_objects(build, &libdir);
+ copy_musl_third_party_objects(build, target, &libdir);
}
}
/// Copies the crt(1,i,n).o startup objects
///
/// Only required for musl targets that statically link to libc
-fn copy_musl_third_party_objects(build: &Build, into: &Path) {
+fn copy_musl_third_party_objects(build: &Build, target: &str, into: &Path) {
for &obj in &["crt1.o", "crti.o", "crtn.o"] {
- copy(&build.config.musl_root.as_ref().unwrap().join("lib").join(obj), &into.join(obj));
+ copy(&build.musl_root(target).unwrap().join("lib").join(obj), &into.join(obj));
}
}
@@ -133,7 +119,7 @@ fn build_startup_objects(build: &Build, target: &str, into: &Path) {
for file in t!(fs::read_dir(build.src.join("src/rtstartup"))) {
let file = t!(file);
let mut cmd = Command::new(&compiler_path);
- build.add_bootstrap_key(&compiler, &mut cmd);
+ build.add_bootstrap_key(&mut cmd);
build.run(cmd.arg("--target").arg(target)
.arg("--emit=obj")
.arg("--out-dir").arg(into)
@@ -199,7 +185,6 @@ pub fn rustc<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
cargo.env("CFG_RELEASE", &build.release)
.env("CFG_RELEASE_CHANNEL", &build.config.channel)
.env("CFG_VERSION", &build.version)
- .env("CFG_BOOTSTRAP_KEY", &build.bootstrap_key)
.env("CFG_PREFIX", build.config.prefix.clone().unwrap_or(String::new()))
.env("CFG_LIBDIR_RELATIVE", "lib");
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index 0f69bcfbb649d..8c0ad1ccf825f 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -56,6 +56,7 @@ pub struct Config {
pub rust_codegen_units: u32,
pub rust_debug_assertions: bool,
pub rust_debuginfo: bool,
+ pub rust_debuginfo_lines: bool,
pub rust_rpath: bool,
pub rustc_default_linker: Option,
pub rustc_default_ar: Option,
@@ -79,6 +80,9 @@ pub struct Config {
// Fallback musl-root for all targets
pub musl_root: Option,
pub prefix: Option,
+ pub docdir: Option,
+ pub libdir: Option,
+ pub mandir: Option,
pub codegen_tests: bool,
pub nodejs: Option,
}
@@ -117,6 +121,7 @@ struct Build {
rustc: Option,
compiler_docs: Option,
docs: Option,
+ submodules: Option,
}
/// TOML representation of how the LLVM build is configured.
@@ -137,6 +142,7 @@ struct Rust {
codegen_units: Option,
debug_assertions: Option,
debuginfo: Option,
+ debuginfo_lines: Option,
debug_jemalloc: Option,
use_jemalloc: Option,
backtrace: Option,
@@ -158,6 +164,7 @@ struct TomlTarget {
cc: Option,
cxx: Option,
android_ndk: Option,
+ musl_root: Option,
}
impl Config {
@@ -221,6 +228,7 @@ impl Config {
config.cargo = build.cargo.map(PathBuf::from);
set(&mut config.compiler_docs, build.compiler_docs);
set(&mut config.docs, build.docs);
+ set(&mut config.submodules, build.submodules);
if let Some(ref llvm) = toml.llvm {
set(&mut config.ccache, llvm.ccache);
@@ -233,6 +241,7 @@ impl Config {
if let Some(ref rust) = toml.rust {
set(&mut config.rust_debug_assertions, rust.debug_assertions);
set(&mut config.rust_debuginfo, rust.debuginfo);
+ set(&mut config.rust_debuginfo_lines, rust.debuginfo_lines);
set(&mut config.rust_optimize, rust.optimize);
set(&mut config.rust_optimize_tests, rust.optimize_tests);
set(&mut config.rust_debuginfo_tests, rust.debuginfo_tests);
@@ -268,6 +277,7 @@ impl Config {
}
target.cxx = cfg.cxx.clone().map(PathBuf::from);
target.cc = cfg.cc.clone().map(PathBuf::from);
+ target.musl_root = cfg.musl_root.clone().map(PathBuf::from);
config.target_config.insert(triple.clone(), target);
}
@@ -322,6 +332,7 @@ impl Config {
("OPTIMIZE", self.rust_optimize),
("DEBUG_ASSERTIONS", self.rust_debug_assertions),
("DEBUGINFO", self.rust_debuginfo),
+ ("DEBUGINFO_LINES", self.rust_debuginfo_lines),
("JEMALLOC", self.use_jemalloc),
("DEBUG_JEMALLOC", self.debug_jemalloc),
("RPATH", self.rust_rpath),
@@ -345,6 +356,36 @@ impl Config {
"CFG_MUSL_ROOT" if value.len() > 0 => {
self.musl_root = Some(PathBuf::from(value));
}
+ "CFG_MUSL_ROOT_X86_64" if value.len() > 0 => {
+ let target = "x86_64-unknown-linux-musl".to_string();
+ let target = self.target_config.entry(target)
+ .or_insert(Target::default());
+ target.musl_root = Some(PathBuf::from(value));
+ }
+ "CFG_MUSL_ROOT_I686" if value.len() > 0 => {
+ let target = "i686-unknown-linux-musl".to_string();
+ let target = self.target_config.entry(target)
+ .or_insert(Target::default());
+ target.musl_root = Some(PathBuf::from(value));
+ }
+ "CFG_MUSL_ROOT_ARM" if value.len() > 0 => {
+ let target = "arm-unknown-linux-musleabi".to_string();
+ let target = self.target_config.entry(target)
+ .or_insert(Target::default());
+ target.musl_root = Some(PathBuf::from(value));
+ }
+ "CFG_MUSL_ROOT_ARMHF" if value.len() > 0 => {
+ let target = "arm-unknown-linux-musleabihf".to_string();
+ let target = self.target_config.entry(target)
+ .or_insert(Target::default());
+ target.musl_root = Some(PathBuf::from(value));
+ }
+ "CFG_MUSL_ROOT_ARMV7" if value.len() > 0 => {
+ let target = "armv7-unknown-linux-musleabihf".to_string();
+ let target = self.target_config.entry(target)
+ .or_insert(Target::default());
+ target.musl_root = Some(PathBuf::from(value));
+ }
"CFG_DEFAULT_AR" if value.len() > 0 => {
self.rustc_default_ar = Some(value.to_string());
}
@@ -357,6 +398,15 @@ impl Config {
"CFG_PREFIX" => {
self.prefix = Some(value.to_string());
}
+ "CFG_DOCDIR" => {
+ self.docdir = Some(value.to_string());
+ }
+ "CFG_LIBDIR" => {
+ self.libdir = Some(value.to_string());
+ }
+ "CFG_MANDIR" => {
+ self.mandir = Some(value.to_string());
+ }
"CFG_LLVM_ROOT" if value.len() > 0 => {
let target = self.target_config.entry(self.build.clone())
.or_insert(Target::default());
@@ -396,9 +446,6 @@ impl Config {
self.rustc = Some(PathBuf::from(value).join("bin/rustc"));
self.cargo = Some(PathBuf::from(value).join("bin/cargo"));
}
- "CFG_NODEJS" if value.len() > 0 => {
- self.nodejs = Some(PathBuf::from(value));
- }
_ => {}
}
}
diff --git a/src/bootstrap/config.toml.example b/src/bootstrap/config.toml.example
index f054b29d0b140..b4730c003d646 100644
--- a/src/bootstrap/config.toml.example
+++ b/src/bootstrap/config.toml.example
@@ -76,6 +76,9 @@
# library and facade crates.
#compiler-docs = false
+# Indicate whether submodules are managed and updated automatically.
+#submodules = true
+
# =============================================================================
# Options for compiling Rust code itself
# =============================================================================
@@ -96,6 +99,9 @@
# Whether or not debuginfo is emitted
#debuginfo = false
+# Whether or not line number debug information is emitted
+#debuginfo-lines = false
+
# Whether or not jemalloc is built and enabled
#use-jemalloc = true
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index 31b7db168b48f..8676f5cc4a1ed 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -25,9 +25,8 @@ use std::process::Command;
use {Build, Compiler};
use util::{cp_r, libdir, is_dylib, cp_filtered, copy};
-use regex::{RegexSet, quote};
-fn package_vers(build: &Build) -> &str {
+pub fn package_vers(build: &Build) -> &str {
match &build.config.channel[..] {
"stable" => &build.release,
"beta" => "beta",
@@ -40,7 +39,7 @@ fn distdir(build: &Build) -> PathBuf {
build.out.join("dist")
}
-fn tmpdir(build: &Build) -> PathBuf {
+pub fn tmpdir(build: &Build) -> PathBuf {
build.out.join("tmp/dist")
}
@@ -315,49 +314,31 @@ pub fn rust_src(build: &Build) {
"mk"
];
- // Exclude paths matching these wildcard expressions
- let excludes = [
- // exclude-vcs
- "CVS", "RCS", "SCCS", ".git", ".gitignore", ".gitmodules", ".gitattributes", ".cvsignore",
- ".svn", ".arch-ids", "{arch}", "=RELEASE-ID", "=meta-update", "=update", ".bzr",
- ".bzrignore", ".bzrtags", ".hg", ".hgignore", ".hgrags", "_darcs",
- // extensions
- "*~", "*.pyc",
- // misc
- "llvm/test/*/*.ll",
- "llvm/test/*/*.td",
- "llvm/test/*/*.s",
- "llvm/test/*/*/*.ll",
- "llvm/test/*/*/*.td",
- "llvm/test/*/*/*.s"
- ];
-
- // Construct a set of regexes for efficiently testing whether paths match one of the above
- // expressions.
- let regex_set = t!(RegexSet::new(
- // This converts a wildcard expression to a regex
- excludes.iter().map(|&s| {
- // Prefix ensures that matching starts on a path separator boundary
- r"^(.*[\\/])?".to_owned() + (
- // Escape the expression to produce a regex matching exactly that string
- "e(s)
- // Replace slashes with a pattern matching either forward or backslash
- .replace(r"/", r"[\\/]")
- // Replace wildcards with a pattern matching a single path segment, ie. containing
- // no slashes.
- .replace(r"\*", r"[^\\/]*")
- // Suffix anchors to the end of the path
- ) + "$"
- })
- ));
-
- // Create a filter which skips files which match the regex set or contain invalid unicode
let filter_fn = move |path: &Path| {
- if let Some(path) = path.to_str() {
- !regex_set.is_match(path)
- } else {
- false
+ let spath = match path.to_str() {
+ Some(path) => path,
+ None => return false,
+ };
+ if spath.ends_with("~") || spath.ends_with(".pyc") {
+ return false
}
+ if spath.contains("llvm/test") || spath.contains("llvm\\test") {
+ if spath.ends_with(".ll") ||
+ spath.ends_with(".td") ||
+ spath.ends_with(".s") {
+ return false
+ }
+ }
+
+ let excludes = [
+ "CVS", "RCS", "SCCS", ".git", ".gitignore", ".gitmodules",
+ ".gitattributes", ".cvsignore", ".svn", ".arch-ids", "{arch}",
+ "=RELEASE-ID", "=meta-update", "=update", ".bzr", ".bzrignore",
+ ".bzrtags", ".hg", ".hgignore", ".hgrags", "_darcs",
+ ];
+ !path.iter()
+ .map(|s| s.to_str().unwrap())
+ .any(|s| excludes.contains(&s))
};
// Copy the directories using our filter
@@ -418,7 +399,7 @@ fn chmod(_path: &Path, _perms: u32) {}
// We have to run a few shell scripts, which choke quite a bit on both `\`
// characters and on `C:\` paths, so normalize both of them away.
-fn sanitize_sh(path: &Path) -> String {
+pub fn sanitize_sh(path: &Path) -> String {
let path = path.to_str().unwrap().replace("\\", "/");
return change_drive(&path).unwrap_or(path);
diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs
new file mode 100644
index 0000000000000..9bc5a7c00abaf
--- /dev/null
+++ b/src/bootstrap/install.rs
@@ -0,0 +1,61 @@
+// 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.
+
+//! Implementation of the install aspects of the compiler.
+//!
+//! This module is responsible for installing the standard library,
+//! compiler, and documentation.
+
+use std::fs;
+use std::borrow::Cow;
+use std::path::Path;
+use std::process::Command;
+
+use Build;
+use dist::{package_vers, sanitize_sh, tmpdir};
+
+/// Installs everything.
+pub fn install(build: &Build, stage: u32, host: &str) {
+ let prefix = build.config.prefix.as_ref().clone().map(|x| Path::new(x))
+ .unwrap_or(Path::new("/usr/local"));
+ let docdir = build.config.docdir.as_ref().clone().map(|x| Cow::Borrowed(Path::new(x)))
+ .unwrap_or(Cow::Owned(prefix.join("share/doc/rust")));
+ let libdir = build.config.libdir.as_ref().clone().map(|x| Cow::Borrowed(Path::new(x)))
+ .unwrap_or(Cow::Owned(prefix.join("lib")));
+ let mandir = build.config.mandir.as_ref().clone().map(|x| Cow::Borrowed(Path::new(x)))
+ .unwrap_or(Cow::Owned(prefix.join("share/man")));
+ let empty_dir = build.out.join("tmp/empty_dir");
+ t!(fs::create_dir_all(&empty_dir));
+ if build.config.docs {
+ install_sh(&build, "docs", "rust-docs", stage, host, prefix,
+ &docdir, &libdir, &mandir, &empty_dir);
+ }
+ install_sh(&build, "std", "rust-std", stage, host, prefix,
+ &docdir, &libdir, &mandir, &empty_dir);
+ install_sh(&build, "rustc", "rustc", stage, host, prefix,
+ &docdir, &libdir, &mandir, &empty_dir);
+ t!(fs::remove_dir_all(&empty_dir));
+}
+
+fn install_sh(build: &Build, package: &str, name: &str, stage: u32, host: &str,
+ prefix: &Path, docdir: &Path, libdir: &Path, mandir: &Path, empty_dir: &Path) {
+ println!("Install {} stage{} ({})", package, stage, host);
+ let package_name = format!("{}-{}-{}", name, package_vers(build), host);
+
+ let mut cmd = Command::new("sh");
+ cmd.current_dir(empty_dir)
+ .arg(sanitize_sh(&tmpdir(build).join(&package_name).join("install.sh")))
+ .arg(format!("--prefix={}", sanitize_sh(prefix)))
+ .arg(format!("--docdir={}", sanitize_sh(docdir)))
+ .arg(format!("--libdir={}", sanitize_sh(libdir)))
+ .arg(format!("--mandir={}", sanitize_sh(mandir)))
+ .arg("--disable-ldconfig");
+ build.run(&mut cmd);
+}
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index c5dbb2a0319f2..7c5a0c7373f88 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -26,7 +26,6 @@ extern crate md5;
extern crate num_cpus;
extern crate rustc_serialize;
extern crate toml;
-extern crate regex;
use std::collections::HashMap;
use std::env;
@@ -62,6 +61,7 @@ mod config;
mod dist;
mod doc;
mod flags;
+mod install;
mod native;
mod sanity;
mod step;
@@ -220,14 +220,14 @@ impl Build {
sanity::check(self);
self.verbose("collecting channel variables");
channel::collect(self);
- // If local-rust is the same as the current version, then force a local-rebuild
+ // If local-rust is the same major.minor as the current version, then force a local-rebuild
let local_version_verbose = output(
Command::new(&self.rustc).arg("--version").arg("--verbose"));
let local_release = local_version_verbose
.lines().filter(|x| x.starts_with("release:"))
.next().unwrap().trim_left_matches("release:").trim();
- if local_release == self.release {
- self.verbose(&format!("auto-detected local-rebuild {}", self.release));
+ if local_release.split('.').take(2).eq(self.release.split('.').take(2)) {
+ self.verbose(&format!("auto-detected local-rebuild {}", local_release));
self.local_rebuild = true;
}
self.verbose("updating submodules");
@@ -243,7 +243,14 @@ impl Build {
// Almost all of these are simple one-liners that shell out to the
// corresponding functionality in the extra modules, where more
// documentation can be found.
- for target in step::all(self) {
+ let steps = step::all(self);
+
+ self.verbose("bootstrap build plan:");
+ for step in &steps {
+ self.verbose(&format!("{:?}", step));
+ }
+
+ for target in steps {
let doc_out = self.out.join(&target.target).join("doc");
match target.src {
Llvm { _dummy } => {
@@ -446,6 +453,8 @@ impl Build {
DistStd { compiler } => dist::std(self, &compiler, target.target),
DistSrc { _dummy } => dist::rust_src(self),
+ Install { stage } => install::install(self, stage, target.target),
+
DebuggerScripts { stage } => {
let compiler = Compiler::new(stage, target.target);
dist::debugger_scripts(self,
@@ -550,12 +559,23 @@ impl Build {
continue
}
+ // `submodule.path` is the relative path to a submodule (from the repository root)
+ // `submodule_path` is the path to a submodule from the cwd
+
+ // use `submodule.path` when e.g. executing a submodule specific command from the
+ // repository root
+ // use `submodule_path` when e.g. executing a normal git command for the submodule
+ // (set via `current_dir`)
+ let submodule_path = self.src.join(submodule.path);
+
match submodule.state {
State::MaybeDirty => {
// drop staged changes
- self.run(git().arg("-C").arg(submodule.path).args(&["reset", "--hard"]));
+ self.run(git().current_dir(&submodule_path)
+ .args(&["reset", "--hard"]));
// drops unstaged changes
- self.run(git().arg("-C").arg(submodule.path).args(&["clean", "-fdx"]));
+ self.run(git().current_dir(&submodule_path)
+ .args(&["clean", "-fdx"]));
},
State::NotInitialized => {
self.run(git_submodule().arg("init").arg(submodule.path));
@@ -564,8 +584,10 @@ impl Build {
State::OutOfSync => {
// drops submodule commits that weren't reported to the (outer) git repository
self.run(git_submodule().arg("update").arg(submodule.path));
- self.run(git().arg("-C").arg(submodule.path).args(&["reset", "--hard"]));
- self.run(git().arg("-C").arg(submodule.path).args(&["clean", "-fdx"]));
+ self.run(git().current_dir(&submodule_path)
+ .args(&["reset", "--hard"]));
+ self.run(git().current_dir(&submodule_path)
+ .args(&["clean", "-fdx"]));
},
}
}
@@ -627,6 +649,7 @@ impl Build {
.env("RUSTC_REAL", self.compiler_path(compiler))
.env("RUSTC_STAGE", stage.to_string())
.env("RUSTC_DEBUGINFO", self.config.rust_debuginfo.to_string())
+ .env("RUSTC_DEBUGINFO_LINES", self.config.rust_debuginfo_lines.to_string())
.env("RUSTC_CODEGEN_UNITS",
self.config.rust_codegen_units.to_string())
.env("RUSTC_DEBUG_ASSERTIONS",
@@ -640,7 +663,7 @@ impl Build {
.env("RUSTDOC_REAL", self.rustdoc(compiler))
.env("RUSTC_FLAGS", self.rustc_flags(target).join(" "));
- self.add_bootstrap_key(compiler, &mut cargo);
+ self.add_bootstrap_key(&mut cargo);
// Specify some various options for build scripts used throughout
// the build.
@@ -652,12 +675,6 @@ impl Build {
.env(format!("CFLAGS_{}", target), self.cflags(target).join(" "));
}
- // If we're building for OSX, inform the compiler and the linker that
- // we want to build a compiler runnable on 10.7
- if target.contains("apple-darwin") {
- cargo.env("MACOSX_DEPLOYMENT_TARGET", "10.7");
- }
-
// Environment variables *required* needed throughout the build
//
// FIXME: should update code to not require this env var
@@ -855,16 +872,11 @@ impl Build {
}
/// Adds the compiler's bootstrap key to the environment of `cmd`.
- fn add_bootstrap_key(&self, compiler: &Compiler, cmd: &mut Command) {
- // In stage0 we're using a previously released stable compiler, so we
- // use the stage0 bootstrap key. Otherwise we use our own build's
- // bootstrap key.
- let bootstrap_key = if compiler.is_snapshot(self) && !self.local_rebuild {
- &self.bootstrap_key_stage0
- } else {
- &self.bootstrap_key
- };
- cmd.env("RUSTC_BOOTSTRAP_KEY", bootstrap_key);
+ fn add_bootstrap_key(&self, cmd: &mut Command) {
+ cmd.env("RUSTC_BOOTSTRAP", "");
+ // FIXME: Transitionary measure to bootstrap using the old bootstrap logic.
+ // Remove this once the bootstrap compiler uses the new login in Issue #36548.
+ cmd.env("RUSTC_BOOTSTRAP_KEY", "62b3e239");
}
/// Returns the compiler's libdir where it stores the dynamic libraries that
@@ -926,7 +938,6 @@ impl Build {
// LLVM/jemalloc/etc are all properly compiled.
if target.contains("apple-darwin") {
base.push("-stdlib=libc++".into());
- base.push("-mmacosx-version-min=10.7".into());
}
// This is a hack, because newer binutils broke things on some vms/distros
// (i.e., linking against unknown relocs disabled by the following flag)
@@ -950,7 +961,11 @@ impl Build {
/// Returns the path to the C++ compiler for the target specified, may panic
/// if no C++ compiler was configured for the target.
fn cxx(&self, target: &str) -> &Path {
- self.cxx[target].path()
+ match self.cxx.get(target) {
+ Some(p) => p.path(),
+ None => panic!("\n\ntarget `{}` is not configured as a host,
+ only as a target\n\n", target),
+ }
}
/// Returns flags to pass to the compiler to generate code for `target`.
@@ -963,7 +978,8 @@ impl Build {
// than an entry here.
let mut base = Vec::new();
- if target != self.config.build && !target.contains("msvc") {
+ if target != self.config.build && !target.contains("msvc") &&
+ !target.contains("emscripten") {
base.push(format!("-Clinker={}", self.cc(target).display()));
}
return base
@@ -971,7 +987,8 @@ impl Build {
/// Returns the "musl root" for this `target`, if defined
fn musl_root(&self, target: &str) -> Option<&Path> {
- self.config.target_config[target].musl_root.as_ref()
+ self.config.target_config.get(target)
+ .and_then(|t| t.musl_root.as_ref())
.or(self.config.musl_root.as_ref())
.map(|p| &**p)
}
diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in
index cc44d45c2cc75..0762ed98472be 100644
--- a/src/bootstrap/mk/Makefile.in
+++ b/src/bootstrap/mk/Makefile.in
@@ -51,6 +51,12 @@ check-cargotest:
$(Q)$(BOOTSTRAP) --step check-cargotest
dist:
$(Q)$(BOOTSTRAP) --step dist
+install:
+ifeq (root user, $(USER) $(patsubst %,user,$(SUDO_USER)))
+ $(Q)echo "'sudo make install' is not supported currently."
+else
+ $(Q)$(BOOTSTRAP) --step install
+endif
tidy:
$(Q)$(BOOTSTRAP) --step check-tidy --stage 0
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index df6408e5fe1c8..1b4e86fb30f25 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -18,9 +18,10 @@
//! LLVM and compiler-rt are essentially just wired up to everything else to
//! ensure that they're always in place if needed.
+use std::fs::{self, File};
+use std::io::{Read, Write};
use std::path::Path;
use std::process::Command;
-use std::fs::{self, File};
use build_helper::output;
use cmake;
@@ -43,11 +44,17 @@ pub fn llvm(build: &Build, target: &str) {
// artifacts are missing) then we keep going, otherwise we bail out.
let dst = build.llvm_out(target);
let stamp = build.src.join("src/rustllvm/llvm-auto-clean-trigger");
+ let mut stamp_contents = String::new();
+ t!(t!(File::open(&stamp)).read_to_string(&mut stamp_contents));
let done_stamp = dst.join("llvm-finished-building");
- build.clear_if_dirty(&dst, &stamp);
- if fs::metadata(&done_stamp).is_ok() {
- return
+ if done_stamp.exists() {
+ let mut done_contents = String::new();
+ t!(t!(File::open(&done_stamp)).read_to_string(&mut done_contents));
+ if done_contents == stamp_contents {
+ return
+ }
}
+ drop(fs::remove_dir_all(&dst));
println!("Building LLVM for {}", target);
@@ -65,7 +72,7 @@ pub fn llvm(build: &Build, target: &str) {
.out_dir(&dst)
.profile(if build.config.llvm_optimize {"Release"} else {"Debug"})
.define("LLVM_ENABLE_ASSERTIONS", assertions)
- .define("LLVM_TARGETS_TO_BUILD", "X86;ARM;AArch64;Mips;PowerPC;SystemZ")
+ .define("LLVM_TARGETS_TO_BUILD", "X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend")
.define("LLVM_INCLUDE_EXAMPLES", "OFF")
.define("LLVM_INCLUDE_TESTS", "OFF")
.define("LLVM_INCLUDE_DOCS", "OFF")
@@ -73,7 +80,9 @@ pub fn llvm(build: &Build, target: &str) {
.define("WITH_POLLY", "OFF")
.define("LLVM_ENABLE_TERMINFO", "OFF")
.define("LLVM_ENABLE_LIBEDIT", "OFF")
- .define("LLVM_PARALLEL_COMPILE_JOBS", build.jobs().to_string());
+ .define("LLVM_PARALLEL_COMPILE_JOBS", build.jobs().to_string())
+ .define("LLVM_TARGET_ARCH", target.split('-').next().unwrap())
+ .define("LLVM_DEFAULT_TARGET_TRIPLE", target);
if target.starts_with("i686") {
cfg.define("LLVM_BUILD_32_BITS", "ON");
@@ -86,9 +95,7 @@ pub fn llvm(build: &Build, target: &str) {
// actually exists most of the time in normal installs of LLVM.
let host = build.llvm_out(&build.config.build).join("bin/llvm-tblgen");
cfg.define("CMAKE_CROSSCOMPILING", "True")
- .define("LLVM_TARGET_ARCH", target.split('-').next().unwrap())
- .define("LLVM_TABLEGEN", &host)
- .define("LLVM_DEFAULT_TARGET_TRIPLE", target);
+ .define("LLVM_TABLEGEN", &host);
}
// MSVC handles compiler business itself
@@ -114,7 +121,7 @@ pub fn llvm(build: &Build, target: &str) {
// tools and libs on all platforms.
cfg.build();
- t!(File::create(&done_stamp));
+ t!(t!(File::create(&done_stamp)).write_all(stamp_contents.as_bytes()));
}
fn check_llvm_version(build: &Build, llvm_config: &Path) {
diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs
index 05c35543e3e5b..969cd70fd57eb 100644
--- a/src/bootstrap/sanity.rs
+++ b/src/bootstrap/sanity.rs
@@ -40,17 +40,23 @@ pub fn check(build: &mut Build) {
panic!("PATH contains invalid character '\"'");
}
}
- let mut need_cmd = |cmd: &OsStr| {
- if !checked.insert(cmd.to_owned()) {
- return
- }
+ let have_cmd = |cmd: &OsStr| {
for path in env::split_paths(&path).map(|p| p.join(cmd)) {
if fs::metadata(&path).is_ok() ||
fs::metadata(path.with_extension("exe")).is_ok() {
- return
+ return Some(path);
}
}
- panic!("\n\ncouldn't find required command: {:?}\n\n", cmd);
+ return None;
+ };
+
+ let mut need_cmd = |cmd: &OsStr| {
+ if !checked.insert(cmd.to_owned()) {
+ return
+ }
+ if have_cmd(cmd).is_none() {
+ panic!("\n\ncouldn't find required command: {:?}\n\n", cmd);
+ }
};
// If we've got a git directory we're gona need git to update
@@ -75,8 +81,13 @@ pub fn check(build: &mut Build) {
need_cmd("python".as_ref());
- // If a manual nodejs was added to the config,
- // of if a nodejs install is detected through config, use it.
+ // Look for the nodejs command, needed for emscripten testing
+ if let Some(node) = have_cmd("node".as_ref()) {
+ build.config.nodejs = Some(node);
+ } else if let Some(node) = have_cmd("nodejs".as_ref()) {
+ build.config.nodejs = Some(node);
+ }
+
if let Some(ref s) = build.config.nodejs {
need_cmd(s.as_ref());
}
@@ -84,6 +95,13 @@ pub fn check(build: &mut Build) {
// We're gonna build some custom C code here and there, host triples
// also build some C++ shims for LLVM so we need a C++ compiler.
for target in build.config.target.iter() {
+ // On emscripten we don't actually need the C compiler to just
+ // build the target artifacts, only for testing. For the sake
+ // of easier bot configuration, just skip detection.
+ if target.contains("emscripten") {
+ continue;
+ }
+
need_cmd(build.cc(target).as_ref());
if let Some(ar) = build.ar(target) {
need_cmd(ar.as_ref());
@@ -93,6 +111,14 @@ pub fn check(build: &mut Build) {
need_cmd(build.cxx(host).as_ref());
}
+ // The msvc hosts don't use jemalloc, turn it off globally to
+ // avoid packaging the dummy liballoc_jemalloc on that platform.
+ for host in build.config.host.iter() {
+ if host.contains("msvc") {
+ build.config.use_jemalloc = false;
+ }
+ }
+
// Externally configured LLVM requires FileCheck to exist
let filecheck = build.llvm_filecheck(&build.config.build);
if !filecheck.starts_with(&build.out) && !filecheck.exists() && build.config.codegen_tests {
@@ -100,15 +126,6 @@ pub fn check(build: &mut Build) {
}
for target in build.config.target.iter() {
- // Either can't build or don't want to run jemalloc on these targets
- if target.contains("rumprun") ||
- target.contains("bitrig") ||
- target.contains("openbsd") ||
- target.contains("msvc") ||
- target.contains("emscripten") {
- build.config.use_jemalloc = false;
- }
-
// Can't compile for iOS unless we're on OSX
if target.contains("apple-ios") &&
!build.config.build.contains("apple-darwin") {
@@ -129,8 +146,8 @@ pub fn check(build: &mut Build) {
}
}
None => {
- panic!("when targeting MUSL either the build.musl-root \
- option or the target.$TARGET.musl-root one must \
+ panic!("when targeting MUSL either the rust.musl-root \
+ option or the target.$TARGET.musl-root option must \
be specified in config.toml")
}
}
diff --git a/src/bootstrap/step.rs b/src/bootstrap/step.rs
index 5f391b70fbe88..3bf0f21192147 100644
--- a/src/bootstrap/step.rs
+++ b/src/bootstrap/step.rs
@@ -140,6 +140,9 @@ macro_rules! targets {
(dist_std, DistStd { compiler: Compiler<'a> }),
(dist_src, DistSrc { _dummy: () }),
+ // install target
+ (install, Install { stage: u32 }),
+
// Misc targets
(android_copy_libs, AndroidCopyLibs { compiler: Compiler<'a> }),
}
@@ -171,6 +174,8 @@ targets!(define_source);
/// into a topologically sorted list which when executed left-to-right will
/// correctly sequence the entire build.
pub fn all(build: &Build) -> Vec {
+ build.verbose("inferred build steps:");
+
let mut ret = Vec::new();
let mut all = HashSet::new();
for target in top_level(build) {
@@ -184,6 +189,7 @@ pub fn all(build: &Build) -> Vec {
set: &mut HashSet>) {
if set.insert(target.clone()) {
for dep in target.deps(build) {
+ build.verbose(&format!("{:?}\n -> {:?}", target, dep));
fill(build, &dep, ret, set);
}
ret.push(target.clone());
@@ -246,8 +252,7 @@ fn top_level(build: &Build) -> Vec {
}
}
- return targets
-
+ targets
}
fn add_steps<'a>(build: &'a Build,
@@ -415,7 +420,6 @@ impl<'a> Step<'a> {
self.check_crate_std(compiler),
self.check_crate_test(compiler),
self.check_debuginfo(compiler),
- self.dist(stage),
];
// If we're testing the build triple, then we know we can
@@ -460,9 +464,12 @@ impl<'a> Step<'a> {
// misc
self.check_linkcheck(stage),
self.check_tidy(stage),
+
+ // can we make the distributables?
+ self.dist(stage),
]);
}
- return base
+ base
}
Source::CheckLinkcheck { stage } => {
vec![self.tool_linkchecker(stage), self.doc(stage)]
@@ -483,7 +490,6 @@ impl<'a> Step<'a> {
Source::CheckCodegenUnits { compiler } |
Source::CheckIncremental { compiler } |
Source::CheckUi { compiler } |
- Source::CheckRustdoc { compiler } |
Source::CheckPretty { compiler } |
Source::CheckCFail { compiler } |
Source::CheckRPassValgrind { compiler } |
@@ -506,6 +512,7 @@ impl<'a> Step<'a> {
self.debugger_scripts(compiler.stage),
]
}
+ Source::CheckRustdoc { compiler } |
Source::CheckRPassFull { compiler } |
Source::CheckRFailFull { compiler } |
Source::CheckCFailFull { compiler } |
@@ -517,7 +524,7 @@ impl<'a> Step<'a> {
self.target(compiler.host).tool_compiletest(compiler.stage)]
}
Source::CheckDocs { compiler } => {
- vec![self.libstd(compiler)]
+ vec![self.libtest(compiler)]
}
Source::CheckErrorIndex { compiler } => {
vec![self.libstd(compiler),
@@ -585,7 +592,11 @@ impl<'a> Step<'a> {
base.push(target.dist_std(compiler));
}
}
- return base
+ base
+ }
+
+ Source::Install { stage } => {
+ vec![self.dist(stage)]
}
Source::AndroidCopyLibs { compiler } => {
diff --git a/src/build_helper/lib.rs b/src/build_helper/lib.rs
index 838cc4f07a9a1..38844fb6c9ef0 100644
--- a/src/build_helper/lib.rs
+++ b/src/build_helper/lib.rs
@@ -25,7 +25,9 @@ pub fn run_silent(cmd: &mut Command) {
};
if !status.success() {
fail(&format!("command did not execute successfully: {:?}\n\
- expected success, got: {}", cmd, status));
+ expected success, got: {}",
+ cmd,
+ status));
}
}
@@ -65,7 +67,9 @@ pub fn output(cmd: &mut Command) -> String {
};
if !output.status.success() {
panic!("command did not execute successfully: {:?}\n\
- expected success, got: {}", cmd, output.status);
+ expected success, got: {}",
+ cmd,
+ output.status);
}
String::from_utf8(output.stdout).unwrap()
}
diff --git a/src/compiler-rt b/src/compiler-rt
index 8598065bd965d..f03ba5a4e8bf1 160000
--- a/src/compiler-rt
+++ b/src/compiler-rt
@@ -1 +1 @@
-Subproject commit 8598065bd965d9713bfafb6c1e766d63a7b17b89
+Subproject commit f03ba5a4e8bf16dcf42dd742a4ce255c36321356
diff --git a/src/doc/book/concurrency.md b/src/doc/book/concurrency.md
index a783650f8ea2d..41d8345b72094 100644
--- a/src/doc/book/concurrency.md
+++ b/src/doc/book/concurrency.md
@@ -4,7 +4,7 @@ Concurrency and parallelism are incredibly important topics in computer
science, and are also a hot topic in industry today. Computers are gaining more
and more cores, yet many programmers aren't prepared to fully utilize them.
-Rust's memory safety features also apply to its concurrency story too. Even
+Rust's memory safety features also apply to its concurrency story. Even
concurrent Rust programs must be memory safe, having no data races. Rust's type
system is up to the task, and gives you powerful ways to reason about
concurrent code at compile time.
@@ -281,8 +281,8 @@ And... still gives us an error.
```
`Arc` by default has immutable contents. It allows the _sharing_ of data
-between threads, but shared mutable data is unsafe and when threads are
-involved can cause data races!
+between threads, but shared mutable data is unsafe—and when threads are
+involved—can cause data races!
Usually when we wish to make something in an immutable position mutable, we use
diff --git a/src/doc/book/const-and-static.md b/src/doc/book/const-and-static.md
index 11aa25ac811c9..e8f17a41cbeab 100644
--- a/src/doc/book/const-and-static.md
+++ b/src/doc/book/const-and-static.md
@@ -1,4 +1,4 @@
-% `const` and `static`
+% const and static
Rust has a way of defining constants with the `const` keyword:
diff --git a/src/doc/book/deref-coercions.md b/src/doc/book/deref-coercions.md
index beb65c4ce358a..cabe66f5b2282 100644
--- a/src/doc/book/deref-coercions.md
+++ b/src/doc/book/deref-coercions.md
@@ -69,7 +69,7 @@ foo(&counted);
All we’ve done is wrap our `String` in an `Rc`. But we can now pass the
`Rc` around anywhere we’d have a `String`. The signature of `foo`
didn’t change, but works just as well with either type. This example has two
-conversions: `Rc` to `String` and then `String` to `&str`. Rust will do
+conversions: `&Rc` to `&String` and then `&String` to `&str`. Rust will do
this as many times as possible until the types match.
Another very common implementation provided by the standard library is:
diff --git a/src/doc/book/getting-started.md b/src/doc/book/getting-started.md
index 700ab2be58932..5add235928272 100644
--- a/src/doc/book/getting-started.md
+++ b/src/doc/book/getting-started.md
@@ -166,12 +166,22 @@ you can find the Rust executables in a directory like
`"C:\Program Files\Rust stable GNU 1.x\bin"`.
Rust does not do its own linking, and so you’ll need to have a linker
-installed. Doing so will depend on your specific system, consult its
-documentation for more details.
-
-If not, there are a number of places where we can get help. The easiest is
-[the #rust-beginners IRC channel on irc.mozilla.org][irc-beginners] and for
-general discussion [the #rust IRC channel on irc.mozilla.org][irc], which we
+installed. Doing so will depend on your specific system. For
+Linux-based systems, Rust will attempt to call `cc` for linking. On
+`windows-msvc` (Rust built on Windows with Microsoft Visual Studio),
+this depends on having [Microsoft Visual C++ Build Tools][msvbt]
+installed. These do not need to be in `%PATH%` as `rustc` will find
+them automatically. In general, if you have your linker in a
+non-traditional location you can call `rustc
+linker=/path/to/cc`, where `/path/to/cc` should point to your linker path.
+
+[msvbt]: http://landinghub.visualstudio.com/visual-cpp-build-tools
+
+If you are still stuck, there are a number of places where we can get
+help. The easiest is
+[the #rust-beginners IRC channel on irc.mozilla.org][irc-beginners]
+and for general discussion
+[the #rust IRC channel on irc.mozilla.org][irc], which we
can access through [Mibbit][mibbit]. Then we'll be chatting with other
Rustaceans (a silly nickname we call ourselves) who can help us out. Other great
resources include [the user’s forum][users] and [Stack Overflow][stackoverflow].
@@ -230,12 +240,13 @@ $ cd hello_world
## Writing and Running a Rust Program
-Next, make a new source file and call it *main.rs*. Rust files always end
-in a *.rs* extension. If you’re using more than one word in your filename, use
-an underscore to separate them; for example, you'd use *hello_world.rs* rather
-than *helloworld.rs*.
+We need to create a source file for our Rust program. Rust files always end
+in a *.rs* extension. If you are using more than one word in your filename,
+use an underscore to separate them; for example, you would use
+*my_program.rs* rather than *myprogram.rs*.
-Now open the *main.rs* file you just created, and type the following code:
+Now, make a new file and call it *main.rs*. Open the file and type
+the following code:
```rust
fn main() {
@@ -494,6 +505,9 @@ $ cargo run
Hello, world!
```
+The `run` command comes in handy when you need to rapidly iterate on a
+project.
+
Notice that this example didn’t re-build the project. Cargo figured out that
the file hasn’t changed, and so it just ran the binary. If you'd modified your
source code, Cargo would have rebuilt the project before running it, and you
diff --git a/src/doc/book/guessing-game.md b/src/doc/book/guessing-game.md
index 22cf6068e4d5a..4e0e372868941 100644
--- a/src/doc/book/guessing-game.md
+++ b/src/doc/book/guessing-game.md
@@ -56,9 +56,7 @@ $ cargo build
Excellent! Open up your `src/main.rs` again. We’ll be writing all of
our code in this file.
-Before we move on, let me show you one more Cargo command: `run`. `cargo run`
-is kind of like `cargo build`, but it also then runs the produced executable.
-Try it out:
+Remember the `run` command from last chapter? Try it out again here:
```bash
$ cargo run
@@ -67,9 +65,8 @@ $ cargo run
Hello, world!
```
-Great! The `run` command comes in handy when you need to rapidly iterate on a
-project. Our game is such a project, we need to quickly test each
-iteration before moving on to the next one.
+Great! Our game is just the kind of project `run` is good for: we need
+to quickly test each iteration before moving on to the next one.
# Processing a Guess
@@ -279,7 +276,7 @@ displaying the message.
[expect]: ../std/result/enum.Result.html#method.expect
[panic]: error-handling.html
-If we leave off calling this method, our program will compile, but
+If we do not call `expect()`, our program will compile, but
we’ll get a warning:
```bash
diff --git a/src/doc/book/lifetimes.md b/src/doc/book/lifetimes.md
index f7d9c94bc454f..df1ee5a293c9d 100644
--- a/src/doc/book/lifetimes.md
+++ b/src/doc/book/lifetimes.md
@@ -50,29 +50,94 @@ complicated. For example, imagine this set of operations:
4. You decide to use the resource.
Uh oh! Your reference is pointing to an invalid resource. This is called a
-dangling pointer or ‘use after free’, when the resource is memory.
+dangling pointer or ‘use after free’, when the resource is memory. A small
+example of such a situation would be:
+
+```rust,compile_fail
+let r; // Introduce reference: r
+{
+ let i = 1; // Introduce scoped value: i
+ r = &i; // Store reference of i in r
+} // i goes out of scope and is dropped.
+
+println!("{}", r); // r still refers to i
+```
To fix this, we have to make sure that step four never happens after step
-three. The ownership system in Rust does this through a concept called
-lifetimes, which describe the scope that a reference is valid for.
+three. In the small example above the Rust compiler is able to report the issue
+as it can see the lifetimes of the various values in the function.
-When we have a function that takes an argument by reference, we can be
-implicit or explicit about the lifetime of the reference:
+When we have a function that takes arguments by reference the situation becomes
+more complex. Consider the following example:
-```rust
-// implicit
-fn foo(x: &i32) {
+```rust,compile_fail,E0106
+fn skip_prefix(line: &str, prefix: &str) -> &str {
+ // ...
+# line
}
-// explicit
-fn bar<'a>(x: &'a i32) {
+let line = "lang:en=Hello World!";
+let lang = "en";
+
+let v;
+{
+ let p = format!("lang:{}=", lang); // -+ p goes into scope
+ v = skip_prefix(line, p.as_str()); // |
+} // -+ p goes out of scope
+println!("{}", v);
+```
+
+Here we have a function `skip_prefix` which takes two `&str` references
+as parameters and returns a single `&str` reference. We call it
+by passing in references to `line` and `p`: Two variables with different
+lifetimes. Now the safety of the `println!`-line depends on whether the
+reference returned by `skip_prefix` function references the still living
+`line` or the already dropped `p` string.
+
+Because of the above ambiguity, Rust will refuse to compile the example
+code. To get it to compile we need to tell the compiler more about the
+lifetimes of the references. This can be done by making the lifetimes
+explicit in the function declaration:
+
+```rust
+fn skip_prefix<'a, 'b>(line: &'a str, prefix: &'b str) -> &'a str {
+ // ...
+# line
}
```
+Let's examine the changes without going too deep into the syntax for now -
+we'll get to that later. The first change was adding the `<'a, 'b>` after the
+method name. This introduces two lifetime parameters: `'a` and `'b`. Next each
+reference in the function signature was associated with one of the lifetime
+parameters by adding the lifetime name after the `&`. This tells the compiler
+how the lifetimes between different references are related.
+
+As a result the compiler is now able to deduce that the return value of
+`skip_prefix` has the same lifetime as the `line` parameter, which makes the `v`
+reference safe to use even after the `p` goes out of scope in the original
+example.
+
+In addition to the compiler being able to validate the usage of `skip_prefix`
+return value, it can also ensure that the implementation follows the contract
+established by the function declaration. This is useful especially when you are
+implementing traits that are introduced [later in the book][traits].
+
+**Note** It's important to understand that lifetime annotations are
+_descriptive_, not _prescriptive_. This means that how long a reference is valid
+is determined by the code, not by the annotations. The annotations, however,
+give information about lifetimes to the compiler that uses them to check the
+validity of references. The compiler can do so without annotations in simple
+cases, but needs the programmers support in complex scenarios.
+
+[traits]: traits.html
+
+# Syntax
+
The `'a` reads ‘the lifetime a’. Technically, every reference has some lifetime
associated with it, but the compiler lets you elide (i.e. omit, see
-["Lifetime Elision"][lifetime-elision] below) them in common cases.
-Before we get to that, though, let’s break the explicit example down:
+["Lifetime Elision"][lifetime-elision] below) them in common cases. Before we
+get to that, though, let’s look at a short example with explicit lifetimes:
[lifetime-elision]: #lifetime-elision
@@ -90,7 +155,8 @@ focus on the lifetimes aspect.
[generics]: generics.html
We use `<>` to declare our lifetimes. This says that `bar` has one lifetime,
-`'a`. If we had two reference parameters, it would look like this:
+`'a`. If we had two reference parameters with different lifetimes, it would
+look like this:
```rust,ignore
diff --git a/src/doc/book/ownership.md b/src/doc/book/ownership.md
index 23ca21b3b4992..a711397b211db 100644
--- a/src/doc/book/ownership.md
+++ b/src/doc/book/ownership.md
@@ -57,13 +57,13 @@ of scope at the end of `foo()`, Rust will clean up everything related to the
vector, even the heap-allocated memory. This happens deterministically, at the
end of the scope.
-We'll cover [vectors] in detail later in this chapter; we only use them
+We covered [vectors] in the previous chapter; we use them
here as an example of a type that allocates space on the heap at runtime. They
behave like [arrays], except their size may change by `push()`ing more
elements onto them.
Vectors have a [generic type][generics] `Vec`, so in this example `v` will have type
-`Vec`. We'll cover generics in detail later in this chapter.
+`Vec`. We'll cover [generics] in detail in a later chapter.
[arrays]: primitive-types.html#arrays
[vectors]: vectors.html
diff --git a/src/doc/book/references-and-borrowing.md b/src/doc/book/references-and-borrowing.md
index 2ec3a00c0df51..1e2f061b06745 100644
--- a/src/doc/book/references-and-borrowing.md
+++ b/src/doc/book/references-and-borrowing.md
@@ -86,7 +86,7 @@ fn main() {
return v.iter().fold(0, |a, &b| a + b);
}
// Borrow two vectors and sum them.
- // This kind of borrowing does not allow mutation to the borrowed.
+ // This kind of borrowing does not allow mutation through the borrowed reference.
fn foo(v1: &Vec, v2: &Vec) -> i32 {
// do stuff with v1 and v2
let s1 = sum_vec(v1);
@@ -240,7 +240,7 @@ fn main() {
In other words, the mutable borrow is held through the rest of our example. What
we want is for the mutable borrow by `y` to end so that the resource can be
-returned to the owner, `x`. `x` can then provide a immutable borrow to `println!`.
+returned to the owner, `x`. `x` can then provide an immutable borrow to `println!`.
In Rust, borrowing is tied to the scope that the borrow is valid for. And our
scopes look like this:
diff --git a/src/doc/book/syntax-index.md b/src/doc/book/syntax-index.md
index 0259db221b6bc..1e05b01d30d46 100644
--- a/src/doc/book/syntax-index.md
+++ b/src/doc/book/syntax-index.md
@@ -61,7 +61,6 @@
* `-` (`- expr`): arithmetic negation. Overloadable (`Neg`).
* `-=` (`var -= expr`): arithmetic subtraction & assignment. Overloadable (`SubAssign`).
* `->` (`fn(…) -> type`, `|…| -> type`): function and closure return type. See [Functions], [Closures].
-* `-> !` (`fn(…) -> !`, `|…| -> !`): diverging function or closure. See [Diverging Functions].
* `.` (`expr.ident`): member access. See [Structs], [Method Syntax].
* `..` (`..`, `expr..`, `..expr`, `expr..expr`): right-exclusive range literal.
* `..` (`..expr`): struct literal update syntax. See [Structs (Update syntax)].
@@ -159,6 +158,10 @@
* `/*!…*/`: inner block doc comment. See [Comments].
* `/**…*/`: outer block doc comment. See [Comments].
+
+
+* `!`: always empty Never type. See [Diverging Functions].
+
* `()`: empty tuple (*a.k.a.* unit), both literal and type.
diff --git a/src/doc/book/testing.md b/src/doc/book/testing.md
index 86729147ed065..3bdf1b7b7f229 100644
--- a/src/doc/book/testing.md
+++ b/src/doc/book/testing.md
@@ -380,9 +380,9 @@ the `tests` directory.
# The `tests` directory
-Each file in `tests/*.rs` directory is treated as individual crate.
-So, to write an integration test, let's make a `tests` directory, and
-put a `tests/integration_test.rs` file inside, with this as its contents:
+Each file in `tests/*.rs` directory is treated as an individual crate.
+To write an integration test, let's make a `tests` directory and
+put a `tests/integration_test.rs` file inside with this as its contents:
```rust,ignore
extern crate adder;
diff --git a/src/doc/book/traits.md b/src/doc/book/traits.md
index d07fb6b7c45bf..b0d954adf6771 100644
--- a/src/doc/book/traits.md
+++ b/src/doc/book/traits.md
@@ -291,7 +291,7 @@ let result = f.write(buf);
We need to `use` the `Write` trait first:
-```rust,ignore
+```rust,no_run
use std::io::Write;
let mut f = std::fs::File::create("foo.txt").expect("Couldn’t create foo.txt");
diff --git a/src/doc/book/type-aliases.md b/src/doc/book/type-aliases.md
index def2e31f3514b..3798336f0a524 100644
--- a/src/doc/book/type-aliases.md
+++ b/src/doc/book/type-aliases.md
@@ -1,4 +1,4 @@
-% `type` Aliases
+% Type Aliases
The `type` keyword lets you declare an alias of another type:
diff --git a/src/doc/book/variable-bindings.md b/src/doc/book/variable-bindings.md
index 30e922d7f4dc0..03f17371de68d 100644
--- a/src/doc/book/variable-bindings.md
+++ b/src/doc/book/variable-bindings.md
@@ -161,7 +161,7 @@ Could not compile `hello_world`.
Rust will not let us use a value that has not been initialized.
-Let take a minute to talk about this stuff we've added to `println!`.
+Let us take a minute to talk about this stuff we've added to `println!`.
If you include two curly braces (`{}`, some call them moustaches...) in your
string to print, Rust will interpret this as a request to interpolate some sort
diff --git a/src/doc/footer.inc b/src/doc/footer.inc
index 7513e524e73a1..77e151235e822 100644
--- a/src/doc/footer.inc
+++ b/src/doc/footer.inc
@@ -5,4 +5,3 @@ or the MIT license, at your op
This file may not be copied, modified, or distributed except according to those terms.
-
diff --git a/src/doc/grammar.md b/src/doc/grammar.md
index be64379b516e7..690d44cc2cb7b 100644
--- a/src/doc/grammar.md
+++ b/src/doc/grammar.md
@@ -764,6 +764,13 @@ bound-list := bound | bound '+' bound-list
bound := path | lifetime
```
+### Never type
+An empty type
+
+```antlr
+never_type : "!" ;
+```
+
### Object types
**FIXME:** grammar?
diff --git a/src/doc/reference.md b/src/doc/reference.md
index b72c3743a69ce..4838ecd2d42e6 100644
--- a/src/doc/reference.md
+++ b/src/doc/reference.md
@@ -2472,8 +2472,7 @@ The currently implemented features of the reference compiler are:
* - `default_type_parameter_fallback` - Allows type parameter defaults to
influence type inference.
-* - `stmt_expr_attributes` - Allows attributes on expressions and
- non-item statements.
+* - `stmt_expr_attributes` - Allows attributes on expressions.
* - `type_ascription` - Allows type ascription expressions `expr: Type`.
@@ -3110,10 +3109,12 @@ the lambda expression captures its environment by reference, effectively
borrowing pointers to all outer variables mentioned inside the function.
Alternately, the compiler may infer that a lambda expression should copy or
move values (depending on their type) from the environment into the lambda
-expression's captured environment.
+expression's captured environment. A lambda can be forced to capture its
+environment by moving values by prefixing it with the `move` keyword.
In this example, we define a function `ten_times` that takes a higher-order
-function argument, and we then call it with a lambda expression as an argument:
+function argument, and we then call it with a lambda expression as an argument,
+followed by a lambda expression that moves values from its environment.
```
fn ten_times(f: F) where F: Fn(i32) {
@@ -3123,6 +3124,9 @@ fn ten_times(f: F) where F: Fn(i32) {
}
ten_times(|j| println!("hello, {}", j));
+
+let word = "konnichiwa".to_owned();
+ten_times(move |j| println!("{}, {}", word, j));
```
### Infinite loops
@@ -3959,6 +3963,16 @@ the top-level type for the implementation of the called method. If no such metho
found, `.deref()` is called and the compiler continues to search for the method
implementation in the returned type `U`.
+## The `Send` trait
+
+The `Send` trait indicates that a value of this type is safe to send from one
+thread to another.
+
+## The `Sync` trait
+
+The `Sync` trait indicates that a value of this type is safe to share between
+multiple threads.
+
# Memory model
A Rust program's memory consists of a static set of *items* and a *heap*.
@@ -4009,9 +4023,9 @@ Methods that take either `self` or `Box` can optionally place them in a
mutable variable by prefixing them with `mut` (similar to regular arguments):
```
-trait Changer {
- fn change(mut self) -> Self;
- fn modify(mut self: Box) -> Box;
+trait Changer: Sized {
+ fn change(mut self) {}
+ fn modify(mut self: Box) {}
}
```
@@ -4064,6 +4078,12 @@ be ignored in favor of only building the artifacts specified by command line.
Rust code into an existing non-Rust application because it will not have
dynamic dependencies on other Rust code.
+* `--crate-type=cdylib`, `#[crate_type = "cdylib"]` - A dynamic system
+ library will be produced. This is used when compiling Rust code as
+ a dynamic library to be loaded from another language. This output type will
+ create `*.so` files on Linux, `*.dylib` files on OSX, and `*.dll` files on
+ Windows.
+
* `--crate-type=rlib`, `#[crate_type = "rlib"]` - A "Rust library" file will be
produced. This is used as an intermediate artifact and can be thought of as a
"static Rust library". These `rlib` files, unlike `staticlib` files, are
diff --git a/src/doc/rust.css b/src/doc/rust.css
index 9c1b3724d8d81..932594b99126d 100644
--- a/src/doc/rust.css
+++ b/src/doc/rust.css
@@ -159,7 +159,7 @@ em {
footer {
border-top: 1px solid #ddd;
- font-size: 14.3px;
+ font-size: 14px;
font-style: italic;
padding-top: 5px;
margin-top: 3em;
@@ -336,13 +336,11 @@ table th {
/* Code snippets */
-.rusttest { display: none; }
pre.rust { position: relative; }
a.test-arrow {
+ background-color: rgba(78, 139, 202, 0.2);
display: inline-block;
position: absolute;
-
- background-color: #4e8bca;
color: #f5f5f5;
padding: 5px 10px 5px 10px;
border-radius: 5px;
@@ -350,6 +348,10 @@ a.test-arrow {
top: 5px;
right: 5px;
}
+a.test-arrow:hover{
+ background-color: #4e8bca;
+ text-decoration: none;
+}
.unstable-feature {
border: 2px solid red;
diff --git a/src/etc/debugger_pretty_printers_common.py b/src/etc/debugger_pretty_printers_common.py
index e713c7c8387fc..eb562877c8573 100644
--- a/src/etc/debugger_pretty_printers_common.py
+++ b/src/etc/debugger_pretty_printers_common.py
@@ -328,7 +328,7 @@ def extract_length_and_ptr_from_slice(slice_val):
UNQUALIFIED_TYPE_MARKERS = frozenset(["(", "[", "&", "*"])
def extract_type_name(qualified_type_name):
- '''Extracts the type name from a fully qualified path'''
+ """Extracts the type name from a fully qualified path"""
if qualified_type_name[0] in UNQUALIFIED_TYPE_MARKERS:
return qualified_type_name
diff --git a/src/etc/gdb_rust_pretty_printing.py b/src/etc/gdb_rust_pretty_printing.py
index 9b163c835c650..afac8d6bbaefc 100755
--- a/src/etc/gdb_rust_pretty_printing.py
+++ b/src/etc/gdb_rust_pretty_printing.py
@@ -170,7 +170,7 @@ def rust_pretty_printer_lookup_function(gdb_val):
#=------------------------------------------------------------------------------
# Pretty Printer Classes
#=------------------------------------------------------------------------------
-class RustStructPrinter:
+class RustStructPrinter(object):
def __init__(self, val, omit_first_field, omit_type_name, is_tuple_like):
self.__val = val
self.__omit_first_field = omit_first_field
@@ -205,11 +205,12 @@ def display_hint(self):
return ""
-class RustSlicePrinter:
+class RustSlicePrinter(object):
def __init__(self, val):
self.__val = val
- def display_hint(self):
+ @staticmethod
+ def display_hint():
return "array"
def to_string(self):
@@ -226,7 +227,7 @@ def children(self):
yield (str(index), (raw_ptr + index).dereference())
-class RustStringSlicePrinter:
+class RustStringSlicePrinter(object):
def __init__(self, val):
self.__val = val
@@ -236,11 +237,12 @@ def to_string(self):
return '"%s"' % raw_ptr.string(encoding="utf-8", length=length)
-class RustStdVecPrinter:
+class RustStdVecPrinter(object):
def __init__(self, val):
self.__val = val
- def display_hint(self):
+ @staticmethod
+ def display_hint():
return "array"
def to_string(self):
@@ -255,7 +257,7 @@ def children(self):
yield (str(index), (gdb_ptr + index).dereference())
-class RustStdStringPrinter:
+class RustStdStringPrinter(object):
def __init__(self, val):
self.__val = val
@@ -266,7 +268,7 @@ def to_string(self):
length=length)
-class RustCStyleVariantPrinter:
+class RustCStyleVariantPrinter(object):
def __init__(self, val):
assert val.type.get_dwarf_type_kind() == rustpp.DWARF_TYPE_CODE_ENUM
self.__val = val
@@ -275,7 +277,7 @@ def to_string(self):
return str(self.__val.get_wrapped_value())
-class IdentityPrinter:
+class IdentityPrinter(object):
def __init__(self, string):
self.string = string
diff --git a/src/etc/lldb_batchmode.py b/src/etc/lldb_batchmode.py
index 7bbb3577f8d93..4952cf4f82c3b 100644
--- a/src/etc/lldb_batchmode.py
+++ b/src/etc/lldb_batchmode.py
@@ -37,14 +37,14 @@
def print_debug(s):
- "Print something if DEBUG_OUTPUT is True"
+ """Print something if DEBUG_OUTPUT is True"""
global DEBUG_OUTPUT
if DEBUG_OUTPUT:
print("DEBUG: " + str(s))
def normalize_whitespace(s):
- "Replace newlines, tabs, multiple spaces, etc with exactly one space"
+ """Replace newlines, tabs, multiple spaces, etc with exactly one space"""
return re.sub("\s+", " ", s)
@@ -71,7 +71,7 @@ def breakpoint_callback(frame, bp_loc, dict):
def execute_command(command_interpreter, command):
- "Executes a single CLI command"
+ """Executes a single CLI command"""
global new_breakpoints
global registered_breakpoints
diff --git a/src/etc/lldb_rust_formatters.py b/src/etc/lldb_rust_formatters.py
index c0a4c3e9ece93..335acae5fb6f7 100644
--- a/src/etc/lldb_rust_formatters.py
+++ b/src/etc/lldb_rust_formatters.py
@@ -171,10 +171,10 @@ def print_val(lldb_val, internal_dict):
#=--------------------------------------------------------------------------------------------------
def print_struct_val(val, internal_dict, omit_first_field, omit_type_name, is_tuple_like):
- '''
+ """
Prints a struct, tuple, or tuple struct value with Rust syntax.
Ignores any fields before field_start_index.
- '''
+ """
assert val.type.get_dwarf_type_kind() == rustpp.DWARF_TYPE_CODE_STRUCT
if omit_type_name:
@@ -221,7 +221,7 @@ def render_child(child_index):
"body": body}
def print_pointer_val(val, internal_dict):
- '''Prints a pointer value with Rust syntax'''
+ """Prints a pointer value with Rust syntax"""
assert val.type.get_dwarf_type_kind() == rustpp.DWARF_TYPE_CODE_PTR
sigil = "&"
type_name = val.type.get_unqualified_type_name()
@@ -275,8 +275,8 @@ def print_std_string_val(val, internal_dict):
#=--------------------------------------------------------------------------------------------------
def print_array_of_values(array_name, data_ptr_val, length, internal_dict):
- '''Prints a contigous memory range, interpreting it as values of the
- pointee-type of data_ptr_val.'''
+ """Prints a contigous memory range, interpreting it as values of the
+ pointee-type of data_ptr_val."""
data_ptr_type = data_ptr_val.type
assert data_ptr_type.get_dwarf_type_kind() == rustpp.DWARF_TYPE_CODE_PTR
diff --git a/src/etc/local_stage0.sh b/src/etc/local_stage0.sh
index f5f39d264a6b0..ee77206640eab 100755
--- a/src/etc/local_stage0.sh
+++ b/src/etc/local_stage0.sh
@@ -18,7 +18,7 @@ LIB_PREFIX=lib
OS=`uname -s`
case $OS in
- ("Linux"|"FreeBSD"|"DragonFly"|"Bitrig"|"OpenBSD"|"SunOS")
+ ("Linux"|"FreeBSD"|"DragonFly"|"Bitrig"|"OpenBSD"|"SunOS"|"Haiku")
BIN_SUF=
LIB_SUF=.so
;;
@@ -71,6 +71,7 @@ cp ${PREFIX}/${LIB_DIR}/${LIB_PREFIX}log*${LIB_SUF} ${TARG_DIR}/stage0/${LIB_DIR
cp ${PREFIX}/${LIB_DIR}/${LIB_PREFIX}rbml*${LIB_SUF} ${TARG_DIR}/stage0/${LIB_DIR}/
cp ${PREFIX}/${LIB_DIR}/${LIB_PREFIX}serialize*${LIB_SUF} ${TARG_DIR}/stage0/${LIB_DIR}/
cp ${PREFIX}/${LIB_DIR}/${LIB_PREFIX}term*${LIB_SUF} ${TARG_DIR}/stage0/${LIB_DIR}/
+cp ${PREFIX}/${LIB_DIR}/${LIB_PREFIX}proc_macro*${LIB_SUF} ${TARG_DIR}/stage0/${LIB_DIR}/
# do not fail if one of the above fails, as all we need is a working rustc!
exit 0
diff --git a/src/etc/platform-intrinsics/generator.py b/src/etc/platform-intrinsics/generator.py
index a4a91170efb3b..e3c08bb35e075 100644
--- a/src/etc/platform-intrinsics/generator.py
+++ b/src/etc/platform-intrinsics/generator.py
@@ -119,16 +119,19 @@ class Void(Type):
def __init__(self):
Type.__init__(self, 0)
- def compiler_ctor(self):
+ @staticmethod
+ def compiler_ctor():
return '::VOID'
def compiler_ctor_ref(self):
return '&' + self.compiler_ctor()
- def rust_name(self):
+ @staticmethod
+ def rust_name():
return '()'
- def type_info(self, platform_info):
+ @staticmethod
+ def type_info(platform_info):
return None
def __eq__(self, other):
@@ -282,7 +285,7 @@ def __eq__(self, other):
class Pointer(Type):
def __init__(self, elem, llvm_elem, const):
- self._elem = elem;
+ self._elem = elem
self._llvm_elem = llvm_elem
self._const = const
Type.__init__(self, BITWIDTH_POINTER)
@@ -503,7 +506,7 @@ def monomorphise(self):
# must be a power of two
assert width & (width - 1) == 0
def recur(processed, untouched):
- if untouched == []:
+ if not untouched:
ret = processed[0]
args = processed[1:]
yield MonomorphicIntrinsic(self._platform, self.intrinsic, width,
@@ -756,22 +759,26 @@ class ExternBlock(object):
def __init__(self):
pass
- def open(self, platform):
+ @staticmethod
+ def open(platform):
return 'extern "platform-intrinsic" {'
- def render(self, mono):
+ @staticmethod
+ def render(mono):
return ' fn {}{}{};'.format(mono.platform_prefix(),
mono.intrinsic_name(),
mono.intrinsic_signature())
- def close(self):
+ @staticmethod
+ def close():
return '}'
class CompilerDefs(object):
def __init__(self):
pass
- def open(self, platform):
+ @staticmethod
+ def open(platform):
return '''\
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
@@ -798,7 +805,8 @@ def open(self, platform):
if !name.starts_with("{0}") {{ return None }}
Some(match &name["{0}".len()..] {{'''.format(platform.platform_prefix())
- def render(self, mono):
+ @staticmethod
+ def render(mono):
return '''\
"{}" => Intrinsic {{
inputs: {{ static INPUTS: [&'static Type; {}] = [{}]; &INPUTS }},
@@ -810,7 +818,8 @@ def render(self, mono):
mono.compiler_ret(),
mono.llvm_name())
- def close(self):
+ @staticmethod
+ def close():
return '''\
_ => return None,
})
diff --git a/src/etc/test-float-parse/runtests.py b/src/etc/test-float-parse/runtests.py
index 896d63b9f0a01..bc141877b373f 100644
--- a/src/etc/test-float-parse/runtests.py
+++ b/src/etc/test-float-parse/runtests.py
@@ -177,7 +177,6 @@ def run(test):
def interact(proc, queue):
- line = ""
n = 0
while proc.poll() is None:
line = proc.stdout.readline()
@@ -185,7 +184,6 @@ def interact(proc, queue):
continue
assert line.endswith('\n'), "incomplete line: " + repr(line)
queue.put(line)
- line = ""
n += 1
if n % UPDATE_EVERY_N == 0:
msg("got", str(n // 1000) + "k", "records")
diff --git a/src/etc/unicode.py b/src/etc/unicode.py
index 822a3894fccb7..bddc83f63d25d 100755
--- a/src/etc/unicode.py
+++ b/src/etc/unicode.py
@@ -82,28 +82,28 @@ def load_unicode_data(f):
canon_decomp = {}
compat_decomp = {}
- udict = {};
- range_start = -1;
+ udict = {}
+ range_start = -1
for line in fileinput.input(f):
- data = line.split(';');
+ data = line.split(';')
if len(data) != 15:
continue
- cp = int(data[0], 16);
+ cp = int(data[0], 16)
if is_surrogate(cp):
continue
if range_start >= 0:
for i in xrange(range_start, cp):
- udict[i] = data;
- range_start = -1;
+ udict[i] = data
+ range_start = -1
if data[1].endswith(", First>"):
- range_start = cp;
- continue;
- udict[cp] = data;
+ range_start = cp
+ continue
+ udict[cp] = data
for code in udict:
- [code_org, name, gencat, combine, bidi,
+ (code_org, name, gencat, combine, bidi,
decomp, deci, digit, num, mirror,
- old, iso, upcase, lowcase, titlecase ] = udict[code];
+ old, iso, upcase, lowcase, titlecase) = udict[code]
# generate char to char direct common and simple conversions
# uppercase to lowercase
@@ -382,7 +382,7 @@ def emit_bool_trie(f, name, t_data, is_pub=True):
global bytes_old, bytes_new
bytes_old += 8 * len(t_data)
CHUNK = 64
- rawdata = [False] * 0x110000;
+ rawdata = [False] * 0x110000
for (lo, hi) in t_data:
for cp in range(lo, hi + 1):
rawdata[cp] = True
diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs
index 5f9ccd1820ca6..7a07e007ce1c4 100644
--- a/src/liballoc/arc.rs
+++ b/src/liballoc/arc.rs
@@ -10,35 +10,11 @@
#![stable(feature = "rust1", since = "1.0.0")]
-//! Threadsafe reference-counted boxes (the `Arc` type).
+//! Thread-safe reference-counting pointers.
//!
-//! The `Arc` type provides shared ownership of an immutable value through
-//! atomic reference counting.
+//! See the [`Arc`][arc] documentation for more details.
//!
-//! `Weak` is a weak reference to the `Arc` box, and it is created by
-//! the `downgrade` method.
-//! # Examples
-//!
-//! Sharing some immutable data between threads:
-//!
-// Note that we **do not** run these tests here. The windows builders get super
-// unhappy of a thread outlives the main thread and then exits at the same time
-// (something deadlocks) so we just avoid this entirely by not running these
-// tests.
-//! ```no_run
-//! use std::sync::Arc;
-//! use std::thread;
-//!
-//! let five = Arc::new(5);
-//!
-//! for _ in 0..10 {
-//! let five = five.clone();
-//!
-//! thread::spawn(move || {
-//! println!("{:?}", five);
-//! });
-//! }
-//! ```
+//! [arc]: struct.Arc.html
use boxed::Box;
@@ -62,72 +38,114 @@ use heap::deallocate;
const MAX_REFCOUNT: usize = (isize::MAX) as usize;
-/// An atomically reference counted wrapper for shared state.
-/// Destruction is deterministic, and will occur as soon as the last owner is
-/// gone. It is marked as `Send` because it uses atomic reference counting.
+/// A thread-safe reference-counting pointer.
///
-/// If you do not need thread-safety, and just need shared ownership, consider
-/// the [`Rc` type](../rc/struct.Rc.html). It is the same as `Arc`, but
-/// does not use atomics, making it both thread-unsafe as well as significantly
-/// faster when updating the reference count.
+/// The type `Arc` provides shared ownership of a value of type `T`,
+/// allocated in the heap. Invoking [`clone`][clone] on `Arc` produces
+/// a new pointer to the same value in the heap. When the last `Arc`
+/// pointer to a given value is destroyed, the pointed-to value is
+/// also destroyed.
///
-/// Note: the inherent methods defined on `Arc` are all associated functions,
-/// which means that you have to call them as e.g. `Arc::get_mut(&value)`
-/// instead of `value.get_mut()`. This is so that there are no conflicts with
-/// methods on the inner type `T`, which are what you want to call in the
-/// majority of cases.
+/// Shared references in Rust disallow mutation by default, and `Arc` is no
+/// exception. If you need to mutate through an `Arc`, use [`Mutex`][mutex],
+/// [`RwLock`][rwlock], or one of the [`Atomic`][atomic] types.
///
-/// # Examples
+/// `Arc` uses atomic operations for reference counting, so `Arc`s can be
+/// sent between threads. In other words, `Arc` implements [`Send`][send]
+/// as long as `T` implements `Send` and [`Sync`][sync]. The disadvantage is
+/// that atomic operations are more expensive than ordinary memory accesses.
+/// If you are not sharing reference-counted values between threads, consider
+/// using [`rc::Rc`][rc] for lower overhead. `Rc` is a safe default, because
+/// the compiler will catch any attempt to send an `Rc` between threads.
+/// However, a library might choose `Arc` in order to give library consumers
+/// more flexibility.
+///
+/// The [`downgrade`][downgrade] method can be used to create a non-owning
+/// [`Weak`][weak] pointer. A `Weak` pointer can be [`upgrade`][upgrade]d
+/// to an `Arc`, but this will return [`None`][option] if the value has
+/// already been dropped.
///
-/// In this example, a large vector of data will be shared by several threads. First we
-/// wrap it with a `Arc::new` and then clone the `Arc` reference for every thread (which will
-/// increase the reference count atomically).
+/// A cycle between `Arc` pointers will never be deallocated. For this reason,
+/// `Weak` is used to break cycles. For example, a tree could have strong
+/// `Arc` pointers from parent nodes to children, and `Weak` pointers from
+/// children back to their parents.
+///
+/// `Arc` automatically dereferences to `T` (via the [`Deref`][deref] trait),
+/// so you can call `T`'s methods on a value of type `Arc`. To avoid name
+/// clashes with `T`'s methods, the methods of `Arc` itself are [associated
+/// functions][assoc], called using function-like syntax:
///
/// ```
/// use std::sync::Arc;
-/// use std::thread;
+/// let my_arc = Arc::new(());
+///
+/// Arc::downgrade(&my_arc);
+/// ```
///
-/// fn main() {
-/// let numbers: Vec<_> = (0..100).collect();
-/// let shared_numbers = Arc::new(numbers);
+/// `Weak` does not auto-dereference to `T`, because the value may have
+/// already been destroyed.
///
-/// for _ in 0..10 {
-/// // prepare a copy of reference here and it will be moved to the thread
-/// let child_numbers = shared_numbers.clone();
+/// [arc]: struct.Arc.html
+/// [weak]: struct.Weak.html
+/// [rc]: ../../std/rc/struct.Rc.html
+/// [clone]: ../../std/clone/trait.Clone.html#tymethod.clone
+/// [mutex]: ../../std/sync/struct.Mutex.html
+/// [rwlock]: ../../std/sync/struct.RwLock.html
+/// [atomic]: ../../std/sync/atomic/index.html
+/// [send]: ../../std/marker/trait.Send.html
+/// [sync]: ../../std/marker/trait.Sync.html
+/// [deref]: ../../std/ops/trait.Deref.html
+/// [downgrade]: struct.Arc.html#method.downgrade
+/// [upgrade]: struct.Weak.html#method.upgrade
+/// [option]: ../../std/option/enum.Option.html
+/// [assoc]: ../../book/method-syntax.html#associated-functions
///
-/// thread::spawn(move || {
-/// let local_numbers = &child_numbers[..];
+/// # Examples
///
-/// // Work with the local numbers
-/// });
-/// }
-/// }
-/// ```
-/// You can also share mutable data between threads safely
-/// by putting it inside `Mutex` and then share `Mutex` immutably
-/// with `Arc` as shown below.
+/// Sharing some immutable data between threads:
///
-// See comment at the top of this file for why the test is no_run
+// Note that we **do not** run these tests here. The windows builders get super
+// unhappy if a thread outlives the main thread and then exits at the same time
+// (something deadlocks) so we just avoid this entirely by not running these
+// tests.
/// ```no_run
-/// use std::sync::{Arc, Mutex};
+/// use std::sync::Arc;
/// use std::thread;
///
-/// let five = Arc::new(Mutex::new(5));
+/// let five = Arc::new(5);
///
/// for _ in 0..10 {
/// let five = five.clone();
///
/// thread::spawn(move || {
-/// let mut number = five.lock().unwrap();
+/// println!("{:?}", five);
+/// });
+/// }
+/// ```
///
-/// *number += 1;
+/// Sharing a mutable `AtomicUsize`:
///
-/// println!("{}", *number); // prints 6
+/// ```no_run
+/// use std::sync::Arc;
+/// use std::sync::atomic::{AtomicUsize, Ordering};
+/// use std::thread;
+///
+/// let val = Arc::new(AtomicUsize::new(5));
+///
+/// for _ in 0..10 {
+/// let val = val.clone();
+///
+/// thread::spawn(move || {
+/// let v = val.fetch_add(1, Ordering::SeqCst);
+/// println!("{:?}", v);
/// });
/// }
/// ```
-
-#[cfg_attr(stage0, unsafe_no_drop_flag)]
+///
+/// See the [`rc` documentation][rc_examples] for more examples of reference
+/// counting in general.
+///
+/// [rc_examples]: ../../std/rc/index.html#examples
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Arc {
ptr: Shared>,
@@ -141,19 +159,18 @@ unsafe impl Sync for Arc {}
#[unstable(feature = "coerce_unsized", issue = "27732")]
impl, U: ?Sized> CoerceUnsized> for Arc {}
-/// A weak pointer to an `Arc`.
+/// A weak version of [`Arc`][arc].
///
-/// Weak pointers will not keep the data inside of the `Arc` alive, and can be
-/// used to break cycles between `Arc` pointers.
+/// `Weak` pointers do not count towards determining if the inner value
+/// should be dropped.
///
-/// A `Weak` pointer can be upgraded to an `Arc` pointer, but
-/// will return `None` if the value has already been dropped.
+/// The typical way to obtain a `Weak` pointer is to call
+/// [`Arc::downgrade`][downgrade].
///
-/// For example, a tree with parent pointers can be represented by putting the
-/// nodes behind strong `Arc` pointers, and then storing the parent pointers
-/// as `Weak` pointers.
-
-#[cfg_attr(stage0, unsafe_no_drop_flag)]
+/// See the [`Arc`][arc] documentation for more details.
+///
+/// [arc]: struct.Arc.html
+/// [downgrade]: struct.Arc.html#method.downgrade
#[stable(feature = "arc_weak", since = "1.4.0")]
pub struct Weak {
ptr: Shared>,
@@ -211,12 +228,15 @@ impl Arc {
Arc { ptr: unsafe { Shared::new(Box::into_raw(x)) } }
}
- /// Unwraps the contained value if the `Arc` has exactly one strong reference.
+ /// Returns the contained value, if the `Arc` has exactly one strong reference.
///
- /// Otherwise, an `Err` is returned with the same `Arc`.
+ /// Otherwise, an [`Err`][result] is returned with the same `Arc` that was
+ /// passed in.
///
/// This will succeed even if there are outstanding weak references.
///
+ /// [result]: ../../std/result/enum.Result.html
+ ///
/// # Examples
///
/// ```
@@ -227,7 +247,7 @@ impl Arc {
///
/// let x = Arc::new(4);
/// let _y = x.clone();
- /// assert_eq!(Arc::try_unwrap(x), Err(Arc::new(4)));
+ /// assert_eq!(*Arc::try_unwrap(x).unwrap_err(), 4);
/// ```
#[inline]
#[stable(feature = "arc_unique", since = "1.4.0")]
@@ -253,7 +273,9 @@ impl Arc {
}
impl Arc {
- /// Downgrades the `Arc` to a `Weak` reference.
+ /// Creates a new [`Weak`][weak] pointer to this value.
+ ///
+ /// [weak]: struct.Weak.html
///
/// # Examples
///
@@ -291,7 +313,27 @@ impl Arc {
}
}
- /// Get the number of weak references to this value.
+ /// Gets the number of [`Weak`][weak] pointers to this value.
+ ///
+ /// Be careful how you use this information, because another thread
+ /// may change the weak count at any time.
+ ///
+ /// [weak]: struct.Weak.html
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(arc_counts)]
+ ///
+ /// use std::sync::Arc;
+ ///
+ /// let five = Arc::new(5);
+ /// let _weak_five = Arc::downgrade(&five);
+ ///
+ /// // This assertion is deterministic because we haven't shared
+ /// // the `Arc` or `Weak` between threads.
+ /// assert_eq!(1, Arc::weak_count(&five));
+ /// ```
#[inline]
#[unstable(feature = "arc_counts", reason = "not clearly useful, and racy",
issue = "28356")]
@@ -299,7 +341,25 @@ impl Arc {
this.inner().weak.load(SeqCst) - 1
}
- /// Get the number of strong references to this value.
+ /// Gets the number of strong (`Arc`) pointers to this value.
+ ///
+ /// Be careful how you use this information, because another thread
+ /// may change the strong count at any time.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(arc_counts)]
+ ///
+ /// use std::sync::Arc;
+ ///
+ /// let five = Arc::new(5);
+ /// let _also_five = five.clone();
+ ///
+ /// // This assertion is deterministic because we haven't shared
+ /// // the `Arc` between threads.
+ /// assert_eq!(2, Arc::strong_count(&five));
+ /// ```
#[inline]
#[unstable(feature = "arc_counts", reason = "not clearly useful, and racy",
issue = "28356")]
@@ -336,8 +396,8 @@ impl Arc {
#[unstable(feature = "ptr_eq",
reason = "newly added",
issue = "36497")]
- /// Return whether two `Arc` references point to the same value
- /// (not just values that compare equal).
+ /// Returns true if the two `Arc`s point to the same value (not
+ /// just values that compare as equal).
///
/// # Examples
///
@@ -362,9 +422,10 @@ impl Arc {
#[stable(feature = "rust1", since = "1.0.0")]
impl Clone for Arc {
- /// Makes a clone of the `Arc`.
+ /// Makes a clone of the `Arc` pointer.
///
- /// This increases the strong reference count.
+ /// This creates another pointer to the same inner value, increasing the
+ /// strong reference count.
///
/// # Examples
///
@@ -420,11 +481,17 @@ impl Deref for Arc {
}
impl Arc {
- /// Make a mutable reference into the given `Arc`.
- /// If the `Arc` has more than one strong reference, or any weak
- /// references, the inner data is cloned.
+ /// Makes a mutable reference into the given `Arc`.
+ ///
+ /// If there are other `Arc` or [`Weak`][weak] pointers to the same value,
+ /// then `make_mut` will invoke [`clone`][clone] on the inner value to
+ /// ensure unique ownership. This is also referred to as clone-on-write.
+ ///
+ /// See also [`get_mut`][get_mut], which will fail rather than cloning.
///
- /// This is also referred to as a copy-on-write.
+ /// [weak]: struct.Weak.html
+ /// [clone]: ../../std/clone/trait.Clone.html#tymethod.clone
+ /// [get_mut]: struct.Arc.html#method.get_mut
///
/// # Examples
///
@@ -439,10 +506,9 @@ impl Arc {
/// *Arc::make_mut(&mut data) += 1; // Won't clone anything
/// *Arc::make_mut(&mut other_data) *= 2; // Won't clone anything
///
- /// // Note: data and other_data now point to different numbers
+ /// // Now `data` and `other_data` point to different values.
/// assert_eq!(*data, 8);
/// assert_eq!(*other_data, 12);
- ///
/// ```
#[inline]
#[stable(feature = "arc_unique", since = "1.4.0")]
@@ -501,8 +567,19 @@ impl Arc {
}
impl Arc {
- /// Returns a mutable reference to the contained value if the `Arc` has
- /// one strong reference and no weak references.
+ /// Returns a mutable reference to the inner value, if there are
+ /// no other `Arc` or [`Weak`][weak] pointers to the same value.
+ ///
+ /// Returns [`None`][option] otherwise, because it is not safe to
+ /// mutate a shared value.
+ ///
+ /// See also [`make_mut`][make_mut], which will [`clone`][clone]
+ /// the inner value when it's shared.
+ ///
+ /// [weak]: struct.Weak.html
+ /// [option]: ../../std/option/enum.Option.html
+ /// [make_mut]: struct.Arc.html#method.make_mut
+ /// [clone]: ../../std/clone/trait.Clone.html#tymethod.clone
///
/// # Examples
///
@@ -564,30 +641,32 @@ impl Arc {
#[stable(feature = "rust1", since = "1.0.0")]
impl Drop for Arc {
- /// Drops the `Arc`.
+ /// Drops the `Arc`.
///
/// This will decrement the strong reference count. If the strong reference
- /// count becomes zero and the only other references are `Weak` ones,
- /// `drop`s the inner value.
+ /// count reaches zero then the only other references (if any) are
+ /// [`Weak`][weak], so we `drop` the inner value.
+ ///
+ /// [weak]: struct.Weak.html
///
/// # Examples
///
/// ```
/// use std::sync::Arc;
///
- /// {
- /// let five = Arc::new(5);
- ///
- /// // stuff
+ /// struct Foo;
///
- /// drop(five); // explicit drop
+ /// impl Drop for Foo {
+ /// fn drop(&mut self) {
+ /// println!("dropped!");
+ /// }
/// }
- /// {
- /// let five = Arc::new(5);
///
- /// // stuff
+ /// let foo = Arc::new(Foo);
+ /// let foo2 = foo.clone();
///
- /// } // implicit drop
+ /// drop(foo); // Doesn't print anything
+ /// drop(foo2); // Prints "dropped!"
/// ```
#[unsafe_destructor_blind_to_params]
#[inline]
@@ -625,10 +704,14 @@ impl Drop for Arc {
}
impl Weak {
- /// Constructs a new `Weak` without an accompanying instance of T.
+ /// Constructs a new `Weak`, without an accompanying instance of `T`.
///
- /// This allocates memory for T, but does not initialize it. Calling
- /// Weak::upgrade() on the return value always gives None.
+ /// This allocates memory for `T`, but does not initialize it. Calling
+ /// [`upgrade`][upgrade] on the return value always gives
+ /// [`None`][option].
+ ///
+ /// [upgrade]: struct.Weak.html#method.upgrade
+ /// [option]: ../../std/option/enum.Option.html
///
/// # Examples
///
@@ -636,6 +719,7 @@ impl Weak {
/// use std::sync::Weak;
///
/// let empty: Weak = Weak::new();
+ /// assert!(empty.upgrade().is_none());
/// ```
#[stable(feature = "downgraded_weak", since = "1.10.0")]
pub fn new() -> Weak {
@@ -652,12 +736,13 @@ impl Weak {
}
impl Weak {
- /// Upgrades a weak reference to a strong reference.
+ /// Upgrades the `Weak` pointer to an [`Arc`][arc], if possible.
///
- /// Upgrades the `Weak` reference to an `Arc`, if possible.
+ /// Returns [`None`][option] if the strong count has reached zero and the
+ /// inner value was destroyed.
///
- /// Returns `None` if there were no strong references and the data was
- /// destroyed.
+ /// [arc]: struct.Arc.html
+ /// [option]: ../../std/option/enum.Option.html
///
/// # Examples
///
@@ -669,6 +754,13 @@ impl Weak {
/// let weak_five = Arc::downgrade(&five);
///
/// let strong_five: Option> = weak_five.upgrade();
+ /// assert!(strong_five.is_some());
+ ///
+ /// // Destroy all strong pointers.
+ /// drop(strong_five);
+ /// drop(five);
+ ///
+ /// assert!(weak_five.upgrade().is_none());
/// ```
#[stable(feature = "arc_weak", since = "1.4.0")]
pub fn upgrade(&self) -> Option> {
@@ -711,9 +803,10 @@ impl Weak {
#[stable(feature = "arc_weak", since = "1.4.0")]
impl Clone for Weak {
- /// Makes a clone of the `Weak`.
+ /// Makes a clone of the `Weak` pointer.
///
- /// This increases the weak reference count.
+ /// This creates another pointer to the same inner value, increasing the
+ /// weak reference count.
///
/// # Examples
///
@@ -745,7 +838,23 @@ impl Clone for Weak {
#[stable(feature = "downgraded_weak", since = "1.10.0")]
impl Default for Weak {
- /// Constructs a new `Weak` without an accompanying instance of T.
+ /// Constructs a new `Weak`, without an accompanying instance of `T`.
+ ///
+ /// This allocates memory for `T`, but does not initialize it. Calling
+ /// [`upgrade`][upgrade] on the return value always gives
+ /// [`None`][option].
+ ///
+ /// [upgrade]: struct.Weak.html#method.upgrade
+ /// [option]: ../../std/option/enum.Option.html
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::sync::Weak;
+ ///
+ /// let empty: Weak = Default::default();
+ /// assert!(empty.upgrade().is_none());
+ /// ```
fn default() -> Weak {
Weak::new()
}
@@ -753,7 +862,7 @@ impl Default for Weak {
#[stable(feature = "arc_weak", since = "1.4.0")]
impl Drop for Weak {
- /// Drops the `Weak`.
+ /// Drops the `Weak` pointer.
///
/// This will decrement the weak reference count.
///
@@ -762,21 +871,22 @@ impl Drop for Weak {
/// ```
/// use std::sync::Arc;
///
- /// {
- /// let five = Arc::new(5);
- /// let weak_five = Arc::downgrade(&five);
- ///
- /// // stuff
+ /// struct Foo;
///
- /// drop(weak_five); // explicit drop
+ /// impl Drop for Foo {
+ /// fn drop(&mut self) {
+ /// println!("dropped!");
+ /// }
/// }
- /// {
- /// let five = Arc::new(5);
- /// let weak_five = Arc::downgrade(&five);
///
- /// // stuff
+ /// let foo = Arc::new(Foo);
+ /// let weak_foo = Arc::downgrade(&foo);
+ /// let other_weak_foo = weak_foo.clone();
///
- /// } // implicit drop
+ /// drop(weak_foo); // Doesn't print anything
+ /// drop(foo); // Prints "dropped!"
+ ///
+ /// assert!(other_weak_foo.upgrade().is_none());
/// ```
fn drop(&mut self) {
let ptr = *self.ptr;
@@ -798,9 +908,9 @@ impl Drop for Weak {
#[stable(feature = "rust1", since = "1.0.0")]
impl PartialEq for Arc {
- /// Equality for two `Arc`s.
+ /// Equality for two `Arc`s.
///
- /// Two `Arc`s are equal if their inner value are equal.
+ /// Two `Arc`s are equal if their inner values are equal.
///
/// # Examples
///
@@ -809,15 +919,15 @@ impl PartialEq for Arc {
///
/// let five = Arc::new(5);
///
- /// five == Arc::new(5);
+ /// assert!(five == Arc::new(5));
/// ```
fn eq(&self, other: &Arc) -> bool {
*(*self) == *(*other)
}
- /// Inequality for two `Arc`s.
+ /// Inequality for two `Arc`s.
///
- /// Two `Arc`s are unequal if their inner value are unequal.
+ /// Two `Arc`s are unequal if their inner values are unequal.
///
/// # Examples
///
@@ -826,7 +936,7 @@ impl PartialEq for Arc {
///
/// let five = Arc::new(5);
///
- /// five != Arc::new(5);
+ /// assert!(five != Arc::new(6));
/// ```
fn ne(&self, other: &Arc) -> bool {
*(*self) != *(*other)
@@ -834,7 +944,7 @@ impl PartialEq for Arc {
}
#[stable(feature = "rust1", since = "1.0.0")]
impl PartialOrd for Arc {
- /// Partial comparison for two `Arc`s.
+ /// Partial comparison for two `Arc`s.
///
/// The two are compared by calling `partial_cmp()` on their inner values.
///
@@ -842,16 +952,17 @@ impl PartialOrd for Arc {
///
/// ```
/// use std::sync::Arc;
+ /// use std::cmp::Ordering;
///
/// let five = Arc::new(5);
///
- /// five.partial_cmp(&Arc::new(5));
+ /// assert_eq!(Some(Ordering::Less), five.partial_cmp(&Arc::new(6)));
/// ```
fn partial_cmp(&self, other: &Arc) -> Option {
(**self).partial_cmp(&**other)
}
- /// Less-than comparison for two `Arc`s.
+ /// Less-than comparison for two `Arc`s.
///
/// The two are compared by calling `<` on their inner values.
///
@@ -862,13 +973,13 @@ impl PartialOrd for Arc {
///
/// let five = Arc::new(5);
///
- /// five < Arc::new(5);
+ /// assert!(five < Arc::new(6));
/// ```
fn lt(&self, other: &Arc) -> bool {
*(*self) < *(*other)
}
- /// 'Less-than or equal to' comparison for two `Arc`s.
+ /// 'Less than or equal to' comparison for two `Arc`s.
///
/// The two are compared by calling `<=` on their inner values.
///
@@ -879,13 +990,13 @@ impl PartialOrd for Arc {
///
/// let five = Arc::new(5);
///
- /// five <= Arc::new(5);
+ /// assert!(five <= Arc::new(5));
/// ```
fn le(&self, other: &Arc) -> bool {
*(*self) <= *(*other)
}
- /// Greater-than comparison for two `Arc`s.
+ /// Greater-than comparison for two `Arc`s.
///
/// The two are compared by calling `>` on their inner values.
///
@@ -896,13 +1007,13 @@ impl PartialOrd for Arc {
///
/// let five = Arc::new(5);
///
- /// five > Arc::new(5);
+ /// assert!(five > Arc::new(4));
/// ```
fn gt(&self, other: &Arc) -> bool {
*(*self) > *(*other)
}
- /// 'Greater-than or equal to' comparison for two `Arc`s.
+ /// 'Greater than or equal to' comparison for two `Arc`s.
///
/// The two are compared by calling `>=` on their inner values.
///
@@ -913,7 +1024,7 @@ impl PartialOrd for Arc {
///
/// let five = Arc::new(5);
///
- /// five >= Arc::new(5);
+ /// assert!(five >= Arc::new(5));
/// ```
fn ge(&self, other: &Arc) -> bool {
*(*self) >= *(*other)
@@ -921,6 +1032,20 @@ impl PartialOrd for Arc {
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Ord for Arc {
+ /// Comparison for two `Arc`s.
+ ///
+ /// The two are compared by calling `cmp()` on their inner values.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::sync::Arc;
+ /// use std::cmp::Ordering;
+ ///
+ /// let five = Arc::new(5);
+ ///
+ /// assert_eq!(Ordering::Less, five.cmp(&Arc::new(6)));
+ /// ```
fn cmp(&self, other: &Arc) -> Ordering {
(**self).cmp(&**other)
}
@@ -951,7 +1076,16 @@ impl fmt::Pointer for Arc {
#[stable(feature = "rust1", since = "1.0.0")]
impl Default for Arc {
- /// Creates a new `Arc`, with the `Default` value for T.
+ /// Creates a new `Arc`, with the `Default` value for `T`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::sync::Arc;
+ ///
+ /// let x: Arc = Default::default();
+ /// assert_eq!(*x, 0);
+ /// ```
fn default() -> Arc {
Arc::new(Default::default())
}
@@ -1002,6 +1136,7 @@ mod tests {
}
#[test]
+ #[cfg_attr(target_os = "emscripten", ignore)]
fn manually_share_arc() {
let v = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let arc_v = Arc::new(v);
diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs
index bc9b6e805efc9..28f4dda140883 100644
--- a/src/liballoc/boxed.rs
+++ b/src/liballoc/boxed.rs
@@ -244,12 +244,14 @@ impl Box {
/// the destructor of `T` and free the allocated memory. Since the
/// way `Box` allocates and releases memory is unspecified, the
/// only valid pointer to pass to this function is the one taken
- /// from another `Box` via the `Box::into_raw` function.
+ /// from another `Box` via the [`Box::into_raw`] function.
///
/// This function is unsafe because improper use may lead to
/// memory problems. For example, a double-free may occur if the
/// function is called twice on the same raw pointer.
///
+ /// [`Box::into_raw`]: struct.Box.html#method.into_raw
+ ///
/// # Examples
///
/// ```
@@ -269,12 +271,14 @@ impl Box {
/// memory previously managed by the `Box`. In particular, the
/// caller should properly destroy `T` and release the memory. The
/// proper way to do so is to convert the raw pointer back into a
- /// `Box` with the `Box::from_raw` function.
+ /// `Box` with the [`Box::from_raw`] function.
///
/// Note: this is an associated function, which means that you have
/// to call it as `Box::into_raw(b)` instead of `b.into_raw()`. This
/// is so that there is no conflict with a method on the inner type.
///
+ /// [`Box::from_raw`]: struct.Box.html#method.from_raw
+ ///
/// # Examples
///
/// ```
diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs
index c6453da3f4697..31491106d97ee 100644
--- a/src/liballoc/lib.rs
+++ b/src/liballoc/lib.rs
@@ -88,7 +88,6 @@
#![feature(staged_api)]
#![feature(unboxed_closures)]
#![feature(unique)]
-#![cfg_attr(stage0, feature(unsafe_no_drop_flag))]
#![feature(unsize)]
#![cfg_attr(not(test), feature(fused, fn_traits, placement_new_protocol))]
diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs
index 23542215fa890..f23ea0ea8bf71 100644
--- a/src/liballoc/raw_vec.rs
+++ b/src/liballoc/raw_vec.rs
@@ -44,7 +44,6 @@ use core::cmp;
/// `shrink_to_fit`, and `from_box` will actually set RawVec's private capacity
/// field. This allows zero-sized types to not be special-cased by consumers of
/// this type.
-#[cfg_attr(stage0, unsafe_no_drop_flag)]
pub struct RawVec {
ptr: Unique,
cap: usize,
@@ -58,11 +57,7 @@ impl RawVec {
pub fn new() -> Self {
unsafe {
// !0 is usize::MAX. This branch should be stripped at compile time.
- let cap = if mem::size_of::() == 0 {
- !0
- } else {
- 0
- };
+ let cap = if mem::size_of::() == 0 { !0 } else { 0 };
// heap::EMPTY doubles as "unallocated" and "zero-sized allocation"
RawVec {
@@ -210,11 +205,7 @@ impl RawVec {
let (new_cap, ptr) = if self.cap == 0 {
// skip to 4 because tiny Vec's are dumb; but not if that would cause overflow
- let new_cap = if elem_size > (!0) / 8 {
- 1
- } else {
- 4
- };
+ let new_cap = if elem_size > (!0) / 8 { 1 } else { 4 };
let ptr = heap::allocate(new_cap * elem_size, align);
(new_cap, ptr)
} else {
@@ -348,7 +339,7 @@ impl RawVec {
let elem_size = mem::size_of::();
// Nothing we can really do about these checks :(
let required_cap = used_cap.checked_add(needed_extra_cap)
- .expect("capacity overflow");
+ .expect("capacity overflow");
// Cannot overflow, because `cap <= isize::MAX`, and type of `cap` is `usize`.
let double_cap = self.cap * 2;
// `double_cap` guarantees exponential growth.
diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs
index 32e5587ff4128..740d13c476222 100644
--- a/src/liballoc/rc.rs
+++ b/src/liballoc/rc.rs
@@ -10,90 +10,139 @@
#![allow(deprecated)]
-//! Unsynchronized reference-counted boxes (the `Rc` type) which are usable
-//! only within a single thread.
+//! Single-threaded reference-counting pointers.
//!
-//! The `Rc` type provides shared ownership of an immutable value.
-//! Destruction is deterministic, and will occur as soon as the last owner is
-//! gone. It is marked as non-sendable because it avoids the overhead of atomic
-//! reference counting.
+//! The type [`Rc`][rc] provides shared ownership of a value of type `T`,
+//! allocated in the heap. Invoking [`clone`][clone] on `Rc` produces a new
+//! pointer to the same value in the heap. When the last `Rc` pointer to a
+//! given value is destroyed, the pointed-to value is also destroyed.
//!
-//! The `downgrade` method can be used to create a non-owning `Weak` pointer
-//! to the box. A `Weak` pointer can be upgraded to an `Rc` pointer, but
-//! will return `None` if the value has already been dropped.
+//! Shared references in Rust disallow mutation by default, and `Rc` is no
+//! exception. If you need to mutate through an `Rc`, use [`Cell`][cell] or
+//! [`RefCell`][refcell].
//!
-//! For example, a tree with parent pointers can be represented by putting the
-//! nodes behind strong `Rc` pointers, and then storing the parent pointers
-//! as `Weak` pointers.
+//! `Rc` uses non-atomic reference counting. This means that overhead is very
+//! low, but an `Rc` cannot be sent between threads, and consequently `Rc`
+//! does not implement [`Send`][send]. As a result, the Rust compiler
+//! will check *at compile time* that you are not sending `Rc`s between
+//! threads. If you need multi-threaded, atomic reference counting, use
+//! [`sync::Arc`][arc].
+//!
+//! The [`downgrade`][downgrade] method can be used to create a non-owning
+//! [`Weak`][weak] pointer. A `Weak` pointer can be [`upgrade`][upgrade]d
+//! to an `Rc`, but this will return [`None`][option] if the value has
+//! already been dropped.
+//!
+//! A cycle between `Rc` pointers will never be deallocated. For this reason,
+//! `Weak` is used to break cycles. For example, a tree could have strong
+//! `Rc` pointers from parent nodes to children, and `Weak` pointers from
+//! children back to their parents.
+//!
+//! `Rc` automatically dereferences to `T` (via the [`Deref`][deref] trait),
+//! so you can call `T`'s methods on a value of type `Rc`. To avoid name
+//! clashes with `T`'s methods, the methods of `Rc` itself are [associated
+//! functions][assoc], called using function-like syntax:
+//!
+//! ```
+//! use std::rc::Rc;
+//! let my_rc = Rc::new(());
+//!
+//! Rc::downgrade(&my_rc);
+//! ```
+//!
+//! `Weak` does not auto-dereference to `T`, because the value may have
+//! already been destroyed.
+//!
+//! [rc]: struct.Rc.html
+//! [weak]: struct.Weak.html
+//! [clone]: ../../std/clone/trait.Clone.html#tymethod.clone
+//! [cell]: ../../std/cell/struct.Cell.html
+//! [refcell]: ../../std/cell/struct.RefCell.html
+//! [send]: ../../std/marker/trait.Send.html
+//! [arc]: ../../std/sync/struct.Arc.html
+//! [deref]: ../../std/ops/trait.Deref.html
+//! [downgrade]: struct.Rc.html#method.downgrade
+//! [upgrade]: struct.Weak.html#method.upgrade
+//! [option]: ../../std/option/enum.Option.html
+//! [assoc]: ../../book/method-syntax.html#associated-functions
//!
//! # Examples
//!
//! Consider a scenario where a set of `Gadget`s are owned by a given `Owner`.
//! We want to have our `Gadget`s point to their `Owner`. We can't do this with
//! unique ownership, because more than one gadget may belong to the same
-//! `Owner`. `Rc` allows us to share an `Owner` between multiple `Gadget`s,
+//! `Owner`. `Rc` allows us to share an `Owner` between multiple `Gadget`s,
//! and have the `Owner` remain allocated as long as any `Gadget` points at it.
//!
-//! ```rust
+//! ```
//! use std::rc::Rc;
//!
//! struct Owner {
-//! name: String
+//! name: String,
//! // ...other fields
//! }
//!
//! struct Gadget {
//! id: i32,
-//! owner: Rc
+//! owner: Rc,
//! // ...other fields
//! }
//!
//! fn main() {
-//! // Create a reference counted Owner.
-//! let gadget_owner : Rc = Rc::new(
-//! Owner { name: String::from("Gadget Man") }
+//! // Create a reference-counted `Owner`.
+//! let gadget_owner: Rc = Rc::new(
+//! Owner {
+//! name: "Gadget Man".to_string(),
+//! }
//! );
//!
-//! // Create Gadgets belonging to gadget_owner. To increment the reference
-//! // count we clone the `Rc` object.
-//! let gadget1 = Gadget { id: 1, owner: gadget_owner.clone() };
-//! let gadget2 = Gadget { id: 2, owner: gadget_owner.clone() };
+//! // Create `Gadget`s belonging to `gadget_owner`. Cloning the `Rc`
+//! // value gives us a new pointer to the same `Owner` value, incrementing
+//! // the reference count in the process.
+//! let gadget1 = Gadget {
+//! id: 1,
+//! owner: gadget_owner.clone(),
+//! };
+//! let gadget2 = Gadget {
+//! id: 2,
+//! owner: gadget_owner.clone(),
+//! };
//!
+//! // Dispose of our local variable `gadget_owner`.
//! drop(gadget_owner);
//!
-//! // Despite dropping gadget_owner, we're still able to print out the name
-//! // of the Owner of the Gadgets. This is because we've only dropped the
-//! // reference count object, not the Owner it wraps. As long as there are
-//! // other `Rc` objects pointing at the same Owner, it will remain
-//! // allocated. Notice that the `Rc` wrapper around Gadget.owner gets
-//! // automatically dereferenced for us.
+//! // Despite dropping `gadget_owner`, we're still able to print out the name
+//! // of the `Owner` of the `Gadget`s. This is because we've only dropped a
+//! // single `Rc`, not the `Owner` it points to. As long as there are
+//! // other `Rc` values pointing at the same `Owner`, it will remain
+//! // allocated. The field projection `gadget1.owner.name` works because
+//! // `Rc` automatically dereferences to `Owner`.
//! println!("Gadget {} owned by {}", gadget1.id, gadget1.owner.name);
//! println!("Gadget {} owned by {}", gadget2.id, gadget2.owner.name);
//!
-//! // At the end of the method, gadget1 and gadget2 get destroyed, and with
-//! // them the last counted references to our Owner. Gadget Man now gets
-//! // destroyed as well.
+//! // At the end of the function, `gadget1` and `gadget2` are destroyed, and
+//! // with them the last counted references to our `Owner`. Gadget Man now
+//! // gets destroyed as well.
//! }
//! ```
//!
//! If our requirements change, and we also need to be able to traverse from
-//! Owner → Gadget, we will run into problems: an `Rc` pointer from Owner
-//! → Gadget introduces a cycle between the objects. This means that their
-//! reference counts can never reach 0, and the objects will remain allocated: a
-//! memory leak. In order to get around this, we can use `Weak` pointers.
-//! These pointers don't contribute to the total count.
+//! `Owner` to `Gadget`, we will run into problems. An `Rc` pointer from `Owner`
+//! to `Gadget` introduces a cycle between the values. This means that their
+//! reference counts can never reach 0, and the values will remain allocated
+//! forever: a memory leak. In order to get around this, we can use `Weak`
+//! pointers.
//!
//! Rust actually makes it somewhat difficult to produce this loop in the first
-//! place: in order to end up with two objects that point at each other, one of
-//! them needs to be mutable. This is problematic because `Rc` enforces
-//! memory safety by only giving out shared references to the object it wraps,
+//! place. In order to end up with two values that point at each other, one of
+//! them needs to be mutable. This is difficult because `Rc` enforces
+//! memory safety by only giving out shared references to the value it wraps,
//! and these don't allow direct mutation. We need to wrap the part of the
-//! object we wish to mutate in a `RefCell`, which provides *interior
+//! value we wish to mutate in a [`RefCell`][refcell], which provides *interior
//! mutability*: a method to achieve mutability through a shared reference.
-//! `RefCell` enforces Rust's borrowing rules at runtime. Read the `Cell`
-//! documentation for more details on interior mutability.
+//! `RefCell` enforces Rust's borrowing rules at runtime.
//!
-//! ```rust
+//! ```
//! use std::rc::Rc;
//! use std::rc::Weak;
//! use std::cell::RefCell;
@@ -111,41 +160,58 @@
//! }
//!
//! fn main() {
-//! // Create a reference counted Owner. Note the fact that we've put the
-//! // Owner's vector of Gadgets inside a RefCell so that we can mutate it
-//! // through a shared reference.
-//! let gadget_owner : Rc = Rc::new(
+//! // Create a reference-counted `Owner`. Note that we've put the `Owner`'s
+//! // vector of `Gadget`s inside a `RefCell` so that we can mutate it through
+//! // a shared reference.
+//! let gadget_owner: Rc = Rc::new(
//! Owner {
//! name: "Gadget Man".to_string(),
-//! gadgets: RefCell::new(Vec::new()),
+//! gadgets: RefCell::new(vec![]),
+//! }
+//! );
+//!
+//! // Create `Gadget`s belonging to `gadget_owner`, as before.
+//! let gadget1 = Rc::new(
+//! Gadget {
+//! id: 1,
+//! owner: gadget_owner.clone(),
+//! }
+//! );
+//! let gadget2 = Rc::new(
+//! Gadget {
+//! id: 2,
+//! owner: gadget_owner.clone(),
//! }
//! );
//!
-//! // Create Gadgets belonging to gadget_owner as before.
-//! let gadget1 = Rc::new(Gadget{id: 1, owner: gadget_owner.clone()});
-//! let gadget2 = Rc::new(Gadget{id: 2, owner: gadget_owner.clone()});
+//! // Add the `Gadget`s to their `Owner`.
+//! {
+//! let mut gadgets = gadget_owner.gadgets.borrow_mut();
+//! gadgets.push(Rc::downgrade(&gadget1));
+//! gadgets.push(Rc::downgrade(&gadget2));
//!
-//! // Add the Gadgets to their Owner. To do this we mutably borrow from
-//! // the RefCell holding the Owner's Gadgets.
-//! gadget_owner.gadgets.borrow_mut().push(Rc::downgrade(&gadget1));
-//! gadget_owner.gadgets.borrow_mut().push(Rc::downgrade(&gadget2));
+//! // `RefCell` dynamic borrow ends here.
+//! }
//!
-//! // Iterate over our Gadgets, printing their details out
-//! for gadget_opt in gadget_owner.gadgets.borrow().iter() {
+//! // Iterate over our `Gadget`s, printing their details out.
+//! for gadget_weak in gadget_owner.gadgets.borrow().iter() {
//!
-//! // gadget_opt is a Weak. Since weak pointers can't guarantee
-//! // that their object is still allocated, we need to call upgrade()
-//! // on them to turn them into a strong reference. This returns an
-//! // Option, which contains a reference to our object if it still
-//! // exists.
-//! let gadget = gadget_opt.upgrade().unwrap();
+//! // `gadget_weak` is a `Weak`. Since `Weak` pointers can't
+//! // guarantee the value is still allocated, we need to call
+//! // `upgrade`, which returns an `Option>`.
+//! //
+//! // In this case we know the value still exists, so we simply
+//! // `unwrap` the `Option`. In a more complicated program, you might
+//! // need graceful error handling for a `None` result.
+//!
+//! let gadget = gadget_weak.upgrade().unwrap();
//! println!("Gadget {} owned by {}", gadget.id, gadget.owner.name);
//! }
//!
-//! // At the end of the method, gadget_owner, gadget1 and gadget2 get
-//! // destroyed. There are now no strong (`Rc`) references to the gadgets.
-//! // Once they get destroyed, the Gadgets get destroyed. This zeroes the
-//! // reference count on Gadget Man, they get destroyed as well.
+//! // At the end of the function, `gadget_owner`, `gadget1`, and `gadget2`
+//! // are destroyed. There are now no strong (`Rc`) pointers to the
+//! // gadgets, so they are destroyed. This zeroes the reference count on
+//! // Gadget Man, so he gets destroyed as well.
//! }
//! ```
@@ -164,13 +230,14 @@ use core::hash::{Hash, Hasher};
use core::intrinsics::{abort, assume};
use core::marker;
use core::marker::Unsize;
-use core::mem::{self, align_of_val, forget, size_of_val, uninitialized};
+use core::mem::{self, align_of_val, forget, size_of, size_of_val, uninitialized};
use core::ops::Deref;
use core::ops::CoerceUnsized;
use core::ptr::{self, Shared};
use core::convert::From;
use heap::deallocate;
+use raw_vec::RawVec;
struct RcBox {
strong: Cell,
@@ -179,16 +246,14 @@ struct RcBox {
}
-/// A reference-counted pointer type over an immutable value.
+/// A single-threaded reference-counting pointer.
///
-/// See the [module level documentation](./index.html) for more details.
+/// See the [module-level documentation](./index.html) for more details.
///
-/// Note: the inherent methods defined on `Rc` are all associated functions,
-/// which means that you have to call them as e.g. `Rc::get_mut(&value)` instead
-/// of `value.get_mut()`. This is so that there are no conflicts with methods
-/// on the inner type `T`, which are what you want to call in the majority of
-/// cases.
-#[cfg_attr(stage0, unsafe_no_drop_flag)]
+/// The inherent methods of `Rc` are all associated functions, which means
+/// that you have to call them as e.g. `Rc::get_mut(&value)` instead of
+/// `value.get_mut()`. This avoids conflicts with methods of the inner
+/// type `T`.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Rc {
ptr: Shared>,
@@ -229,12 +294,15 @@ impl Rc {
}
}
- /// Unwraps the contained value if the `Rc` has exactly one strong reference.
+ /// Returns the contained value, if the `Rc` has exactly one strong reference.
///
- /// Otherwise, an `Err` is returned with the same `Rc`.
+ /// Otherwise, an [`Err`][result] is returned with the same `Rc` that was
+ /// passed in.
///
/// This will succeed even if there are outstanding weak references.
///
+ /// [result]: ../../std/result/enum.Result.html
+ ///
/// # Examples
///
/// ```
@@ -245,7 +313,7 @@ impl Rc {
///
/// let x = Rc::new(4);
/// let _y = x.clone();
- /// assert_eq!(Rc::try_unwrap(x), Err(Rc::new(4)));
+ /// assert_eq!(*Rc::try_unwrap(x).unwrap_err(), 4);
/// ```
#[inline]
#[stable(feature = "rc_unique", since = "1.4.0")]
@@ -268,7 +336,11 @@ impl Rc {
}
}
- /// Checks if `Rc::try_unwrap` would return `Ok`.
+ /// Checks whether [`Rc::try_unwrap`][try_unwrap] would return
+ /// [`Ok`][result].
+ ///
+ /// [try_unwrap]: struct.Rc.html#method.try_unwrap
+ /// [result]: ../../std/result/enum.Result.html
///
/// # Examples
///
@@ -284,7 +356,7 @@ impl Rc {
/// let x = Rc::new(4);
/// let _y = x.clone();
/// assert!(!Rc::would_unwrap(&x));
- /// assert_eq!(Rc::try_unwrap(x), Err(Rc::new(4)));
+ /// assert_eq!(*Rc::try_unwrap(x).unwrap_err(), 4);
/// ```
#[unstable(feature = "rc_would_unwrap",
reason = "just added for niche usecase",
@@ -294,8 +366,35 @@ impl Rc {
}
}
+impl Rc {
+ /// Constructs a new `Rc` from a string slice.
+ #[doc(hidden)]
+ #[unstable(feature = "rustc_private",
+ reason = "for internal use in rustc",
+ issue = "0")]
+ pub fn __from_str(value: &str) -> Rc {
+ unsafe {
+ // Allocate enough space for `RcBox`.
+ let aligned_len = 2 + (value.len() + size_of::() - 1) / size_of::();
+ let vec = RawVec::::with_capacity(aligned_len);
+ let ptr = vec.ptr();
+ forget(vec);
+ // Initialize fields of `RcBox`.
+ *ptr.offset(0) = 1; // strong: Cell::new(1)
+ *ptr.offset(1) = 1; // weak: Cell::new(1)
+ ptr::copy_nonoverlapping(value.as_ptr(), ptr.offset(2) as *mut u8, value.len());
+ // Combine the allocation address and the string length into a fat pointer to `RcBox`.
+ let rcbox_ptr: *mut RcBox = mem::transmute([ptr as usize, value.len()]);
+ assert!(aligned_len * size_of::() == size_of_val(&*rcbox_ptr));
+ Rc { ptr: Shared::new(rcbox_ptr) }
+ }
+ }
+}
+
impl Rc {
- /// Creates a new `Weak` reference from this value.
+ /// Creates a new [`Weak`][weak] pointer to this value.
+ ///
+ /// [weak]: struct.Weak.html
///
/// # Examples
///
@@ -312,7 +411,22 @@ impl Rc {
Weak { ptr: this.ptr }
}
- /// Get the number of weak references to this value.
+ /// Gets the number of [`Weak`][weak] pointers to this value.
+ ///
+ /// [weak]: struct.Weak.html
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(rc_counts)]
+ ///
+ /// use std::rc::Rc;
+ ///
+ /// let five = Rc::new(5);
+ /// let _weak_five = Rc::downgrade(&five);
+ ///
+ /// assert_eq!(1, Rc::weak_count(&five));
+ /// ```
#[inline]
#[unstable(feature = "rc_counts", reason = "not clearly useful",
issue = "28356")]
@@ -320,7 +434,20 @@ impl Rc {
this.weak() - 1
}
- /// Get the number of strong references to this value.
+ /// Gets the number of strong (`Rc`) pointers to this value.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(rc_counts)]
+ ///
+ /// use std::rc::Rc;
+ ///
+ /// let five = Rc::new(5);
+ /// let _also_five = five.clone();
+ ///
+ /// assert_eq!(2, Rc::strong_count(&five));
+ /// ```
#[inline]
#[unstable(feature = "rc_counts", reason = "not clearly useful",
issue = "28356")]
@@ -328,8 +455,10 @@ impl